第 10 章 扩展实战:新行为挂在哪

dsh 的扩展哲学:新行为附加到已有文档记录的扩展点。本章整理官方架构文档中的"归属映射"与扩展实操手册索引。

10.1 扩展点归属映射

我想……目标机制
添加模型提供方在 ctx.llm 上注册其适配器
添加面向模型的能力在 ctx.tools 上注册;其 schema 加入提示词组装
让某个会话拥有不同的能力集合组装一个 agent preset;其中的服务行需要 isolate realm
添加 shell 执行注册 ctx.shell 后端;本地后端通过 ctx.subprocess spawn 进程
添加持久化终端执行注册 ctx.terminals 后端和 dsh-tool-terminal
添加用户命令在 ctx.commands 上注册;它无需模型轮次即可分派
添加后台工作在 ctx.jobs 上注册;job_* 工具负责收集或停止
从外部 webhook 启动 Session在 ctx.webhookRuntime 上注册可信规则,并挂载提供方适配器
添加文件系统访问或策略注册 ctx.fs 提供方,或监听 fs/* 事件
限制所启动的进程使用 ctx.sandbox 后端;消费方在启动进程前包装 argv
拦截请求、工具或轮次使用相应的 agent/* 或 tools/* 事件;agent/turn-stopping 会停止轮次
添加模型可见上下文调用 agent.inject();它会落到下一次获准的请求中
添加 UI 或编辑器集成驱动 ctx.agents 并从 session/event 渲染
添加 Web Client Chat 节点注册 ConversationNodeDefinition + keyed renderer
添加持久会话状态扩展 SessionEventMap;从日志渲染和回放
生成会话标题注册唯一的 ctx.sessionTitle 提供方
管理同会话目标使用 ctx.goals;通过 agent/* 续跑
在轮次边界 fork 会话ctx.agents.create({ sessionId, seed, meta: { parentSession, seedLength } })——只有经 agent-loop 发布的会话才会持久化
在新后端存储会话基于共享的句柄脚手架实现 SessionPersistence(create/open/stat/list/export)
将注册项限定到单个 agent使用该 agent 的 agent.ctx

10.2 三个事件域再强调

改动的第一个决定通常是选对事件域:

  • 会话事件:追加到日志、经 session/event 广播的持久事实——当某个事实必须在重新加载后仍然存在时使用;

  • Agent 事件(agent/*):携带活跃 Agent 的实时扩展点——观察或拦截进行中的工作;

  • 能力事件:向 seam(fs/*、tools/*、telemetry/*)附加策略和适配器,无需导入循环。

10.3 官方实操手册(Cookbook)索引

官方 扩展实操手册 将功能映射到能力,并索引了分步指南:

10.4 设计一个新 Seam 的检查清单

结合第 9 章的三角色定义,添加一项能力时应当:

  1. Service Definition:声明接口与 ctx.<key>(注意扁平命名空间,起有辨识度的名字);

  2. Service Provider:实现接口,通过声明合并把 key 加进 Context 接口类型;

  3. Consumer:通常是面向模型的工具,用 inject 声明硬依赖,或用 ctx.get() 探测可选依赖;

  4. 每个 ctx.effect()/ctx.on()/注册调用都要保证可逆(自带 disposer 或返回一个);

  5. "模型可见即已记录":凡是会进入模型请求的内容,必须新增一个会话事件并从日志渲染;

  6. waterfall 监听器若只做观察/标注,必须调用 next()。

10.5 如何决定"用事件还是用服务"

官方实践规则一句话:

拦截和策略优先使用事件;直接能力调用优先使用服务方法。

  • 想在别人做事的前后观察/包装/否决 → 监听 agent/*、tools/*、fs/* 等事件;

  • 想主动调用一项能力 → 通过 ctx.<key> 直接调用服务方法。


依据官方 Architecture → 新行为的归属位置 与扩展实操手册整理。

DeepSeek Harness / 第 10 章 扩展实战:新行为挂在哪 0 字 0 行 cosolar
2026-09-17T10:12:14.036315417Z 2026-09-17T10:39:04.249820557Z