Clarify DeepSeek Harness architecture

This commit is contained in:
wuyang6
2026-08-14 11:23:05 +08:00
parent a03dc0e1e4
commit de38186ff4
4 changed files with 386 additions and 50 deletions
@@ -0,0 +1,84 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="860" viewBox="0 0 1440 860" role="img" aria-labelledby="title desc">
<title id="title">DeepSeek Harness greet 请求调用图</title>
<desc id="desc">用户请求进入已经启动的 Agent,模型调用 greet 工具并返回结果;SessionEvent 在下方记录事实,但不是调用链的下一跳。</desc>
<defs>
<style>
.bg { fill: #f7f4ec; }
.title { font: 700 30px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #183a34; }
.subtitle { font: 400 18px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #60706a; }
.box { fill: #fffdf8; stroke: #286458; stroke-width: 2; rx: 18; }
.focus { fill: #fff2df; stroke: #ca6715; stroke-width: 2.4; rx: 18; }
.event { fill: #edf5f1; stroke: #557b72; stroke-width: 2; rx: 18; }
.label { font: 650 19px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #1f413a; }
.body { font: 400 16px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #354c47; }
.small { font: 400 15px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #66766f; }
.solid { stroke: #286458; stroke-width: 3; fill: none; marker-end: url(#arrow); }
.return { stroke: #ca6715; stroke-width: 3; fill: none; marker-end: url(#arrow-orange); }
.dash { stroke: #7a8c86; stroke-width: 2.2; stroke-dasharray: 8 8; fill: none; marker-end: url(#arrow-gray); }
</style>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L0,6 L9,3 z" fill="#286458"/></marker>
<marker id="arrow-orange" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L0,6 L9,3 z" fill="#ca6715"/></marker>
<marker id="arrow-gray" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L0,6 L9,3 z" fill="#7a8c86"/></marker>
</defs>
<rect class="bg" width="1440" height="860" rx="32"/>
<text class="title" x="64" y="64">一次 greet 请求:消息在已启动的组件之间怎样移动</text>
<text class="subtitle" x="64" y="98">这是一张运行时调用图;Profile、Bundle 和 Fiber 装配已经完成。</text>
<rect class="box" x="58" y="168" width="180" height="106"/>
<text class="label" x="82" y="207">用户入口</text>
<text class="body" x="82" y="238">Web / ACP / SDK</text>
<rect class="box" x="288" y="168" width="180" height="106"/>
<text class="label" x="312" y="207">Agent inbox</text>
<text class="body" x="312" y="238">“向 Ada 问好”</text>
<rect class="box" x="518" y="150" width="220" height="142"/>
<text class="label" x="542" y="190">Agent loop</text>
<text class="body" x="542" y="222">组装历史、系统提示</text>
<text class="body" x="542" y="248">和可用工具 schema</text>
<rect class="focus" x="788" y="150" width="220" height="142"/>
<text class="label" x="812" y="190">LLM</text>
<text class="body" x="812" y="222">决定调用工具:</text>
<text class="body" x="812" y="250">greet({ name: "Ada" })</text>
<rect class="box" x="1058" y="132" width="320" height="178"/>
<text class="label" x="1082" y="170">Guarded tool pipeline</text>
<text class="body" x="1082" y="204">pre-execute → approval → guard</text>
<text class="body" x="1082" y="232">→ execute → post-execute → result</text>
<text class="small" x="1082" y="268">最终调用 greet handler</text>
<path class="solid" d="M238 221 H280"/>
<path class="solid" d="M468 221 H510"/>
<path class="solid" d="M738 221 H780"/>
<path class="solid" d="M1008 221 H1050"/>
<rect class="focus" x="1058" y="374" width="320" height="112"/>
<text class="label" x="1082" y="414">greet 工具返回</text>
<text class="body" x="1082" y="450">“Hello, Ada!”</text>
<path class="return" d="M1218 310 V366"/>
<rect class="box" x="788" y="374" width="220" height="112"/>
<text class="label" x="812" y="414">LLM 继续生成</text>
<text class="body" x="812" y="450">把工具结果写成回答</text>
<path class="return" d="M1058 430 H1016"/>
<rect class="box" x="518" y="374" width="220" height="112"/>
<text class="label" x="542" y="414">Agent loop 收束</text>
<text class="body" x="542" y="450">提交 assistant/message</text>
<path class="return" d="M788 430 H746"/>
<rect class="box" x="288" y="374" width="180" height="112"/>
<text class="label" x="312" y="414">用户收到回答</text>
<text class="body" x="312" y="450">“已向 Ada 问好”</text>
<path class="return" d="M518 430 H476"/>
<rect class="event" x="140" y="610" width="1160" height="156"/>
<text class="label" x="170" y="650">SessionEvent 日志:记录旁路,不是请求的“下一跳”</text>
<text class="body" x="170" y="687">用户消息、step/start、模型消息、工具调用、工具结果和最终回答分别追加为 durable facts。</text>
<text class="body" x="170" y="719">历史重建、resume、fork、故障修复和 UI 投影都从这些事实派生。</text>
<path class="dash" d="M378 274 C378 430 380 520 444 600"/>
<path class="dash" d="M1218 486 C1218 540 1130 560 1080 602"/>
<path class="dash" d="M628 486 C628 545 650 565 676 602"/>
<text class="small" x="66" y="824">记忆锚点:Agent loop 决定“下一步做什么”;Tools 执行“具体动作”;SessionEvent 记录“发生过什么”。</text>
</svg>

After

Width:  |  Height:  |  Size: 5.4 KiB

@@ -0,0 +1,80 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="860" viewBox="0 0 1440 860" role="img" aria-labelledby="title desc">
<title id="title">DeepSeek Harness 协议边界图</title>
<desc id="desc">Web、ACP 和 SDK 从外部驱动 Agent;MCP 把外部工具接入 Tools;Cordis 位于 dsh 的 Node 进程内部,负责组件装配而不是远程通信。</desc>
<defs>
<style>
.bg { fill: #f7f4ec; }
.title { font: 700 30px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #183a34; }
.subtitle { font: 400 18px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #60706a; }
.outside { fill: #fffdf8; stroke: #70817b; stroke-width: 2; rx: 18; }
.inside { fill: #edf5f1; stroke: #286458; stroke-width: 2; rx: 18; }
.boundary { fill: none; stroke: #286458; stroke-width: 3; stroke-dasharray: 12 8; rx: 26; }
.focus { fill: #fff2df; stroke: #ca6715; stroke-width: 2.4; rx: 18; }
.label { font: 650 20px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #1f413a; }
.body { font: 400 16px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #354c47; }
.small { font: 400 15px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #66766f; }
.arrow { stroke: #286458; stroke-width: 3; fill: none; marker-end: url(#arrow); }
.bi { stroke: #ca6715; stroke-width: 3; fill: none; marker-start: url(#arrow-orange-start); marker-end: url(#arrow-orange); }
</style>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L0,6 L9,3 z" fill="#286458"/></marker>
<marker id="arrow-orange" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L0,6 L9,3 z" fill="#ca6715"/></marker>
<marker id="arrow-orange-start" markerWidth="10" markerHeight="10" refX="1" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M9,0 L9,6 L0,3 z" fill="#ca6715"/></marker>
</defs>
<rect class="bg" width="1440" height="860" rx="32"/>
<text class="title" x="64" y="64">协议边界:谁从哪里接进 Harness</text>
<text class="subtitle" x="64" y="98">先看进程边界,再看协议名称;Cordis 位于 dsh 进程内部,不是远程协议。</text>
<text class="small" x="62" y="150">dsh 进程外:驱动端</text>
<rect class="outside" x="60" y="176" width="260" height="116"/>
<text class="label" x="86" y="216">浏览器</text>
<text class="body" x="86" y="250">产品 UI 和交互</text>
<rect class="outside" x="60" y="342" width="260" height="116"/>
<text class="label" x="86" y="382">ACP Client</text>
<text class="body" x="86" y="416">编辑器或另一个 Agent</text>
<rect class="outside" x="60" y="508" width="260" height="116"/>
<text class="label" x="86" y="548">Python / TS 程序</text>
<text class="body" x="86" y="582">自动化、批量任务、评测器</text>
<rect class="boundary" x="420" y="132" width="680" height="604"/>
<text class="label" x="450" y="170">dsh:TypeScript / Node.js 进程</text>
<rect class="inside" x="466" y="202" width="250" height="92"/>
<text class="label" x="490" y="240">Web adapter</text>
<text class="body" x="490" y="268">HTTP POST / WebSocket</text>
<rect class="inside" x="466" y="342" width="250" height="92"/>
<text class="label" x="490" y="380">ACP adapter</text>
<text class="body" x="490" y="408">ACP JSON-RPC over stdio</text>
<rect class="inside" x="466" y="482" width="250" height="92"/>
<text class="label" x="490" y="520">SDK server</text>
<text class="body" x="490" y="548">line JSON-RPC 2.0 over stdio</text>
<rect class="focus" x="792" y="274" width="250" height="118"/>
<text class="label" x="816" y="314">Agent loop</text>
<text class="body" x="816" y="346">Web / ACP / SDK</text>
<text class="body" x="816" y="370">都从外部驱动整个 Agent</text>
<rect class="focus" x="792" y="454" width="250" height="118"/>
<text class="label" x="816" y="494">Tools registry</text>
<text class="body" x="816" y="526">本地工具与 MCP 工具</text>
<text class="body" x="816" y="550">以统一名称注册</text>
<rect class="inside" x="548" y="634" width="414" height="68"/>
<text class="label" x="572" y="676">Cordis:装配并管理以上进程内插件</text>
<path class="arrow" d="M320 234 H458"/>
<path class="arrow" d="M320 400 H458"/>
<path class="arrow" d="M320 566 H458"/>
<path class="arrow" d="M716 248 C760 248 760 316 784 326"/>
<path class="arrow" d="M716 388 H784"/>
<path class="arrow" d="M716 528 C760 528 760 364 784 350"/>
<path class="arrow" d="M917 392 V446"/>
<text class="small" x="1146" y="150">dsh 进程外:能力提供端</text>
<rect class="outside" x="1140" y="342" width="250" height="146"/>
<text class="label" x="1166" y="382">MCP Server</text>
<text class="body" x="1166" y="416">stdio 或 Streamable HTTP</text>
<text class="small" x="1166" y="450">当前只桥接 Tools</text>
<path class="bi" d="M1042 512 C1094 512 1094 420 1132 420"/>
<rect class="outside" x="120" y="778" width="1200" height="54"/>
<text class="body" x="148" y="812">记忆锚点:Web / ACP / SDK 把“请求”送进 Agent;MCP 把“工具”送进 Tools;Cordis 只负责 dsh 进程内的组装与生命周期。</text>
</svg>

After

Width:  |  Height:  |  Size: 5.3 KiB

@@ -0,0 +1,93 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="860" viewBox="0 0 1440 860" role="img" aria-labelledby="title desc">
<title id="title">DeepSeek Harness 启动装配图</title>
<desc id="desc">Profile、Bundle 和 patch 先形成有效配置,Cordis Loader 再创建插件 Fiber;虚线表示服务依赖,不表示请求调用顺序。</desc>
<defs>
<style>
.bg { fill: #f7f4ec; }
.title { font: 700 30px -apple-system, BlinkMacSystemFont, "PingFang SC", "Noto Sans CJK SC", sans-serif; fill: #183a34; }
.subtitle { font: 400 18px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #60706a; }
.box { fill: #fffdf8; stroke: #286458; stroke-width: 2; rx: 18; }
.config { fill: #edf5f1; stroke: #286458; stroke-width: 2; rx: 16; }
.focus { fill: #fff2df; stroke: #ca6715; stroke-width: 2.4; rx: 18; }
.pending { fill: #fff9e8; stroke: #aa7a12; stroke-width: 2; rx: 18; }
.label { font: 650 20px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #1f413a; }
.body { font: 400 17px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #354c47; }
.small { font: 400 15px -apple-system, BlinkMacSystemFont, "PingFang SC", sans-serif; fill: #66766f; }
.solid { stroke: #286458; stroke-width: 3; fill: none; marker-end: url(#arrow); }
.dash { stroke: #b17220; stroke-width: 2.5; stroke-dasharray: 9 8; fill: none; marker-end: url(#arrow-orange); }
.divider { stroke: #cdd8d2; stroke-width: 1.5; }
</style>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L0,6 L9,3 z" fill="#286458"/></marker>
<marker id="arrow-orange" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L0,6 L9,3 z" fill="#b17220"/></marker>
</defs>
<rect class="bg" width="1440" height="860" rx="32"/>
<text class="title" x="64" y="64">启动装配:谁被创建、谁等待谁</text>
<text class="subtitle" x="64" y="98">这是一张依赖和生命周期图,不是一次用户请求的调用顺序。</text>
<text class="small" x="66" y="143">第一步:多层配置合成最终插件清单</text>
<rect class="config" x="64" y="165" width="240" height="102"/>
<text class="label" x="88" y="201">Bundle</text>
<text class="body" x="88" y="232">可复用的默认插件组合</text>
<rect class="config" x="344" y="165" width="240" height="102"/>
<text class="label" x="368" y="201">Profile patch</text>
<text class="body" x="368" y="232">为某种产品形态做选择</text>
<rect class="config" x="624" y="165" width="240" height="102"/>
<text class="label" x="648" y="201">Harness home patch</text>
<text class="body" x="648" y="232">用户或部署环境覆盖</text>
<rect class="config" x="904" y="165" width="210" height="102"/>
<text class="label" x="928" y="201">CLI --patch</text>
<text class="body" x="928" y="232">本次启动覆盖</text>
<rect class="focus" x="1154" y="165" width="222" height="102"/>
<text class="label" x="1178" y="201">有效配置行</text>
<text class="body" x="1178" y="232">按稳定 id 得到结果</text>
<path class="solid" d="M304 216 H336"/>
<path class="solid" d="M584 216 H616"/>
<path class="solid" d="M864 216 H896"/>
<path class="solid" d="M1114 216 H1146"/>
<text class="small" x="1065" y="292">后层命中同一 id 时,整段 config 替换,不做深合并</text>
<line class="divider" x1="64" y1="326" x2="1376" y2="326"/>
<text class="small" x="66" y="371">第二步:Loader 为配置行创建 Fiber;Fiber 是否启动由服务依赖决定</text>
<path class="solid" d="M1000 364 H1050"/>
<text class="small" x="1060" y="370">Loader 创建 Fiber</text>
<path class="dash" d="M1212 364 H1262"/>
<text class="small" x="1272" y="370">消费者 → 提供方</text>
<rect class="focus" x="524" y="394" width="392" height="92"/>
<text class="label" x="550" y="430">Root Context + Loader</text>
<text class="body" x="550" y="460">读取有效配置,为每一行挂载运行实例 Fiber</text>
<rect class="box" x="70" y="560" width="245" height="128"/>
<text class="label" x="94" y="598">LLM provider Fiber</text>
<text class="body" x="94" y="630">提供 ctx.llm</text>
<text class="small" x="94" y="660">ACTIVE</text>
<rect class="box" x="370" y="560" width="245" height="128"/>
<text class="label" x="394" y="598">Tools provider Fiber</text>
<text class="body" x="394" y="630">提供 ctx.tools</text>
<text class="small" x="394" y="660">ACTIVE</text>
<rect class="pending" x="670" y="560" width="245" height="128"/>
<text class="label" x="694" y="598">greet-tool Fiber</text>
<text class="body" x="694" y="630">inject: tools</text>
<text class="small" x="694" y="660">PENDING → ACTIVE</text>
<rect class="pending" x="970" y="540" width="330" height="168"/>
<text class="label" x="994" y="578">Agent loop Fiber</text>
<text class="body" x="994" y="610">inject: agents, sessions,</text>
<text class="body" x="994" y="638">llm, tools, systemPrompt</text>
<text class="small" x="994" y="674">依赖齐全后才能处理请求</text>
<path class="solid" d="M650 486 L206 550"/>
<path class="solid" d="M690 486 L500 550"/>
<path class="solid" d="M750 486 L792 550"/>
<path class="solid" d="M810 486 L1110 530"/>
<path class="dash" d="M670 624 H625"/>
<text class="small" x="628" y="610">等待 tools</text>
<path class="dash" d="M970 592 C850 505 350 500 248 551"/>
<text class="small" x="625" y="516">等待 llm</text>
<path class="dash" d="M970 650 C860 710 694 720 600 676"/>
<text class="small" x="735" y="744">等待 tools 等服务</text>
<rect class="config" x="64" y="770" width="1312" height="58"/>
<text class="body" x="88" y="806">记忆锚点:配置行决定“挂载什么”;inject 决定“何时能启动”;Fiber/effect 决定“变化时怎样卸载和重建”。</text>
</svg>

After

Width:  |  Height:  |  Size: 5.9 KiB