dsh-decision-layer 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.en.md +49 -0
- package/README.md +53 -0
- package/cordis.patch.yml +3 -0
- package/icon.svg +18 -0
- package/lib/client.js +1288 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +78 -0
- package/service/.gitkeep +0 -0
- package/service/backend.mjs +127 -0
- package/service/config-store.mjs +203 -0
- package/service/danger-gate.mjs +143 -0
- package/service/dsh.mjs +175 -0
- package/service/log-store.mjs +70 -0
- package/service/loop-guard.mjs +52 -0
- package/service/manager-api.mjs +87 -0
- package/service/narrowing.mjs +149 -0
- package/service/self-check.mjs +94 -0
- package/service/session-state.mjs +116 -0
- package/skills/decision-layer/SKILL.md +15 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 xbzbing
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# dsh-decision-layer
|
|
2
|
+
|
|
3
|
+
> 中文:[README.md](<README.md>)
|
|
4
|
+
|
|
5
|
+
`dsh-decision-layer` adds structured, explicitly scoped decisions to the DeepSeek Harness (DSH) agent loop, backed by a pluggable adjudication backend. Dangerous-call gating, output self-check, tool narrowing, and loop prevention hook into the agent loop as automatic interventions.
|
|
6
|
+
|
|
7
|
+
> **0.4.0 is a preview release.** The plugin works, but how much real value the adjudication interventions add is still being explored — every threshold is an unvalidated heuristic default. Treat it as something to observe, not a proven guarantee of impact. See [ROADMAP.md](<ROADMAP.md>) for scope and progress.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Published to npm and GitHub.
|
|
12
|
+
|
|
13
|
+
From npm (append `@latest`):
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
dsh plugin --profile web add dsh-decision-layer@latest
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or from GitHub (no version — follows the branch or tag; the repository ships the built `lib/client.js`):
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
dsh plugin --profile web add github:xbzbing/dsh-decision-layer
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Or build locally and install the `file:` path:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm ci --ignore-scripts
|
|
29
|
+
npm run build:client
|
|
30
|
+
dsh plugin --profile web add file:/absolute/path/dsh-decision-layer
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Restart `dsh web` and refresh after installing or updating: the host and client halves build their mount and bundle manifests at server start, so a page refresh alone may not reflect changes. The management API only accepts same-origin requests on the local loopback web server. Do not enter a production key before confirming the destination and data flow.
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
- **Manual verdicts** — `decision_evaluate` and the `decision-layer` skill submit `noul`, `score`, or `choice` questions; `decision_check_connection` tests connectivity. Neither counts as an automatic decision or changes agent behavior.
|
|
38
|
+
- **Configurable backend** — defaults to `https://api.typesafe.ai` and `jev-latest`, with per-field URL/key/model overrides under the same protocol. No request without a key. Custom HTTP endpoints require address-bound plaintext-risk confirmation.
|
|
39
|
+
- **Dangerous-call gate** — before a destructive tool call, a redacted summary asks the backend for allow/ask/deny. A model allow only downgrades to native host approval; a deny is enforced monotonically; backend failure, low confidence, or invalid results defer to host approval. Rules are configurable.
|
|
40
|
+
- **Output self-check** — scores the final output at turn end against a rubric (0–2, a probability-weighted mean across levels, so it can be fractional). Observe-only by default; an opt-in low-score re-prompt appends one prompt on your behalf when the score is low and the model is confident, at most once per turn.
|
|
41
|
+
- **Tool narrowing** — at turn start, a noul judges each optional tool's relevance to the task and drops the ones not needed (relevance probability below the drop threshold, default 0.3, configurable), intersecting the host-allowed set and never expanding it. Enforced by default; switch to observe-only to log without changing the tool set. Three safeguards: core tools (read/write/edit/shell/search/todos, plus agent meta-abilities such as asking the user, goals, skills, delivery, background jobs, and teamwork) are always kept and never judged; more optional tools than the candidate cap (default 20, configurable) falls back to observe only; fewer than 5 tools remaining is treated as untrustworthy and skipped. Tools matching a **keep-prefix** allowlist (defaults to `mcp__openviking` and `team_task_`) are also always kept and never judged — good for resident, on-demand tools like memory, retrieval, and teamwork.
|
|
42
|
+
- **Loop guard** — deterministic and backend-free; denies the same call repeated consecutively past a threshold. Always on and outside the per-feature switches.
|
|
43
|
+
- **Session panel** — a dock trigger below the composer opens the panel with automatic-decision metrics (attempts, fallbacks, model suggestions vs actual outcomes), the master switch, and the decision log, with an empty state before any automatic decision. The master switch pauses only automatic intervention.
|
|
44
|
+
- **Per-feature switches** — the config page has an independent switch for the danger gate, output self-check, and tool narrowing, all on by default; turning one off drops that intervention. The loop guard is not covered by these switches.
|
|
45
|
+
- **Persisted decision log** — beyond the in-memory panel, decisions are written in full per session to `~/.config/dsh-decision-layer/logs` for research. Files roll by running-instance port and date (`decisions-<port>-YYYY-MM-DD.jsonl`), are batched, and retained for 30 days. Writing is best-effort: a failed flush drops that batch and never breaks the decision path.
|
|
46
|
+
|
|
47
|
+
## Safety boundary and development
|
|
48
|
+
|
|
49
|
+
Automatic intervention only subtracts: the gate only denies, narrowing only removes tools, and neither grants new permissions. The gate defers to native DSH approval on backend failure rather than allowing; self-check, narrowing, and loop-guard errors skip intervention. The redacted summary sent to the backend carries only tool name and command/path with secret redaction — never file content. Node.js `>=20.11`; `npm test` and `npm run build:client` run local checks. Rebuild and commit `lib/client.js` with any client change. 0.4.0 is a preview: the interventions work, but their real value and thresholds are still being explored — feedback on misjudgments and feel observed in the decision log is welcome.
|
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# dsh-decision-layer
|
|
2
|
+
|
|
3
|
+
> English: [README.en.md](<README.en.md>)
|
|
4
|
+
|
|
5
|
+
DeepSeek Harness(DSH)的结构化裁决插件。它把有明确判断标准的问题交给同协议的裁决后端,供 agent 在需要时使用,并在 agent loop 上接入危险门控、产出自检、工具收窄和防循环等自动介入。
|
|
6
|
+
|
|
7
|
+
> **0.4.0 是体验版。** 插件功能已可用,但裁决介入能带来多少实际价值仍在探索中——各决策点的阈值都是未经验证的启发式默认值,建议先以观察心态体验,别当成经过验证的效果保证。功能与后续进度以 [ROADMAP.md](<ROADMAP.md>) 为准。
|
|
8
|
+
|
|
9
|
+
## 安装
|
|
10
|
+
|
|
11
|
+
已发布到 npm 与 GitHub。
|
|
12
|
+
|
|
13
|
+
从 npm 安装(补 `@latest`):
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
dsh plugin --profile web add dsh-decision-layer@latest
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
或从 GitHub 安装(不带版本,跟随分支或 tag;仓库已含构建产物 `lib/client.js`):
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
dsh plugin --profile web add github:xbzbing/dsh-decision-layer
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
也可从源码本地构建后用 `file:` 安装:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npm ci --ignore-scripts
|
|
29
|
+
npm run build:client
|
|
30
|
+
dsh plugin --profile web add file:/绝对路径/dsh-decision-layer
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
安装或更新后需重启 `dsh web` 服务再刷新页面:host 与 client 两半在服务启动时生成挂载与 bundle 清单,仅刷新页面可能看不到变化。插件管理 API 只接受本机 loopback Web 服务上的同源请求;把 DSH Web 绑定到所有网卡时该接口会拒绝请求。不要在未确认目标地址和数据流向前填入生产 Key。
|
|
34
|
+
|
|
35
|
+
## 功能
|
|
36
|
+
|
|
37
|
+
- **手动裁决**:`decision_evaluate` 工具与 `decision-layer` skill 支持显式提交 `noul`、`score`、`choice` 问题,`decision_check_connection` 做连通测试。手动调用和连通测试不计入自动裁决指标,也不改变 agent 行为。
|
|
38
|
+
- **可配置后端**:默认 `https://api.typesafe.ai`、`jev-latest`,URL、Key、model 可逐字段覆盖;仅支持相同的结构化裁决协议。未配置 Key 时不发送请求。自定义 HTTP 地址需针对实际目标确认明文传输风险,地址变更须重新确认。
|
|
39
|
+
- **危险门控**:破坏性工具调用执行前用脱敏摘要请后端给放行 / 询问 / 拒绝建议。模型建议不能授予宿主未允许的权限——放行只降级为宿主原生审批,拒绝经监控守卫单调生效;后端失败、低置信或响应不合法时交回宿主审批。危险规则可增删配置。
|
|
40
|
+
- **产出自检**:回合结束用评分量表给最终产出打分(0–2,按各档位概率加权,可能是小数)。默认只提示、不打断;可开启「低分补完」,得分偏低且模型有把握时以你的名义追加一次补完提示,同一回合最多补一次。
|
|
41
|
+
- **工具收窄**:回合开始时用 noul 逐个判断可选工具与本轮任务的相关性,摘掉用不上的(相关性概率低于摘除阈值,默认 0.3、可配),只在宿主已允许的集合内取交集、不扩权。默认真正生效,可切到「仅观察」只记录不改工具集。三重保护:核心工具(读写、编辑、Shell、检索、待办,以及问用户、目标、技能、交付、后台作业、协作等 agent 元能力)始终保留、不参与判定;可选工具超过候选上限(默认 20,可配)时自动降为仅观察;保留下来不足 5 个时视为判定不可信、跳过。**保留工具前缀**白名单里的工具(默认含 `mcp__openviking`、`team_task_`)也始终保留、不参与判定,适合记忆 / 检索、协作这类常驻、按需触发的工具。
|
|
42
|
+
- **防循环**:确定性判断,不走后端;同一调用连续重复超过阈值即拒绝,打断死循环。始终生效,不在决策点开关范围内。
|
|
43
|
+
- **会话面板**:输入框下方的 dock 触发器弹出面板,展示自动裁决指标(评估数、失败回退、模型建议与实际结果分列)、会话总开关和决策日志;无自动裁决时显示空态。总开关关闭只暂停自动介入,不影响手动裁决。
|
|
44
|
+
- **决策点开关**:详情页配置里,危险门控、产出自检、工具收窄各有独立开关,默认全开;关掉某个决策点就不再对应地介入。防循环不在此范围。
|
|
45
|
+
- **决策日志落盘**:决策记录在内存面板之外,还按会话全量落盘到 `~/.config/dsh-decision-layer/logs`,供研究回看。文件按运行实例端口和日期滚动切分(`decisions-<端口>-YYYY-MM-DD.jsonl`),批量写入,保留 30 天。写盘为尽力而为,失败只丢当批、不影响决策路径。
|
|
46
|
+
|
|
47
|
+
## 安全边界
|
|
48
|
+
|
|
49
|
+
自动介入只减不增:门控只拒绝、收窄只删工具,都不给 agent 新权限。危险门控在后端失败或无法可靠交接时交回 DSH 原生审批,不因裁决故障直接放行;自检、收窄与防循环异常则跳过介入。发送到后端的危险摘要只含工具名与命令 / 路径并对疑似密钥脱敏,不含文件内容。
|
|
50
|
+
|
|
51
|
+
## 开发
|
|
52
|
+
|
|
53
|
+
服务端使用 Node.js `>=20.11`(`.mjs`,无需构建);客户端用 TypeScript + esbuild 构建。`npm test` 跑本地测试,`npm run build:client` 生成 `lib/client.js`。改动客户端后需重建并连同 `lib/client.js` 一起提交,否则 GitHub 安装拿到的是旧 bundle。0.4.0 为体验版:介入能力已可用,但实际价值与阈值仍在探索,欢迎反馈决策日志观察到的误判与体感。
|
package/cordis.patch.yml
ADDED
package/icon.svg
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<defs>
|
|
3
|
+
<radialGradient id="rg1" cx="42%" cy="38%" r="70%">
|
|
4
|
+
<stop offset="0" stop-color="#3FB27A"/><stop offset="1" stop-color="#0F6B3C"/>
|
|
5
|
+
</radialGradient>
|
|
6
|
+
<clipPath id="rc1"><circle cx="18" cy="18" r="14"/></clipPath>
|
|
7
|
+
</defs>
|
|
8
|
+
<circle cx="18" cy="18" r="15.2" fill="#0B3D22" stroke="#0A2E1A" stroke-width="1.4"/>
|
|
9
|
+
<circle cx="18" cy="18" r="14" fill="url(#rg1)"/>
|
|
10
|
+
<g clip-path="url(#rc1)" stroke="#0C5A32" stroke-width="1">
|
|
11
|
+
<path d="M8 4 V32 M13 4 V32 M18 4 V32 M23 4 V32 M28 4 V32"/>
|
|
12
|
+
<path d="M4 8 H32 M4 13 H32 M4 18 H32 M4 23 H32 M4 28 H32"/>
|
|
13
|
+
</g>
|
|
14
|
+
<path d="M18 13.2 L21.6 22.2 L18 19.4 L14.4 22.2 Z" fill="#E23B2E"/>
|
|
15
|
+
<circle cx="24" cy="11" r="1.9" fill="#EAF7EF"/>
|
|
16
|
+
<circle cx="12" cy="24" r="1.6" fill="#EAF7EF"/>
|
|
17
|
+
<circle cx="25" cy="25" r="1.5" fill="#EAF7EF"/>
|
|
18
|
+
</svg>
|