安装
在 DeepSeek Harness 里通过 dsh-market 安装
dsh plugin --profile web add dshmarket
或使用命令行
dsh plugin --profile web add github:JohnXu22786/hooks-adapter
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络。请先审阅源码,并尽量锁定 commit(github:owner/repo#sha)。
README
hooks-adapter
一个面向 DeepSeek Harness(dsh)的 hooks 配置兼容层:读取主流 agent harness 已有的 hooks 配置文件(如 .claude/settings.json 中的 hooks 声明、.codex/hooks.json、opencode.json 的 hooks 段),把它们的生命周期事件映射到 dsh 的扩展点,并执行 shell / webhook / oracle / proxy 四类 handler——让同一份 hooks 配置在不同的 harness 之间原样复用。
- 零运行时依赖(Node ≥ 18,纯 ESM + JSDoc 类型)
- 配置只读不迁移:你已有的 hooks 声明不用改写
- 四类 handler 全支持:命令执行、HTTP 回调、LLM 评估、子代理委派
- 超时控制、失败降级策略、友好的配置校验(
validate子命令) - 三种接入方式:dsh 插件(Cordis
apply)、stdio JSON-lines 协议(任意宿主)、一次性 CLI
hooks-adapter/
├── package.json # dsh bundle 清单(dsh.bundle + exports)
├── cordis.patch.yml # 组合包层:向插件树插入本插件
├── dsh/plugin.js # dsh 入口:Cordis 插件(name + apply(ctx, config))
├── lib/ # 运行时核心(可独立于 dsh 使用)
│ ├── index.js # CLI 入口 + 编程接口导出
│ ├── events.js # 规范事件目录 + 四方言映射表 + matcher 语义
│ ├── discover.js # 配置文件发现(全局/项目/本地)
│ ├── parse.js # 四方言解析器(全部走诊断,不抛错)
│ ├── config.js # 运行时组装:合并、disableAllHooks、默认值
│ ├── contract.js # stdin JSON 契约构造 + 响应解码 + 决策折叠
│ ├── execute.js # 四类 handler 执行器 + 超时 + 进程树清理
│ ├── dispatch.js # 分发管道:matcher 匹配、顺序执行、blockable 约束
│ └── serve.js # stdio JSON-lines 协议服务
├── docs/ # 配置格式、事件映射、契约、接入说明、CLI 指南
├── examples/ # 四方言示例配置 + 本地 mock LLM
└── test/ # node:test 测试(111 项)
它能做什么
在 .claude/settings.json 里声明 hooks(无论你之前为哪个 harness 写的),在 dsh 中它们照常生效:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "guard.sh", "timeout": 10 }
]
}
],
"Stop": [
{ "hooks": [ { "type": "command", "command": "notify-send done" } ] }
]
}
}
配置文件须为严格 JSON(不支持注释);examples/ 下有完整的四方言示例。
PreToolUse→ 工具执行前的拦截点:handler 退出码 2 / JSONdecision: "block"会阻止工具调用(或转为 ask 交人工确认)PostToolUse/PostToolUseFailure→ 工具执行后(互斥触发):拒绝写回为结果反馈、追加上下文UserPromptSubmit/SessionStart/Stop/SubagentStart/SubagentStop/SessionEnd→ 注入上下文、拒绝提示词、强制模型继续Notification/PreCompact→ 手动或经 stdio 协议触发
四类 handler(配置里的 type 字段按各 harness 习惯书写,内部归一):
| 配置 type | 内部 kind | 行为 | 默认超时 |
|---|---|---|---|
command |
shell |
起 shell 进程,stdin 喂 JSON 契约 | 600s |
http |
webhook |
POST JSON 到 URL,响应体即决策 | 600s |
prompt |
oracle |
调 LLM 端点评估,{ok:false} 即拒绝 |
30s |
agent / subagent |
proxy |
委派给子代理 runner(可配置命令) | 60s |
快速开始
方式一:dsh 插件(推荐)
# 在包含本插件 checkout 的目录中
dsh plugin --profile demo add ./hooks-adapter
dsh --profile demo
加载后插件自动发现项目与用户目录下的 hooks 配置(见下)。也可在 profile 的 cordis.patch.yml 中覆盖配置行:
- replace:
- id: hooks-adapter
config:
configPath: /abs/path/to/hooks.json # 固定使用单一文件(跳过发现)
discover: false
llm: { baseUrl: "https://api.example.com/v1", model: "eval-small" }
proxy: { command: "dsh run --quiet" }
接入细节见 docs/INTEGRATION.md。
在 DSH 中安装
直接用 dsh 插件命令从 GitHub 仓库安装:
dsh plugin --profile demo add github:JohnXu22786/hooks-adapter
本包是 dsh bundle(dsh.bundle.patch → cordis.patch.yml),添加后即插入插件树,下次启动 dsh 时自动发现 hooks 配置。卸载:
dsh plugin --profile demo remove hooks-adapter
方式二:stdio 协议(任意宿主)
echo '{"op":"ping"}' | node lib/index.js listen --config hooks.json
echo '{"op":"dispatch","event":"PreToolUse","payload":{"tool_name":"Bash","tool_input":{}}}' | node lib/index.js listen
协议说明见 docs/CONTRACT.md。
方式三:一次性 CLI
node lib/index.js validate # 检查所有可发现的配置,退出码 0/1
node lib/index.js run --event PreToolUse --payload payload.json
node lib/index.js dump # 打印合并后的生效配置
node lib/index.js list # 列出发现到的配置文件
配置从哪里来
自动发现并按顺序合并(后者追加同名事件的组;disableAllHooks 以最具体的文件为准):
| 顺序 | 文件 | 方言 |
|---|---|---|
| 1 | ~/.claude/settings.json |
claude |
| 2 | ~/.codex/hooks.json |
codex |
| 3 | ~/.config/opencode/opencode.json |
opencode |
| 4 | ~/.config/hooks-adapter/hooks.json |
native |
| 5 | <项目>/.claude/settings.json |
claude |
| 6 | <项目>/.codex/hooks.json |
codex |
| 7 | <项目>/opencode.json |
opencode |
| 8 | <项目>/.dsh-hooks.json |
native |
| 9 | <项目>/.claude/settings.local.json |
claude |
- 环境变量
HOOKS_ADAPTER_CONFIG(等价于--config)与HOOKS_ADAPTER_HOME(等价于--home) - 任意文件缺失都静默跳过;存在的文件若有问题,只产生诊断,不阻止启动
- 配置文件格式细节见 docs/CONFIG.md
事件映射
每种 harness 的事件名映射到一套规范事件(session:start、tool:before……),再绑定到 dsh 的扩展点:
| 规范事件 | claude 方言 | codex 方言 | opencode 方言 | dsh 扩展点 |
|---|---|---|---|---|
session:start |
SessionStart |
SessionStart |
session.created |
agent/session-start |
session:end |
SessionEnd |
SessionEnd |
session.deleted |
session/disposed |
prompt:submit |
UserPromptSubmit |
UserPromptSubmit |
chat.message |
agent/pre-step |
tool:before |
PreToolUse |
PreToolUse |
tool.execute.before |
tools/pre-execute |
tool:after |
PostToolUse / PostToolUseFailure |
PostToolUse |
tool.execute.after |
tools/post-execute |
turn:stop |
Stop |
Stop |
session.idle |
agent/turn-stopping |
subagent:start |
SubagentStart |
SubagentStart |
tool.execute.before.subagent |
subagent/start |
subagent:end |
SubagentStop |
SubagentStop |
tool.execute.after.subagent |
subagent/end |
notice |
Notification |
Notification |
notification |
手动 / stdio |
compact:before |
PreCompact |
— | experimental.session.compacting |
手动 / stdio |
完整语义(可阻塞性、matcher 规则、载荷字段)见 docs/EVENTS.md。
契约
- stdin JSON:
session_id、transcript_path、cwd、hook_event_name、permission_mode+ 事件字段(tool_name/tool_input/tool_use_id/tool_response/prompt/source……) - 退出码:
0= 放行(stdout 为 JSON 时解析决策);2= 拒绝(stderr 为原因);其他非零 = 非阻塞错误 - stdout JSON:
decision、continue/stopReason、systemMessage、hookSpecificOutput.permissionDecision(allow/deny/ask)、additionalContext、updatedInput;oracle 应答{ok: true|false, reason} - 多 hook 折叠:
deny > ask > allow;任一continue:false即停;上下文按 hook 顺序累加 - 细节与 stdio 协议见 docs/CONTRACT.md
测试
node --test
(默认测试发现模式即可跑全部 111 项测试;辅助脚本在 test-support/,不会被误当测试。)
许可证
基于 MIT License 发布。