[Bug] 媒体较多的会话恢复失败:wireClone 整体序列化触发 Invalid string length
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 2/5
- 見積もり時間
- 1〜3時間
- 初心者へのやさしさ
- 85/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- node.js, typescript
- 領域
- cli
調査の方向性
バグは packages/klient/src/transports/memory/dispatcher.ts にあります。67 行目の wireClone と、487 行目のその呼び出しです。添付の repro.mjs を Node で実行して RangeError を再現し、その後、agentContextMemoryService.get に対するメッセージごとのクローン処理を示された方針に沿って実装してください。完了とは、セッションの再開が成功し、クローンされたメッセージが元のメッセージの SHA-256 と一致することを意味します。
索引モデルが issue の本文から書いたものです。
説明
你运行的 Kimi Code 版本是?
2.3.0。源码定位基准为上游提交 b5e28fd6beac752a2cdcc0ff2f5fdf40e6494fbb;另外核对了当前 main 快照 7ccac2b45b8a3481c76f771bb99c043b562de2c5,相关 dispatcher.ts 文件仍是同一实现。
你使用的是哪个开放平台/订阅?
问题发生于本地恢复会话阶段,尚未发送模型请求;具体订阅未提供。
你使用的是哪个模型?
k3.1-pro。下面的纯本地序列化复现不依赖模型或账号。
你的电脑平台是?
macOS / Apple Silicon (darwin, arm64)。隔离诊断环境:Node.js v26.10.0,node:buffer.constants.MAX_STRING_LENGTH = 536870888。
你遇到了什么问题?
恢复一个包含大量图片、视频历史的长会话时失败,界面显示:
Error: Failed to resume session <session-id>: Invalid string length
在完整会话副本中进行隔离恢复,捕获到以下调用链(本地路径、会话标识均已省略):
RangeError: Invalid string length
at JSON.stringify (<anonymous>)
at wireClone (<bundle>)
at Object.call (<bundle>; memory dispatcher)
at async call (<bundle>)
at async Promise.all (index 0)
at async Object.getContext (<bundle>)
at async Promise.all (index 0)
at async SDKRpcClientV2.resumedAgentState (<bundle>)
at async SDKRpcClientV2.resumedSessionSummary (<bundle>)
定位到 packages/klient/src/transports/memory/dispatcher.ts 中的 wireClone:
export function wireClone<T>(value: T): T {
if (value === undefined) return value;
return JSON.parse(JSON.stringify(value)) as T;
}
createMemoryDispatcher.call 对整个返回值执行 wireClone(result)。当返回值是 agentContextMemoryService.get() 载入媒体后的完整消息数组时,整个数组的 JSON 超过 V8 单个字符串长度上限;每条消息本身则仍在上限以内。
实际会话的脱敏测量值:
| 项目 | 数值 |
|---|---|
| 载入后的有效上下文消息数 | 870 |
| 各条消息 JSON 长度之和 | 778,163,547 字符 |
| 最大单条消息 JSON 长度 | 120,156,570 字符 |
| 当前运行时单字符串长度上限 | 536,870,888 字符 |
| 上下文 token 计数 | 851,376 |
上述总长度通过逐条序列化后累加得到,没有构造超大成功字符串。磁盘上的主 wire.jsonl 约 164 MB,因此只检查该文件大小不能反映媒体载入后的大小。所有 32 个 Agent 的 JSONL 均可解析;所有引用的媒体都存在,987 个 blob 均通过其编码约定的内容哈希校验。
复现步骤?
实际触发路径:
- 在同一会话中积累多次图片、视频输入,使载入媒体后的历史整体 JSON 大于运行时的
MAX_STRING_LENGTH,但单条消息仍小于该上限。 - 退出后,通过
kimi --session <id>或会话选择器恢复。 getContext()经内存 dispatcher 返回完整消息数组时,JSON.stringify抛出上述错误,恢复失败。
以下是下层序列化逻辑的独立复现,不是完整 CLI 会话生成器。仅使用合成文本,不需要账号、真实媒体、会话文件或网络:
// repro.mjs
import assert from 'node:assert/strict';
import { constants } from 'node:buffer';
function wireClone(value) {
if (value === undefined) return value;
return JSON.parse(JSON.stringify(value));
}
const part = 'x'.repeat(8 * 1024 * 1024);
const count = Math.floor(constants.MAX_STRING_LENGTH / part.length) + 1;
const history = Array.from({ length: count }, () => ({
role: 'user',
content: [{ type: 'text', text: part }],
}));
assert.throws(() => wireClone(history), {
name: 'RangeError',
message: 'Invalid string length',
});
const cloned = history.map(wireClone);
assert.equal(cloned.length, history.length);
for (let i = 0; i < cloned.length; i++) {
assert.notEqual(cloned[i], history[i]);
assert.equal(cloned[i].content[0].text, part);
}
console.log('whole-array clone fails; per-message clone preserves all messages');
运行 node --max-old-space-size=4096 repro.mjs。在上述 Node 版本实测通过:64 条消息,合成 payload 共 536,870,912 字符,整体克隆复现 RangeError,逐条克隆成功。该测试需要足够内存。
期望的行为是什么?
当每条消息均可单独表示时,恢复会话不应要求把所有载入后的媒体和历史拼接成一个超大 JSON 字符串。希望保留已有上下文和媒体,并正常恢复会话。
补充信息:已验证的修复方向
对该返回消息数组的调用点进行局部修改即可绕过整体字符串上限,例如:
const result = await (member as (...a: unknown[]) => unknown).apply(instance, callArgs);
if (
service === 'agentContextMemoryService' &&
method === 'get' &&
Array.isArray(result)
) {
return result.map(wireClone);
}
return wireClone(result);
此建议仅针对 get() 返回的实际消息对象数组;每条消息继续使用原有 JSON round-trip 语义。它仍需要足够的总内存,不解决单条消息本身超过字符串上限的情况。
在完整副本中验证,对相同会话的 870 条有效上下文消息按消息克隆成功,逐条 JSON 内容的 SHA-256 在克隆前后完全一致,没有通过删历史、移除媒体、重新摘要或新建会话规避问题。另外验证了普通文本、Unicode、可选字段、多模态内容及工具调用结构的逐条克隆一致性。
这里报告的是本地恢复与上下文克隆;没有将整个载入后的上下文直接发送到模型,也没有用真实模型请求验证补丁。为保护隐私,不附完整会话、原始媒体、截图、凭据或未脱敏的诊断包。
- 主要言語
- TypeScript
- スター
- 8k
- フォーク
- 1.3k
- 平均マージ
- 1日 1時間
- マージ済み PR(30日)
- 130
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
MoonshotAI/kimi-code のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
MoonshotAI/kimi-code#4398 ·
メンテナーはふだん 1 日以内に返信
-
[Bug] vis reports legacy tool-triggered swarm sessions as active対応中かも @louisss1016 が 1 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
MoonshotAI/kimi-code#4395 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
MoonshotAI/kimi-code#4392 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
MoonshotAI/kimi-code#4381 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
MoonshotAI/kimi-code#4368 ·
メンテナーはふだん 1 日以内に返信
MoonshotAI/kimi-code の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1〜3時間 初心者へのやさしさ 84/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 83/100
keptinventory/kept#336 ·
メンテナーはふだん 1 日以内に返信
-
good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
-
hemi-earn
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
vetro-protocol/vetro-monorepo#1013 ·
メンテナーはふだん 1 日以内に返信