MoonshotAI / MoonshotAI/kimi-code
[Bug] 通用工具输出截断会拆开 UTF-16 surrogate pair
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
你运行的 Kimi Code 版本是?
源码复现,commit 46233953795c62051b433956db60c6c218d2cede(未使用已安装 CLI 复现)。发布前已同步上游 main 并复核相关源码。
你使用的是哪个开放平台/订阅?
不适用:不涉及登录/模型请求,源码隔离复现。
你使用的是哪个模型?
不适用:未调用模型。
你的电脑平台是?
uname -mprs:Linux 6.18.38-Unraid x86_64 unknown;Node.js v26.5.1。
你遇到了什么问题?
Bash/MCP 返回包含 emoji 的长日志;字符刚好跨越 head/tail、每行或 retained cap 边界时,模型预览出现孤立 UTF-16 surrogate,TextEncoder 落盘可变成替换字符。
通用 spill 服务直接 slice(0,4096)、slice(tailStart)、每行 slice 和 retained slice;accumulator 也直接 slice。Read 已有 surrogate 边界检查,不能据此误称通用服务也已修复。
复现步骤?
- checkout
46233953795c62051b433956db60c6c218d2cede,在仓库根目录执行。 - 将以下脚本保存到仓库外的
/tmp/kimi-repro-2.mjs,执行node /tmp/kimi-repro-2.mjs。不需要登录或安装 monorepo 依赖。 - 本次实际观测:
{ headWellFormed: false, lastCodeUnit: 'd83d' }。
import fs from 'node:fs';
import vm from 'node:vm';
import { stripTypeScriptTypes } from 'node:module';
const read = p => fs.readFileSync(p, 'utf8');
const load = (source, extra = {}) => {
const ctx = vm.createContext(extra);
vm.runInContext(stripTypeScriptTypes(source), ctx);
return ctx;
};
const source = read('packages/agent-core-v2/src/agent/toolResultTruncation/toolResultTruncationService.ts');
const fragment = source.slice(source.indexOf('function appendPreviewLines('), source.indexOf('function dropInlineSuffixLines('));
const ctx = load('const TOOL_RESULT_PREVIEW_HEAD_CHARS = 4096; const TOOL_RESULT_PREVIEW_TAIL_CHARS = 1024;' + fragment);
const lines = [];
ctx.appendPreviewLines(lines, 'a'.repeat(4095) + '😀' + 'b'.repeat(52000));
console.log({ headWellFormed: lines[2].isWellFormed(), lastCodeUnit: lines[2].charCodeAt(lines[2].length - 1).toString(16) });
复现边界:从当前源码摘取函数/方法执行,显式模拟依赖边界;不是完整 CLI 或仓库 Vitest 测试。
期望的行为是什么?
- 合法 Unicode 输入经过通用裁切后不产生孤立 surrogate,前缀和后缀均保持完整码点。
- 边界调整不超出现有字符预算,预览范围标注与实际内容一致。
- 覆盖 head/tail 的 emoji 边界,并保持 ASCII 行为不变。
补充信息
本次执行验证聚焦 appendPreviewLines 的 head 边界;其余 slice 裁切点为源码审查结果,不宣称均已端到端复现。#3611 是 VS Code 导出 topic 截断;#3645 是 Read 分页的 Unicode 保护,且 Read 绕过通用 spill;#3233 是远程运行时的 spill 路径问题,均不同于此通用预览边界。
已检索当前 open/closed issues 和 PR:external editor/signal、surrogate/Unicode/truncation、MCP pagination/nextCursor/listTools 及对应源码符号。未发现与此具体路径和触发条件等价的记录;不据此保证绝无重复。
固定源码、对应测试与参考边界
- https://github.com/MoonshotAI/kimi-code/blob/46233953795c62051b433956db60c6c218d2cede/packages/agent-core-v2/src/agent/toolResultTruncation/toolResultTruncationService.ts#L52-L60
- https://github.com/MoonshotAI/kimi-code/blob/46233953795c62051b433956db60c6c218d2cede/packages/agent-core-v2/src/agent/toolResultTruncation/toolResultTruncationService.ts#L173-L191
- https://github.com/MoonshotAI/kimi-code/blob/46233953795c62051b433956db60c6c218d2cede/packages/agent-core-v2/src/agent/toolResultTruncation/toolResultTruncationService.ts#L308-L319
- https://github.com/MoonshotAI/kimi-code/blob/46233953795c62051b433956db60c6c218d2cede/packages/agent-core-v2/src/tool/output-accumulator.ts#L30-L36
- https://github.com/MoonshotAI/kimi-code/blob/46233953795c62051b433956db60c6c218d2cede/packages/agent-core-v2/test/agent/toolResultTruncation/toolResultTruncation.test.ts#L64-L95
- https://github.com/MoonshotAI/kimi-code/blob/46233953795c62051b433956db60c6c218d2cede/packages/agent-core-v2/test/tool/output-accumulator.test.ts#L99-L134
- https://github.com/openai/codex/blob/5b1d6560181680f95cde95c14ed042acc02248ed/codex-rs/utils/string/src/truncate.rs#L86-L123
- https://github.com/openai/codex/blob/5b1d6560181680f95cde95c14ed042acc02248ed/codex-rs/utils/output-truncation/src/lib.rs#L20-L37
- https://github.com/openai/codex/blob/5b1d6560181680f95cde95c14ed042acc02248ed/codex-rs/utils/string/src/truncate/tests.rs#L54-L84
借鉴前缀/后缀只落在字符边界的约束;TS 中按 surrogate pair 修正 UTF-16 索引,不照搬 UTF-8 字节偏移。
只运行上述隔离复现,未运行仓库完整测试套件或 Codex 测试;源码引用用于定位与讨论,不代表已经实现修复。
Contribution
- 我愿意自己提交修复此 bug 的 PR(请先等待维护者在本 issue 中批准)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in packages/agent-core-v2/src/agent/toolResultTruncation/toolResultTruncationService.ts, focusing on the listed head, tail, line, and retained slicing points, then inspect packages/agent-core-v2/src/tool/output-accumulator.ts. Run the named toolResultTruncation and output-accumulator tests, adding coverage for emoji at each boundary; done means valid Unicode remains intact without changing ASCII behavior or exceeding the existing character budget.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100