Reference

从零复刻 DSH:完整实施蓝图

配套参考页:用于实现与源码精读时反复查阅。

目标:如果你不复制官方源码,而是从空目录开始重建一个架构等价的 DSH,这一页就是实施蓝图。

1. 先定仓库边界,不要先写 UI

建议把“稳定契约”和“可替换实现”拆成独立 package。下面不是官方目录的逐字复制,而是根据 DSH 的能力 seam 抽出的学习型等价结构。

packages/
  core/
    context/          # plugin/effect/scope runtime facade
    session/          # append-only events + projection
    agent/            # Agent interface + registry + factory contract
    agent-loop/       # only concrete turn/step driver
    tools/            # definition registry + guarded pipeline
    system-prompt/    # sections/variables/tool-schema assembly
    llm/              # request/message/stream vocabulary + adapter registry
  providers/
    llm-deepseek/
    fs-local/
    shell-local/
    session-jsonl/
    session-sqlite/
  consumers/
    tool-read/
    tool-bash/
    tool-terminal/
  boot/
    app-boot/
    profile-loader/
apps/
  headless/
  web/

2. 七个先冻结的接口

接口必须稳定的内容暂时不要冻结
Sessionappend、events、deriveMessages、fork/resume 边界具体磁盘格式
Agentid、ctx、send/cancel/whenIdle、registry lifecycle具体 loop class
LLMModelRequest、StreamChunk、LlmErrorprovider wire JSON
ToolsToolDefinition、visibility、execute pipelinebash/read 的实现
Promptsection/variable/tool schema assembly具体 persona 文案
Scopeglobal → agent 的解析规则UI 状态
Boot配置层合成 → 插件树 → rollback某个 profile 名称

3. Session 数据结构:先设计事件,再设计类

type SessionEvent = {
  seq: number
  time: number
  type: string
  data: JsonValue
  ignorable?: true
}

interface Session {
  readonly id: string
  append(type: string, data: JsonValue, meta?: SurfaceMeta): SessionEvent
  deriveMessages(): ModelMessage[]
  snapshot(): readonly SessionEvent[]
}

关键规则:seq 单调;事件一旦 append 就不可改;未知且非 ignorable 的事件在恢复时拒绝;所有模型可见输入必须存在可回放来源。

4. Agent 发布事务

prepare session
prepare scoped context
prepare concrete agent
run setup(scope)
validate commit hooks
enter session registry
enter agent registry
announce session/created
announce agent/created
start driver

on any failure:
  stop private driver if started
  dispose scope
  detach exact agent entry
  detach exact session entry

不要把“创建对象”与“让其他组件看见对象”混在一起。publication boundary 是竞争条件和回滚正确性的中心。

5. Turn/Step driver 的最小状态机

wake -> running
open turn
claim inbox batch
pre-step waterfall
if rejected: close turn
else:
  repeat:
    open step
    derive history from log
    assemble prompt + visible tools
    request model
    persist raw chunks + final assistant anchor
    execute proposed tools through guarded pipeline
    close step
    claim follow-up / steering
  until no work remains
turn-stopping serial checkpoint
close turn
flush durability
idle

6. 工具执行必须有“权威执行点”

工具调用从模型出来后不能直接 definition.execute()。所有调用必须穿过同一个 pipeline,才能统一实现审批、沙箱、超时、审计、结果规范化和取消。任何绕过这个执行点的“方便 API”都会成为安全漏洞。

7. LLM streaming 设计

Adapter 输出应是闭合 discriminated union;Loop 记录 raw chunk 以保证 UI fidelity,同时由共享 assembler 折叠成最终 assistant message。不要让每个 provider 自己决定 Session 怎么记。

8. Scope 的最低验收

同时创建 A/B 两个 agent:全局注册 read;仅 A scoped 注册 bash;仅 B scoped persona 改名。A 的 prompt/tools 不应污染 B。销毁 A 后,B 仍正常运行,且全局 registry 不残留 A 的 effect。

9. Boot/Config 的最低验收

  1. 基础 bundle 提供默认 LLM、tools、persistence。
  2. profile patch 能替换 LLM provider。
  3. CLI overlay 能临时关闭一个工具。
  4. 任何挂载失败都会 dispose 已成功挂载的前置插件。
  5. dump-config 的结果与实际 mount tree 一致。

10. 生产级补齐顺序

阶段新增先写的测试
P0mock LLM + 1 tool + event log两 step 工具循环
P1scoped context两个 agent 能力隔离
P2DeepSeek stream adapterchunk 组装与 abort
P3JSONL persistence/resume重启后模型历史等价
P4tool policy/scheduler独占与并行顺序
P5profile/bundle/patchprovider 仅靠配置替换
P6Web projection刷新 UI 不改变事实状态
P7HMR / lifecycle hardening反复 reload 无资源泄漏

11. 一模一样的真正判据

不要用“页面像不像”验收。用契约验收:事件语义、scope 隔离、provider 可替换、失败回滚、持久恢复、取消传播、工具调度、配置叠层。如果这些行为一致,才是 harness 层面的等价;UI 只是最后一层。