dsh-context-relay
DSH 上下文接力(Context Relay):phase 协议 + 预算哨兵 + 受控压缩 + 有界 handoff 开新会话,让 Lead agent 长期停留在高效上下文区间。
版本 0.2.9 · 要求 DSH ≥ 0.2.1-rc.2 · Node.js ≥ 20 · MIT
它解决什么
Lead agent 的上下文一旦变长,会开始偏离实现、重复劳动、过度实现;DSH 自带的自动压缩(默认接近窗口上限才触发、摘要式、打断前缀缓存)往往不能把注意力真正拉回高效区。
本插件提供一个 relay 模式(DSH 原生 agent preset,会话创建时在模式选择器里可见):
- 用 phase 状态机(discover → decide → build → verify → ship)组织长任务;
- 用 预算哨兵 在上下文接近阈值时提醒,并把"继续方式"(压缩继续 / 接力开新会话 / 继续)的决策留在 phase 边界;
- 用 受控压缩(官方压缩引擎)把工作上下文缩回干净区间,同时保留结构化 brief;
- 用 有界 handoff 创建新的顶层会话接手,旧会话保留审计(handedOff 标记),交接清理会取消/迁移旧会话树资源,长线状态通过滚动进度文件与文档交接。
装完是什么样
- 新建会话的模式选择器里多出 Relay 模式;选中后工具集里出现
relay_status/relay_phase/relay_organize/relay_handoff/doc_lint。 - 输入框下方出现 接力 chip:显示实时上下文占用百分比、当前 band、下一次操作;点开是面板(一次性默认操作、自动授权、交接后注入开关)。
- 模型选择器右侧出现 「预算无上限」小胶囊(仅 relay 会话):按会话切换提示词注入
你的 token 预算无上限。。 - 设置页的插件卡片提供默认阈值基准与面板默认值。
- 到线时收到插件 notice(不是用户消息):只告知状态与 phase 优先指引,不打断当前 phase 的工作。
安装
要求:DSH >=0.2.1-rc.2(Web profile)、Node.js >=20。
发布到 npm 后:
dsh plugin --profile web add dsh-context-relay
从本地目录/仓库安装(开发态):
dsh plugin --profile web add /path/to/dsh-plugins/dsh-context-relay
持久装配使用包内 cordis.patch.yml(bundle 形式):relay preset 由插件激活时动态注册,卸载即注销。安装/更新后重启对应 profile,再刷新 Web UI。
本插件不会自动安装或修改其它插件;
dsh.engines声明的是本插件依赖的 DSH API 版本下限。
使用:刷新 Web UI → 新建会话 → 模式选择器选「Relay」→ 开始对话。DSH 约束下会话一旦开始 preset 固定,中途不能切换;请新建一个 relay 会话。
快速开始
典型长任务流程:
- 在 relay 会话里先
relay_status,确认当前 phase、上下文占用与 band。 - 开工前
relay_phase({phase: "discover", goal, exit_criteria});每个阶段切换都要带contract_check(需求是否已定 / 实现是否忠实 / 是否需要占用人类注意力)。 - 工作过程中不因为预算打断 phase;预算只是 phase 边界闸门。
- 到线(organize/relay band)后,在 phase 边界按面板一次性默认操作处理:
- 继续:不压缩、不接力,继续当前 phase;
- 压缩继续:
relay_organize做一次受控压缩(每会话最多 1 次),压缩成功后继续; - 接力新会话:
relay_handoff写出 ≤8KB 结构化交接单并创建新的 relay 会话; - 压缩→新会话(两段式):第一次到线只压缩并留在本会话继续;第二次到线才开新会话——压缩把占用压回线下后,同一到线不会先压缩再交接(
relay_handoff返回two-stage-not-due)。已知边界:若压缩后仍停留在线以上,无信号区分同一/下一次到线,按到线口径放行(见「已知限制」)。
- 交付前进
ship需要新上下文独立审查(user_gate.review)+ 大白话汇报(user_gate.report)。
安全边界与代价
- 压缩与接力都要过官方审批硬门(
handoffApproval: 'required',默认):relay_organize/relay_handoff执行前由 DSH 弹出审批;只有 allowed-once 才放行。免审只来自面板autoCompress/autoHandoff/authorizeNext(一次性)。 - 接力会创建新会话并消耗额度,并会中断旧会话树中运行中的队友/子智能体、取消其后台任务、把定时任务迁移到新会话;旧会话保留审计(
handedOff标记)。交接后请勿继续在旧会话工作——插件不强制阻止(技术上仍可继续/再次交接)。 - 压缩有损:压缩后旧对话细节只保留结构化 brief;重要结论请写进文档/handoff。
- 不自动循环:relay 保持 human-gated;需要重复性、可离屏的整块劳动请用官方 Ralph / workflow / subagent,不要用 relay 自研自动循环。
- P0 规则:不可逆/对外/付费/凭据/删除动作先向人类报备并取得明确 Go;本插件不会替你自动批准这些动作。
- 数据文件:
~/.dsh/data/dsh-context-relay/settings.json(人类设置)与panel.json(按会话面板状态);消息/会话内容仍由 DSH 自身存储。
配置
宿主插件 config(可选)
| 键 | 默认 | 说明 |
|---|---|---|
threshold / settings.threshold |
35 | 阈值基准(%):organize 线 = 基准,warn = 基准−5,relay 硬线 = 基准+10(默认 warn 30 / organize 35 / relay 45)。 |
settings |
{threshold:35, defaultOperation:null, autoChoose:false, autoCompress:false, autoHandoff:false, unlimitedBudget:true} |
侧栏卡片的初始默认值;人类保存的 settings.json 优先。 |
thresholds |
比例 0.35/0.40/0.50 | legacy 阈值(仅当没有 settings 来源时生效)。 |
panelPath / settingsPath |
~/.dsh/data/dsh-context-relay/… |
面板/设置持久化路径覆盖。 |
injectBrief |
true |
压缩成功后是否把 brief 注入下一 step(归因实验可关)。 |
handoffApproval |
'required' |
压缩/接力官方审批硬门;无审批 UI 的部署可设 'off'(残余风险见 docs/VERDICT.md)。 |
inheritOnHandoff |
true |
接力继承旧会话模型路由与权限档;false 回部署默认。 |
presetId |
'relay' |
注册的模式 id。 |
面板状态(按会话)
panel.json 中每个会话 9 个字段:defaultOperation、autoChoose、autoCompress、autoHandoff、handedOff、authorizeNext、autoDecision、unlimitedBudget、handoffUnlimitedBudget。人类在 composer 面板写入会保存该会话快照;agent 内部状态只落显式字段,不固化默认值。
工具
| 工具 | 作用 |
|---|---|
relay_status |
读当前上下文占用/band/phase/预算 headroom/建议;phase 开始与派活前调用。 |
relay_phase |
声明/切换 phase;校验 exit_criteria、contract_check、warn 档 budget_plan;ship 需要 user_gate。 |
relay_organize |
受控压缩:写 phase brief(自动附 doc_lint 结论与关键文档入口)→ 调官方压缩引擎 → 成功后注入 brief。每会话最多 1 次(force 需人类坚持)。 |
relay_handoff |
生成 ≤8KB 有界交接单(含滚动进度文件),创建新 relay 会话并交接清理旧会话树。 |
doc_lint |
四项目录/文档体检(quota / banned / index / git),输出 ≤2KB。 |
HTTP API(宿主)
GET /context-relay/settings、PUT /context-relay/settings:侧栏默认值(六字段,部分更新合并)。GET /context-relay/panel?sessionId=、PUT /context-relay/panel:按会话面板状态(含relay标记,供 composer 胶囊判断是否显示)。GET /context-relay/api:最后一次 handoff 发布箱快照(M3 提示通道)。
这些路由默认只在本机 GUI 认证后可用(非公开 API)。
已知限制
- 重载插件前创建的旧会话使用旧 agent 平面;新行为(注入开关/审批/面板字段)以重载后新建的 relay 会话为准。
- 本插件只在 DSH Web profile 验证;headless/其它部署未验证。
- 压缩/接力的实际效果与模型、任务长度相关,阈值不是普适最优;按需在侧栏调整基准。
- 视觉细节(chip 间距、开关/胶囊位置、窄宽度换行、popover 换行)未做自动化视觉回归,需安装后目检。
- 两段式闸门边界:
relay_handoff只在「已压缩且当前未到线(band=ok/warn)」时拒绝;若压缩后仍停留 organize/relay,无到线计数区分同一/下一次到线,按到线口径放行。两段式仅单测覆盖,无真机端到端接力(会创建会话/耗额度)。 - 压缩保真/收益未做 A/B:小样本实验测得一次压缩后事实保留约 54%、两次约 8%(高方差);brief 注入改善结果,但严格有/无注入 A/B 未跑(
injectBrief:false是关闭臂)。阈值拐点同样未做 A/B。 - 面板落盘失败:
panel.json写盘失败时状态只存内存(persisted:false),重启即丢;settings 写盘是持久化优先(500,不半提交)。 - 接力继承权限:
inheritOnHandoff:true时danger-full-access/never会话会继承同等权限档;人类检查点是审批闸门(autoHandoff/authorizeNext可跳过)。 - 冷启动 chip:live 与派生都不可得时显示中性降级态(比例
?),两段式预设可能先显示「压缩」直到下一 step 自愈。 - 文档与 UI 语言:文档以中文为真源;composer chip/popover/侧栏卡片/dock notice 文案仅中文。
开发
npm test # node --test test/*.test.mjs
npm run check # 全部入口语法检查
目录:lib/policy.js(纯策略函数)、lib/panel-store.js(面板状态)、lib/agent.js + lib/agent/*(preset 平面实现)、lib/index.js(Host 平面/HTTP)、lib/client.js(Web UI bundle)、lib/preset-base.js(官方 ptc preset 资产)、skills/(随包技能)。
设计/验收文档:docs/SPEC.md(现行规范)、docs/DESIGN.md(设计)、docs/VERDICT.md(经验裁决)、docs/CHANGELOG.md(历史)。完整中文长文档(归档,含开发细节):docs/README.zh-CN.full.md。
License
MIT
No comments yet. Be the first to write one.