【deepseek-harness】DeepSeek Harness (dsh) 系统级架构分析之三

第四部分:基础设施与客户端模块群

以下为 dsh 基础设施与客户端模块群的深度分析,涵盖 session/session-query/storage/settings/credentials/identity/interaction/guard/hooks/todo/plan/goal/feedback/schedule/jobs/spill/runtime-diagnostics/boot/bundle/preset/api/sdk/typert/client/host/extensions/acp/attachment/context/workspace/util 三十一个模块。

目录

  1. [session --- 持久化会话数据](#session — 持久化会话数据)
  2. [session-query --- 会话查询](#session-query — 会话查询)
  3. [storage --- 存储能力](#storage — 存储能力)
  4. [settings --- 用户设置](#settings — 用户设置)
  5. [credentials --- 凭证管理](#credentials — 凭证管理)
  6. [identity --- 身份标识](#identity — 身份标识)
  7. [interaction --- 交互/审批](#interaction — 交互/审批)
  8. [guard --- 安全防护](#guard — 安全防护)
  9. [hooks --- 钩子桥接](#hooks — 钩子桥接)
  10. [todo --- 待办工具](#todo — 待办工具)
  11. [plan --- 计划模式](#plan — 计划模式)
  12. [goal --- 目标管理](#goal — 目标管理)
  13. [feedback --- 反馈](#feedback — 反馈)
  14. [schedule --- 调度](#schedule — 调度)
  15. [jobs --- 后台任务](#jobs — 后台任务)
  16. [spill --- 溢出管理](#spill — 溢出管理)
  17. [runtime-diagnostics --- 运行时诊断](#runtime-diagnostics — 运行时诊断)
  18. [boot --- 启动引导](#boot — 启动引导)
  19. [bundle --- 打包分发](#bundle — 打包分发)
  20. [preset --- 预设组合](#preset — 预设组合)
  21. [api --- 远程 API 网关](#api — 远程 API 网关)
  22. [sdk --- JSON-RPC 协议](#sdk — JSON-RPC 协议)
  23. [typert --- 类型图](#typert — 类型图)
  24. [client --- 客户端](#client — 客户端)
  25. [host --- 宿主](#host — 宿主)
  26. [extensions --- 扩展](#extensions — 扩展)
  27. [acp --- Agent Client Protocol](#acp — Agent Client Protocol)
  28. [attachment --- 附件](#attachment — 附件)
  29. [context --- 上下文插件](#context — 上下文插件)
  30. [workspace --- 工作区](#workspace — 工作区)
  31. [util --- 工具库](#util — 工具库)
  32. 基础设施协作总览

session

路径 : packages/session/

核心作用: 事件溯源的会话持久化层,管理 Agent 会话的生命周期事件(turn/start, turn/end, user/message, assistant/message, tool/* 等),提供会话格式版本化、写后序列化链和检查点策略。

架构图

#mermaid-svg-PcJODCIbME1nVXcJ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PcJODCIbME1nVXcJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PcJODCIbME1nVXcJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PcJODCIbME1nVXcJ .error-icon{fill:#552222;}#mermaid-svg-PcJODCIbME1nVXcJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PcJODCIbME1nVXcJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PcJODCIbME1nVXcJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PcJODCIbME1nVXcJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PcJODCIbME1nVXcJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PcJODCIbME1nVXcJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PcJODCIbME1nVXcJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PcJODCIbME1nVXcJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PcJODCIbME1nVXcJ .marker.cross{stroke:#333333;}#mermaid-svg-PcJODCIbME1nVXcJ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PcJODCIbME1nVXcJ p{margin:0;}#mermaid-svg-PcJODCIbME1nVXcJ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-PcJODCIbME1nVXcJ .cluster-label text{fill:#333;}#mermaid-svg-PcJODCIbME1nVXcJ .cluster-label span{color:#333;}#mermaid-svg-PcJODCIbME1nVXcJ .cluster-label span p{background-color:transparent;}#mermaid-svg-PcJODCIbME1nVXcJ .label text,#mermaid-svg-PcJODCIbME1nVXcJ span{fill:#333;color:#333;}#mermaid-svg-PcJODCIbME1nVXcJ .node rect,#mermaid-svg-PcJODCIbME1nVXcJ .node circle,#mermaid-svg-PcJODCIbME1nVXcJ .node ellipse,#mermaid-svg-PcJODCIbME1nVXcJ .node polygon,#mermaid-svg-PcJODCIbME1nVXcJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PcJODCIbME1nVXcJ .rough-node .label text,#mermaid-svg-PcJODCIbME1nVXcJ .node .label text,#mermaid-svg-PcJODCIbME1nVXcJ .image-shape .label,#mermaid-svg-PcJODCIbME1nVXcJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-PcJODCIbME1nVXcJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PcJODCIbME1nVXcJ .rough-node .label,#mermaid-svg-PcJODCIbME1nVXcJ .node .label,#mermaid-svg-PcJODCIbME1nVXcJ .image-shape .label,#mermaid-svg-PcJODCIbME1nVXcJ .icon-shape .label{text-align:center;}#mermaid-svg-PcJODCIbME1nVXcJ .node.clickable{cursor:pointer;}#mermaid-svg-PcJODCIbME1nVXcJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PcJODCIbME1nVXcJ .arrowheadPath{fill:#333333;}#mermaid-svg-PcJODCIbME1nVXcJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PcJODCIbME1nVXcJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PcJODCIbME1nVXcJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PcJODCIbME1nVXcJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PcJODCIbME1nVXcJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PcJODCIbME1nVXcJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PcJODCIbME1nVXcJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PcJODCIbME1nVXcJ .cluster text{fill:#333;}#mermaid-svg-PcJODCIbME1nVXcJ .cluster span{color:#333;}#mermaid-svg-PcJODCIbME1nVXcJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PcJODCIbME1nVXcJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PcJODCIbME1nVXcJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-PcJODCIbME1nVXcJ .icon-shape,#mermaid-svg-PcJODCIbME1nVXcJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PcJODCIbME1nVXcJ .icon-shape p,#mermaid-svg-PcJODCIbME1nVXcJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PcJODCIbME1nVXcJ .icon-shape .label rect,#mermaid-svg-PcJODCIbME1nVXcJ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PcJODCIbME1nVXcJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PcJODCIbME1nVXcJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PcJODCIbME1nVXcJ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-PcJODCIbME1nVXcJ .core>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .core span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .core tspan{fill:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .persist>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .persist span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .persist tspan{fill:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .policy>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .policy span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .policy tspan{fill:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .proj>*{fill:#bd10e0!important;stroke:#9c0bb3!important;color:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .proj span{fill:#bd10e0!important;stroke:#9c0bb3!important;color:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .proj tspan{fill:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .title>*{fill:#f8e71c!important;stroke:#c5b416!important;color:#333!important;}#mermaid-svg-PcJODCIbME1nVXcJ .title span{fill:#f8e71c!important;stroke:#c5b416!important;color:#333!important;}#mermaid-svg-PcJODCIbME1nVXcJ .title tspan{fill:#333!important;}#mermaid-svg-PcJODCIbME1nVXcJ .tele>*{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .tele span{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-PcJODCIbME1nVXcJ .tele tspan{fill:#fff!important;} session-projection
session-checkpoint-policy
session-persistence
session 核心包
session-telemetry
SessionTelemetry

遥测协调器
OTel Backend

OpenTelemetry后端
session-title-llm
SessionTitle

标题服务
TitleLlmProvider

LLM标题生成器
Session

会话实体
SessionHeader

会话头元数据
SessionEvent

会话事件
SessionId

品牌类型ID
SessionPersistence

持久化服务
JSONL 后端

追加写入
CheckpointPolicy

检查点策略
FlushGate

刷新门控
SessionProjection

会话投影
Surface

表面节点

关键类/函数表

名称 类型 职责
Session 会话实体,持有事件日志、表面节点(Surface)、头部元数据,提供 append() 追加事件
SessionHeader 接口 会话元数据:id、cwd、createdAt、parentSession
SessionEvent 类型联合 事件溯源事件类型(user/message, assistant/message, turn/start, turn/end, tool/* 等)
SessionId 品牌类型 Branded<'SessionId'>,跨包边界的编译时类型安全
SessionPersistence 服务 持久化服务,提供 list() 枚举和会话加载
SessionProjection 投影 会话事件折叠投影,通过 SessionProjectionMap 声明合并扩展
SessionTitle 服务 会话标题生成服务,支持 LLM 提供商注册
CheckpointPolicy 插件 语义检查点策略:模型请求前、工具分派前、步骤边界刷新持久化
SessionTelemetryCoordinator 服务 遥测协调器,管理记录发射和共享策略
foldPlanMode() 函数 从会话事件折叠计划模式状态(last-write-wins)
registerSessionTitleLlmProvider() 函数 注册 LLM 标题生成提供商

架构要点

  • 事件溯源模式:所有状态变化以不可变事件追加到会话日志,投影通过折叠事件派生当前状态
  • 格式版本化SessionFormatVersion 标记日志格式版本,跨版本兼容通过格式迁移处理
  • 写后序列化链Session.append() 先在内存中追加事件,通过检查点策略在语义边界刷新到持久化后端
  • 检查点策略session-checkpoint-policy 在模型请求前(llm/stream)、工具分派前(tools/execute)、步骤边界(agent/pre-step)设置刷新门控,确保持久化完成后才执行副作用
  • 遥测共享策略FULL/FEEDBACK_ONLY/DISABLED 三级共享策略,feedback/record 事件可触发反馈门控的会话前缀共享

session-query

路径 : packages/session-query/

核心作用: 会话查询能力,提供跨会话搜索、事件搜索、会话谱系追踪和事件读取工具,支持工作区访问控制。

架构图

#mermaid-svg-G7lgTTQmjrTF17qn{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-G7lgTTQmjrTF17qn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-G7lgTTQmjrTF17qn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-G7lgTTQmjrTF17qn .error-icon{fill:#552222;}#mermaid-svg-G7lgTTQmjrTF17qn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-G7lgTTQmjrTF17qn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-G7lgTTQmjrTF17qn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-G7lgTTQmjrTF17qn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-G7lgTTQmjrTF17qn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-G7lgTTQmjrTF17qn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-G7lgTTQmjrTF17qn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-G7lgTTQmjrTF17qn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-G7lgTTQmjrTF17qn .marker.cross{stroke:#333333;}#mermaid-svg-G7lgTTQmjrTF17qn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-G7lgTTQmjrTF17qn p{margin:0;}#mermaid-svg-G7lgTTQmjrTF17qn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-G7lgTTQmjrTF17qn .cluster-label text{fill:#333;}#mermaid-svg-G7lgTTQmjrTF17qn .cluster-label span{color:#333;}#mermaid-svg-G7lgTTQmjrTF17qn .cluster-label span p{background-color:transparent;}#mermaid-svg-G7lgTTQmjrTF17qn .label text,#mermaid-svg-G7lgTTQmjrTF17qn span{fill:#333;color:#333;}#mermaid-svg-G7lgTTQmjrTF17qn .node rect,#mermaid-svg-G7lgTTQmjrTF17qn .node circle,#mermaid-svg-G7lgTTQmjrTF17qn .node ellipse,#mermaid-svg-G7lgTTQmjrTF17qn .node polygon,#mermaid-svg-G7lgTTQmjrTF17qn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-G7lgTTQmjrTF17qn .rough-node .label text,#mermaid-svg-G7lgTTQmjrTF17qn .node .label text,#mermaid-svg-G7lgTTQmjrTF17qn .image-shape .label,#mermaid-svg-G7lgTTQmjrTF17qn .icon-shape .label{text-anchor:middle;}#mermaid-svg-G7lgTTQmjrTF17qn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-G7lgTTQmjrTF17qn .rough-node .label,#mermaid-svg-G7lgTTQmjrTF17qn .node .label,#mermaid-svg-G7lgTTQmjrTF17qn .image-shape .label,#mermaid-svg-G7lgTTQmjrTF17qn .icon-shape .label{text-align:center;}#mermaid-svg-G7lgTTQmjrTF17qn .node.clickable{cursor:pointer;}#mermaid-svg-G7lgTTQmjrTF17qn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-G7lgTTQmjrTF17qn .arrowheadPath{fill:#333333;}#mermaid-svg-G7lgTTQmjrTF17qn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-G7lgTTQmjrTF17qn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-G7lgTTQmjrTF17qn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-G7lgTTQmjrTF17qn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-G7lgTTQmjrTF17qn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-G7lgTTQmjrTF17qn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-G7lgTTQmjrTF17qn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-G7lgTTQmjrTF17qn .cluster text{fill:#333;}#mermaid-svg-G7lgTTQmjrTF17qn .cluster span{color:#333;}#mermaid-svg-G7lgTTQmjrTF17qn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-G7lgTTQmjrTF17qn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-G7lgTTQmjrTF17qn rect.text{fill:none;stroke-width:0;}#mermaid-svg-G7lgTTQmjrTF17qn .icon-shape,#mermaid-svg-G7lgTTQmjrTF17qn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-G7lgTTQmjrTF17qn .icon-shape p,#mermaid-svg-G7lgTTQmjrTF17qn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-G7lgTTQmjrTF17qn .icon-shape .label rect,#mermaid-svg-G7lgTTQmjrTF17qn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-G7lgTTQmjrTF17qn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-G7lgTTQmjrTF17qn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-G7lgTTQmjrTF17qn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-G7lgTTQmjrTF17qn .core>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-G7lgTTQmjrTF17qn .core span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-G7lgTTQmjrTF17qn .core tspan{fill:#fff!important;}#mermaid-svg-G7lgTTQmjrTF17qn .tool>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-G7lgTTQmjrTF17qn .tool span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-G7lgTTQmjrTF17qn .tool tspan{fill:#fff!important;}#mermaid-svg-G7lgTTQmjrTF17qn .access>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-G7lgTTQmjrTF17qn .access span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-G7lgTTQmjrTF17qn .access tspan{fill:#fff!important;} tool-session-query
session-query 核心
SessionQuery

查询服务
SearchEngine

搜索引擎
LineageTracer

谱系追踪
Presentation

模型文本渲染
WorkspaceAccess

工作区访问控制
Tool Definitions

工具定义

关键类/函数表

名称 类型 职责
SessionSearchHit 接口 会话搜索结果项,包含头部、最佳匹配事件、可用性状态
SessionEventSearchHit 接口 事件搜索结果项,包含 seq、类型、片段
SessionLineageTrace 接口 会话谱系追踪,祖先和后代关系
SessionEventTraceObservation 接口 事件追踪观察,替换链、派生事件
SessionEventWindow 接口 事件窗口,目标事件及前后邻居
formatSessionSearch() 函数 渲染会话搜索结果为模型可读文本
formatEventSearch() 函数 渲染事件搜索结果
formatSessionTrace() 函数 渲染会话谱系追踪
workspaceAccess 对象 工作区访问控制:读取标题、授权后代访问

架构要点

  • 工作区访问控制 :通过 workspaceAccess 模块实现工作区边界检查,祖先/后代访问需要工作区授权
  • 模型文本渲染Presentation 模块将查询结果格式化为模型可读的结构化文本,包含序号、时间戳、片段
  • 三层查询:会话搜索(跨会话)、事件搜索(单会话内)、事件读取(单事件+上下文窗口)

storage

路径 : packages/storage/

核心作用: 存储能力枢纽,提供命名后端注册表和挂载的数据形式(KV 等),自身不执行 IO------后端拥有介质,数据形式拥有语义。

架构图

#mermaid-svg-CcE0jKc3nxuenpY5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CcE0jKc3nxuenpY5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CcE0jKc3nxuenpY5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CcE0jKc3nxuenpY5 .error-icon{fill:#552222;}#mermaid-svg-CcE0jKc3nxuenpY5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CcE0jKc3nxuenpY5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CcE0jKc3nxuenpY5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CcE0jKc3nxuenpY5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CcE0jKc3nxuenpY5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CcE0jKc3nxuenpY5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CcE0jKc3nxuenpY5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CcE0jKc3nxuenpY5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CcE0jKc3nxuenpY5 .marker.cross{stroke:#333333;}#mermaid-svg-CcE0jKc3nxuenpY5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CcE0jKc3nxuenpY5 p{margin:0;}#mermaid-svg-CcE0jKc3nxuenpY5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CcE0jKc3nxuenpY5 .cluster-label text{fill:#333;}#mermaid-svg-CcE0jKc3nxuenpY5 .cluster-label span{color:#333;}#mermaid-svg-CcE0jKc3nxuenpY5 .cluster-label span p{background-color:transparent;}#mermaid-svg-CcE0jKc3nxuenpY5 .label text,#mermaid-svg-CcE0jKc3nxuenpY5 span{fill:#333;color:#333;}#mermaid-svg-CcE0jKc3nxuenpY5 .node rect,#mermaid-svg-CcE0jKc3nxuenpY5 .node circle,#mermaid-svg-CcE0jKc3nxuenpY5 .node ellipse,#mermaid-svg-CcE0jKc3nxuenpY5 .node polygon,#mermaid-svg-CcE0jKc3nxuenpY5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CcE0jKc3nxuenpY5 .rough-node .label text,#mermaid-svg-CcE0jKc3nxuenpY5 .node .label text,#mermaid-svg-CcE0jKc3nxuenpY5 .image-shape .label,#mermaid-svg-CcE0jKc3nxuenpY5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-CcE0jKc3nxuenpY5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CcE0jKc3nxuenpY5 .rough-node .label,#mermaid-svg-CcE0jKc3nxuenpY5 .node .label,#mermaid-svg-CcE0jKc3nxuenpY5 .image-shape .label,#mermaid-svg-CcE0jKc3nxuenpY5 .icon-shape .label{text-align:center;}#mermaid-svg-CcE0jKc3nxuenpY5 .node.clickable{cursor:pointer;}#mermaid-svg-CcE0jKc3nxuenpY5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CcE0jKc3nxuenpY5 .arrowheadPath{fill:#333333;}#mermaid-svg-CcE0jKc3nxuenpY5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CcE0jKc3nxuenpY5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CcE0jKc3nxuenpY5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CcE0jKc3nxuenpY5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CcE0jKc3nxuenpY5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CcE0jKc3nxuenpY5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CcE0jKc3nxuenpY5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CcE0jKc3nxuenpY5 .cluster text{fill:#333;}#mermaid-svg-CcE0jKc3nxuenpY5 .cluster span{color:#333;}#mermaid-svg-CcE0jKc3nxuenpY5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CcE0jKc3nxuenpY5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CcE0jKc3nxuenpY5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-CcE0jKc3nxuenpY5 .icon-shape,#mermaid-svg-CcE0jKc3nxuenpY5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CcE0jKc3nxuenpY5 .icon-shape p,#mermaid-svg-CcE0jKc3nxuenpY5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CcE0jKc3nxuenpY5 .icon-shape .label rect,#mermaid-svg-CcE0jKc3nxuenpY5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CcE0jKc3nxuenpY5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CcE0jKc3nxuenpY5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CcE0jKc3nxuenpY5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-CcE0jKc3nxuenpY5 .hub>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-CcE0jKc3nxuenpY5 .hub span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-CcE0jKc3nxuenpY5 .hub tspan{fill:#fff!important;}#mermaid-svg-CcE0jKc3nxuenpY5 .backend>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-CcE0jKc3nxuenpY5 .backend span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-CcE0jKc3nxuenpY5 .backend tspan{fill:#fff!important;}#mermaid-svg-CcE0jKc3nxuenpY5 .domain>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-CcE0jKc3nxuenpY5 .domain span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-CcE0jKc3nxuenpY5 .domain tspan{fill:#fff!important;} storage-domain
后端层
storage 枢纽
Storage

存储枢纽服务
BackendRegistry

后端注册表
StorageForms

数据形式表
JSON Backend

文件树后端
SQLite Backend

数据库后端
KvFacet

KV操作面
Domain Layer

领域层
DomainGlobal

领域全局单例
KvTable

KV表
defineDomain

领域定义

chmentError | 类 | 附件错误,携带稳定错误码(INVALID_IMAGE/IMAGE_TOO_LARGE/ATTACHMENT_CORRUPT等) | |ImageAttachmentRef| 接口 | 持久化图像引用:attachmentId、mediaType、bytes、width、height | |ImageAttachmentLimits| 接口 | 部署解析的限制:maxImageBytes、maxImagesPerMessage 等 | |SaveImageAttachment| 接口 | 保存请求:data、mediaType、name | |StoredImageAttachment| 接口 | 存储结果:ref + data | |LocalAttachmentStore| 类 | 本地后端,基于DSH_HOME/attachments/v1| |detectImage()| 函数 | 完全解码光栅图像,返回格式和尺寸 | |probeImage()| 函数 | 仅解析头部,不完整解码像素 | |saveImageFile()| 函数 | 保存图像:哈希→暂存→link→目录同步 | |readImageFile()| 函数 | 读取图像:读取→哈希验证→头部验证 | |validateImageFile()| 函数 | 验证图像不持久化 | |ensureDurableHome()| 函数 | 确保 DSH_HOME 目录持久性 | |ensureDurableDirectory()| 函数 | 确保目录及其祖先持久性 | |syncDirectory()` | 函数 | 同步目录条目(fsync) |

架构要点

  • 内容寻址 :对象按 sha256:<hash> 存储,相同内容自动去重(link EEXIST 时验证)
  • 不可变存储:写入后不可修改,读取时验证哈希完整性
  • 持久性保证:写入后 fsync 文件和目录,确保崩溃后条目持久
  • 两阶段写入:暂存文件→link 到目标→同步目录→清理暂存
  • 双重验证 :写入时完全解码(detectImage),读取时仅探头部(probeImage
  • 进程级持久性证明ensureDurableHome 每进程独立执行一次 DSH_HOME 持久性证明
  • 显示名清洗 :剥离路径分隔符(/\),防止本地路径泄露到引用和会话日志

context

路径 : packages/context/

核心作用 : 上下文插件群,包含 agent-instructions(工作区指令加载器)、session-reference(会话引用)、time-context(时间上下文)和 tmux-context(tmux 上下文)。

架构图

#mermaid-svg-7tdqBqhfYgu8Yyfe{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7tdqBqhfYgu8Yyfe .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7tdqBqhfYgu8Yyfe .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7tdqBqhfYgu8Yyfe .error-icon{fill:#552222;}#mermaid-svg-7tdqBqhfYgu8Yyfe .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7tdqBqhfYgu8Yyfe .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7tdqBqhfYgu8Yyfe .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7tdqBqhfYgu8Yyfe .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7tdqBqhfYgu8Yyfe .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7tdqBqhfYgu8Yyfe .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7tdqBqhfYgu8Yyfe .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7tdqBqhfYgu8Yyfe .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7tdqBqhfYgu8Yyfe .marker.cross{stroke:#333333;}#mermaid-svg-7tdqBqhfYgu8Yyfe svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7tdqBqhfYgu8Yyfe p{margin:0;}#mermaid-svg-7tdqBqhfYgu8Yyfe .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7tdqBqhfYgu8Yyfe .cluster-label text{fill:#333;}#mermaid-svg-7tdqBqhfYgu8Yyfe .cluster-label span{color:#333;}#mermaid-svg-7tdqBqhfYgu8Yyfe .cluster-label span p{background-color:transparent;}#mermaid-svg-7tdqBqhfYgu8Yyfe .label text,#mermaid-svg-7tdqBqhfYgu8Yyfe span{fill:#333;color:#333;}#mermaid-svg-7tdqBqhfYgu8Yyfe .node rect,#mermaid-svg-7tdqBqhfYgu8Yyfe .node circle,#mermaid-svg-7tdqBqhfYgu8Yyfe .node ellipse,#mermaid-svg-7tdqBqhfYgu8Yyfe .node polygon,#mermaid-svg-7tdqBqhfYgu8Yyfe .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7tdqBqhfYgu8Yyfe .rough-node .label text,#mermaid-svg-7tdqBqhfYgu8Yyfe .node .label text,#mermaid-svg-7tdqBqhfYgu8Yyfe .image-shape .label,#mermaid-svg-7tdqBqhfYgu8Yyfe .icon-shape .label{text-anchor:middle;}#mermaid-svg-7tdqBqhfYgu8Yyfe .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7tdqBqhfYgu8Yyfe .rough-node .label,#mermaid-svg-7tdqBqhfYgu8Yyfe .node .label,#mermaid-svg-7tdqBqhfYgu8Yyfe .image-shape .label,#mermaid-svg-7tdqBqhfYgu8Yyfe .icon-shape .label{text-align:center;}#mermaid-svg-7tdqBqhfYgu8Yyfe .node.clickable{cursor:pointer;}#mermaid-svg-7tdqBqhfYgu8Yyfe .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7tdqBqhfYgu8Yyfe .arrowheadPath{fill:#333333;}#mermaid-svg-7tdqBqhfYgu8Yyfe .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7tdqBqhfYgu8Yyfe .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7tdqBqhfYgu8Yyfe .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7tdqBqhfYgu8Yyfe .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7tdqBqhfYgu8Yyfe .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7tdqBqhfYgu8Yyfe .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7tdqBqhfYgu8Yyfe .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7tdqBqhfYgu8Yyfe .cluster text{fill:#333;}#mermaid-svg-7tdqBqhfYgu8Yyfe .cluster span{color:#333;}#mermaid-svg-7tdqBqhfYgu8Yyfe div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7tdqBqhfYgu8Yyfe .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7tdqBqhfYgu8Yyfe rect.text{fill:none;stroke-width:0;}#mermaid-svg-7tdqBqhfYgu8Yyfe .icon-shape,#mermaid-svg-7tdqBqhfYgu8Yyfe .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7tdqBqhfYgu8Yyfe .icon-shape p,#mermaid-svg-7tdqBqhfYgu8Yyfe .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7tdqBqhfYgu8Yyfe .icon-shape .label rect,#mermaid-svg-7tdqBqhfYgu8Yyfe .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7tdqBqhfYgu8Yyfe .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7tdqBqhfYgu8Yyfe .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7tdqBqhfYgu8Yyfe :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-7tdqBqhfYgu8Yyfe .instruct>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-7tdqBqhfYgu8Yyfe .instruct span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-7tdqBqhfYgu8Yyfe .instruct tspan{fill:#fff!important;}#mermaid-svg-7tdqBqhfYgu8Yyfe .ref>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-7tdqBqhfYgu8Yyfe .ref span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-7tdqBqhfYgu8Yyfe .ref tspan{fill:#fff!important;}#mermaid-svg-7tdqBqhfYgu8Yyfe .time>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-7tdqBqhfYgu8Yyfe .time span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-7tdqBqhfYgu8Yyfe .time tspan{fill:#fff!important;}#mermaid-svg-7tdqBqhfYgu8Yyfe .tmux>*{fill:#bd10e0!important;stroke:#9c0bb3!important;color:#fff!important;}#mermaid-svg-7tdqBqhfYgu8Yyfe .tmux span{fill:#bd10e0!important;stroke:#9c0bb3!important;color:#fff!important;}#mermaid-svg-7tdqBqhfYgu8Yyfe .tmux tspan{fill:#fff!important;} tmux-context
Tmux Context

tmux上下文
time-context
Time Context

时间上下文
Timestamp

时间戳
Request Zone

请求时区
session-reference
Session Reference

会话引用
Projection

投影
URI

统一资源标识
Serialization

序列化
agent-instructions
Agent Instructions

工作区指令加载器
Files Loader

文件发现与读取
Render Engine

渲染引擎
State Manager

状态管理器
Config

配置
Digest

内容摘要

关键类/函数表

名称 类型 职责
apply() 函数 挂载工作区指令加载器
loadBaselineInstructions() 函数 发现、读取、渲染基线指令链
loadBaselineInstructionSet() 函数 加载基线+保留的文件
discoverBaselineInstructionFiles() 函数 发现主机可见的指令候选
findProjectRoot() 函数 向上查找项目根(标记文件)
ancestorChain() 函数 构建根到 cwd 的目录链
dedupInstructionFilesByDirectory() 函数 按目录去重(trimmed 内容摘要)
renderWorkspaceContext() 函数 渲染基线指令链
renderWorkspaceInstructionSet() 函数 渲染基线+保留文件
renderInstructionChanges() 函数 渲染对账批次
reconcileInstructionContext() 函数 对账指令上下文
baselineInstructionState() 函数 将基线文件转为比较和元数据状态
probeScopeInstruction() 函数 探测指令作用域
readScopeInstruction() 函数 读取已探测的指令
instructionContentSha1() 函数 计算内容 SHA-1
trimmedInstructionDigest() 函数 计算修剪内容摘要(去空白)
workspaceBaselineIdentity() 函数 基线身份标识
candidateScopeKey() 函数 每候选作用域键
instructionScopeKey() 函数 指令作用域键
Config 配置 dshHome、projectRootMarkers、maxBytes、instructionFileCandidates 等
InstructionVersionCache 类型 WeakMap<Session, Map> 每会话元数据缓存
AgentInstructionChange 接口 指令变更:set/replace/remove
AgentInstructionSource 接口 指令来源声明(合并到 MessageSourceMap)

架构要点

  • 三层指令发现 :用户全局($DSH_HOME/AGENTS.md)→ 项目根到 cwd 的目录链 → 每目录候选文件(AGENTS.mdCLAUDE.md + .local 覆盖)
  • 字节预算maxBytes 限制渲染后文本长度,超出时从最不特定开始省略,最特定文件二分截断
  • 内容去重:按目录修剪内容摘要去重,同目录相同内容的不同候选只保留首个
  • 动态对账:文件工具触碰(read/write/edit)后异步重新加载和对账指令上下文
  • 步骤边界 :步骤内触碰延迟到 step/end 后投影,步骤外立即投影
  • 投影排队 :通过 projectionTails WeakMap 确保同 Agent 投影串行执行
  • system-reminder 框架 :渲染文本包裹在 <system-reminder> 标签中,框架在消息内容中烘焙
  • 版本缓存InstructionVersionCache 通过 WeakMap 隔离每会话的元数据缓存
  • 基线替换 :配置变更时通过 replacePreviousBaseline 标记完整替换前序基线

session-reference 架构要点

  • 会话引用投影:将会话引用结构投影到模型上下文
  • URI 标识:通过 URI 标识会话引用目标
  • 序列化:支持会话引用的序列化和反序列化

time-context 架构要点

  • 时间戳:为模型提供当前时间戳上下文
  • 请求时区request-zone 处理请求的时区信息

workspace

路径 : packages/workspace/

核心作用 : 工作区实体注册表(ctx.workspaceRegistry),管理工作区记录、稳定的注册表顺序和经头部验证的会话成员关系。基于存储域数据形式,通过 fs.realpath 规范化路径作为唯一标识。

架构图

#mermaid-svg-VNDxmRnvDcBoTdXF{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VNDxmRnvDcBoTdXF .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VNDxmRnvDcBoTdXF .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VNDxmRnvDcBoTdXF .error-icon{fill:#552222;}#mermaid-svg-VNDxmRnvDcBoTdXF .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VNDxmRnvDcBoTdXF .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VNDxmRnvDcBoTdXF .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VNDxmRnvDcBoTdXF .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VNDxmRnvDcBoTdXF .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VNDxmRnvDcBoTdXF .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VNDxmRnvDcBoTdXF .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VNDxmRnvDcBoTdXF .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VNDxmRnvDcBoTdXF .marker.cross{stroke:#333333;}#mermaid-svg-VNDxmRnvDcBoTdXF svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VNDxmRnvDcBoTdXF p{margin:0;}#mermaid-svg-VNDxmRnvDcBoTdXF .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VNDxmRnvDcBoTdXF .cluster-label text{fill:#333;}#mermaid-svg-VNDxmRnvDcBoTdXF .cluster-label span{color:#333;}#mermaid-svg-VNDxmRnvDcBoTdXF .cluster-label span p{background-color:transparent;}#mermaid-svg-VNDxmRnvDcBoTdXF .label text,#mermaid-svg-VNDxmRnvDcBoTdXF span{fill:#333;color:#333;}#mermaid-svg-VNDxmRnvDcBoTdXF .node rect,#mermaid-svg-VNDxmRnvDcBoTdXF .node circle,#mermaid-svg-VNDxmRnvDcBoTdXF .node ellipse,#mermaid-svg-VNDxmRnvDcBoTdXF .node polygon,#mermaid-svg-VNDxmRnvDcBoTdXF .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VNDxmRnvDcBoTdXF .rough-node .label text,#mermaid-svg-VNDxmRnvDcBoTdXF .node .label text,#mermaid-svg-VNDxmRnvDcBoTdXF .image-shape .label,#mermaid-svg-VNDxmRnvDcBoTdXF .icon-shape .label{text-anchor:middle;}#mermaid-svg-VNDxmRnvDcBoTdXF .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VNDxmRnvDcBoTdXF .rough-node .label,#mermaid-svg-VNDxmRnvDcBoTdXF .node .label,#mermaid-svg-VNDxmRnvDcBoTdXF .image-shape .label,#mermaid-svg-VNDxmRnvDcBoTdXF .icon-shape .label{text-align:center;}#mermaid-svg-VNDxmRnvDcBoTdXF .node.clickable{cursor:pointer;}#mermaid-svg-VNDxmRnvDcBoTdXF .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VNDxmRnvDcBoTdXF .arrowheadPath{fill:#333333;}#mermaid-svg-VNDxmRnvDcBoTdXF .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VNDxmRnvDcBoTdXF .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VNDxmRnvDcBoTdXF .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VNDxmRnvDcBoTdXF .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VNDxmRnvDcBoTdXF .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VNDxmRnvDcBoTdXF .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VNDxmRnvDcBoTdXF .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VNDxmRnvDcBoTdXF .cluster text{fill:#333;}#mermaid-svg-VNDxmRnvDcBoTdXF .cluster span{color:#333;}#mermaid-svg-VNDxmRnvDcBoTdXF div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VNDxmRnvDcBoTdXF .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VNDxmRnvDcBoTdXF rect.text{fill:none;stroke-width:0;}#mermaid-svg-VNDxmRnvDcBoTdXF .icon-shape,#mermaid-svg-VNDxmRnvDcBoTdXF .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VNDxmRnvDcBoTdXF .icon-shape p,#mermaid-svg-VNDxmRnvDcBoTdXF .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VNDxmRnvDcBoTdXF .icon-shape .label rect,#mermaid-svg-VNDxmRnvDcBoTdXF .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VNDxmRnvDcBoTdXF .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VNDxmRnvDcBoTdXF .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VNDxmRnvDcBoTdXF :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-VNDxmRnvDcBoTdXF .core>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-VNDxmRnvDcBoTdXF .core span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-VNDxmRnvDcBoTdXF .core tspan{fill:#fff!important;}#mermaid-svg-VNDxmRnvDcBoTdXF .data>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-VNDxmRnvDcBoTdXF .data span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-VNDxmRnvDcBoTdXF .data tspan{fill:#fff!important;}#mermaid-svg-VNDxmRnvDcBoTdXF .path>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-VNDxmRnvDcBoTdXF .path span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-VNDxmRnvDcBoTdXF .path tspan{fill:#fff!important;}#mermaid-svg-VNDxmRnvDcBoTdXF .inv>*{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-VNDxmRnvDcBoTdXF .inv span{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-VNDxmRnvDcBoTdXF .inv tspan{fill:#fff!important;} 不变量
路径
数据层
workspace 核心
WorkspaceRegistry

工作区注册表
WorkspaceEntity

工作区实体
WorkspaceEntityHost

实体宿主接口
workspaceDomainSpec

域规格
WorkspaceRecord

工作区记录
WorkspaceDomainState

域状态
Types

公共类型
realpathNormalize

路径规范化
Workspace Invariant

工作区不变量

关键类/函数表

名称 类型 职责
WorkspaceRegistry 服务 工作区注册表 ctx.workspaceRegistry,依赖 storageDomainsessionPersistence
WorkspaceEntity 单个 Workspace 实现,持有记录快照,所有写入通过私有 mutate()
WorkspaceEntityHost 接口 实体宿主:table()/sessionPath()/readSessionHeader()/rememberSessionPath()
Workspace 接口 消费者接口:id、path、title、sessionIds、setTitle/attachSession/insertSessionBefore/detachSession/status
WorkspaceId 品牌类型 Branded<'WorkspaceId'>,生成的 UUID
WorkspaceRecord Zod 推断 持久化记录:path、title、sessionIds、createdAt、updatedAt
WorkspaceDomainState Zod 推断 域状态:initialized、workspaceIds、archivedSessionIds、pendingMutation
workspaceDomainSpec 域规格 defineDomain({ name: 'workspace', version: 2, ... })
realpathNormalize() 函数 通过 fs.realpath 规范化目录路径
WorkspaceMoveInvalidError 移动会话时引用了不在账户中的会话
WorkspaceUnknownSessionError 归档时引用了未知的会话
WorkspaceOrderInvalidError 重排序时引用了未知的工作区

架构要点

  • realpath 唯一标识 :工作区路径通过 fs.realpath 规范化作为唯一标识------尾斜杠、.. 和符号链接都被解析
  • 头部验证成员关系:会话成员关系需要同时满足:id 在账户中 AND 会话头部的规范化 cwd 等于工作区路径
  • 待定变更恢复pendingMutation 标记在域状态中,启动时恢复未完成的创建/删除操作
  • 操作序列化enqueueOperation() 确保所有注册表写操作串行执行
  • Bootstrap:首次启动时从会话头部按 cwd 分组创建工作区记录
  • 过滤候选修剪:每次接受的变更都执行持久化的过滤候选修剪(移除无效 sessionIds)
  • 不变量检查:域变更事件验证注册表缓存与域表的一致性------删除时缓存必须已移除,写入时缓存必须已存在
  • 归档集:归档会话保留 sessionIds 槽位,取消归档恢复位置

util

路径 : packages/util/

核心作用: 共享工具库集合,提供品牌类型、原生命令执行、启动环境快照、DSH 路径解析、超时算术、输出保留和原子写入等基础能力。

架构图

#mermaid-svg-Ude4EIP9d3qWqkc8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ude4EIP9d3qWqkc8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ude4EIP9d3qWqkc8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ude4EIP9d3qWqkc8 .error-icon{fill:#552222;}#mermaid-svg-Ude4EIP9d3qWqkc8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ude4EIP9d3qWqkc8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ude4EIP9d3qWqkc8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ude4EIP9d3qWqkc8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ude4EIP9d3qWqkc8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ude4EIP9d3qWqkc8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ude4EIP9d3qWqkc8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ude4EIP9d3qWqkc8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ude4EIP9d3qWqkc8 .marker.cross{stroke:#333333;}#mermaid-svg-Ude4EIP9d3qWqkc8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ude4EIP9d3qWqkc8 p{margin:0;}#mermaid-svg-Ude4EIP9d3qWqkc8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Ude4EIP9d3qWqkc8 .cluster-label text{fill:#333;}#mermaid-svg-Ude4EIP9d3qWqkc8 .cluster-label span{color:#333;}#mermaid-svg-Ude4EIP9d3qWqkc8 .cluster-label span p{background-color:transparent;}#mermaid-svg-Ude4EIP9d3qWqkc8 .label text,#mermaid-svg-Ude4EIP9d3qWqkc8 span{fill:#333;color:#333;}#mermaid-svg-Ude4EIP9d3qWqkc8 .node rect,#mermaid-svg-Ude4EIP9d3qWqkc8 .node circle,#mermaid-svg-Ude4EIP9d3qWqkc8 .node ellipse,#mermaid-svg-Ude4EIP9d3qWqkc8 .node polygon,#mermaid-svg-Ude4EIP9d3qWqkc8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Ude4EIP9d3qWqkc8 .rough-node .label text,#mermaid-svg-Ude4EIP9d3qWqkc8 .node .label text,#mermaid-svg-Ude4EIP9d3qWqkc8 .image-shape .label,#mermaid-svg-Ude4EIP9d3qWqkc8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Ude4EIP9d3qWqkc8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Ude4EIP9d3qWqkc8 .rough-node .label,#mermaid-svg-Ude4EIP9d3qWqkc8 .node .label,#mermaid-svg-Ude4EIP9d3qWqkc8 .image-shape .label,#mermaid-svg-Ude4EIP9d3qWqkc8 .icon-shape .label{text-align:center;}#mermaid-svg-Ude4EIP9d3qWqkc8 .node.clickable{cursor:pointer;}#mermaid-svg-Ude4EIP9d3qWqkc8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Ude4EIP9d3qWqkc8 .arrowheadPath{fill:#333333;}#mermaid-svg-Ude4EIP9d3qWqkc8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Ude4EIP9d3qWqkc8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Ude4EIP9d3qWqkc8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ude4EIP9d3qWqkc8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Ude4EIP9d3qWqkc8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ude4EIP9d3qWqkc8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Ude4EIP9d3qWqkc8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Ude4EIP9d3qWqkc8 .cluster text{fill:#333;}#mermaid-svg-Ude4EIP9d3qWqkc8 .cluster span{color:#333;}#mermaid-svg-Ude4EIP9d3qWqkc8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Ude4EIP9d3qWqkc8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Ude4EIP9d3qWqkc8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Ude4EIP9d3qWqkc8 .icon-shape,#mermaid-svg-Ude4EIP9d3qWqkc8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ude4EIP9d3qWqkc8 .icon-shape p,#mermaid-svg-Ude4EIP9d3qWqkc8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Ude4EIP9d3qWqkc8 .icon-shape .label rect,#mermaid-svg-Ude4EIP9d3qWqkc8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ude4EIP9d3qWqkc8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Ude4EIP9d3qWqkc8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Ude4EIP9d3qWqkc8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-Ude4EIP9d3qWqkc8 .type>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .type span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .type tspan{fill:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .cmd>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .cmd span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .cmd tspan{fill:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .env>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .env span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .env tspan{fill:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .path>*{fill:#bd10e0!important;stroke:#9c0bb3!important;color:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .path span{fill:#bd10e0!important;stroke:#9c0bb3!important;color:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .path tspan{fill:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .timeout>*{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .timeout span{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .timeout tspan{fill:#fff!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .retain>*{fill:#f8e71c!important;stroke:#c5b416!important;color:#333!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .retain span{fill:#f8e71c!important;stroke:#c5b416!important;color:#333!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .retain tspan{fill:#333!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .atomic>*{fill:#50e3c2!important;stroke:#2bb89a!important;color:#333!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .atomic span{fill:#50e3c2!important;stroke:#2bb89a!important;color:#333!important;}#mermaid-svg-Ude4EIP9d3qWqkc8 .atomic tspan{fill:#333!important;} atomic-write
writeFileAtomic

原子文件写入
withFileLock

文件锁
output-retention
ItemRetainer

项保留器
formatRetentionNotice

保留通知格式化
TextRetainer

文本保留器
timeout
deadline

截止时间
TimeoutReason

超时原因
idleWatchdog

空闲看门狗
clampTimeout

钳制超时
timeoutOf

超时判定
home-paths
resolveDshHome

解析DSH主目录
expandHomePath

展开主目录前缀
canonicalizeWatchPath

规范化监视路径
launch-environment
LaunchEnvironmentSnapshot

启动环境快照
Layers

层级: process/project-env/user-env
native-command
runNativeCommand

原生命令执行器
brand
Branded<B>

品牌类型原语

关键类/函数表

名称 类型 职责
Branded<B> 类型 编译时品牌类型原语,零运行时成本
runNativeCommand() 函数 无 shell 的 execFile 执行器,utf8 stdio + abort 传播 + Windows 隐藏
LaunchEnvironmentSnapshot 接口 不可变启动环境快照,按层级信任顺序解析变量
createLaunchEnvironmentSnapshot() 函数 从各层内容构建快照
launchEnvironmentOf() 函数 从上下文获取启动环境快照
resolveDshHome() 函数 解析 DSH 主目录:配置 > $DSH_HOME > ~/.dsh
defaultDshHome() 函数 默认 DSH 主目录:~/.dsh
expandHomePath() 函数 展开 ~/~//~\ 前缀
canonicalizeWatchPath() 函数 为文件监视器规范化路径(最深存在祖先 realpath + 缺失后缀)
dshHomeDisplay() 函数 用户友好显示形式(~/.dsh$DSH_HOME
dshHomePath() 函数 在 DSH 主目录下拼接路径段
deadline() 函数 融合上游取消和可识别超时,返回 Deadline(信号 + 清理)
idleWatchdog() 函数 可重武装的空闲看门狗,计时器仅在 next() 待出时存在
clampTimeout() 函数 验证、默认、钳制超时值
TimeoutReason 超时原因:携带能力拥有的 code 和 timeoutMs
timeoutOf() 函数 从信号或原因载体恢复超时原因
MAX_TIMER_DELAY_MS 常量 Node 计时器不钳制为 1ms 的最大延迟
ItemRetainer<T> 有序逻辑单元保留器,head 策略
TextRetainer 字节导向文本流保留器,head/tail/headTail 策略
RetainedItems<T> 接口 项保留结果
RetainedText 接口 文本保留结果
formatRetentionNotice() 函数 格式化保留通知(标准化省略子句 + 工具恢复指导)
describeOmitted() 函数 标准化省略措辞
writeFileAtomic() 函数 原子文件替换:随机后缀兄弟文件 + rename
withFileLock() 函数 跨进程写入锁:wx 创建 .lock 兄弟文件
WriteFileAtomicOptions 接口 写入选项:mode(必需)+ dirMode(可选)

架构要点

  • 品牌类型原语Branded<B> 是纯类型工具,零运行时代码,各包品牌自己拥有的 ID
  • 层级信任顺序 :启动环境按 process > project-env > user-env 信任顺序解析,Windows 大小写折叠
  • 冻结快照:启动环境快照在构建后不可变,后续 chdir/工作区切换/会话恢复观察相同值
  • 超时融合AbortSignal.any 融合上游取消和超时,竞速解析为单个原因
  • UTF-8 边界安全TextRetainer.finish() 在切割处修剪部分 UTF-8 序列,永不发出替换字符
  • 原子写入wx 标志独占创建防止符号链接植入,同目录兄弟 rename 确保原子性
  • 跨进程锁:指数退避重试(20ms→200ms),2 秒超时,从不移除现有锁(文件年龄不能证明所有者已停止)

基础设施协作总览

DeepSeek Harness 的基础设施模块群通过分层协作支撑整个 AI Agent 运行时。以下总览图展示了核心基础设施模块之间的协作关系:
#mermaid-svg-2XmrbMHk7r3YlixI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2XmrbMHk7r3YlixI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2XmrbMHk7r3YlixI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2XmrbMHk7r3YlixI .error-icon{fill:#552222;}#mermaid-svg-2XmrbMHk7r3YlixI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2XmrbMHk7r3YlixI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2XmrbMHk7r3YlixI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2XmrbMHk7r3YlixI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2XmrbMHk7r3YlixI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2XmrbMHk7r3YlixI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2XmrbMHk7r3YlixI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2XmrbMHk7r3YlixI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2XmrbMHk7r3YlixI .marker.cross{stroke:#333333;}#mermaid-svg-2XmrbMHk7r3YlixI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2XmrbMHk7r3YlixI p{margin:0;}#mermaid-svg-2XmrbMHk7r3YlixI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2XmrbMHk7r3YlixI .cluster-label text{fill:#333;}#mermaid-svg-2XmrbMHk7r3YlixI .cluster-label span{color:#333;}#mermaid-svg-2XmrbMHk7r3YlixI .cluster-label span p{background-color:transparent;}#mermaid-svg-2XmrbMHk7r3YlixI .label text,#mermaid-svg-2XmrbMHk7r3YlixI span{fill:#333;color:#333;}#mermaid-svg-2XmrbMHk7r3YlixI .node rect,#mermaid-svg-2XmrbMHk7r3YlixI .node circle,#mermaid-svg-2XmrbMHk7r3YlixI .node ellipse,#mermaid-svg-2XmrbMHk7r3YlixI .node polygon,#mermaid-svg-2XmrbMHk7r3YlixI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2XmrbMHk7r3YlixI .rough-node .label text,#mermaid-svg-2XmrbMHk7r3YlixI .node .label text,#mermaid-svg-2XmrbMHk7r3YlixI .image-shape .label,#mermaid-svg-2XmrbMHk7r3YlixI .icon-shape .label{text-anchor:middle;}#mermaid-svg-2XmrbMHk7r3YlixI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2XmrbMHk7r3YlixI .rough-node .label,#mermaid-svg-2XmrbMHk7r3YlixI .node .label,#mermaid-svg-2XmrbMHk7r3YlixI .image-shape .label,#mermaid-svg-2XmrbMHk7r3YlixI .icon-shape .label{text-align:center;}#mermaid-svg-2XmrbMHk7r3YlixI .node.clickable{cursor:pointer;}#mermaid-svg-2XmrbMHk7r3YlixI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2XmrbMHk7r3YlixI .arrowheadPath{fill:#333333;}#mermaid-svg-2XmrbMHk7r3YlixI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2XmrbMHk7r3YlixI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2XmrbMHk7r3YlixI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2XmrbMHk7r3YlixI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2XmrbMHk7r3YlixI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2XmrbMHk7r3YlixI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2XmrbMHk7r3YlixI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2XmrbMHk7r3YlixI .cluster text{fill:#333;}#mermaid-svg-2XmrbMHk7r3YlixI .cluster span{color:#333;}#mermaid-svg-2XmrbMHk7r3YlixI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2XmrbMHk7r3YlixI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2XmrbMHk7r3YlixI rect.text{fill:none;stroke-width:0;}#mermaid-svg-2XmrbMHk7r3YlixI .icon-shape,#mermaid-svg-2XmrbMHk7r3YlixI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2XmrbMHk7r3YlixI .icon-shape p,#mermaid-svg-2XmrbMHk7r3YlixI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2XmrbMHk7r3YlixI .icon-shape .label rect,#mermaid-svg-2XmrbMHk7r3YlixI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2XmrbMHk7r3YlixI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2XmrbMHk7r3YlixI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2XmrbMHk7r3YlixI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-2XmrbMHk7r3YlixI .boot>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .boot span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .boot tspan{fill:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .storage>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .storage span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .storage tspan{fill:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .session>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .session span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .session tspan{fill:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .config>*{fill:#bd10e0!important;stroke:#9c0bb3!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .config span{fill:#bd10e0!important;stroke:#9c0bb3!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .config tspan{fill:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .security>*{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .security span{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .security tspan{fill:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .workspace>*{fill:#50e3c2!important;stroke:#2bb89a!important;color:#333!important;}#mermaid-svg-2XmrbMHk7r3YlixI .workspace span{fill:#50e3c2!important;stroke:#2bb89a!important;color:#333!important;}#mermaid-svg-2XmrbMHk7r3YlixI .workspace tspan{fill:#333!important;}#mermaid-svg-2XmrbMHk7r3YlixI .tool>*{fill:#f8e71c!important;stroke:#c5b416!important;color:#333!important;}#mermaid-svg-2XmrbMHk7r3YlixI .tool span{fill:#f8e71c!important;stroke:#c5b416!important;color:#333!important;}#mermaid-svg-2XmrbMHk7r3YlixI .tool tspan{fill:#333!important;}#mermaid-svg-2XmrbMHk7r3YlixI .comm>*{fill:#ff6b6b!important;stroke:#e55353!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .comm span{fill:#ff6b6b!important;stroke:#e55353!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .comm tspan{fill:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .client>*{fill:#4ecdc4!important;stroke:#3bb5ac!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .client span{fill:#4ecdc4!important;stroke:#3bb5ac!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .client tspan{fill:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .diag>*{fill:#a55eea!important;stroke:#8e44ad!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .diag span{fill:#a55eea!important;stroke:#8e44ad!important;color:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .diag tspan{fill:#fff!important;}#mermaid-svg-2XmrbMHk7r3YlixI .util>*{fill:#dfe6e9!important;stroke:#b2bec3!important;color:#333!important;}#mermaid-svg-2XmrbMHk7r3YlixI .util span{fill:#dfe6e9!important;stroke:#b2bec3!important;color:#333!important;}#mermaid-svg-2XmrbMHk7r3YlixI .util tspan{fill:#333!important;} 工具库
诊断层
客户端层
通信层
工具层
工作区层
安全层
配置层
会话层
存储层
启动层
Boot

启动引导
LaunchEnvironment

启动环境快照
HomePaths

DSH主目录解析
Storage Hub

存储枢纽
StorageDomain

领域层
Backend

后端: JSON/SQLite
Session

会话实体
SessionPersistence

会话持久化
CheckpointPolicy

检查点策略
SessionQuery

会话查询
Settings

用户设置
Credentials

凭证管理
Preset

预设组合
Guard

安全防护
Interaction

交互/审批
Attachment

附件存储
WorkspaceRegistry

工作区注册表
Context

上下文插件
Spill

溢出管理
Hooks

钩子桥接
Todo

待办工具
Plan

计划模式
Goal

目标管理
Jobs

后台任务
Schedule

调度
Feedback

反馈
API Gateway

API网关
SDK Protocol

JSON-RPC协议
ACP Bridge

Agent客户端协议
Typert

类型图
Client

客户端运行时
Host

宿主能力
Extensions

扩展系统
RuntimeDiagnostics

运行时诊断
SessionTelemetry

会话遥测
Brand

品牌类型
Timeout

超时算术
OutputRetention

输出保留
AtomicWrite

原子写入
NativeCommand

原生命令

协作说明

  1. 启动与存储初始化Boot 阶段首先通过 LaunchEnvironment 捕获启动环境快照,通过 HomePaths 解析 DSH 主目录,然后初始化 Storage 枢纽。Storage 挂载后端(JSON/SQLite),StorageDomain 在后端之上构建领域抽象(DomainGlobalKvTable)。

  2. 会话持久化链Session 实体通过 SessionPersistence 持久化到存储后端。CheckpointPolicy 在语义边界(模型请求前、工具分派前、步骤边界)调用 sessions.flush() 确保持久化完成。SessionQuery 在持久化会话之上提供跨会话搜索和谱系追踪。

  3. 配置与预设SettingsCredentials 通过 Storage 持久化。PresetSession 事件折叠旋钮状态(沙箱模式、审批策略),通过 derive() 匹配预设规格。

  4. 安全与交互Guard 提供沙箱模式控制,Interaction 提供审批瀑布和用户问题。Attachment 提供内容寻址的不可变附件存储,通过 Storage 的本地后端持久化。

  5. 工作区管理WorkspaceRegistry 依赖 StorageDomain(域表)和 SessionPersistence(会话头部索引),通过 fs.realpath 规范化路径作为工作区唯一标识。Context(agent-instructions)发现和渲染工作区指令,依赖 Workspace 的路径信息。SpillDSH_HOME 下管理溢出文件。

  6. 工具生态HooksTodoPlanGoalJobsScheduleFeedback 等工具模块都通过 Session 追加事件,通过 SessionProjection 派生投影状态。TimeoutJobsScheduleHooks 提供超时算术。OutputRetentionSpill 提供有界输出保留。

  7. 通信与客户端API Gateway 通过 Typert 生成的 Remote 命名空间暴露主机能力,SDK 提供 JSON-RPC 传输层,ACP 通过 stdio 暴露自动化接口。Client 通过 API 连接主机,Host 提供目录选择等宿主能力,Extensions 管理动态插件。

  8. 诊断与遥测RuntimeDiagnostics 聚合各子系统运行时状态,SessionTelemetry 通过 OpenTelemetry 导出遥测数据,Feedback 事件可触发反馈门控的会话共享。

  9. 工具库横切Brand 为所有跨边界 ID 提供编译时类型安全;AtomicWriteSettingsCredentials 等提供原子文件替换和跨进程锁;NativeCommandHost 的原生集成提供无 shell 命令执行。

  10. 不变量伴生 :每个包都有一个不变量伴生插件,通过 ctx.invariants.register() 注册包级不变量检查,确保运行时状态一致性。大多数工具模块的不变量验证会话事件(如 todo/write 的列表完整性、plan/mode 的布尔状态)。Workspace 的不变量验证注册表缓存与域表的一致性。


本文档基于 DeepSeek Harness 项目源码分析生成,覆盖 31 个模块(create 包不存在,已跳过)。所有 Mermaid 图使用 graph TB 方向和 classDef 着色。分析日期:2026-08-18。


复制代码
class Storage,BackendRegistry,Forms hub
class JsonBackend,SqliteBackend,KvFacet backend
class DomainLayer,DomainGlobal,KvTable,DefineDomain domain


### 关键类/函数表

| 名称 | 类型 | 职责 |
|------|------|------|
| `Storage` | 服务 | 存储枢纽,`ctx.storage`,管理后端注册和数据形式挂载 |
| `BackendRegistry` | 类 | 命名后端注册表,支持注册/解析/列表,防止重复注册 |
| `StorageBackend` | 接口 | 后端契约:拥有一种介质,暴露 KV 操作面和 `close()` |
| `KvFacet` | 接口 | KV 操作面:`open()` 打开单元,返回 `KvUnit` |
| `KvUnit` | 接口 | 已打开单元:`loadAll()`、`putRecord()`、`deleteRecord()`、`setGlobal()`、`close()` |
| `KvUnitDescriptor` | 接口 | 单元描述符:名称、版本、表名列表、是否有全局单例 |
| `StorageError` | 类 | 存储错误类,携带稳定错误码 |
| `StorageErrorCode` | 类型 | 错误码联合:`backend-not-found`、`duplicate-backend`、`version-mismatch` 等 |
| `UNIT_NAME_RE` | 常量 | 单元/表名正则:`/^[a-z][a-z0-9_]*$/` |
| `storageBackendServiceKey()` | 函数 | 派生后端生命周期服务键 |
| `defineDomain()` | 函数 | 领域定义:名称、版本、全局模式、表规格 |
| `DomainGlobal<T>` | 接口 | 领域全局单例:`get()`/`set()` |
| `KvTable<K, V>` | 接口 | KV 表:`get()`/`put()`/`delete()`/`update()`/`entries()`/`size` |

### 架构要点

- **后端不可知**:存储枢纽自身不执行任何 IO,后端拥有介质(文件树、数据库文件),数据形式拥有语义
- **多后端共存**:多个后端可同时挂载,由消费者配置决定路由
- **单元版本化**:`KvUnitDescriptor.version` 在首次物化时标记介质,版本不匹配拒绝 `version-mismatch`
- **领域层**:`storage-domain` 在 KV 之上构建领域抽象------`DomainGlobal` 单例和 `KvTable` 表接口,通过 `defineDomain()` 声明领域规格
- **写链序列化**:领域层运行每单元一个写链,确保写操作顺序一致

---

## settings

**路径**: `packages/settings/`
**核心作用**: 用户设置管理,提供命名空间设置存储和配置读写能力。

### 架构图

```mermaid
graph TB
    subgraph "settings 核心"
        SettingsService[Settings<br/>设置服务]
        Namespace[Namespace<br/>命名空间]
        SettingsPath[SettingsPath<br/>设置路径]
    end

    subgraph "settings-local"
        LocalBackend[LocalSettings<br/>本地设置后端]
        JsonStore[JSON Store<br/>文件存储]
    end

    SettingsService --> Namespace
    Namespace --> SettingsPath
    SettingsService --> LocalBackend
    LocalBackend --> JsonStore

    classDef core fill:#4a90d9,stroke:#357abd,color:#fff
    classDef local fill:#f5a623,stroke:#d48b0a,color:#fff

    class SettingsService,Namespace,SettingsPath core
    class LocalBackend,JsonStore local

关键类/函数表

名称 类型 职责
Settings 服务 设置服务 ctx.settings,提供命名空间读写
SettingsNamespaceView 接口 命名空间视图,暴露路径操作和值读取
SettingsPathOpView 接口 设置路径操作视图
LocalSettings 本地设置后端,基于 JSON 文件存储
Config 配置 设置插件配置

架构要点

  • 命名空间隔离:设置按命名空间组织,每个命名空间独立管理其配置路径
  • 原子写入 :本地设置后端使用 writeFileAtomic 实现原子替换,通过 withFileLock 序列化跨进程写入
  • 客户端投影 :通过 ./client./types 双出口投影,零重复

credentials

路径 : packages/credentials/

核心作用: 凭证管理,提供 API 密钥、令牌等敏感凭证的安全存储和读取能力。

架构图

#mermaid-svg-OhU2HT7BiWTlULLK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-OhU2HT7BiWTlULLK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-OhU2HT7BiWTlULLK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-OhU2HT7BiWTlULLK .error-icon{fill:#552222;}#mermaid-svg-OhU2HT7BiWTlULLK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-OhU2HT7BiWTlULLK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-OhU2HT7BiWTlULLK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-OhU2HT7BiWTlULLK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-OhU2HT7BiWTlULLK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-OhU2HT7BiWTlULLK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-OhU2HT7BiWTlULLK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-OhU2HT7BiWTlULLK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-OhU2HT7BiWTlULLK .marker.cross{stroke:#333333;}#mermaid-svg-OhU2HT7BiWTlULLK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-OhU2HT7BiWTlULLK p{margin:0;}#mermaid-svg-OhU2HT7BiWTlULLK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-OhU2HT7BiWTlULLK .cluster-label text{fill:#333;}#mermaid-svg-OhU2HT7BiWTlULLK .cluster-label span{color:#333;}#mermaid-svg-OhU2HT7BiWTlULLK .cluster-label span p{background-color:transparent;}#mermaid-svg-OhU2HT7BiWTlULLK .label text,#mermaid-svg-OhU2HT7BiWTlULLK span{fill:#333;color:#333;}#mermaid-svg-OhU2HT7BiWTlULLK .node rect,#mermaid-svg-OhU2HT7BiWTlULLK .node circle,#mermaid-svg-OhU2HT7BiWTlULLK .node ellipse,#mermaid-svg-OhU2HT7BiWTlULLK .node polygon,#mermaid-svg-OhU2HT7BiWTlULLK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-OhU2HT7BiWTlULLK .rough-node .label text,#mermaid-svg-OhU2HT7BiWTlULLK .node .label text,#mermaid-svg-OhU2HT7BiWTlULLK .image-shape .label,#mermaid-svg-OhU2HT7BiWTlULLK .icon-shape .label{text-anchor:middle;}#mermaid-svg-OhU2HT7BiWTlULLK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-OhU2HT7BiWTlULLK .rough-node .label,#mermaid-svg-OhU2HT7BiWTlULLK .node .label,#mermaid-svg-OhU2HT7BiWTlULLK .image-shape .label,#mermaid-svg-OhU2HT7BiWTlULLK .icon-shape .label{text-align:center;}#mermaid-svg-OhU2HT7BiWTlULLK .node.clickable{cursor:pointer;}#mermaid-svg-OhU2HT7BiWTlULLK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-OhU2HT7BiWTlULLK .arrowheadPath{fill:#333333;}#mermaid-svg-OhU2HT7BiWTlULLK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-OhU2HT7BiWTlULLK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-OhU2HT7BiWTlULLK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OhU2HT7BiWTlULLK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-OhU2HT7BiWTlULLK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OhU2HT7BiWTlULLK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-OhU2HT7BiWTlULLK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-OhU2HT7BiWTlULLK .cluster text{fill:#333;}#mermaid-svg-OhU2HT7BiWTlULLK .cluster span{color:#333;}#mermaid-svg-OhU2HT7BiWTlULLK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-OhU2HT7BiWTlULLK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-OhU2HT7BiWTlULLK rect.text{fill:none;stroke-width:0;}#mermaid-svg-OhU2HT7BiWTlULLK .icon-shape,#mermaid-svg-OhU2HT7BiWTlULLK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-OhU2HT7BiWTlULLK .icon-shape p,#mermaid-svg-OhU2HT7BiWTlULLK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-OhU2HT7BiWTlULLK .icon-shape .label rect,#mermaid-svg-OhU2HT7BiWTlULLK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-OhU2HT7BiWTlULLK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-OhU2HT7BiWTlULLK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-OhU2HT7BiWTlULLK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-OhU2HT7BiWTlULLK .core>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-OhU2HT7BiWTlULLK .core span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-OhU2HT7BiWTlULLK .core tspan{fill:#fff!important;}#mermaid-svg-OhU2HT7BiWTlULLK .local>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-OhU2HT7BiWTlULLK .local span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-OhU2HT7BiWTlULLK .local tspan{fill:#fff!important;}#mermaid-svg-OhU2HT7BiWTlULLK .err>*{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-OhU2HT7BiWTlULLK .err span{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-OhU2HT7BiWTlULLK .err tspan{fill:#fff!important;} credentials-local
credentials 核心
CredentialStore

凭证存储服务
CredentialView

凭证视图
CredentialError

凭证错误
LocalCredentialStore

本地凭证后端
Encrypted Store

加密存储

关键类/函数表

名称 类型 职责
CredentialStore 服务 凭证存储服务 ctx.credentials
CredentialView 接口 凭证客户端视图,包含提供商和模型信息
CredentialError 凭证错误类
LocalCredentialStore 本地凭证后端实现

架构要点

  • 安全隔离:凭证通过独立服务管理,不混入通用设置
  • 客户端安全投影CredentialView 只暴露必要的非敏感信息给客户端
  • 与设置分离:凭证独立于设置命名空间,避免意外泄露

identity

路径 : packages/identity/

核心作用: 身份标识管理,提供匿名用户 ID 和会话身份追踪能力。

关键类/函数表

名称 类型 职责
getOrCreateAnonymousUserId() 函数 获取或创建匿名用户 ID,用于遥测和反馈
AnonymousUserId 类型 匿名用户标识符

架构要点

  • 匿名身份:为遥测和反馈提供匿名用户标识,不泄露个人信息
  • 持久化:匿名 ID 持久化存储在 DSH_HOME 下

interaction

路径 : packages/interaction/

核心作用: 交互与审批能力,提供用户问题、审批请求和交互式决策的框架。

架构图

#mermaid-svg-vjjg3fhfH117dNgp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-vjjg3fhfH117dNgp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-vjjg3fhfH117dNgp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-vjjg3fhfH117dNgp .error-icon{fill:#552222;}#mermaid-svg-vjjg3fhfH117dNgp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-vjjg3fhfH117dNgp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-vjjg3fhfH117dNgp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-vjjg3fhfH117dNgp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-vjjg3fhfH117dNgp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-vjjg3fhfH117dNgp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-vjjg3fhfH117dNgp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-vjjg3fhfH117dNgp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-vjjg3fhfH117dNgp .marker.cross{stroke:#333333;}#mermaid-svg-vjjg3fhfH117dNgp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-vjjg3fhfH117dNgp p{margin:0;}#mermaid-svg-vjjg3fhfH117dNgp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-vjjg3fhfH117dNgp .cluster-label text{fill:#333;}#mermaid-svg-vjjg3fhfH117dNgp .cluster-label span{color:#333;}#mermaid-svg-vjjg3fhfH117dNgp .cluster-label span p{background-color:transparent;}#mermaid-svg-vjjg3fhfH117dNgp .label text,#mermaid-svg-vjjg3fhfH117dNgp span{fill:#333;color:#333;}#mermaid-svg-vjjg3fhfH117dNgp .node rect,#mermaid-svg-vjjg3fhfH117dNgp .node circle,#mermaid-svg-vjjg3fhfH117dNgp .node ellipse,#mermaid-svg-vjjg3fhfH117dNgp .node polygon,#mermaid-svg-vjjg3fhfH117dNgp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-vjjg3fhfH117dNgp .rough-node .label text,#mermaid-svg-vjjg3fhfH117dNgp .node .label text,#mermaid-svg-vjjg3fhfH117dNgp .image-shape .label,#mermaid-svg-vjjg3fhfH117dNgp .icon-shape .label{text-anchor:middle;}#mermaid-svg-vjjg3fhfH117dNgp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-vjjg3fhfH117dNgp .rough-node .label,#mermaid-svg-vjjg3fhfH117dNgp .node .label,#mermaid-svg-vjjg3fhfH117dNgp .image-shape .label,#mermaid-svg-vjjg3fhfH117dNgp .icon-shape .label{text-align:center;}#mermaid-svg-vjjg3fhfH117dNgp .node.clickable{cursor:pointer;}#mermaid-svg-vjjg3fhfH117dNgp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-vjjg3fhfH117dNgp .arrowheadPath{fill:#333333;}#mermaid-svg-vjjg3fhfH117dNgp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-vjjg3fhfH117dNgp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-vjjg3fhfH117dNgp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vjjg3fhfH117dNgp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-vjjg3fhfH117dNgp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vjjg3fhfH117dNgp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-vjjg3fhfH117dNgp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-vjjg3fhfH117dNgp .cluster text{fill:#333;}#mermaid-svg-vjjg3fhfH117dNgp .cluster span{color:#333;}#mermaid-svg-vjjg3fhfH117dNgp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-vjjg3fhfH117dNgp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-vjjg3fhfH117dNgp rect.text{fill:none;stroke-width:0;}#mermaid-svg-vjjg3fhfH117dNgp .icon-shape,#mermaid-svg-vjjg3fhfH117dNgp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-vjjg3fhfH117dNgp .icon-shape p,#mermaid-svg-vjjg3fhfH117dNgp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-vjjg3fhfH117dNgp .icon-shape .label rect,#mermaid-svg-vjjg3fhfH117dNgp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-vjjg3fhfH117dNgp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-vjjg3fhfH117dNgp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-vjjg3fhfH117dNgp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-vjjg3fhfH117dNgp .core>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-vjjg3fhfH117dNgp .core span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-vjjg3fhfH117dNgp .core tspan{fill:#fff!important;}#mermaid-svg-vjjg3fhfH117dNgp .approval>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-vjjg3fhfH117dNgp .approval span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-vjjg3fhfH117dNgp .approval tspan{fill:#fff!important;}#mermaid-svg-vjjg3fhfH117dNgp .question>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-vjjg3fhfH117dNgp .question span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-vjjg3fhfH117dNgp .question tspan{fill:#fff!important;} user-questions
user-approval
interaction 核心
Interaction

交互服务
ApprovalRequest

审批请求
UserQuestion

用户问题
ApprovalWaterfall

审批瀑布
ApprovalPolicy

审批策略
QuestionService

问题服务
UserQuestionError

问题错误

关键类/函数表

名称 类型 职责
ApprovalRequest 接口 审批请求:代理、工具调用 ID、选项列表
ApprovalWaterfall 机制 审批瀑布:多个监听器依次处理审批请求
ApprovalPolicy 类型 审批策略:never/always/on-failure
UserQuestion 服务 用户问题服务,支持多选/单选问题
UserQuestionError 用户问题错误

架构要点

  • 审批瀑布 :多个审批提供者通过 ctx.on('approval/request', ...) 串联,依次评估审批请求
  • 一次性审批 :ACP 桥接器提供 allow-once/reject-once 选项,从不推断持久授权
  • 问题服务:支持向用户提出结构化问题并等待回答

guard

路径 : packages/guard/

核心作用: 安全防护层,提供沙箱模式控制和工具执行防护。

关键类/函数表

名称 类型 职责
Guard 服务 安全防护服务
SandboxMode 类型 沙箱模式:off/workspace/full
GuardPolicy 接口 防护策略配置

架构要点

  • 沙箱模式:控制 Agent 工具执行的范围限制
  • 与预设联动:沙箱模式是预设匹配的关键维度之一

hooks

路径 : packages/hooks/

核心作用 : 钩子桥接系统,将 Claude Code 和 Codex 的命令钩子适配到 dsh 的扩展点。hook-protocol 提供共享执行和解析层,hooks-claude-codehooks-codex 是提供者特定的桥接器。

架构图

#mermaid-svg-HEjUR2kAGYB7gBrU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HEjUR2kAGYB7gBrU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HEjUR2kAGYB7gBrU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HEjUR2kAGYB7gBrU .error-icon{fill:#552222;}#mermaid-svg-HEjUR2kAGYB7gBrU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HEjUR2kAGYB7gBrU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HEjUR2kAGYB7gBrU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HEjUR2kAGYB7gBrU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HEjUR2kAGYB7gBrU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HEjUR2kAGYB7gBrU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HEjUR2kAGYB7gBrU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HEjUR2kAGYB7gBrU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HEjUR2kAGYB7gBrU .marker.cross{stroke:#333333;}#mermaid-svg-HEjUR2kAGYB7gBrU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HEjUR2kAGYB7gBrU p{margin:0;}#mermaid-svg-HEjUR2kAGYB7gBrU .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-HEjUR2kAGYB7gBrU .cluster-label text{fill:#333;}#mermaid-svg-HEjUR2kAGYB7gBrU .cluster-label span{color:#333;}#mermaid-svg-HEjUR2kAGYB7gBrU .cluster-label span p{background-color:transparent;}#mermaid-svg-HEjUR2kAGYB7gBrU .label text,#mermaid-svg-HEjUR2kAGYB7gBrU span{fill:#333;color:#333;}#mermaid-svg-HEjUR2kAGYB7gBrU .node rect,#mermaid-svg-HEjUR2kAGYB7gBrU .node circle,#mermaid-svg-HEjUR2kAGYB7gBrU .node ellipse,#mermaid-svg-HEjUR2kAGYB7gBrU .node polygon,#mermaid-svg-HEjUR2kAGYB7gBrU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-HEjUR2kAGYB7gBrU .rough-node .label text,#mermaid-svg-HEjUR2kAGYB7gBrU .node .label text,#mermaid-svg-HEjUR2kAGYB7gBrU .image-shape .label,#mermaid-svg-HEjUR2kAGYB7gBrU .icon-shape .label{text-anchor:middle;}#mermaid-svg-HEjUR2kAGYB7gBrU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-HEjUR2kAGYB7gBrU .rough-node .label,#mermaid-svg-HEjUR2kAGYB7gBrU .node .label,#mermaid-svg-HEjUR2kAGYB7gBrU .image-shape .label,#mermaid-svg-HEjUR2kAGYB7gBrU .icon-shape .label{text-align:center;}#mermaid-svg-HEjUR2kAGYB7gBrU .node.clickable{cursor:pointer;}#mermaid-svg-HEjUR2kAGYB7gBrU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-HEjUR2kAGYB7gBrU .arrowheadPath{fill:#333333;}#mermaid-svg-HEjUR2kAGYB7gBrU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-HEjUR2kAGYB7gBrU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-HEjUR2kAGYB7gBrU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HEjUR2kAGYB7gBrU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-HEjUR2kAGYB7gBrU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HEjUR2kAGYB7gBrU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-HEjUR2kAGYB7gBrU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-HEjUR2kAGYB7gBrU .cluster text{fill:#333;}#mermaid-svg-HEjUR2kAGYB7gBrU .cluster span{color:#333;}#mermaid-svg-HEjUR2kAGYB7gBrU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-HEjUR2kAGYB7gBrU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-HEjUR2kAGYB7gBrU rect.text{fill:none;stroke-width:0;}#mermaid-svg-HEjUR2kAGYB7gBrU .icon-shape,#mermaid-svg-HEjUR2kAGYB7gBrU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-HEjUR2kAGYB7gBrU .icon-shape p,#mermaid-svg-HEjUR2kAGYB7gBrU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-HEjUR2kAGYB7gBrU .icon-shape .label rect,#mermaid-svg-HEjUR2kAGYB7gBrU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-HEjUR2kAGYB7gBrU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-HEjUR2kAGYB7gBrU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-HEjUR2kAGYB7gBrU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-HEjUR2kAGYB7gBrU .shared>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-HEjUR2kAGYB7gBrU .shared span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-HEjUR2kAGYB7gBrU .shared tspan{fill:#fff!important;}#mermaid-svg-HEjUR2kAGYB7gBrU .cc>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-HEjUR2kAGYB7gBrU .cc span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-HEjUR2kAGYB7gBrU .cc tspan{fill:#fff!important;}#mermaid-svg-HEjUR2kAGYB7gBrU .codex>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-HEjUR2kAGYB7gBrU .codex span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-HEjUR2kAGYB7gBrU .codex tspan{fill:#fff!important;} hooks-codex
hooks-claude-code
hook-protocol 共享层
runHook

钩子执行器
matchesMatcher

匹配器
Codec

编解码
mergeHookOutputs

输出合并
createDetachedRuns

分离运行
HookEvent

钩子事件
parseClaudeCodeConfig

CC配置解析
ClaudeCode Bridge

CC桥接器
substituteCommand

变量替换
Codex Bridge

Codex桥接器

关键类/函数表

名称 类型 职责
runHook() 函数 执行单个命令钩子,带超时和 abort 传播
matchesMatcher() 函数 匹配器评估:正则匹配工具名/参数
mergeHookOutputs() 函数 合并多个钩子输出为单个决策
createDetachedRuns() 函数 创建分离运行的钩子(不阻塞主流程)
appendHookInvoked() 函数 追加钩子调用事件到会话日志
appendHookResult() 函数 追加钩子结果事件
MatcherGroup 接口 匹配器组:matcher + hooks 列表
HookOutput 接口 钩子输出:stdout、stderr、退出码
MergedHookOutcome 接口 合并后的钩子决策
parseClaudeCodeConfig() 函数 解析 CC 钩子配置为匹配器组
substituteCommand() 函数 替换 ${CLAUDE_PLUGIN_ROOT}${CLAUDE_PROJECT_DIR}

架构要点

  • 共享执行层hook-protocol 提供编解码、匹配、执行、合并的通用实现,桥接器只需处理提供者特定格式
  • CC 事件映射:支持 SessionStart、UserPromptSubmit、PreToolUse、PostToolUse、Stop、SubagentStart、SubagentStop 七种事件
  • 变量替换:在解析时对命令字符串进行变量替换,而非运行时
  • 分离运行createDetachedRuns 支持不阻塞主流程的钩子执行
  • 匹配器诊断 :无效正则表达式在配置解析时即抛出 SyntaxError

todo

路径 : packages/todo/

核心作用 : 模型可见的整列表替换待办工具。每次调用追加 todo/write 快照到会话日志,重放为 last-write-wins。

架构图

#mermaid-svg-ggUKGuvl28U3gCrl{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ggUKGuvl28U3gCrl .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ggUKGuvl28U3gCrl .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ggUKGuvl28U3gCrl .error-icon{fill:#552222;}#mermaid-svg-ggUKGuvl28U3gCrl .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ggUKGuvl28U3gCrl .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ggUKGuvl28U3gCrl .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ggUKGuvl28U3gCrl .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ggUKGuvl28U3gCrl .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ggUKGuvl28U3gCrl .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ggUKGuvl28U3gCrl .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ggUKGuvl28U3gCrl .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ggUKGuvl28U3gCrl .marker.cross{stroke:#333333;}#mermaid-svg-ggUKGuvl28U3gCrl svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ggUKGuvl28U3gCrl p{margin:0;}#mermaid-svg-ggUKGuvl28U3gCrl .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ggUKGuvl28U3gCrl .cluster-label text{fill:#333;}#mermaid-svg-ggUKGuvl28U3gCrl .cluster-label span{color:#333;}#mermaid-svg-ggUKGuvl28U3gCrl .cluster-label span p{background-color:transparent;}#mermaid-svg-ggUKGuvl28U3gCrl .label text,#mermaid-svg-ggUKGuvl28U3gCrl span{fill:#333;color:#333;}#mermaid-svg-ggUKGuvl28U3gCrl .node rect,#mermaid-svg-ggUKGuvl28U3gCrl .node circle,#mermaid-svg-ggUKGuvl28U3gCrl .node ellipse,#mermaid-svg-ggUKGuvl28U3gCrl .node polygon,#mermaid-svg-ggUKGuvl28U3gCrl .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ggUKGuvl28U3gCrl .rough-node .label text,#mermaid-svg-ggUKGuvl28U3gCrl .node .label text,#mermaid-svg-ggUKGuvl28U3gCrl .image-shape .label,#mermaid-svg-ggUKGuvl28U3gCrl .icon-shape .label{text-anchor:middle;}#mermaid-svg-ggUKGuvl28U3gCrl .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ggUKGuvl28U3gCrl .rough-node .label,#mermaid-svg-ggUKGuvl28U3gCrl .node .label,#mermaid-svg-ggUKGuvl28U3gCrl .image-shape .label,#mermaid-svg-ggUKGuvl28U3gCrl .icon-shape .label{text-align:center;}#mermaid-svg-ggUKGuvl28U3gCrl .node.clickable{cursor:pointer;}#mermaid-svg-ggUKGuvl28U3gCrl .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ggUKGuvl28U3gCrl .arrowheadPath{fill:#333333;}#mermaid-svg-ggUKGuvl28U3gCrl .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ggUKGuvl28U3gCrl .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ggUKGuvl28U3gCrl .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ggUKGuvl28U3gCrl .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ggUKGuvl28U3gCrl .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ggUKGuvl28U3gCrl .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ggUKGuvl28U3gCrl .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ggUKGuvl28U3gCrl .cluster text{fill:#333;}#mermaid-svg-ggUKGuvl28U3gCrl .cluster span{color:#333;}#mermaid-svg-ggUKGuvl28U3gCrl div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ggUKGuvl28U3gCrl .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ggUKGuvl28U3gCrl rect.text{fill:none;stroke-width:0;}#mermaid-svg-ggUKGuvl28U3gCrl .icon-shape,#mermaid-svg-ggUKGuvl28U3gCrl .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ggUKGuvl28U3gCrl .icon-shape p,#mermaid-svg-ggUKGuvl28U3gCrl .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ggUKGuvl28U3gCrl .icon-shape .label rect,#mermaid-svg-ggUKGuvl28U3gCrl .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ggUKGuvl28U3gCrl .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ggUKGuvl28U3gCrl .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ggUKGuvl28U3gCrl :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-ggUKGuvl28U3gCrl .tool>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-ggUKGuvl28U3gCrl .tool span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-ggUKGuvl28U3gCrl .tool tspan{fill:#fff!important;}#mermaid-svg-ggUKGuvl28U3gCrl .inv>*{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-ggUKGuvl28U3gCrl .inv span{fill:#e74c3c!important;stroke:#c0392b!important;color:#fff!important;}#mermaid-svg-ggUKGuvl28U3gCrl .inv tspan{fill:#fff!important;}#mermaid-svg-ggUKGuvl28U3gCrl .proj>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-ggUKGuvl28U3gCrl .proj span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-ggUKGuvl28U3gCrl .proj tspan{fill:#fff!important;} 会话投影
不变量
tool-todo
defineTool

todo工具定义
toTodoList

规范化列表
Types

类型声明
Client

客户端投影
validateTodos

不变量验证
todos 投影

TodoItem\[\] | null

关键类/函数表

名称 类型 职责
defineTool('todo_write') 工具 模型面向的待办写入工具
toTodoList() 函数 规范化模型输入为 TodoItem[]:去空白、去重、并行策略检查
TodoItem 接口 待办项:content + status(pending/in_progress/completed)
validateTodos() 函数 不变量验证:数组、非空内容、去重、合法状态
Config 配置 allowParallelInProgress:是否允许多个 in_progress
SessionProjectionMap.todos 声明合并 todos 投影键声明

架构要点

  • 整列表替换:每次调用携带完整替换列表,无增量更新
  • 并行策略allowParallelInProgress 配置控制是否允许多个 in_progress
  • 投影声明合并 :通过 SessionProjectionMap 声明合并扩展 todos 投影键
  • 双出口投影./types 供主机消费者,./client 供客户端聚合,零内容重复

plan

路径 : packages/plan/

核心作用 : 计划模式是按 Agent 记录的协作状态。激活时,部署拥有的指导段落包含在每个模型请求中,exit_plan_mode 工具呈现完成计划供用户审查。

架构图

#mermaid-svg-MzkIylE49Si4D3oX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MzkIylE49Si4D3oX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MzkIylE49Si4D3oX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MzkIylE49Si4D3oX .error-icon{fill:#552222;}#mermaid-svg-MzkIylE49Si4D3oX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MzkIylE49Si4D3oX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MzkIylE49Si4D3oX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MzkIylE49Si4D3oX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MzkIylE49Si4D3oX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MzkIylE49Si4D3oX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MzkIylE49Si4D3oX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MzkIylE49Si4D3oX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MzkIylE49Si4D3oX .marker.cross{stroke:#333333;}#mermaid-svg-MzkIylE49Si4D3oX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MzkIylE49Si4D3oX p{margin:0;}#mermaid-svg-MzkIylE49Si4D3oX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MzkIylE49Si4D3oX .cluster-label text{fill:#333;}#mermaid-svg-MzkIylE49Si4D3oX .cluster-label span{color:#333;}#mermaid-svg-MzkIylE49Si4D3oX .cluster-label span p{background-color:transparent;}#mermaid-svg-MzkIylE49Si4D3oX .label text,#mermaid-svg-MzkIylE49Si4D3oX span{fill:#333;color:#333;}#mermaid-svg-MzkIylE49Si4D3oX .node rect,#mermaid-svg-MzkIylE49Si4D3oX .node circle,#mermaid-svg-MzkIylE49Si4D3oX .node ellipse,#mermaid-svg-MzkIylE49Si4D3oX .node polygon,#mermaid-svg-MzkIylE49Si4D3oX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MzkIylE49Si4D3oX .rough-node .label text,#mermaid-svg-MzkIylE49Si4D3oX .node .label text,#mermaid-svg-MzkIylE49Si4D3oX .image-shape .label,#mermaid-svg-MzkIylE49Si4D3oX .icon-shape .label{text-anchor:middle;}#mermaid-svg-MzkIylE49Si4D3oX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MzkIylE49Si4D3oX .rough-node .label,#mermaid-svg-MzkIylE49Si4D3oX .node .label,#mermaid-svg-MzkIylE49Si4D3oX .image-shape .label,#mermaid-svg-MzkIylE49Si4D3oX .icon-shape .label{text-align:center;}#mermaid-svg-MzkIylE49Si4D3oX .node.clickable{cursor:pointer;}#mermaid-svg-MzkIylE49Si4D3oX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MzkIylE49Si4D3oX .arrowheadPath{fill:#333333;}#mermaid-svg-MzkIylE49Si4D3oX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MzkIylE49Si4D3oX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MzkIylE49Si4D3oX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MzkIylE49Si4D3oX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MzkIylE49Si4D3oX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MzkIylE49Si4D3oX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MzkIylE49Si4D3oX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MzkIylE49Si4D3oX .cluster text{fill:#333;}#mermaid-svg-MzkIylE49Si4D3oX .cluster span{color:#333;}#mermaid-svg-MzkIylE49Si4D3oX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MzkIylE49Si4D3oX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MzkIylE49Si4D3oX rect.text{fill:none;stroke-width:0;}#mermaid-svg-MzkIylE49Si4D3oX .icon-shape,#mermaid-svg-MzkIylE49Si4D3oX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MzkIylE49Si4D3oX .icon-shape p,#mermaid-svg-MzkIylE49Si4D3oX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MzkIylE49Si4D3oX .icon-shape .label rect,#mermaid-svg-MzkIylE49Si4D3oX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MzkIylE49Si4D3oX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MzkIylE49Si4D3oX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MzkIylE49Si4D3oX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-MzkIylE49Si4D3oX .core>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-MzkIylE49Si4D3oX .core span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-MzkIylE49Si4D3oX .core tspan{fill:#fff!important;}#mermaid-svg-MzkIylE49Si4D3oX .event>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-MzkIylE49Si4D3oX .event span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-MzkIylE49Si4D3oX .event tspan{fill:#fff!important;}#mermaid-svg-MzkIylE49Si4D3oX .interact>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-MzkIylE49Si4D3oX .interact span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-MzkIylE49Si4D3oX .interact tspan{fill:#fff!important;} 交互
会话事件
plan-mode 核心
PlanModeController

计划模式控制器
PlanModeConfig

配置
exit_plan_mode

退出工具
PlanProjection

计划投影
plan/mode

计划模式事件
command/run

命令运行事件
ReviewQuestion

审查问题
User Feedback

用户反馈

关键类/函数表

名称 类型 职责
PlanModeController 服务 计划模式控制器 ctx.planMode
PlanModeConfig 接口 配置:section 指导段落
PlanProjection 接口 投影:active + pending
EXIT_PLAN_MODE 常量 退出工具名称 'exit_plan_mode'
SessionEventMap['plan/mode'] 声明合并 计划模式事件:{ active: boolean }
SessionProjectionMap.plan 声明合并 计划投影键声明
resolveConfig() 函数 验证部署指导配置
foldPlanMode() 函数 从事件折叠计划模式状态

架构要点

  • 日志状态 :计划模式状态记录在会话日志中(plan/mode 事件),恢复和分叉无需活动镜像
  • 待定状态:用户选择在下一个接受的回合前步骤前保持待定
  • 工具目录稳定exit_plan_mode 工具在计划模式未激活时也保持注册,模式切换只改变提示段落
  • 审查交互:退出工具通过用户问题服务呈现审查选择(批准/继续计划)

goal

路径 : packages/goal/

核心作用 : 目标管理工具,提供 get_goalcreate_goalupdate_goal 模型面向工具,支持目标创建、完成和阻塞的状态管理。

架构图

#mermaid-svg-kMkbDlIJTtnfT6s3{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kMkbDlIJTtnfT6s3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kMkbDlIJTtnfT6s3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kMkbDlIJTtnfT6s3 .error-icon{fill:#552222;}#mermaid-svg-kMkbDlIJTtnfT6s3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kMkbDlIJTtnfT6s3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kMkbDlIJTtnfT6s3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kMkbDlIJTtnfT6s3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kMkbDlIJTtnfT6s3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kMkbDlIJTtnfT6s3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kMkbDlIJTtnfT6s3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kMkbDlIJTtnfT6s3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kMkbDlIJTtnfT6s3 .marker.cross{stroke:#333333;}#mermaid-svg-kMkbDlIJTtnfT6s3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kMkbDlIJTtnfT6s3 p{margin:0;}#mermaid-svg-kMkbDlIJTtnfT6s3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kMkbDlIJTtnfT6s3 .cluster-label text{fill:#333;}#mermaid-svg-kMkbDlIJTtnfT6s3 .cluster-label span{color:#333;}#mermaid-svg-kMkbDlIJTtnfT6s3 .cluster-label span p{background-color:transparent;}#mermaid-svg-kMkbDlIJTtnfT6s3 .label text,#mermaid-svg-kMkbDlIJTtnfT6s3 span{fill:#333;color:#333;}#mermaid-svg-kMkbDlIJTtnfT6s3 .node rect,#mermaid-svg-kMkbDlIJTtnfT6s3 .node circle,#mermaid-svg-kMkbDlIJTtnfT6s3 .node ellipse,#mermaid-svg-kMkbDlIJTtnfT6s3 .node polygon,#mermaid-svg-kMkbDlIJTtnfT6s3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kMkbDlIJTtnfT6s3 .rough-node .label text,#mermaid-svg-kMkbDlIJTtnfT6s3 .node .label text,#mermaid-svg-kMkbDlIJTtnfT6s3 .image-shape .label,#mermaid-svg-kMkbDlIJTtnfT6s3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-kMkbDlIJTtnfT6s3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kMkbDlIJTtnfT6s3 .rough-node .label,#mermaid-svg-kMkbDlIJTtnfT6s3 .node .label,#mermaid-svg-kMkbDlIJTtnfT6s3 .image-shape .label,#mermaid-svg-kMkbDlIJTtnfT6s3 .icon-shape .label{text-align:center;}#mermaid-svg-kMkbDlIJTtnfT6s3 .node.clickable{cursor:pointer;}#mermaid-svg-kMkbDlIJTtnfT6s3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kMkbDlIJTtnfT6s3 .arrowheadPath{fill:#333333;}#mermaid-svg-kMkbDlIJTtnfT6s3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kMkbDlIJTtnfT6s3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kMkbDlIJTtnfT6s3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kMkbDlIJTtnfT6s3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kMkbDlIJTtnfT6s3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kMkbDlIJTtnfT6s3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kMkbDlIJTtnfT6s3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kMkbDlIJTtnfT6s3 .cluster text{fill:#333;}#mermaid-svg-kMkbDlIJTtnfT6s3 .cluster span{color:#333;}#mermaid-svg-kMkbDlIJTtnfT6s3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kMkbDlIJTtnfT6s3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kMkbDlIJTtnfT6s3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-kMkbDlIJTtnfT6s3 .icon-shape,#mermaid-svg-kMkbDlIJTtnfT6s3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kMkbDlIJTtnfT6s3 .icon-shape p,#mermaid-svg-kMkbDlIJTtnfT6s3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kMkbDlIJTtnfT6s3 .icon-shape .label rect,#mermaid-svg-kMkbDlIJTtnfT6s3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kMkbDlIJTtnfT6s3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kMkbDlIJTtnfT6s3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kMkbDlIJTtnfT6s3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-kMkbDlIJTtnfT6s3 .tool>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-kMkbDlIJTtnfT6s3 .tool span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-kMkbDlIJTtnfT6s3 .tool tspan{fill:#fff!important;}#mermaid-svg-kMkbDlIJTtnfT6s3 .domain>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-kMkbDlIJTtnfT6s3 .domain span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-kMkbDlIJTtnfT6s3 .domain tspan{fill:#fff!important;}#mermaid-svg-kMkbDlIJTtnfT6s3 .auth>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-kMkbDlIJTtnfT6s3 .auth span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-kMkbDlIJTtnfT6s3 .auth tspan{fill:#fff!important;} 权限模型
goal 领域
tool-goal
Goal Tools

目标工具集
Authority

权限检查
Wrapup

收尾指令
GoalView

目标视图
GoalId

目标ID
GoalRef

目标引用
Goals Service

目标服务
direct-human

直接人类输入
goal-round

目标回合

关键类/函数表

名称 类型 职责
goalToolExecution() 函数 认证调用代理和驱动边界
requireDirectHuman() 函数 要求直接人类输入权限
completionAuthority() 函数 解析完成权限:直接人类或目标回合
GoalToolAuthority 类型 权限联合:direct-human
renderWrapupContext() 函数 渲染终端自主目标更新的收尾指令
GoalView 接口 目标视图:id、revision、roundsStarted
GoalId 品牌类型 Branded<'GoalId'>

架构要点

  • 权限模型:目标操作需要权限------直接人类输入或当前目标回合
  • 驱动边界检查goalToolExecution() 验证调用代理是当前活动驱动发起者
  • 收尾指令:自主目标回合结束后注入收尾上下文,让模型向用户致辞
  • 回合匹配 :通过 isMatchingGoalRound() 验证当前回合是否为目标许可回合

feedback

路径 : packages/feedback/

核心作用 : 会话反馈机制,包括 /feedback 命令(追加 feedback/record 事件)和消息级反馈(持久化到存储域)。

架构图

#mermaid-svg-R45az4kWlrHStOnd{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-R45az4kWlrHStOnd .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-R45az4kWlrHStOnd .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-R45az4kWlrHStOnd .error-icon{fill:#552222;}#mermaid-svg-R45az4kWlrHStOnd .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-R45az4kWlrHStOnd .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-R45az4kWlrHStOnd .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-R45az4kWlrHStOnd .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-R45az4kWlrHStOnd .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-R45az4kWlrHStOnd .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-R45az4kWlrHStOnd .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-R45az4kWlrHStOnd .marker{fill:#333333;stroke:#333333;}#mermaid-svg-R45az4kWlrHStOnd .marker.cross{stroke:#333333;}#mermaid-svg-R45az4kWlrHStOnd svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-R45az4kWlrHStOnd p{margin:0;}#mermaid-svg-R45az4kWlrHStOnd .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-R45az4kWlrHStOnd .cluster-label text{fill:#333;}#mermaid-svg-R45az4kWlrHStOnd .cluster-label span{color:#333;}#mermaid-svg-R45az4kWlrHStOnd .cluster-label span p{background-color:transparent;}#mermaid-svg-R45az4kWlrHStOnd .label text,#mermaid-svg-R45az4kWlrHStOnd span{fill:#333;color:#333;}#mermaid-svg-R45az4kWlrHStOnd .node rect,#mermaid-svg-R45az4kWlrHStOnd .node circle,#mermaid-svg-R45az4kWlrHStOnd .node ellipse,#mermaid-svg-R45az4kWlrHStOnd .node polygon,#mermaid-svg-R45az4kWlrHStOnd .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-R45az4kWlrHStOnd .rough-node .label text,#mermaid-svg-R45az4kWlrHStOnd .node .label text,#mermaid-svg-R45az4kWlrHStOnd .image-shape .label,#mermaid-svg-R45az4kWlrHStOnd .icon-shape .label{text-anchor:middle;}#mermaid-svg-R45az4kWlrHStOnd .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-R45az4kWlrHStOnd .rough-node .label,#mermaid-svg-R45az4kWlrHStOnd .node .label,#mermaid-svg-R45az4kWlrHStOnd .image-shape .label,#mermaid-svg-R45az4kWlrHStOnd .icon-shape .label{text-align:center;}#mermaid-svg-R45az4kWlrHStOnd .node.clickable{cursor:pointer;}#mermaid-svg-R45az4kWlrHStOnd .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-R45az4kWlrHStOnd .arrowheadPath{fill:#333333;}#mermaid-svg-R45az4kWlrHStOnd .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-R45az4kWlrHStOnd .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-R45az4kWlrHStOnd .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-R45az4kWlrHStOnd .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-R45az4kWlrHStOnd .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-R45az4kWlrHStOnd .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-R45az4kWlrHStOnd .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-R45az4kWlrHStOnd .cluster text{fill:#333;}#mermaid-svg-R45az4kWlrHStOnd .cluster span{color:#333;}#mermaid-svg-R45az4kWlrHStOnd div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-R45az4kWlrHStOnd .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-R45az4kWlrHStOnd rect.text{fill:none;stroke-width:0;}#mermaid-svg-R45az4kWlrHStOnd .icon-shape,#mermaid-svg-R45az4kWlrHStOnd .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-R45az4kWlrHStOnd .icon-shape p,#mermaid-svg-R45az4kWlrHStOnd .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-R45az4kWlrHStOnd .icon-shape .label rect,#mermaid-svg-R45az4kWlrHStOnd .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-R45az4kWlrHStOnd .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-R45az4kWlrHStOnd .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-R45az4kWlrHStOnd :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-R45az4kWlrHStOnd .cmd>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-R45az4kWlrHStOnd .cmd span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-R45az4kWlrHStOnd .cmd tspan{fill:#fff!important;}#mermaid-svg-R45az4kWlrHStOnd .msg>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-R45az4kWlrHStOnd .msg span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-R45az4kWlrHStOnd .msg tspan{fill:#fff!important;}#mermaid-svg-R45az4kWlrHStOnd .tele>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-R45az4kWlrHStOnd .tele span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-R45az4kWlrHStOnd .tele tspan{fill:#fff!important;} 遥测集成
command-feedback
message-feedback
MessageFeedback

消息反馈
Spec

存储规格
MessageFeedbackItem

反馈项
Storage Domain

存储域
feedback 命令

反馈命令
recordFeedback

记录反馈
feedback/record

反馈事件
SessionTelemetry

遥测
SharingDisclosure

共享披露

关键类/函数表

名称 类型 职责
recordFeedback() 函数 记录反馈到会话日志(feedback/record 事件)
executeFeedbackCommand() 函数 执行 /feedback 命令:验证、记录、确认
sharingDisclosure() 函数 生成共享策略披露文本
MessageFeedbackItem 接口 消息反馈项:messageId、rating、note、version
MessageFeedbackRating 类型 评分:positive
messageFeedbackRowSchema Zod 模式 消息反馈行持久化模式
messageFeedbackItemSchema Zod 模式 反馈项模式,含时间戳一致性验证

架构要点

  • 双层反馈 :会话级反馈(feedback/record 事件,追加到会话日志)和消息级反馈(独立存储域 sidecar)
  • 共享披露/feedback 确认包含会话共享策略状态(full/feedback-only/disabled
  • 匿名用户:反馈确认包含匿名用户 ID
  • 消息反馈存储域:消息级反馈使用独立存储域,按会话生命周期隔离

schedule

路径 : packages/schedule/

核心作用: 调度系统,为根 Agent 提供一次性提醒和重复提醒能力。使用实时计时器投影和事务序列化确保调度一致性。

架构图

#mermaid-svg-MlO7UUvqx9X8hPg1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-MlO7UUvqx9X8hPg1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-MlO7UUvqx9X8hPg1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-MlO7UUvqx9X8hPg1 .error-icon{fill:#552222;}#mermaid-svg-MlO7UUvqx9X8hPg1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-MlO7UUvqx9X8hPg1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-MlO7UUvqx9X8hPg1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-MlO7UUvqx9X8hPg1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-MlO7UUvqx9X8hPg1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-MlO7UUvqx9X8hPg1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-MlO7UUvqx9X8hPg1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-MlO7UUvqx9X8hPg1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-MlO7UUvqx9X8hPg1 .marker.cross{stroke:#333333;}#mermaid-svg-MlO7UUvqx9X8hPg1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-MlO7UUvqx9X8hPg1 p{margin:0;}#mermaid-svg-MlO7UUvqx9X8hPg1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-MlO7UUvqx9X8hPg1 .cluster-label text{fill:#333;}#mermaid-svg-MlO7UUvqx9X8hPg1 .cluster-label span{color:#333;}#mermaid-svg-MlO7UUvqx9X8hPg1 .cluster-label span p{background-color:transparent;}#mermaid-svg-MlO7UUvqx9X8hPg1 .label text,#mermaid-svg-MlO7UUvqx9X8hPg1 span{fill:#333;color:#333;}#mermaid-svg-MlO7UUvqx9X8hPg1 .node rect,#mermaid-svg-MlO7UUvqx9X8hPg1 .node circle,#mermaid-svg-MlO7UUvqx9X8hPg1 .node ellipse,#mermaid-svg-MlO7UUvqx9X8hPg1 .node polygon,#mermaid-svg-MlO7UUvqx9X8hPg1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-MlO7UUvqx9X8hPg1 .rough-node .label text,#mermaid-svg-MlO7UUvqx9X8hPg1 .node .label text,#mermaid-svg-MlO7UUvqx9X8hPg1 .image-shape .label,#mermaid-svg-MlO7UUvqx9X8hPg1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-MlO7UUvqx9X8hPg1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-MlO7UUvqx9X8hPg1 .rough-node .label,#mermaid-svg-MlO7UUvqx9X8hPg1 .node .label,#mermaid-svg-MlO7UUvqx9X8hPg1 .image-shape .label,#mermaid-svg-MlO7UUvqx9X8hPg1 .icon-shape .label{text-align:center;}#mermaid-svg-MlO7UUvqx9X8hPg1 .node.clickable{cursor:pointer;}#mermaid-svg-MlO7UUvqx9X8hPg1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-MlO7UUvqx9X8hPg1 .arrowheadPath{fill:#333333;}#mermaid-svg-MlO7UUvqx9X8hPg1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-MlO7UUvqx9X8hPg1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-MlO7UUvqx9X8hPg1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MlO7UUvqx9X8hPg1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-MlO7UUvqx9X8hPg1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MlO7UUvqx9X8hPg1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-MlO7UUvqx9X8hPg1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-MlO7UUvqx9X8hPg1 .cluster text{fill:#333;}#mermaid-svg-MlO7UUvqx9X8hPg1 .cluster span{color:#333;}#mermaid-svg-MlO7UUvqx9X8hPg1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-MlO7UUvqx9X8hPg1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-MlO7UUvqx9X8hPg1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-MlO7UUvqx9X8hPg1 .icon-shape,#mermaid-svg-MlO7UUvqx9X8hPg1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-MlO7UUvqx9X8hPg1 .icon-shape p,#mermaid-svg-MlO7UUvqx9X8hPg1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-MlO7UUvqx9X8hPg1 .icon-shape .label rect,#mermaid-svg-MlO7UUvqx9X8hPg1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-MlO7UUvqx9X8hPg1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-MlO7UUvqx9X8hPg1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-MlO7UUvqx9X8hPg1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-MlO7UUvqx9X8hPg1 .core>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-MlO7UUvqx9X8hPg1 .core span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-MlO7UUvqx9X8hPg1 .core tspan{fill:#fff!important;}#mermaid-svg-MlO7UUvqx9X8hPg1 .type>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-MlO7UUvqx9X8hPg1 .type span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-MlO7UUvqx9X8hPg1 .type tspan{fill:#fff!important;}#mermaid-svg-MlO7UUvqx9X8hPg1 .runtime>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-MlO7UUvqx9X8hPg1 .runtime span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-MlO7UUvqx9X8hPg1 .runtime tspan{fill:#fff!important;}#mermaid-svg-MlO7UUvqx9X8hPg1 .persist>*{fill:#bd10e0!important;stroke:#9c0bb3!important;color:#fff!important;}#mermaid-svg-MlO7UUvqx9X8hPg1 .persist span{fill:#bd10e0!important;stroke:#9c0bb3!important;color:#fff!important;}#mermaid-svg-MlO7UUvqx9X8hPg1 .persist tspan{fill:#fff!important;} 持久化
运行时
调度类型
schedule 核心
ScheduleRuntime

调度运行时
runScheduleTransaction

事务序列化
Domain Logic

领域逻辑
OneShotSchedule

一次性调度
EverySchedule

重复调度
TimerProjection

计时器投影
DueDecision

到期决策
Drive Loop

驱动循环
flushSchedulePersistence

刷新持久化

关键类/函数表

名称 类型 职责
ScheduleRuntime 一次性实时计时器投影,驱动到期决策
runScheduleTransaction() 函数 Agent 级事务序列化
foldScheduleEvents() 函数 折叠调度事件为当前状态
resolveEveryOccurrence() 函数 解析重复调度的下一次发生
renderReminderFraming() 函数 渲染提醒框架文本
renderEveryReminderBatchFraming() 函数 渲染批量提醒框架
flushSchedulePersistence() 函数 刷新调度持久化
ScheduleLogError 调度日志错误
FoldedSchedules 接口 折叠后的调度状态:active 列表
DueDecision 类型 到期决策:one-shot/every/wait
MAX_TIMER_DELAY_MS 常量 Node 计时器最大延迟

架构要点

  • Agent 级序列化 :通过 WeakMap<Agent, Promise> 实现每 Agent 事务串行化
  • 到期决策dueDecision() 按优先级选择到期的一次性调度、批量到期重复调度、或等待下一次唤醒
  • 合并触发:多个触发合并到一次驱动循环,避免重复计算
  • 计时器管理:实时计时器投影,到期前清除并重设
  • 提醒框架:提醒消息使用 framing 文本包装,注入到 Agent inbox

jobs

路径 : packages/jobs/

核心作用: 后台任务能力,提供进程内作业注册表,支持任务启动、取消、等待和输出读取。

架构图

#mermaid-svg-rYzx0nWTs3CFoFKv{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rYzx0nWTs3CFoFKv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rYzx0nWTs3CFoFKv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rYzx0nWTs3CFoFKv .error-icon{fill:#552222;}#mermaid-svg-rYzx0nWTs3CFoFKv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rYzx0nWTs3CFoFKv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rYzx0nWTs3CFoFKv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rYzx0nWTs3CFoFKv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rYzx0nWTs3CFoFKv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rYzx0nWTs3CFoFKv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rYzx0nWTs3CFoFKv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rYzx0nWTs3CFoFKv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rYzx0nWTs3CFoFKv .marker.cross{stroke:#333333;}#mermaid-svg-rYzx0nWTs3CFoFKv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rYzx0nWTs3CFoFKv p{margin:0;}#mermaid-svg-rYzx0nWTs3CFoFKv .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rYzx0nWTs3CFoFKv .cluster-label text{fill:#333;}#mermaid-svg-rYzx0nWTs3CFoFKv .cluster-label span{color:#333;}#mermaid-svg-rYzx0nWTs3CFoFKv .cluster-label span p{background-color:transparent;}#mermaid-svg-rYzx0nWTs3CFoFKv .label text,#mermaid-svg-rYzx0nWTs3CFoFKv span{fill:#333;color:#333;}#mermaid-svg-rYzx0nWTs3CFoFKv .node rect,#mermaid-svg-rYzx0nWTs3CFoFKv .node circle,#mermaid-svg-rYzx0nWTs3CFoFKv .node ellipse,#mermaid-svg-rYzx0nWTs3CFoFKv .node polygon,#mermaid-svg-rYzx0nWTs3CFoFKv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rYzx0nWTs3CFoFKv .rough-node .label text,#mermaid-svg-rYzx0nWTs3CFoFKv .node .label text,#mermaid-svg-rYzx0nWTs3CFoFKv .image-shape .label,#mermaid-svg-rYzx0nWTs3CFoFKv .icon-shape .label{text-anchor:middle;}#mermaid-svg-rYzx0nWTs3CFoFKv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rYzx0nWTs3CFoFKv .rough-node .label,#mermaid-svg-rYzx0nWTs3CFoFKv .node .label,#mermaid-svg-rYzx0nWTs3CFoFKv .image-shape .label,#mermaid-svg-rYzx0nWTs3CFoFKv .icon-shape .label{text-align:center;}#mermaid-svg-rYzx0nWTs3CFoFKv .node.clickable{cursor:pointer;}#mermaid-svg-rYzx0nWTs3CFoFKv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rYzx0nWTs3CFoFKv .arrowheadPath{fill:#333333;}#mermaid-svg-rYzx0nWTs3CFoFKv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rYzx0nWTs3CFoFKv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rYzx0nWTs3CFoFKv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rYzx0nWTs3CFoFKv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rYzx0nWTs3CFoFKv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rYzx0nWTs3CFoFKv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rYzx0nWTs3CFoFKv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rYzx0nWTs3CFoFKv .cluster text{fill:#333;}#mermaid-svg-rYzx0nWTs3CFoFKv .cluster span{color:#333;}#mermaid-svg-rYzx0nWTs3CFoFKv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rYzx0nWTs3CFoFKv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rYzx0nWTs3CFoFKv rect.text{fill:none;stroke-width:0;}#mermaid-svg-rYzx0nWTs3CFoFKv .icon-shape,#mermaid-svg-rYzx0nWTs3CFoFKv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rYzx0nWTs3CFoFKv .icon-shape p,#mermaid-svg-rYzx0nWTs3CFoFKv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rYzx0nWTs3CFoFKv .icon-shape .label rect,#mermaid-svg-rYzx0nWTs3CFoFKv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rYzx0nWTs3CFoFKv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rYzx0nWTs3CFoFKv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rYzx0nWTs3CFoFKv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-rYzx0nWTs3CFoFKv .abs>*{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-rYzx0nWTs3CFoFKv .abs span{fill:#4a90d9!important;stroke:#357abd!important;color:#fff!important;}#mermaid-svg-rYzx0nWTs3CFoFKv .abs tspan{fill:#fff!important;}#mermaid-svg-rYzx0nWTs3CFoFKv .impl>*{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-rYzx0nWTs3CFoFKv .impl span{fill:#f5a623!important;stroke:#d48b0a!important;color:#fff!important;}#mermaid-svg-rYzx0nWTs3CFoFKv .impl tspan{fill:#fff!important;}#mermaid-svg-rYzx0nWTs3CFoFKv .scope>*{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-rYzx0nWTs3CFoFKv .scope span{fill:#7ed321!important;stroke:#5da018!important;color:#fff!important;}#mermaid-svg-rYzx0nWTs3CFoFKv .scope tspan{fill:#fff!important;} 作用域
jobs-local 实现
jobs 抽象层
JobRegistry

作业注册表抽象
JobId

品牌类型
JobSnapshot

作业快照
JobStart

启动规格
LocalJobRegistry

本地注册表
TrackedTask

追踪任务
ScopedLayers

作用域分层
JobLayer

作业层
Controllers

控制器
JobDoneListeners

完成监听器
JobsChangedListeners

变更监听器

关键类/函数表

名称 类型 职责
JobRegistry 抽象服务 作业注册表 ctx.jobs
LocalJobRegistry 进程内实现,内存存储所有记录
JobId 品牌类型 Branded<'JobId'>
JobSnapshot 接口 不可变快照:id、kind、label、status、output
JobStart 接口 启动规格:kind、label、owner、run()、outputLimitBytes
JobStatus 类型 running/stopping/completed/killed/failed
JobKind 类型 作业类型字符串
JobOutcome 类型 作业结果
JobDoneListener 类型 完成监听器
JobsChangedListener 类型 变更监听器
TrackedTask 接口 内部追踪记录(不对外暴露)
JobLayer 作用域层:控制器、监听器、变更通知
ScopedLayers 作用域分层管理
TASK_WAIT_TIMEOUT 常量 等待超时码
DEFAULT_MAX_CONCURRENT_TASKS_PER_OWNER 常量 默认每 owner 最大并发:10

架构要点

  • 作用域分层:作业控制器和监听器按注册上下文的作用域分层,读取是 owner 相对的
  • 快照隔离snapshot() 只返回不可变快照,永不返回活动状态
  • 并发限制:每 owner 最大并发作业数限制,超出拒绝
  • 生命周期独立:注册表记录比生产者和控制器光纤寿命更长
  • 清理钩子:Agent 或服务销毁时取消活动工作并等待合规生产者

相关推荐
Behaviour2 小时前
Unity AI 生态横评对比:官方 AI Beta / Unity CLI / 团结 Codely / 社区 MCP 四大阵营选型
人工智能·unity·ai·游戏引擎·aigc·ai编程
学习星球2 小时前
OpenHarness 全面配置教学——从游戏开发工作流引入
c++·游戏·ai·ai编程
catchadmin2 小时前
NativePHP v4 让 Blade 构建原生 iOS 与 Android 界面
android·ios·ai·php
DS随心转小程序2 小时前
AI pdf 数字化文档落地攻略,靠 AI 导出鸭补齐转换短板,从痛点到实测详解智能化文档导出逻辑
人工智能·豆包·deepseek·ai导出鸭
进阶的小名2 小时前
Spring AI 2.0 探索:多 OpenAI-Compatible 模型接入,以及下一代 Session 记忆管理
java·人工智能·后端·gpt·spring·ai·chatgpt
uncle_ll3 小时前
LlamaIndex 全栈实战指南:架构解构、RAG 核心原理与私有知识库工程化落地方案
架构·llm·agent·rag·llamaindex
新知图书3 小时前
8.4 处理智能体的工具调用与输出解析《LangGraph开发AI Agent实践》
人工智能·agent·ai agent·智能体
玫瑰互动GEO3 小时前
海外GEO优化案例-ChatGPT搜索关键词排名GEO优化案例详解(含RAG机制与Tokenization技术拆解)
人工智能·ai·chatgpt·geo优化
冬奇Lab3 小时前
Code Agent 解剖(10):agent 崩了怎么恢复,对话历史存在哪?
人工智能·开源·agent