diff --git a/.changeset/tidy-media-tool-hints.md b/.changeset/tidy-media-tool-hints.md new file mode 100644 index 00000000000..3777306e636 --- /dev/null +++ b/.changeset/tidy-media-tool-hints.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Stop recommending specific other tools in Read tool descriptions and error messages, which could point models to tools that are not available. diff --git a/packages/agent-core-v2/src/agent/tools/os/read/read.md b/packages/agent-core-v2/src/agent/tools/os/read/read.md index 8cfab273b0a..8597a664793 100644 --- a/packages/agent-core-v2/src/agent/tools/os/read/read.md +++ b/packages/agent-core-v2/src/agent/tools/os/read/read.md @@ -8,7 +8,7 @@ When you need several files, prefer to read them in parallel: emit multiple `Rea - Returns up to ${MAX_LINES} lines or ${MAX_BYTES_KB} KB per call, whichever comes first; lines longer than ${MAX_LINE_LENGTH} chars are truncated mid-line. - Page larger files with `line_offset` (1-based start line) and `n_lines`. Omit `n_lines` to read up to the ${MAX_LINES}-line cap. - Sensitive files (`.env` files, credential stores, SSH private keys, and similar secrets) are refused to protect secrets; do not attempt to read them. Templates and public keys are exempt: `.env.example` / `.env.sample` / `.env.template` and public SSH keys such as `id_rsa.pub` read normally. -- UTF-8 text files are read directly. UTF-16 LE/BE text files (with or without a BOM) are detected automatically and transcoded to UTF-8 for display; the status block notes the detected encoding, and Edit/Write on such a file still expect UTF-8 — convert its encoding first (e.g. `iconv` via Bash). Other encodings (e.g. GBK), binary files, and files containing NUL bytes are refused; use `ReadMediaFile` for images or video, and Bash or an MCP tool for other binary formats. +- UTF-8 text files are read directly. UTF-16 LE/BE text files (with or without a BOM) are detected automatically and transcoded to UTF-8 for display; the status block notes the detected encoding, and Edit/Write on such a file still expect UTF-8 — convert its encoding first (e.g. with `iconv`). Other encodings (e.g. GBK), binary files, and files containing NUL bytes are refused. - Negative line_offset reads from the end of the file (for example, -100 reads the last 100 lines); the absolute value cannot exceed ${MAX_LINES}. - Output format: `\t` per line. - A `...` status block is appended after the file content; it summarizes how much was read (line and byte counts, truncation, line-ending notes) and is not part of the file itself. diff --git a/packages/agent-core-v2/src/agent/tools/os/read/readTool.ts b/packages/agent-core-v2/src/agent/tools/os/read/readTool.ts index 887df614530..e7d1b6b76d1 100644 --- a/packages/agent-core-v2/src/agent/tools/os/read/readTool.ts +++ b/packages/agent-core-v2/src/agent/tools/os/read/readTool.ts @@ -181,18 +181,14 @@ async function* decodedLines(lines: readonly string[]): AsyncGenerator { } function notReadableFileOutput(path: string): string { - return ( - `"${path}" is not readable as UTF-8 text. ` + - 'If it is an image or video, use ReadMediaFile. ' + - 'For other binary formats, use Bash or an MCP tool if available.' - ); + return `"${path}" is not readable as UTF-8 text. Only text files can be read.`; } function notUtf8DecodableFileOutput(path: string): string { return ( `"${path}" is not valid UTF-8 or UTF-16 text. ` + 'Only UTF-8 and UTF-16 text files can be read; ' + - 'for other encodings (e.g. GBK), convert the file to UTF-8 first (e.g. `iconv` via Bash).' + 'for other encodings (e.g. GBK), convert the file to UTF-8 first (e.g. with `iconv`).' ); } @@ -275,7 +271,7 @@ export class ReadTool implements IReadTool { if (fileType.kind === 'image' || fileType.kind === 'video') { return { isError: true, - output: `"${args.path}" is a ${fileType.kind} file. Use ReadMediaFile to read image or video files.`, + output: `"${args.path}" is ${fileType.kind === 'image' ? 'an' : 'a'} ${fileType.kind} file. Only text files can be read.`, }; } @@ -289,7 +285,7 @@ export class ReadTool implements IReadTool { output: `"${args.path}" is ${encodingDisplayName(detection.encoding)} text but too large to transcode ` + `(${String(stat.size)} bytes > ${String(TRANSCODE_MAX_BYTES)}). ` + - 'Convert it to UTF-8 first (e.g. `iconv` via Bash).', + 'Convert it to UTF-8 first (e.g. with `iconv`).', }; } const decoded = decodeUtfText(await fs.readBytes(safePath), detection.encoding); diff --git a/packages/agent-core-v2/src/features/plan/profile/plan.ts b/packages/agent-core-v2/src/features/plan/profile/plan.ts index 534042eb9c6..1c29497bf81 100644 --- a/packages/agent-core-v2/src/features/plan/profile/plan.ts +++ b/packages/agent-core-v2/src/features/plan/profile/plan.ts @@ -22,8 +22,8 @@ const PLAN_ROLE = '1. What you already know from the information provided\n' + '2. What questions remain unanswered that would benefit from explore agent investigation\n' + '3. Your implementation plan (either preliminary if questions remain, or final if sufficient context exists)\n\n' + - 'You are a read-only planning agent: you can read and search files (Read, Glob, Grep, ReadMediaFile) ' + - 'and consult the web (WebSearch, FetchURL), but you have no shell and no file-editing tools. ' + + 'You are a read-only planning agent: you can read and search files ' + + 'and consult the web, but you have no shell and no file-editing tools. ' + 'Where the general instructions tell you to make changes with tools, that does not apply to you — ' + 'do not attempt to run commands or modify files. Your deliverable is the plan itself, returned as ' + 'your final message.'; diff --git a/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts b/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts index 2d18c202978..d371f684782 100644 --- a/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts +++ b/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts @@ -656,7 +656,7 @@ describe('FullCompaction', () => { event: 'compaction_finished', properties: expect.objectContaining({ source: 'manual', - tokens_before: 15_004, + tokens_before: 14_980, retry_count: 1, trace_id: 'trace-compact-1', }), @@ -1039,7 +1039,7 @@ describe('FullCompaction', () => { properties: expect.objectContaining({ agent_id: 'main', source: 'manual', - tokens_before: 15_004, + tokens_before: 14_980, duration_ms: expect.any(Number), round: 1, retry_count: 0, @@ -1264,7 +1264,7 @@ describe('FullCompaction', () => { event: 'compaction_failed', properties: expect.objectContaining({ source: 'manual', - tokens_before: 15_004, + tokens_before: 14_980, duration_ms: expect.any(Number), retry_count: 4, error_type: 'APIConnectionError', diff --git a/packages/agent-core-v2/test/agent/loop/loop.test.ts b/packages/agent-core-v2/test/agent/loop/loop.test.ts index bf78addf34a..eeaf5d18288 100644 --- a/packages/agent-core-v2/test/agent/loop/loop.test.ts +++ b/packages/agent-core-v2/test/agent/loop/loop.test.ts @@ -134,8 +134,8 @@ describe('Agent loop', () => { [emit] turn.step.started { "time": "