DEEPSEEK HARNESS 插件工具包
让业务包只写业务。
连接、推送、委托、校验——这几件与业务无关、却每个项目都要重写一遍的事,收进一个包里,默认安全,按需启用。
v0.1.0 · 尚未发布到 npm
六个 Service
壹 · 连接 WebSocket 客户端 · ctx.agentWs 仅 wss:// 的 WebSocket 客户端:可刷新的鉴权请求头、心跳、指数退避重连、并发与背压控制;鉴权失败或指定关闭码时进入 failed 状态并可慢速重试。 贰 · 推送 钉钉推送 · ctx.dingtalk 通过钉钉 dws CLI 发送文本 / Markdown 消息,支持 user / bot / webhook 身份、群聊 / 单聊 / 多群、@ 人、幂等键和 dryRun。 叁 · 推送 飞书推送 · ctx.feishu 通过飞书官方 CLI lark-cli 发送文本 / Markdown 消息,支持 bot / user 身份、群聊 / 单聊 / 多群、@ 人、幂等键和 dryRun。 肆 · 通知 通知渠道 · ctx.notify 与渠道无关的通知:业务包只调用 ctx.notify.send(),同一时间发往一个渠道(钉钉或飞书)。渠道由配置决定,也可以在运行中用 ctx.notify.use() 切换,不需要改业务代码。 伍 · 委托 Agent 任务 · ctx.agentTasks 调用 dsh 已注册的 subagent provider(如 claude-code、codex)执行一次性任务:默认只读权限、每个任务独立目录、类型化的 JSON Schema 输出、并发与排队上限。 陆 · 校验 Jev 判断 · ctx.jev 调用 TypeSafe Jev 或本地部署的 Laya(二选一),返回 Choice / Noul / Score 的类型化判断和概率;一次 judge() 有严格的总时长。
默认安全
- 密钥只从环境变量、钥匙串或 dsh 凭据文件读取,不传给本包启动的任何子进程;钉钉、飞书的凭据由 dws、lark-cli 自己管理。
- 来自 WebSocket 的数据和 Agent 的输出都视为不可信:Agent 默认只读、在独立的空目录中运行,输出经过 Schema 与业务白名单校验后才应触发副作用。
- 只允许
wss://,不关闭证书校验,不跟随重定向。 - 日志和错误统一脱敏,不记录鉴权头、API Key、webhook token 与完整消息正文。
按需启用
六个 Service 在本包的 bundle 中以禁用状态注册。只有在 Profile 的 cordis.patch.yml 中启用的 Service 才会加载并校验配置;未启用的 Service 不影响其他部分。
- id: agent-kit-ws
disabled: false
- id: agent-kit-feishu
disabled: false
config:
identity: bot
defaultTarget: { chatId: oc_xxxx }
- id: agent-kit-notify
disabled: false
config:
channel: feishu 装了可选的运维工具 @mc/dsh-agent-kit-admin 时,也可以用 setup 交互式生成这段配置,或在 dsh Web 的设置页里直接勾选。
业务包长这样
业务包只 inject 用到的 Service,协议、路由、模板和流程留在自己的代码里。发通知用 ctx.notify,渠道留给运维切换。
export const inject = ['agentWs', 'notify', 'agentTasks', 'jev']
export function apply(ctx: Context, config: Config) {
ctx.agentWs.connect<Frame>({
url: config.url,
headers: async () => ({ 'X-Token': await getToken() }),
onMessage: async (frame, { signal }) => {
// 委托:外部数据用 untrusted() 包裹,Agent 默认只读
const draft = await ctx.agentTasks.run<Result>({
provider: 'claude-code',
title: `classify ${frame.id}`,
prompt: [CLASSIFY_INSTRUCTIONS, untrusted('event', frame.input)],
outputSchema: ResultSchema,
signal,
})
// 校验:用 Jev 判断候选结果是否与输入相符
const { answers } = await ctx.jev.judge({
state: { input: frame.input, candidate: draft.output },
questions: { wrong: noul('候选结果与输入证据不符') },
signal,
})
// 通知:不相符时告警;发到钉钉还是飞书由 agent-kit-notify 的 channel 决定
if (answers.wrong.noul >= 0.7) {
await ctx.notify.send({ title: '需要人工复核', markdown: render(frame, draft), idempotencyKey: frame.id })
}
},
})
} 三步开始
$dsh plugin --profile my-agent add @mc/dsh-agent-kit @mc/dsh-agent-kit-admin $npx @mc/dsh-agent-kit-admin setup --profile my-agent $npx @mc/dsh-agent-kit-admin doctor --profile my-agent @mc/dsh-agent-kit-admin 是可选的运维工具(setup、doctor 与设置页);不装它时,直接编辑 cordis.patch.yml 即可。