@weniatall/dsh-task-models 0.0.0-stage → 0.2.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/README.md +169 -2
- package/cordis.patch.yml +36 -0
- package/lib/client.js +933 -0
- package/lib/core.js +387 -0
- package/lib/index.js +780 -0
- package/package.json +76 -4
package/README.md
CHANGED
|
@@ -1,3 +1,170 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-task-models
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
DeepSeek Harness (DSH) 独立插件:**在设置里为不同类型的子任务配置不同模型**,并可选地让
|
|
4
|
+
TypeSafe Jev(System One 决策模型)参与“这个子任务属于哪一类 / 该用哪个模型”的判断。
|
|
5
|
+
|
|
6
|
+
本插件不依赖任何 Agent Preset 或角色路由插件;只要安装并启用,就会对当前会话委派出的子代理
|
|
7
|
+
(`subagent`、`workflow` 的 `agent()`、以及它们派生的孙代理)生效。主会话自身的模型选择不会
|
|
8
|
+
被改写。
|
|
9
|
+
|
|
10
|
+
## 特性
|
|
11
|
+
|
|
12
|
+
- **按任务类型路由**:内置 `explore`、`implement`、`review`、`test`、`research`、`docs` 六类,
|
|
13
|
+
可添加任意自定义类型;每类独立选择 Provider、模型和思考档位。
|
|
14
|
+
- **规则优先**:子任务 label(如 `[review]`)或关键词命中时直接路由,零额外模型调用。
|
|
15
|
+
- **可选 Jev**:规则未命中时,把截断后的父任务/子任务文本发给 Jev,让它在已配置任务类型 +
|
|
16
|
+
`general` 中选一个;Jev 只返回任务类型 id,不会发明模型或 Provider。
|
|
17
|
+
- **可选轻量分类**:不想用 Jev 时,可配置一个轻量模型作为回退分类器。
|
|
18
|
+
- **按子代理决策一次**:首次请求决定后缓存,后续请求沿用同一模型,不会在工具循环中来回切换。
|
|
19
|
+
- **安全回退**:Jev 不可用、超时、低置信度、输出非法,或分类器未配置时,保持当前路由。
|
|
20
|
+
- **可观测**:设置页提供 Jev 状态、API Key 保存和测试按钮;密钥只写本地文件,不回显。
|
|
21
|
+
- **独立设置命名空间**:`task-models`,通过专用 Connection RPC 读写,不依赖宿主设置 allowlist。
|
|
22
|
+
|
|
23
|
+
## 安装
|
|
24
|
+
|
|
25
|
+
从 GitHub Release 安装(插件管理器的「自有插件」页也能直接点安装):
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
dsh plugin --profile web add https://github.com/veildawn/dsh-plugins/releases/download/dsh-task-models@v0.2.0/dsh-task-models-0.2.0.tgz
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
> 包名已在 `package.json` 中迁移到 npm scope `@weniatall/dsh-task-models`,但该包尚未
|
|
32
|
+
> 首次发布到 npm registry(Trusted Publishing 只能给已存在的包授权)。在完成首次发布前,
|
|
33
|
+
> 请使用上面的 GitHub Release tarball 安装;插件管理器在 `allowTarball` 开启时也走这条
|
|
34
|
+
> 渠道。
|
|
35
|
+
|
|
36
|
+
或在仓库内打包安装:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
cd plugins/dsh-task-models
|
|
40
|
+
npm test
|
|
41
|
+
npm pack
|
|
42
|
+
dsh plugin --profile web add ./dsh-task-models-0.2.0.tgz
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
> 本仓库的 `AGENTS.md` 规定:除非用户明确要求,不在本机部署插件或重启服务。开发验证请只运行
|
|
46
|
+
> `npm test` / `npm pack --dry-run`。
|
|
47
|
+
|
|
48
|
+
## 设置
|
|
49
|
+
|
|
50
|
+
打开 **设置 → 任务模型**:
|
|
51
|
+
|
|
52
|
+
1. 勾选“启用按任务类型路由子任务”。
|
|
53
|
+
2. 为内置任务类型选择模型;也可以“添加任务类型”创建自定义类型。
|
|
54
|
+
3. 选择规则未命中时的回退方式:
|
|
55
|
+
- **保持当前路由**(默认):不覆盖会话原有路由;其他插件的路由仍然生效;
|
|
56
|
+
- **用轻量模型分类**:需要先配置“轻量分类模型”。
|
|
57
|
+
4. 可选启用 Jev,填写 API Key(或留空使用环境变量/密钥文件)、Base URL、模型和阈值。
|
|
58
|
+
|
|
59
|
+
对应的 YAML:
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
task-models:
|
|
63
|
+
routing:
|
|
64
|
+
enabled: true
|
|
65
|
+
fallback: taskRole # taskRole | llm
|
|
66
|
+
useJev: true
|
|
67
|
+
respectExplicitChildModel: true
|
|
68
|
+
classifier: # fallback=llm 时使用;留空表示不用
|
|
69
|
+
provider: ai-proxy
|
|
70
|
+
model: deepseek-v4-flash
|
|
71
|
+
reasoningEffort: low
|
|
72
|
+
profiles:
|
|
73
|
+
- id: review
|
|
74
|
+
name: 审查与复核
|
|
75
|
+
detail: 代码审查、正确性检查、安全与质量复核。
|
|
76
|
+
keywords: [审查, review, audit]
|
|
77
|
+
provider: ai-proxy
|
|
78
|
+
model: deepseek-v4
|
|
79
|
+
reasoningEffort: high
|
|
80
|
+
enabled: true
|
|
81
|
+
jev:
|
|
82
|
+
enabled: false
|
|
83
|
+
baseURL: https://api.typesafe.ai
|
|
84
|
+
model: jev-latest
|
|
85
|
+
minConfidence: 0.6
|
|
86
|
+
timeoutMs: 3000
|
|
87
|
+
maxStateChars: 8000
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
任务类型 ID 会转为小写,必须匹配 `[a-z][a-z0-9_-]*`,且不能与 `default`、`task`、`general` 重名。内置类型没有配置模型时不参与匹配;清空模型即禁用该类型。
|
|
91
|
+
|
|
92
|
+
## 决策顺序
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
子任务首次请求:
|
|
96
|
+
1. label 命中任务类型 ID / 关键词(规则)
|
|
97
|
+
2. 规则未命中且启用 Jev → Jev choice
|
|
98
|
+
3. 仍未命中且 fallback=llm → 轻量分类模型
|
|
99
|
+
4. 仍未命中 → 保持当前路由
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
- 规则并列(tie)不会按配置顺序随机选择,而是交给 Jev/轻量模型/回退。
|
|
103
|
+
- 其他子系统通过 `modelRole` 标记的内部子代理、计划模式、非子代理会话都会旁路。
|
|
104
|
+
- 子任务如果显式选择了与父级当前路由不同的模型,默认跳过任务类型路由,避免无声覆盖
|
|
105
|
+
(`respectExplicitChildModel`)。显式选择恰好等于父级基线时无法检测,见“已知限制”。
|
|
106
|
+
- 第二次及后续请求会重放缓存的任务类型路由;不会退回父级/当前模型。
|
|
107
|
+
|
|
108
|
+
## 与 Agent Preset 无关
|
|
109
|
+
|
|
110
|
+
本插件不读取、不要求、也不依赖任何 Agent Preset(标准模式、无 Preset 或任何自定义模式下的
|
|
111
|
+
行为一致),不注册 Preset,也不修改会话的 Preset。它只依据“是否为子代理”和自身设置决定是否
|
|
112
|
+
路由;主会话模型始终不被改写。
|
|
113
|
+
|
|
114
|
+
## Jev 与密钥
|
|
115
|
+
|
|
116
|
+
- 设置页只保留一个 **API Key** 输入框;保存后写入本机固定路径
|
|
117
|
+
`~/.dsh/task-models/typesafe.key`(文件 `0600`,目录 `0700`),不写入 profile patch。
|
|
118
|
+
- 不再读取环境变量或外部密钥文件配置;未保存 Key 时 `jevStatus` 显示未配置。
|
|
119
|
+
- `jevStatus` 只返回“是否已配置”和模型名,不返回 Key 或掩码。
|
|
120
|
+
- 启用 Jev 后,规则未命中时会把父任务、子任务 label/prompt(截断到 `maxStateChars`)发送到
|
|
121
|
+
TypeSafe;图片不会发送。敏感任务请关闭 Jev 或改用仅规则/轻量分类。
|
|
122
|
+
- 首次子任务请求最多增加 `timeoutMs` 的等待;Jev 失败只告警一次,不阻塞子任务。
|
|
123
|
+
|
|
124
|
+
## 工作流成员模型标注
|
|
125
|
+
|
|
126
|
+
本插件还会增强聊天中的 **workflow 运行卡片**:开启后,每个成员行会显示该成员实际使用的模型
|
|
127
|
+
(例如 `claude-opus-4-6`),并在悬停时显示 `provider/model` 与思考档位。
|
|
128
|
+
|
|
129
|
+
实现方式:
|
|
130
|
+
|
|
131
|
+
- Host 端在每次子代理 `agent/request` 后记录其**最终生效**的 provider/model/effort,覆盖本插件
|
|
132
|
+
路由、其他角色路由以及显式子代理模型三种来源。
|
|
133
|
+
- 对插件升级/重启前已存在的 workflow,Host 会尽力从 `~/.dsh/sessions/**/<childId>/session.v4.jsonl(.zstd)`
|
|
134
|
+
的 `request/header` 回溯该成员的最终模型;读不到日志时静默留空,不影响运行。
|
|
135
|
+
- Client 端以 `priority: -1` 覆盖宿主的 `workflow-run` 渲染器(DSH 支持的 keyed slot 阴影机制),
|
|
136
|
+
保留运行/阶段状态、展开收起与运行中成员跳转,只额外加入模型徽标。
|
|
137
|
+
- 模型信息通过本插件自己的 `/task-models-settings` RPC 的 `childModels` 方法读取;面板每 2 秒
|
|
138
|
+
刷新一次,子代理首次请求完成后徽标即出现。
|
|
139
|
+
- 未知模型且成员仍在运行时显示“模型…”;已完成但未知则不显示,避免猜测。
|
|
140
|
+
|
|
141
|
+
> 该增强依赖宿主 `conversation.chat.node` 的 keyed slot 与 `workflow-run` 节点数据。若未来 DSH
|
|
142
|
+
> 改动该 UI,可能需要跟随升级;禁用/卸载本插件会立即恢复宿主原生 workflow 卡片。
|
|
143
|
+
|
|
144
|
+
## 与 DSH 的边界
|
|
145
|
+
|
|
146
|
+
- 不 patch `ctx.subagents.start`;只在公开的 `agent/pre-step` / `agent/request` 上工作。
|
|
147
|
+
- 不新增子代理工具,不修改 `subagent` / `workflow` 的工具 schema。
|
|
148
|
+
- 不处理 ACP / Codex / Claude Code 等外部进程子代理的模型选择;这些由各自外部进程决定。
|
|
149
|
+
- 主任务自动分类、识图委派、顾问复核不在本插件职责内;由宿主或相应插件负责。本插件只处理
|
|
150
|
+
子任务模型映射。
|
|
151
|
+
- 已运行的子代理在设置修改后保持原路由;新子代理使用新设置。
|
|
152
|
+
- 显式选择恰好等于父级当前路由时无法检测,可能被任务类型路由覆盖。
|
|
153
|
+
- 宿主 `subagentModelSelection` 的 allowedModels 不会在本插件路由层再次强制;需要严格白名单时
|
|
154
|
+
请关闭本插件的任务路由或 `respectExplicitChildModel` 不能覆盖的部分改由宿主控制。
|
|
155
|
+
|
|
156
|
+
## 开发与测试
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
cd plugins/dsh-task-models
|
|
160
|
+
npm test # core + routing + package + 宿主设置门禁
|
|
161
|
+
npm pack --dry-run
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
测试覆盖:配置默认值与校验、关键词/label 规则、tie 回退、Jev choice 解析、自定义 Jev HTTP
|
|
165
|
+
端点、低置信度回退、轻量分类、显式 route 跳过、主会话/内部子代理旁路、设置 RPC 和客户端
|
|
166
|
+
bundle 渲染。
|
|
167
|
+
|
|
168
|
+
## License
|
|
169
|
+
|
|
170
|
+
MIT
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Ensure @deepseek-ai/dsh-client-connection has webStartup + webServer injected
|
|
2
|
+
# so rpc.handle can register HTTP routes.
|
|
3
|
+
# NOTE: webRuntime is intentionally NOT injected: the dsh-web-app web-runtime
|
|
4
|
+
# row that provides it no longer activates on DSH desktop 0.2.1+, so injecting
|
|
5
|
+
# it makes `connection` wait forever and no RPC channel gets registered.
|
|
6
|
+
# webStartup must stay listed because a patch row's `inject` REPLACES the
|
|
7
|
+
# previous one wholesale (last write wins).
|
|
8
|
+
- id: connection
|
|
9
|
+
inject:
|
|
10
|
+
- webStartup
|
|
11
|
+
- webServer
|
|
12
|
+
|
|
13
|
+
# Mount per-task-type subagent routing with no forced model assignments.
|
|
14
|
+
# Configure mappings in Settings -> 任务模型; an empty profile table preserves
|
|
15
|
+
# native DSH behavior.
|
|
16
|
+
- insert:
|
|
17
|
+
- id: task-models
|
|
18
|
+
# `name` is the cordis loader module identifier: it must be the package
|
|
19
|
+
# name, otherwise `import(name)` looks for a package that does not exist
|
|
20
|
+
# and the plugin silently fails to load. `@` is a YAML reserved character,
|
|
21
|
+
# so the scalar must be quoted.
|
|
22
|
+
name: '@weniatall/dsh-task-models'
|
|
23
|
+
config:
|
|
24
|
+
routing:
|
|
25
|
+
enabled: false
|
|
26
|
+
fallback: taskRole
|
|
27
|
+
useJev: true
|
|
28
|
+
respectExplicitChildModel: true
|
|
29
|
+
profiles: []
|
|
30
|
+
jev:
|
|
31
|
+
enabled: false
|
|
32
|
+
baseURL: https://api.typesafe.ai
|
|
33
|
+
model: jev-latest
|
|
34
|
+
minConfidence: 0.6
|
|
35
|
+
timeoutMs: 3000
|
|
36
|
+
maxStateChars: 8000
|