第 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 章的三角色定义,添加一项能力时应当:
Service Definition:声明接口与
ctx.<key>(注意扁平命名空间,起有辨识度的名字);Service Provider:实现接口,通过声明合并把 key 加进
Context接口类型;Consumer:通常是面向模型的工具,用
inject声明硬依赖,或用ctx.get()探测可选依赖;每个
ctx.effect()/ctx.on()/注册调用都要保证可逆(自带 disposer 或返回一个);"模型可见即已记录":凡是会进入模型请求的内容,必须新增一个会话事件并从日志渲染;
waterfall 监听器若只做观察/标注,必须调用
next()。
10.5 如何决定"用事件还是用服务"
官方实践规则一句话:
拦截和策略优先使用事件;直接能力调用优先使用服务方法。
想在别人做事的前后观察/包装/否决 → 监听
agent/*、tools/*、fs/*等事件;想主动调用一项能力 → 通过
ctx.<key>直接调用服务方法。
依据官方 Architecture → 新行为的归属位置 与扩展实操手册整理。
DeepSeek Harness
/
第 10 章 扩展实战:新行为挂在哪
0 字
0 行