mirror of
https://github.com/Narcooo/inkos.git
synced 2026-08-29 07:14:24 +08:00
feat(agent): 添加 write 工具,支持创建和覆盖写入文件
pi-agent 会话新增 write 工具,路径限制在 books/ 下, 自动创建父目录,safeBooksPath 防路径穿越。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import {
|
||||
createSubAgentTool,
|
||||
createReadTool,
|
||||
createEditTool,
|
||||
createWriteFileTool,
|
||||
createGrepTool,
|
||||
createLsTool,
|
||||
} from "./agent-tools.js";
|
||||
@@ -233,6 +234,7 @@ export async function runAgentSession(
|
||||
createSubAgentTool(pipeline, bookId),
|
||||
createReadTool(projectRoot),
|
||||
createEditTool(projectRoot),
|
||||
createWriteFileTool(projectRoot),
|
||||
createGrepTool(projectRoot),
|
||||
createLsTool(projectRoot),
|
||||
],
|
||||
|
||||
@@ -78,6 +78,7 @@ export function buildAgentSystemPrompt(bookId: string | null, language: string):
|
||||
- agent="exporter" 导出书籍(参数:format: txt/md/epub, approvedOnly: true/false)
|
||||
- **read** — 读取书籍的设定文件或章节内容
|
||||
- **edit** — 编辑设定文件(如修改角色名、调整世界观)
|
||||
- **write** — 创建新文件或覆盖写入已有文件
|
||||
- **grep** — 搜索内容(如"哪一章提到了某个角色")
|
||||
- **ls** — 列出文件或章节
|
||||
|
||||
@@ -119,6 +120,7 @@ export function buildAgentSystemPrompt(bookId: string | null, language: string):
|
||||
- agent="exporter" export book (params: format: txt/md/epub, approvedOnly: true/false)
|
||||
- **read** — Read truth files or chapter content
|
||||
- **edit** — Edit truth files (rename characters, adjust world settings)
|
||||
- **write** — Create a new file or overwrite an existing file
|
||||
- **grep** — Search content across chapters
|
||||
- **ls** — List files or chapters
|
||||
|
||||
|
||||
@@ -247,6 +247,42 @@ export function createEditTool(projectRoot: string): AgentTool<typeof EditParams
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 3b. Write File Tool
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const WriteFileParams = Type.Object({
|
||||
path: Type.String({ description: "File path relative to books/" }),
|
||||
content: Type.String({ description: "Full file content to write" }),
|
||||
});
|
||||
|
||||
export function createWriteFileTool(projectRoot: string): AgentTool<typeof WriteFileParams> {
|
||||
const booksRoot = join(projectRoot, "books");
|
||||
|
||||
return {
|
||||
name: "write",
|
||||
description:
|
||||
"Create a new file or overwrite an existing file. " +
|
||||
"Path is relative to books/. Parent directories are created automatically.",
|
||||
label: "Write File",
|
||||
parameters: WriteFileParams,
|
||||
async execute(
|
||||
_toolCallId: string,
|
||||
params: Static<typeof WriteFileParams>,
|
||||
): Promise<AgentToolResult<undefined>> {
|
||||
try {
|
||||
const filePath = safeBooksPath(booksRoot, params.path);
|
||||
const { mkdir } = await import("node:fs/promises");
|
||||
await mkdir(resolve(filePath, ".."), { recursive: true });
|
||||
await writeFile(filePath, params.content, "utf-8");
|
||||
return textResult(`File "${params.path}" written successfully.`);
|
||||
} catch (err: any) {
|
||||
return textResult(`Failed to write "${params.path}": ${err?.message ?? String(err)}`);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 4. Grep Tool
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export { buildAgentSystemPrompt } from "./agent-system-prompt.js";
|
||||
export { createSubAgentTool, createReadTool, createEditTool, createGrepTool, createLsTool } from "./agent-tools.js";
|
||||
export { createSubAgentTool, createReadTool, createEditTool, createWriteFileTool, createGrepTool, createLsTool } from "./agent-tools.js";
|
||||
export { runAgentSession, evictAgentCache, type AgentSessionConfig, type AgentSessionResult } from "./agent-session.js";
|
||||
|
||||
Reference in New Issue
Block a user