qwen-code 隐私安全工具结果边界诊断基于 HMAC 与精确字节核算的 opt-in 调试机制解析【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code导读本文剖析 qwen-code 中的隐私安全工具结果边界诊断Privacy-Safe Tool-Result Boundary Diagnostics机制它通过一组仅在显式开启调试日志时才生效的观测事件解释超大型工具结果在生产态、模型 finalization、会话录制、ACP/Headless 投影与实际写入端之间发生的所有表示变换。读者将掌握该机制的开启方式、事件契约、HMAC 摘要方案、限流与故障隔离策略以及它在核心调度器、录制服务、ACP 与 Headless 各条内置工具结果链路中的落点。背景与目标回答大型工具结果在哪里变了在 AI 编程代理运行中同一个工具结果会以多种表示形态流转模型侧文本、显示文本、ACP 内容与原始输出、Headless 内容最终写入会话录制文件或 ACP/Headless 传输帧。当结果超过 64 KiB 甚至数百 KiB 时不同环节可能发生截断、预算裁剪、文本投影、去重等变换问题排查者往往难以判断到底在哪一步、以何种方式变了。该诊断机制为此提供了一条隐私安全的观测路径它只记录大小、进程内 HMAC、变更状态与脱敏后的制品摘要绝不落盘工具输出的原文、提示词、路径或各类 ID。设计文档位于 docs/design/2026-08-13-privacy-safe-tool-result-boundary-diagnostics.md核心实现位于 packages/core/src/tools/tool-result-boundary-diagnostics.tsCore 侧观测器与 packages/cli/src/nonInteractive/tool-result-boundary-diagnostics.tsCLI 侧投影/线缆关联助手。启用方式QWEN_DEBUG_LOG_FILE 与调试会话诊断事件属于 debug-log 体系遵循与普通调试日志一致的启用规则。核心判定函数isDebugLogFileEnabled()位于 packages/core/src/utils/debugLogger.ts当环境变量QWEN_DEBUG_LOG_FILE存在且其值去除空白、转小写后不等于、0、false、off、no时启用。开启后日志按会话写入全局调试目录并在latest符号链接指向当前实际写入的文件。边界诊断在此基础上还有第二重条件必须存在一个活跃的 debug-log 会话。综合判定函数为 packages/core/src/tools/tool-result-boundary-diagnostics.ts#L129-L135 中的isToolResultBoundaryDiagnosticsEnabled()即isDebugLogFileEnabled() boundaryLogger.isEnabled()。会话解析优先级为async-local 会话runWithDebugLogSession/runWithoutDebugLogSession daemon 上下文中的 async-local session IDsessionIdContext 进程级会话setDebugLogSession。这意味着在 daemon/ACP 模式下一个进程承载多个并发会话时日志会正确地归属到各自的会话文件不会互相串写。即便未开启代码路径上也几乎零开销观测器在扫描、哈希任何值之前先做 enablement 检查且所有观测值均以惰性函数values: () [...]形式传入未启用时根本不会遍历工具结果。事件契约什么被记录、什么永不记录事件触发门槛一个事件只有在满足以下任一条件时才产生常量定义见 packages/core/src/tools/tool-result-boundary-diagnostics.ts#L24-L27至少一种文本表示按 JSON 字符串精确 UTF-8 字节数计算超过65,536 字节TOOL_RESULT_BOUNDARY_JSON_BYTE_THRESHOLD观测到的边界前后表示发生了变化mutated true例如投影改写、录制去重或显示文本裁剪。事件字段每个事件事件名qwen-code.tool_result.boundary记录字段含义stage边界阶段producer/producer_input/producer_output/finalizer_input/finalizer_output/recorder_input/recorder_output/acp_projection_input/acp_projection_output/acp_wire/headless_projection_input/headless_projection_output/headless_wiremutated该边界是否改变了表示values[]每个文本槽位representationmodel_text/display/acp_content/acp_raw_output/headless_content、slot同表示下的第几个、codeUnitsJS 码元数、rawUtf8Bytes原始 UTF-8 字节、jsonUtf8BytesJSON 字符串转义后的精确 UTF-8 字节、hmacSha256进程内 HMAC-SHA-256 十六进制摘要artifacts[]每个工具调用的制品摘要stateundecided/none/reusable 去重后的kindsfile/link/html/image/video/audio/pdf/notebook/document/other/unknownsessionHmacSha256/promptHmacSha256/toolCallHmacSha256/toolCallHmacSha256s/toolNameHmacSha256各类标识符的进程内 HMAC批量写入场景使用数组形态保持与工具调用 ID 相同的顺序wireUtf8BytesACP / Headless 写入边界的精确序列化帧字节数永不进入事件的字段输出文本、提示词、制品路径/标题/URL、会话 ID、提示词 ID、工具调用 ID、工具名、参数、文件系统路径。结构化富显示rich display不会被递归检查——Phase 2 字节契约只覆盖文本模型、显示、ACP content/raw 与 Headless content 四种表示。HMAC 方案细节HMAC 密钥由randomBytes(32)在进程启动后随机生成一次tool-result-boundary-diagnostics.ts#L252因此每次进程重启后所有 HMAC 都会变化不会形成跨进程的稳定内容指纹。哈希函数hmacString()tool-result-boundary-diagnostics.ts#L388-L396对每个字符串独立处理先写入一个 8 字节大端序的字节长度前缀value.length * 2再以 UTF-16LE 码元更新 HMAC。值之间绝不拼接后统一哈希这保留了合法 Unicode 字符串与孤立代理项lone surrogate字符串之间的区分度同时保证同一进程内相等值的摘要可比较。JSON 字节精确核算jsonStringByteLength()tool-result-boundary-diagnostics.ts#L398-L439逐码元计算一个字符串被 JSON.stringify 后的精确 UTF-8 字节数起始引号计 2 字节与\各计 2 字节控制字符按短转义\b\t\n\f\r计 2 字节、其他计 6 字节\uXXXX常规字符按 UTF-8 编码长度计 1/2/3 字节代理对按 4 字节、孤立代理按 6 字节。判定函数jsonStringExceedsByteLength()支持stopAfterBytes提前终止在超过阈值后立即停止扫描避免对超大字符串做无谓的全量计算。覆盖范围所有内置工具结果路由原设计将观测点铺设在每条内置工具结果链路上本文结合源码逐一对应1. 调度器生产者边界CoreToolSchedulerCoreToolScheduler同时服务交互式、Headless 与 agent 执行它在工具执行落定后记录原始生产者输入与终态输出使得调度器侧持久化、截断、hook 与显示压缩在 finalization 之前即可归因。观测发生在observeSyntheticProducer()packages/core/src/core/coreToolScheduler.ts#L4942-L4975stage: producer采集responseParts经toolResultPartDiagnosticValues提取的model_text槽位与response.resultDisplaydisplay槽位并附带toolResultBoundaryArtifact()计算的制品摘要。同一调用只观测一次producerObserved守卫。2. 投机执行speculative生产者路由投机执行直接调用工具因此在execute()落定后记录同样的生产者边界packages/core/src/followup/speculation.ts#L70 调用observeToolResultBoundary。3. Finalizer 输入/输出面向模型的聚合finalizeToolResponses()覆盖交互式、Headless、ACP、agent 与投机执行的模型面向聚合。观测函数接收finalizer_input/finalizer_output阶段、预算条目与变异条目索引仅对选中的条目逐条观测并携带工具名、调用 ID 与制品摘要packages/core/src/tools/tool-response-finalizer.ts#L60-L92。agent-core.ts的调用点位于 packages/core/src/agents/runtime/agent-core.ts#L1614。4. 录制边界ChatRecordingService.recordToolResultChatRecordingService.recordToolResult()是共享的录制器边界它分别观测recorder_input与recorder_outputpackages/core/src/services/chatRecordingService.ts#L2366-L2389通过isDeepStrictEqual惰性判断显示文本是否被录制流程改写并在构造 transcript 记录前剥离录制专用诊断元数据persistedOutputFiles、boundaryArtifact被显式删除。5. ACP 实时与回放投递投影前后 线缆ACP live 与 replay 投递在文本投影的紧前、紧后各观测一次acp_projection_input/acp_projection_output观测函数为observeAcpToolResultProjection()packages/cli/src/nonInteractive/tool-result-boundary-diagnostics.ts#L33-L67调用点位于 packages/cli/src/acp-integration/session/Session.ts#L7705 与回放页 packages/cli/src/acp-integration/session/history-replay-page.ts#L208。投影前后若任一事件合格则通过WeakMap 弱引用projectedAcpUpdates把变更状态 安全制品摘要 会话 ID关联到后续的实际写入对象避免强引用造成内存泄漏。线缆边界由observeAcpToolResultWire()实现ACP NDJSON hook 提供序列化负载字节数诊断在其基础上额外加上该传输写入的单个换行字节wireUtf8Bytes: payloadUtf8Bytes 1。调用点位于 packages/cli/src/acp-integration/acpAgent.ts#L2820。多更新批量写入时以toolCallHmacSha256s数组保持顺序。一次事件发出后即从 WeakMap 中删除投影记录。6. Headless 共享适配器投影与写入器Headless JSON、stream-json、持久化 SDK 传输、subagent、Text 保留与 DualOutput 在共享适配器投影处统一观测observeHeadlessToolResultProjection()BaseJsonOutputAdapter.ts#L1137 调用负责headless_projection_input/headless_projection_output写入边界上JSON 写入器JsonOutputAdapter对整帧调用observeHeadlessJsonToolResultWire(this.messages, frame)packages/cli/src/nonInteractive/io/JsonOutputAdapter.ts#L133stream-json 写入器StreamJsonOutputAdapter逐消息调用observeHeadlessToolResultWire(message, frame)packages/cli/src/nonInteractive/io/StreamJsonOutputAdapter.ts#L73。两者都以Buffer.byteLength(frame, utf8)提供精确的帧字节数Text 保留链路没有工具结果线缆帧因此不产生headless_wire事件对应测试断言见下。subagent 进度只携带这份封闭枚举摘要且仅当诊断启用时——原始持久化路径与结构化制品永不进入该事件路径。7. 明确排除的范围自定义适配器与预构建的自定义tool_result消息不属于内置 Headless 路由不在观测范围内通用帧限制、背压、回放聚合限制与制品生命周期仍由各自独立机制跟踪。失败与限流行为观测器遵循诊断永不影响业务的原则故障隔离enablement 检查在任何扫描/哈希之前执行所有观测、哈希、分类、日志代码包裹在 try/catch 失败边界内异常被吞掉绝不改变值或写入路径。源码中每个调用点都注释着// Diagnostics must not affect tool execution/projection/delivery。进程级限流每 60 秒窗口TOOL_RESULT_BOUNDARY_LOG_WINDOW_MS最多发出 50 条合格事件TOOL_RESULT_BOUNDARY_LOG_LIMIT超出部分仅递增 suppressed 计数窗口后的首条合格事件会带上累计的suppressedCount然后清零。与大型帧归因的分工qwen serve的 large-pipe-frame 观测器仍是 ≥256 KiB 帧的唯一 daemon 归因机制本诊断只做表示关联与精确写入尺寸对照不产生生产遥测也不替代大型帧归因。兼容性与变更面该功能在未启用时是纯诊断性的不改动工具结果、投影、transcript、schema、ACP 消息、Headless 消息、SDK 类型或协议版本调试日志文件仅在显式开启后新增 JSON 形状的行。每行以 debugLogger 的标准格式输出时间戳 级别 可选 tag[TOOL_RESULT_BOUNDARY] 可选 trace 上下文 消息事件体为qwen-code.tool_result.boundaryJSON.stringify(event)。由于 HMAC 密钥进程内随机生成HMAC 在每次进程重启后必然变化——这既是隐私特性也意味着跨进程关联必须依赖字节数与变更模式而非摘要。验证体系测试覆盖了事件的每个维度主要测试文件packages/core/src/tools/tool-result-boundary-diagnostics.test.ts587 行精确 JSON 字节核算含转义与 Unicode、孤立代理项、HMAC 相等性与变异不匹配、标识符脱敏断言日志行不包含任何原文/ID 子串、制品三态与种类归一化、混合批量制品摘要保序、enablement、限流与 suppressed 计数、故障隔离、Core 边界集成packages/cli/src/nonInteractive/tool-result-boundary-diagnostics.test.tsACP live/replay 投影、ACP NDJSON 字节数、Headless JSON/stream-json 写入器字节数、Text 保留链路不产生线缆事件。此外设计还规定了一个确定性 fake-MCP 演练对一份 499,999 字节的工具结果横跨 Headless JSON、stream-json、持久化 stream-json/SDK 传输、Text 与可行的 ACP 链路记录前后证据验证日志中的写入字节精确、进程内 HMAC 可关联、fixture 文本与标识符不出现、生产者制品尺寸/哈希不变、用户可见输出不变。结语隐私安全工具结果边界诊断是 qwen-code 调试栈中既要可观测、又要可审计、还不能泄密的典型设计以 65,536 字节 JSON 字节阈值 变更判定双条件筛选合格事件以进程内 HMAC-SHA-256 8 字节长度前缀哈希保证可比性而不产生稳定内容指纹以 50 条/60 秒限流与失败边界保证诊断零侵入最终把表示在哪里、以多大尺寸、变没变这组事实以完全脱敏的形式写进调试日志。排查大型工具结果在录制、投影或传输中的尺寸异常时开启QWEN_DEBUG_LOG_FILE后对照producer → finalizer → recorder → projection → wire各阶段的jsonUtf8Bytes与wireUtf8Bytes即可快速定位变化发生的边界。【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考