- Accueil
- Plugins
- Compétences
- dsh-agenote
dsh-agenote
shinebreaker/dsh-agenote
Installer
dsh plugin --profile web add github:shinebreaker/dsh-agenoteREADME
dsh-agenote
DeepSeek Harness(DSH)的 agenote 集成插件。
把 agenote 知识库接进 DSH 会话:system prompt 注入健康度摘要、任务完成时提示 agent 做经验留痕,外加三个斜杠命令快捷入口。
本插件是 agenote-pi(pi/omp 扩展)在 DSH 上的对等实现,二者共享同一套行为规范(agenote-skills)与同一个 agenote CLI,不重复实现任何知识库逻辑。
它做什么
| 触发点 | DSH 事件 | 行为 |
|---|---|---|
| system prompt 拼装 | systemPrompt.section | 注入 agenote health 摘要(总数/孤立率/过时率/薄弱类别/记忆统计)——背景知识,不产生 turn |
| 用户消息进入 | agent/inbox/inserted | 记住最近一条真实用户发言,用于信号判定 |
| 新一轮开始 | agent/status(running) | 作废待发的空闲计时器 |
| 工具执行完毕 | tools/result | 标记本轮「真的干过活」(空闲兜底的门槛依据) |
| turn 收尾 | agent/turn-stopping | 检测完成信号 → 注入 review 提示;并武装空闲兜底 |
| 会话销毁 | agent/disposed | 清计时器、释放会话状态 |
命令:
| 命令 | 说明 |
|---|---|
/agenote-summarize | 在当前会话触发经验总结 + 留痕(按 agenote-review skill 执行) |
/agenote-curate | 触发 KB 策展(按 agenote-curator skill 执行) |
/agenote-health | 直接回显 agenote health 报告(纯只读) |
前两个命令不直接跑 CLI——只把任务提示投进会话,流程编排与写盘决策由 agent 按对应 skill 主导。这保证了「行为规范」只有一份真相源(agenote-skills),不会在插件里长出第二份。
安装
# 在本仓库目录下,通过 DSH 的 plugin_manager 安装(推荐)
# 或在会话中让 agent 执行:plugin_manager install_bundle <本目录绝对路径>
安装会在当前 profile 的 package.json 里以 link: 方式登记依赖,并把 dsh-agenote 追加进 dsh.profile.bundles。
profile 为 patchReload: live 时(web profile 默认如此),新 bundle 会热挂载到已存在的会话,无需重启即可生效——实测:安装后同一会话的下一轮就出现了 agent/created 注入的健康度摘要。
两条注意事项:
install_bundle/set_bundle在运行中的进程上可能返回application: failed+agenote (dsh-agenote): failed to import。这是该次调用自身的诊断,不代表 bundle 未被采用——请以「冷启动日志无失败」与「会话里是否真的看到注入」为准,不要据此改代码。- 改了源码之后需要重启:运行中的进程持有旧的模块图,重新加载要冷启动。
依赖
agenoteCLI 在PATH中(which agenote)。可用环境变量AGENOTE_BIN覆盖可执行名。- 可选:
agenote-base/agenote-curator/agenote-reviewskills 已安装(命令注入的提示词会引用它们)。
配置
配置从 cordis 行的 config 下发(见 cordis.patch.yml 注释)。全部字段可选,默认值由插件导出的 Config schema 声明(index.js 组合,字段定义在 hooks.js / commands.js):Cordis 加载时用它校验配置并填默认值,非法配置在加载期直接失败(invalid config: ...),不会带着错值跑起来:
- id: agenote
config:
hooks:
enabled: true # 总开关
status: true # system prompt 注入健康度摘要
completionSignals: true # turn 收尾检测完成信号
idleFallback: true # 空闲兜底(无人值守场景)
signals: ["搞定", "done."] # 覆盖内置信号清单
debounceMs: 300000 # 触发冷却期(durable log 推导)
idleMs: 300000 # 空闲兜底阈值
statusTtlMs: 300000 # 健康度摘要缓存时长(0 = 每个请求重算)
commands:
enabled: true
设计要点
几个刻意的取舍,改动前请先读:
- 健康度摘要走 system-prompt section,不走
agent.followup()。followup的语义是"排一个独立后续 turn 并唤醒 driver"——agent/created时调用它,等于插件在用户开口前替用户"发言",driver 被唤醒后模型把摘要当指令处理并回复(表现为"新会话一打开 agent 就自说自话",已修)。背景知识类注入用ctx.systemPrompt.section(),随每次请求进入 system prompt,不产生 turn。 agent.followup()只用于任务提示(review/curate)。这两个投递点都没有待执行的 step;steer只作用于「最近的 step」,会把消息停在 inbox 里等下一次唤醒。followup才等价于 pi 的sendUserMessage({deliverAs:'followUp'})。- subagent 豁免(
session.header.origin === 'subagent')。DSH 的 subagent 是同进程独立 agent,同一个插件实例会收到它们的事件:worker 的内部对话不该投 review 提示(污染 handoff),也不该各自武装 idle 计时器(大量委派时表现为 idle 兜底"反复触发")。 - 防抖与「已触发」从 durable log 推导,不存内存标志。内存标志在
agent/created(含 resume/clear/compact)时被重置——web 刷新即 resume,同一会话干完活又触发一次。改扫会话日志:source.plugin === 'agenote-hooks'的user/message事件即本插件既往注入,resume/重启后答案不变。 - 每会话状态用
Map<sessionId, state>,不用模块级标量。一个进程里可并存多个会话(web 多标签、subagent),模块级状态会串台——这正是 pi 版历史上修过的 bug。 - 自注入反馈环防护。注入的提示词自身含「完成」等信号词;
agent/inbox/inserted只认source.kind === 'user'的消息(本插件注入的 source.kind 是'plugin'),回路在来源层面断开。 - 不 import
@deepseek-ai/*。本包经link:部署时模块 realpath 落在源码目录,Node 的node_modules父级检索够不到$DSH_HOME/profiles/node_modules共享 fallback。需要上游纯函数(createUserMessage)时在lib.js里复刻并注明出处;上游改语义需手动同步。 - 配置走 Standard Schema,不手写 normalize。插件导出
Config(Standard Schema v1 节点,lib.js里手搓的 schemastery 最小子集,语义逐条对齐上游),Cordis 加载时用它校验 cordis.yml 行下发的 config 并填默认值;非法值(如debounceMs: -1、signals: [])在加载期抛ValidationError,而不是被静默回退。字段与默认值的单一真相源在hooks.js/commands.js的Config声明里,新增可调项必须加在那里。 - 空闲兜底以「跑过工具的轮次」为门槛,不用裸 turn 数。turn 数无法区分「完成了一段工作」与「回答了一个问题」——纯对话轮同样推进 turn,会导致兜底在纯聊天上误报(实测发生过)。判据是
workedThisTurn(仅在该轮tools/result触发过时才成立)。 - 不重复实现行为规范。信号清单、写入流程、卡片格式全部归
agenote-skills;插件只做「事件触发 + 命令快捷入口」。 - 归因。所有 CLI 调用都带
AGENOTE_AGENT=dsh(lib.js:runKb)。该变量只给卡片打归因标签,不做写入隔离,但不带的话归因会错误落到默认 agent(omp)。
与 agenote-pi 的差异
| agenote-pi(pi/omp) | dsh-agenote | |
|---|---|---|
| 形态 | 单文件 TS,运行时自动扫描 | Cordis bundle(package.json + YAML patch),经 plugin_manager 安装 |
| 健康度摘要 | pi-ui 欢迎框显示(不注入对话) | systemPrompt.section(进入 system prompt,不产生 turn) |
| turn 收尾 | agent_end | agent/turn-stopping |
| 任务提示投递 | sendUserMessage({deliverAs:'followUp'}) | agent.followup(createUserMessage(...)) |
| subagent 守卫 | isSubagentProcess() 嗅探子进程 argv/env | session.header.origin === 'subagent'(持久化权威字段) |
| 防抖依据 | 模块级内存变量 | durable session log 推导(跨 resume/重启稳定) |
| 归因 | AGENOTE_AGENT=pi | AGENOTE_AGENT=dsh |
开发
无构建步骤,纯 ESM。改完源码后:
node --check index.js hooks.js commands.js lib.js # 语法检查
node --input-type=module -e "import('./index.js').then(m=>{const v=m.Config['~standard'].validate;console.log(JSON.stringify(v(undefined)));console.log(JSON.stringify(v({hooks:{debounceMs:-1}}).issues??null))})" # 配置 schema:全默认值 / 非法值报 issues
dsh --profile <profile> --no-open --port 3099 # 新进程冷启动,确认无激活失败
plugin_manager set_bundle 在运行中的进程上可能报 failed to import——那是该次调用自身的诊断,旧模块图仍能服务已挂载的行。判断依据看「冷启动日志无失败」+「会话里是否真的看到注入」,不要据此改代码。
许可
MIT。见 LICENSE。
Plugins associés
auto-claude-code-research-in-sleep
wanshuiyin/auto-claude-code-research-in-sleep
archify
tt-a1i/archify
dsh-web (dsh-skill-explorer)
zhu1090093659/dsh-web
dsh-web-ui (dsh-skill-explorer)
zhu1090093659/dsh-web-ui