
kimi-cli Wire 协议端到端测试指南--wireJSON-RPC 测试矩阵、执行规则与源码印证【免费下载链接】kimi-cliKimi Code CLI is your next CLI agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kimi-cli导读本文基于仓库 tests_e2e/AGENTS.md 展开系统讲解 kimi-cli 的 Wire 模式端到端测试体系它只通过kimi --wire暴露的 JSON-RPC Wire 消息协议进行黑盒验证不涉及 Shell UI、Print、ACP 等交互界面。读完本文你将掌握 Wire 测试的完整矩阵W-01 ~ W-42、执行环境隔离规则、_scripted_echo脚本化回放机制以及测试与 src/kimi_cli/wire/ 源码实现之间的对应关系可直接用于理解、运行和扩展这套协议级回归测试。一、Wire 模式与 Wire E2E 测试的定位Wire 是 kimi-cli 面向外部宿主程序提供的协议层CLI 通过--wire标志见 src/kimi_cli/cli/init.py帮助文本标注为experimental以标准输入/输出运行一个 JSON-RPC 服务宿主程序如编辑器插件、Agent 框架用行分隔 JSON 与之对话接收事件流event、应答请求request、发送方法调用initialize/prompt/cancel/steer/replay/set_plan_mode。因此 Wire E2E 测试的目标与范围被严格限定为只测kimi --wire的 JSON-RPC 与 Wire 消息不测Shell UI / Print / ACP / Term / 快捷键等界面层不测--agent okabe不测W-23、W-26、W-29、W-27这些编号留给环境变量覆盖类场景即 env overrides。这个范围声明并非随意取舍而是为了让测试聚焦协议契约本身任何 Shell 渲染、快捷键绑定或 UI 模式切换引入的差异都不会污染 Wire 协议层的断言。测试方宿主只需关心自己发送的 JSON-RPC 请求是否得到符合规范的响应与事件。二、执行规则如何启动与隔离测试环境2.1 基础命令与覆盖开关默认情况下测试通过uv run kimi启动被测进程如需替换可执行体例如调试 Rust 版kimi-agent设置环境变量KIMI_E2E_WIRE_CMD# 默认 uv run kimi --wire ... # 覆盖为其他二进制 KIMI_E2E_WIRE_CMD../kimi-agent-rs/target/debug/kimi-agent pytest tests_e2e KIMI_E2E_WIRE_CMDkimi-agent pytest tests_e2e辅助模块 tests_e2e/wire_helpers.py 中的base_command()会读取该环境变量并用shlex.split解析为命令参数_wire_base_command()负责在命令末尾自动补上--wire若缺失保证无论覆盖与否被测进程总是以 Wire 服务模式启动。另有一个调试开关KIMI_TEST_TRACE1开启后会在测试进程内打印STDIN/STDOUT的原始报文便于排查协议问题见 wire_helpers.py。2.2 环境隔离绝不触碰真实~/.kimi协议测试最大的污染风险是读到开发者机器上真实会话与配置。执行规则要求每次测试隔离HOME、USERPROFILE与KIMI_SHARE_DIR三个环境变量指向tmp_path下的临时目录make_home_dir/make_env见 wire_helpers.py使用临时--work-dir让会话记录、工作区文件都落在临时目录这样所有 session 数据被重定向到home_dir/.kimi即share_dir(home_dir)测试结束即丢弃。2.3 快照测试与先空后补策略测试使用inline_snapshot做快照断言。它的特点是快照可以从空开始后续运行测试时由inline-snapshot自动回填/更新。这意味着开发者在新增 Wire 场景时可以先只写行为骨架发送什么、期待什么状态再让工具把真实报文固化进源码形成稳定的回归基线。仓库中的大量用例如 tests_e2e/test_wire_protocol.py正是以snapshot(...)形式保存了完整的事件序列。2.4 传输格式假设行分隔 JSON 且可交错Wire 流量是行分隔 JSON服务端从 stdin 逐行读入_read_loop使用readline见 src/kimi_cli/wire/server.py输出端每行一条event/request/response。event、request与响应可能相互交错——因此测试读取端collect_until_response/collect_until_requestwire_helpers.py采用持续读行、按id匹配响应、按method收集事件/请求的策略而不是假设固定顺序。这正是并发 subagent、后台审批等场景能稳定测通的底层前提。三、测试矩阵总览W-01 ~ W-42分组编号验证点启动与协议W-01 ~ W-06握手、外部工具注册/冲突、免握手 prompt、LLM 未设置、最大步数提示词与事件流W-07 ~ W-12基础 turn、多行输入、ContentPart 输入、thinking 开关、并发、取消工具与审批W-13 ~ W-18Shell 审批、拒绝、按会话批准、YOLO、DisplayBlock、参数流式拼接会话与上下文W-19 ~ W-24session 文件、续接、/clear、/compact、状态统计配置与运行时标志W-25 / W-28 / W-30内联--config、--model覆盖、--work-dir扩展Agent/Skill/MCPW-31 ~ W-36内置/自定义 agent 边界、subagents、skill、flow、MCP韧性与错误W-37 ~ W-42非法 JSON、非法请求、未知方法、非法参数、空取消、LLM 错误以下各节按分组逐一展开并结合源码与测试用例说明为什么这样测、底层发生了什么。四、启动与协议W-01 ~ W-06W-01 握手initialize客户端发送initialize后服务端返回protocol_version、server名称 版本与非空的slash_commands列表。对应实现见_handle_initializeserver.py。需要注意文档与实现的版本差异tests_e2e/AGENTS.md中 W-01 描述为返回protocol_version1.1而当前仓库 src/kimi_cli/wire/protocol.py 定义WIRE_PROTOCOL_VERSION 1.10、WIRE_PROTOCOL_LEGACY_VERSION 1.1实际断言test_wire_protocol.py也校验protocol_version 1.10。即1.1 是向后兼容的旧版协议标识当前实现对外通告 1.10wire.jsonl 读取时也会依据文件头 metadata 判断按新版本还是旧版本解析src/kimi_cli/wire/file.py。握手响应还包含slash_commands来自soul.available_slash_commands的{name, description, aliases}列表快照中可见init、compact、clear、yolo、afk、plan、add-dir、export、import、skill:kimi-cli-help、skill:skill-creator等external_tools仅当有注册请求时accepted/rejected两个数组hookssupported_events与configured本仓库支持的钩子事件集见HOOK_EVENT_TYPES快照中列出PreToolUse、PostToolUse、UserPromptSubmit、Stop、SubagentStart、PreCompact、Notification等 13 个capabilities当前固定返回{supports_question: true}。W-02 外部工具注册与调用在initialize的params.external_tools中声明工具name/description/parametersJSON Schema随后 LLM 触发ToolCallRequestmethod: request客户端执行后返回ToolResultturn 正常结束。完整报文流程见 test_external_tool_call事件序列为TurnBegin → StepBegin → ContentPart → ToolCall → StatusUpdate → ToolCallRequest(request) → ToolResult → StepBegin → ContentPart → StatusUpdate → TurnEnd。W-03 外部工具冲突注册一个与内置工具同名的工具如Shell会被拒绝。服务端在_handle_initialize中通过toolset.find(tool.name)判断若已存在且不是WireExternalTool类型则拒绝并给出 reasonconflicts with builtin toolserver.py。测试断言见 test_initialize_external_tool_conflict。W-04 免握手 prompt不发送initialize直接promptturn 仍能完成——_handle_prompt中if not self._initialized: self._track_session_started(None)server.py即握手不是 prompt 的前置条件只是协议能力协商。测试见 test_prompt_without_initialize。W-05 LLM 未设置-32001配置缺失导致 LLM 未配置时run_soul抛出LLMNotSet_handle_prompt映射为ErrorCodes.LLM_NOT_SET -32001消息 LLM is not setserver.py。W-06 最大步数statusmax_steps_reached设置很小的--max-steps-per-turn如1后prompt 响应返回{status: max_steps_reached, steps: N}。配置项在 src/kimi_cli/config.py 的LoopControl.max_steps_per_turn默认 1000ge1兼容别名max_steps_per_run异常MaxStepsReached在_handle_prompt中被捕获并转为成功响应携带该状态server.py。测试见 test_wire_prompt.py。五、提示词与事件流W-07 ~ W-12W-07 基础 turn 流程TurnBegin → StepBegin → ContentPart(text) → StatusUpdate → TurnEnd是最基本的生命周期任何 prompt 都必须以此形态输出。TurnBegin.user_input携带原始输入StepBegin.n为步序号TurnEnd标志 turn 结束若被中断可能省略见 src/kimi_cli/wire/types.py。W-08 多行输入TurnBegin.user_input中的换行必须被完整保留测试校验多行 prompt 在事件中逐字回显。W-09 ContentPart 数组输入user_input支持ContentPart[]形式text/image/audio/video前提是初始化时声明了对应 capabilities。消息模型见JSONRPCPromptMessage.Params.user_input: str | list[ContentPart]src/kimi_cli/wire/jsonrpc.py内容部件类型TextPart/ImageURLPart/AudioURLPart/VideoURLPart/ThinkPart来自kosong.message。W-10 thinking 开关需真实 LLM--thinking时事件流包含ContentPart(typethink)--no-thinking则不输出。该用例被标记为Real LLM Placeholder见第八节脚本化回放无法模拟思考块。W-11 并发 prompt-32000turn 进行中再次发送prompt返回ErrorCodes.INVALID_STATE -32000An agent turn is already in progress。判定依据是_is_streaming_cancel_event is not None见_handle_prompt开头server.py。当前实现不支持排队多个输入源码中留有 TODO 注释。W-12 取消 turn需真实 LLM发送cancel返回{}原始prompt最终以statuscancelled结束RunCancelled异常捕获server.py过程中可能伴随StepInterrupted事件。cancel处理逻辑见_handle_cancelserver.py。六、工具与审批W-13 ~ W-18W-13 / W-14 / W-15Shell 审批三态W-13 approveShell工具触发ApprovalRequestmethod: request客户端回ApprovalResponse{response: approve}后ToolResult返回、turn 继续。测试使用build_approval_response(msg, approve)作为request_handler自动应答test_wire_approvals_tools.py。W-14 reject回reject后 turn 直接结束、工具不执行。W-15 approve_for_session回approve_for_session后本会话后续同类阻塞审批不再弹出。审批的请求/应答模型在 src/kimi_cli/wire/types.pyApprovalRequest以asyncio.Future挂起等待resolve(response, feedback)唤醒等待方ApprovalResponse.Kind为approve | approve_for_session | reject并支持feedback字段拒绝时给模型的指示。服务端转发与解析见_request_approval与_handle_responseserver.py。W-16 YOLO跳过阻塞审批--yolo启动时所有阻塞审批自动通过。start_wire(yoloTrue)会在命令中注入该标志wire_helpers.py大部分不涉及审批分支的用例都以yoloTrue运行避免测试被审批请求卡住。W-17 DisplayBlock 覆盖Shell/WriteFile/StrReplaceFile/SetTodoList等工具触发的ApprovalRequest必须携带预期display类型如shell、todo、diff等。DisplayBlock 体系在 src/kimi_cli/wire/types.py 中导出BriefDisplayBlock、DiffDisplayBlock、TodoDisplayBlock、ShellDisplayBlock、BackgroundTaskDisplayBlock等测试通过_display_types()抽取 payload 中的 display 类型列表逐一校验。W-18 工具参数流式拼接LLM 流式输出时ToolCallPart.arguments_part是参数片段客户端需要把所有片段拼接成完整 JSON 参数。这对应kosong.message.ToolCallPart的合并语义——服务端 Wire 层同时提供原始流与合并流两条通道Wire.soul_side.send对MergeableMixin类型的消息做merge_in_place合并缓冲src/kimi_cli/wire/init.pyUI 侧可选择ui_side(mergeTrue/False)订阅。七、会话与上下文W-19 ~ W-24W-19 / W-20session 文件与续接W-19--session id启动并完成一轮后在home_dir/.kimi/sessions/work_dir_md5/id/下生成context.jsonl、wire.jsonl、state.json断言见 test_wire_sessions.py。wire.jsonl由WireFile负责首行为 metadata{type:metadata,protocol_version:...}后续每行是一条带timestamp的WireMessageRecordsrc/kimi_cli/wire/file.py。W-20--continue启动后向同一个session 文件追加内容而不是覆盖。消息录制由Wire内部的_WireRecorder消费合并队列并append_message落盘src/kimi_cli/wire/init.py。这些落盘文件同时支撑replay方法_handle_replay逐条读出wire.jsonl记录并重新以event/request形式推送server.py实现离线重放上一次会话。W-21/clear清除上下文/clear后下一次prompt不依赖先前上下文。对应 slash 命令实现位于soul层Wire 测试验证的是清除后的事件流与首次运行等价。W-22/compact手动压缩/compact触发CompactionBegin → CompactionEnd事件对。协议约束src/kimi_cli/wire/types.pyCompactionBegin必须发生在某个 step 内StepBegin与下一个StepBegin/StepInterrupted之间且其后必须紧跟CompactionEnd。W-24 状态统计StatusUpdate.context_usage百分比浮点、context_tokens、max_context_tokens、token_usageTokenUsage类型合法且在 turn 进行中持续变化字段定义见 src/kimi_cli/wire/types.py。测试辅助函数normalize_value会对浮点做round(value, 6)归一化保证快照稳定wire_helpers.py。八、配置与运行时标志W-25 / W-28 / W-30W-25--config内联配置支持以 JSON/TOML 字符串直接传配置测试见 test_wire_config.pyconfig_text传入 JSON 字符串含default_model、models、providers无需配置文件。start_wire对config_text使用--config参数wire_helpers.py。W-28--model覆盖default_modelCLI 标志--model的优先级高于配置中的default_model验证命令行覆盖配置的解析层级。W-30--work-dir生效需真实 LLM用真实模型问当前目录在哪里验证--work-dir被正确透传为工作目录——这是唯一能端到端证明工作区路径语义的方式因此同样被列为 Real LLM 用例。九、扩展Agent / Skill / MCPW-31 ~ W-36W-31内置defaultagent 调用SendDMail应失败或被拒绝——验证内置 agent 的工具边界默认 agent 无权访问后台通知类工具。W-32--agent-file指定自定义 agent 时其 toolset 不含某工具相关调用被拒绝。start_wire通过--agent-file注入wire_helpers.py。W-33 子代理需真实 LLMprompt 要求并行调用两个 task 工具各自运行shell sleep 0.5和shell sleep 1验证SubagentEvent流式推送、ToolResult与多个并发ApprovalRequest。SubagentEvent用WireMessageEnvelope包裹内层事件src/kimi_cli/wire/types.py并兼容旧字段名task_tool_call_id。W-34 Skill 调用创建测试 skill通过/skill:test注入SKILL.md内容Wire 模式下没有/helpskill 是主要的知识注入通道。测试在--skills-dir下建SKILL.md并断言上下文被注入test_wire_skills_mcp.py。W-35 Flow skill/flow:name运行流程直到END验证 flow 型 skill 的终止语义。W-36 MCP用 Pythonfastmcp写测试服务器通过--mcp-config-file加载验证 MCP 工具可用。握手阶段服务端还会通过MCPStatusSnapshot/MCPServerSnapshot事件上报各服务器的pending/connecting/connected/failed/unauthorized状态src/kimi_cli/wire/types.py。十、韧性与错误处理W-37 ~ W-42错误码定义集中在 src/kimi_cli/wire/jsonrpc.py 的ErrorCodes测试逐一验证编号场景错误码W-37非法 JSON 行如{not-json}-32700Parse Error消息 Invalid JSON formatW-38非法请求如jsonrpc: 2.1-32600Invalid RequestW-39未知方法method: nope-32601Method Not Found消息为 Unexpected method received: nopeW-40非法参数prompt缺params.user_input-32602Invalid ParamsInvalid parameters for methodpromptW-41无活动 turn 时cancel-32000INVALID_STATENo agent turn is in progressW-42不支持的模型 / 服务错误-32002LLM_NOT_SUPPORTED /-32003CHAT_PROVIDER_ERROR测试用例见 test_wire_errors.py非法 JSON 在_read_loop的json.loads阶段捕获server.py非法请求/非法参数分别在通用JSONRPCMessage校验与JSONRPCInMessageAdapter.validate_python阶段拦截server.py。另有一个未在矩阵编号中列出的-32004AUTH_EXPIRED用于 OAuth 会话 401 时提示用户重新登录server.py。十一、测试辅助设施wire_helpers 的关键机制wire_helpers.py 是整套测试的驱动引擎除前述环境隔离外还有几个值得理解的设计_scripted_echo脚本化 Providerwrite_scripted_config生成一个配置其中providers指向类型为_scripted_echo的 provider通过环境变量KIMI_SCRIPTED_ECHO_SCRIPTS指向脚本文件wire_helpers.py。脚本行支持text: 内容输出文本与tool_call: JSON模拟工具调用两种 DSL因此绝大多数用例无需真实 LLM即可确定性复现完整事件流。脚本化工具调用可用build_shell_tool_call、build_set_todo_call、build_ask_user_tool_call构造。应答构造器build_approval_response、build_tool_result_response、build_question_response分别按协议组装ApprovalResponse、ToolResult、QuestionResponse的 JSON-RPC result。报文归一化normalize_value/normalize_response负责把临时路径替换为tmp/home_dir/work_dir占位符、UUID 替换为uuid、统一换行与路径分隔符、补齐error.data与return_value.extras等可选字段使快照跨平台、跨机器稳定。消息排序归一summarize_messages配合_normalize_step_block把单个 step 内的事件重排为固定顺序stream 事件 → StatusUpdate → requests → approvals → ToolResult并按ToolCall出现顺序排列ToolResultwire_helpers.py从而消除多 subagent 并发带来的时序抖动。超时与读取LineReader用后台线程读管道兼容 Windows 无select()的环境read_json带 5 秒默认超时避免死等。十二、Real LLM 占位符与测试选择AGENTS.md 末尾明确W-10thinking、W-12cancel、W-30work-dir、W-33subagents必须使用真实 provider其余全部走_scripted_echo。这一划分的合理性在于思考块输出、取消时序、真实目录感知、并行子代理的流式行为都属于模型/运行时真实行为脚本无法忠实模拟其余 38 个用例覆盖的是协议契约消息形状、错误码、状态机、持久化用脚本化回放即可获得确定性与毫秒级速度适合作为 CI 回归集。十三、与源码实现的对应关系小结测试关注点核心源码位置协议版本与消息模型src/kimi_cli/wire/protocol.py、src/kimi_cli/wire/jsonrpc.py服务端分派与处理方法src/kimi_cli/wire/server.py_dispatch_msg/_handle_*Wire 消息类型Event / Requestsrc/kimi_cli/wire/types.py双队列广播与录制src/kimi_cli/wire/init.pysession 落盘与重放src/kimi_cli/wire/file.py--wireCLI 入口src/kimi_cli/cli/init.pymax_steps_per_turn配置src/kimi_cli/config.py测试驱动与归一化tests_e2e/wire_helpers.py结语Wire E2E 测试把 kimi-cli 的协议层从完整产品中独立出来用 42 个编号用例覆盖握手、事件流、审批、会话、扩展与错误处理六个维度配合_scripted_echo实现除四个真实 LLM 场景外全部确定性回归。理解这套测试矩阵与src/kimi_cli/wire/源码的对应关系既能帮助你快速定位协议实现问题也能作为扩展 Wire 协议新方法、新事件类型、新能力协商时的规范参照先补测试矩阵再改实现最后用inline_snapshot固化新契约。【免费下载链接】kimi-cliKimi Code CLI is your next CLI agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kimi-cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考