@duke-dsh-plugins/dsh-agent-approval 1.6.0 → 1.7.1
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 +8 -5
- package/client.js +23 -17
- package/package.json +12 -3
- package/typert.host.js +27 -0
package/README.md
CHANGED
|
@@ -61,8 +61,8 @@
|
|
|
61
61
|
# 本地开发:pnpm 软链到本仓库,改代码即生效(无需重新复制)
|
|
62
62
|
dsh plugin --profile web add /path/to/dsh-agent-approval
|
|
63
63
|
|
|
64
|
-
# 正式发布:从 GitHub Release tarball
|
|
65
|
-
dsh plugin --profile web add https://github.com/MoonlitDropOfBlood/dsh-agent-approval/releases/download/v1.
|
|
64
|
+
# 正式发布:从 GitHub Release tarball 安装(资产名为 npm pack 的 scope 形式)
|
|
65
|
+
dsh plugin --profile web add https://github.com/MoonlitDropOfBlood/dsh-agent-approval/releases/download/v1.7.1/duke-dsh-plugins-dsh-agent-approval-1.7.1.tgz
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
重启 DSH 后:设置面板出现 **Agent 审批** 页;`/permission` 菜单出现第四项 **Agent 审批**。
|
|
@@ -87,10 +87,11 @@ dsh plugin --profile web add https://github.com/MoonlitDropOfBlood/dsh-agent-app
|
|
|
87
87
|
```
|
|
88
88
|
dsh-agent-approval/
|
|
89
89
|
├── index.js # Host 半:AgentApprovalService(审批瀑布抢占 + spawn 审批 Agent + 审计)
|
|
90
|
-
├── client.js # Client 半:设置页「Agent 审批」+
|
|
91
|
-
├── typert.host.js # Typert Host manifest(agentApproval
|
|
90
|
+
├── client.js # Client 半:设置页「Agent 审批」+ 会话「审批」审计标签页 bundle
|
|
91
|
+
├── typert.host.js # Typert Host manifest(agentApproval 9 个 Remote 方法的描述)
|
|
92
92
|
├── cordis.patch.yml # dsh bundle patch(挂载行 + permission 预设表覆盖)
|
|
93
93
|
├── scripts/patch-glyph.mjs # 可选:权限菜单图标补丁(标准安装不自动执行)
|
|
94
|
+
├── scripts/check-typert-manifest.mjs # npm run check 用:双代 Typert codec 契约冒烟
|
|
94
95
|
├── .github/workflows/ # GitHub Actions 发布
|
|
95
96
|
├── AGENTS.md # 面向 AI agent 的开发指南(含踩坑)
|
|
96
97
|
└── LICENSE # MIT
|
|
@@ -99,11 +100,13 @@ dsh-agent-approval/
|
|
|
99
100
|
## 开发
|
|
100
101
|
|
|
101
102
|
```bash
|
|
102
|
-
npm run check # node --check
|
|
103
|
+
npm run check # node --check 全部脚本 + 双代 Typert 契约冒烟(scripts/check-typert-manifest.mjs)
|
|
103
104
|
dsh plugin --profile web add /path/to/dsh-agent-approval # 安装/重装到本机 DSH profile
|
|
104
105
|
npm run patch:glyph # 可选:权限菜单图标
|
|
105
106
|
```
|
|
106
107
|
|
|
108
|
+
**兼容性**:支持 DSH 0.1.5-rc.3 ~ 0.1.7-rc.1。v1.7.0 起 Typert manifest / Client Remote 描述符的每个 codec 同时携带 `schema`(≤0.1.5 的 zod 契约)与 `create()` 工厂(0.1.7 的新契约),任一宿主代际都能注册;旧版本(≤1.6.0)在 0.1.7 上会被 typert-loader 以 "has no create() factory" 拒绝,Remote 全部失效。
|
|
109
|
+
|
|
107
110
|
详见 [AGENTS.md](AGENTS.md)——记录了 DSH 正式插件(Host/Client/Typert 三件套)的完整机制、审批瀑布 prepend 抢占与结构化子代理裁决的踩坑。
|
|
108
111
|
|
|
109
112
|
## License
|
package/client.js
CHANGED
|
@@ -92,7 +92,7 @@ window.__ModuleLoader__.load({
|
|
|
92
92
|
draws the same shield + AI-star glyph patch-glyph.mjs used, as a
|
|
93
93
|
currentColor mask so hover/selected/disabled colors all follow the shell.
|
|
94
94
|
Scope guard: only menus that already render the official glyph set
|
|
95
|
-
(sibling rows carry span
|
|
95
|
+
(sibling rows carry the Menu primitive's itemIcon span) qualify — the composer /permission
|
|
96
96
|
menu does; the settings PermissionRow dropdown (settings.general 权限 row,
|
|
97
97
|
portaled to <body>) renders NO icons for any preset, so an icon there
|
|
98
98
|
would be an uninvited extra and is deliberately left unmarked. */
|
|
@@ -156,17 +156,20 @@ window.__ModuleLoader__.load({
|
|
|
156
156
|
// inside button[role=menuitem]; an icon-less row starts at the label.
|
|
157
157
|
// Glyph-set guard: only mark our row in menus where the official
|
|
158
158
|
// presets already render their permissionGlyphs (sibling rows carry
|
|
159
|
-
//
|
|
160
|
-
//
|
|
161
|
-
//
|
|
162
|
-
// <
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
//
|
|
159
|
+
// the Menu primitive's icon span). The class-name substring is
|
|
160
|
+
// "itemIcon" (v1.7.0, widened from "_itemIcon_"): CSS-modules compiles
|
|
161
|
+
// the source name differently across host generations
|
|
162
|
+
// (`_itemIcon_<hash>_` vs `<hash>_itemIcon`), and the Menu moved from
|
|
163
|
+
// dsh-client-ui-conversation to dsh-client-ui-permission-presets in
|
|
164
|
+
// 0.1.7-rc.1. The composer /permission menu qualifies; the settings
|
|
165
|
+
// PermissionRow dropdown (portaled to <body>, no item icons for any
|
|
166
|
+
// preset) does NOT, so the glyph no longer leaks into the settings
|
|
167
|
+
// page. (The selected-row checkmark svg is class "_check_", not
|
|
168
|
+
// "itemIcon", so it cannot fake the guard.)
|
|
166
169
|
const menus = document.querySelectorAll('[role="menu"]');
|
|
167
170
|
const glyphMenus = [];
|
|
168
171
|
for (let i = 0; i < menus.length; i++) {
|
|
169
|
-
if (menus[i].querySelector('span[class*="
|
|
172
|
+
if (menus[i].querySelector('span[class*="itemIcon"]') !== null) glyphMenus.push(menus[i]);
|
|
170
173
|
}
|
|
171
174
|
const items = document.querySelectorAll('[role="menu"] button[role="menuitem"]');
|
|
172
175
|
for (let i = 0; i < items.length; i++) {
|
|
@@ -220,22 +223,25 @@ window.__ModuleLoader__.load({
|
|
|
220
223
|
// client assembly mounts only the official namespaces, so a plugin must
|
|
221
224
|
// mount its own. Mirrors the invocations in typert.host.js (id,
|
|
222
225
|
// service/namespace/method). zod is not requirable in the browser module
|
|
223
|
-
// loader, so codecs use passthrough schemas
|
|
224
|
-
//
|
|
226
|
+
// loader, so codecs use passthrough schemas. The wire contract spans two
|
|
227
|
+
// host generations (v1.7.0): the client Remote registry validates
|
|
228
|
+
// `codec.schema.parse` on DSH ≤ 0.1.5-rc.3 but a `codec.create()` factory
|
|
229
|
+
// on 0.1.7-rc.1+ ("strict codec has no create() factory" kills the mount),
|
|
230
|
+
// so every codec carries BOTH fields over the same passthrough schema.
|
|
225
231
|
const passthrough = () => ({ parse: (v) => v });
|
|
232
|
+
const strictCodec = (typeSymbol) => {
|
|
233
|
+
const schema = passthrough();
|
|
234
|
+
return { mode: "strict", typeSymbol, schema, create: () => schema };
|
|
235
|
+
};
|
|
226
236
|
const param = (typeSymbol) => [
|
|
227
237
|
{
|
|
228
238
|
name: "request",
|
|
229
239
|
wire: "request",
|
|
230
240
|
source: "json",
|
|
231
|
-
codec:
|
|
241
|
+
codec: strictCodec(typeSymbol),
|
|
232
242
|
},
|
|
233
243
|
];
|
|
234
|
-
const result = (typeSymbol) => (
|
|
235
|
-
mode: "strict",
|
|
236
|
-
typeSymbol,
|
|
237
|
-
schema: passthrough(),
|
|
238
|
-
});
|
|
244
|
+
const result = (typeSymbol) => strictCodec(typeSymbol);
|
|
239
245
|
const CLIENT_REMOTE = {
|
|
240
246
|
package: "dsh-agent-approval",
|
|
241
247
|
descriptors: [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duke-dsh-plugins/dsh-agent-approval",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "Agent-decided approvals for DeepSeek Harness: a workspace-write base permission mode where an independent approval judge (an isolated subagent, or the TypeSafe Jev decision model via direct API) evaluates every sandbox escalation (risky operations are rejected), with a configurable approval model and a per-session audit trail in the conversation window's 审批 tab.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -32,17 +32,26 @@
|
|
|
32
32
|
},
|
|
33
33
|
"client": {
|
|
34
34
|
"platform": "web"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"dsh": "^0.1.5-rc.3"
|
|
35
38
|
}
|
|
36
39
|
},
|
|
37
40
|
"peerDependencies": {
|
|
38
41
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
39
|
-
"@deepseek-ai/dsh
|
|
42
|
+
"@deepseek-ai/dsh": "^0.1.5-rc.3",
|
|
43
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.0-rc.7 || ^0.1.7-rc.1"
|
|
44
|
+
},
|
|
45
|
+
"peerDependenciesMeta": {
|
|
46
|
+
"@deepseek-ai/dsh": {
|
|
47
|
+
"optional": true
|
|
48
|
+
}
|
|
40
49
|
},
|
|
41
50
|
"dependencies": {
|
|
42
51
|
"zod": "^4.4.3"
|
|
43
52
|
},
|
|
44
53
|
"scripts": {
|
|
45
54
|
"patch:glyph": "node scripts/patch-glyph.mjs",
|
|
46
|
-
"check": "node --check index.js && node --check client.js && node --check typert.host.js && node --check scripts/patch-glyph.mjs"
|
|
55
|
+
"check": "node --check index.js && node --check client.js && node --check typert.host.js && node --check scripts/patch-glyph.mjs && node --check scripts/check-typert-manifest.mjs && node scripts/check-typert-manifest.mjs"
|
|
47
56
|
}
|
|
48
57
|
}
|
package/typert.host.js
CHANGED
|
@@ -12,6 +12,17 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Result schemas are STRICT: every Host return value must match exactly
|
|
14
14
|
* (fields present, types correct), or the gateway validation fails.
|
|
15
|
+
*
|
|
16
|
+
* Codec wire format spans two host generations (v1.7.0): DSH ≤ 0.1.5-rc.3
|
|
17
|
+
* validates and parses through `codec.schema` (a zod v4 instance — the
|
|
18
|
+
* typert-loader checked `"_zod" in schema`, the gateway called
|
|
19
|
+
* `codec.schema.parse`), while DSH 0.1.7-rc.1+ replaced that contract with a
|
|
20
|
+
* `codec.create()` FACTORY (the loader now rejects any codec "with no create()
|
|
21
|
+
* factory"; the gateway calls `codec.create().parse`). Every codec below
|
|
22
|
+
* therefore carries BOTH fields: `schema` keeps 0.1.5 loading, `create` keeps
|
|
23
|
+
* 0.1.7 loading, and both generations parse through the same zod instance.
|
|
24
|
+
* Removing either field breaks one generation at startup (the typert-loader
|
|
25
|
+
* throw is why 0.1.7 refused this manifest before v1.7.0).
|
|
15
26
|
*/
|
|
16
27
|
|
|
17
28
|
import { z } from "zod";
|
|
@@ -230,6 +241,7 @@ export const TYPERT = {
|
|
|
230
241
|
mode: "strict",
|
|
231
242
|
typeSymbol: "dsh-agent-approval#AgentApprovalStateResult",
|
|
232
243
|
schema: stateResultSchema,
|
|
244
|
+
create: () => stateResultSchema,
|
|
233
245
|
},
|
|
234
246
|
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
235
247
|
},
|
|
@@ -248,6 +260,7 @@ export const TYPERT = {
|
|
|
248
260
|
mode: "strict",
|
|
249
261
|
typeSymbol: "dsh-agent-approval#AgentApprovalSetModelRequest",
|
|
250
262
|
schema: _agentApproval_setModel_parameter_0$schema,
|
|
263
|
+
create: () => _agentApproval_setModel_parameter_0$schema,
|
|
251
264
|
},
|
|
252
265
|
},
|
|
253
266
|
],
|
|
@@ -255,6 +268,7 @@ export const TYPERT = {
|
|
|
255
268
|
mode: "strict",
|
|
256
269
|
typeSymbol: "dsh-agent-approval#AgentApprovalSetModelResult",
|
|
257
270
|
schema: setModelResultSchema,
|
|
271
|
+
create: () => setModelResultSchema,
|
|
258
272
|
},
|
|
259
273
|
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
260
274
|
},
|
|
@@ -273,6 +287,7 @@ export const TYPERT = {
|
|
|
273
287
|
mode: "strict",
|
|
274
288
|
typeSymbol: "dsh-agent-approval#AgentApprovalSetJevRequest",
|
|
275
289
|
schema: _agentApproval_setJevConfig_parameter_0$schema,
|
|
290
|
+
create: () => _agentApproval_setJevConfig_parameter_0$schema,
|
|
276
291
|
},
|
|
277
292
|
},
|
|
278
293
|
],
|
|
@@ -280,6 +295,7 @@ export const TYPERT = {
|
|
|
280
295
|
mode: "strict",
|
|
281
296
|
typeSymbol: "dsh-agent-approval#AgentApprovalSetJevResult",
|
|
282
297
|
schema: setJevResultSchema,
|
|
298
|
+
create: () => setJevResultSchema,
|
|
283
299
|
},
|
|
284
300
|
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
285
301
|
},
|
|
@@ -298,6 +314,7 @@ export const TYPERT = {
|
|
|
298
314
|
mode: "strict",
|
|
299
315
|
typeSymbol: "dsh-agent-approval#AgentApprovalSetTimeoutRequest",
|
|
300
316
|
schema: _agentApproval_setApprovalTimeout_parameter_0$schema,
|
|
317
|
+
create: () => _agentApproval_setApprovalTimeout_parameter_0$schema,
|
|
301
318
|
},
|
|
302
319
|
},
|
|
303
320
|
],
|
|
@@ -305,6 +322,7 @@ export const TYPERT = {
|
|
|
305
322
|
mode: "strict",
|
|
306
323
|
typeSymbol: "dsh-agent-approval#AgentApprovalSetTimeoutResult",
|
|
307
324
|
schema: setTimeoutResultSchema,
|
|
325
|
+
create: () => setTimeoutResultSchema,
|
|
308
326
|
},
|
|
309
327
|
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
310
328
|
},
|
|
@@ -323,6 +341,7 @@ export const TYPERT = {
|
|
|
323
341
|
mode: "strict",
|
|
324
342
|
typeSymbol: "dsh-agent-approval#AgentApprovalToggleRequest",
|
|
325
343
|
schema: _agentApproval_toggle_parameter_0$schema,
|
|
344
|
+
create: () => _agentApproval_toggle_parameter_0$schema,
|
|
326
345
|
},
|
|
327
346
|
},
|
|
328
347
|
],
|
|
@@ -330,6 +349,7 @@ export const TYPERT = {
|
|
|
330
349
|
mode: "strict",
|
|
331
350
|
typeSymbol: "dsh-agent-approval#AgentApprovalToggleResult",
|
|
332
351
|
schema: toggleResultSchema,
|
|
352
|
+
create: () => toggleResultSchema,
|
|
333
353
|
},
|
|
334
354
|
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
335
355
|
},
|
|
@@ -348,6 +368,7 @@ export const TYPERT = {
|
|
|
348
368
|
mode: "strict",
|
|
349
369
|
typeSymbol: "dsh-agent-approval#AgentApprovalAddRuleRequest",
|
|
350
370
|
schema: _agentApproval_addRule_parameter_0$schema,
|
|
371
|
+
create: () => _agentApproval_addRule_parameter_0$schema,
|
|
351
372
|
},
|
|
352
373
|
},
|
|
353
374
|
],
|
|
@@ -355,6 +376,7 @@ export const TYPERT = {
|
|
|
355
376
|
mode: "strict",
|
|
356
377
|
typeSymbol: "dsh-agent-approval#AgentApprovalRulesResult",
|
|
357
378
|
schema: addRuleResultSchema,
|
|
379
|
+
create: () => addRuleResultSchema,
|
|
358
380
|
},
|
|
359
381
|
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
360
382
|
},
|
|
@@ -373,6 +395,7 @@ export const TYPERT = {
|
|
|
373
395
|
mode: "strict",
|
|
374
396
|
typeSymbol: "dsh-agent-approval#AgentApprovalRemoveRuleRequest",
|
|
375
397
|
schema: _agentApproval_removeRule_parameter_0$schema,
|
|
398
|
+
create: () => _agentApproval_removeRule_parameter_0$schema,
|
|
376
399
|
},
|
|
377
400
|
},
|
|
378
401
|
],
|
|
@@ -380,6 +403,7 @@ export const TYPERT = {
|
|
|
380
403
|
mode: "strict",
|
|
381
404
|
typeSymbol: "dsh-agent-approval#AgentApprovalRulesResult",
|
|
382
405
|
schema: removeRuleResultSchema,
|
|
406
|
+
create: () => removeRuleResultSchema,
|
|
383
407
|
},
|
|
384
408
|
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
385
409
|
},
|
|
@@ -398,6 +422,7 @@ export const TYPERT = {
|
|
|
398
422
|
mode: "strict",
|
|
399
423
|
typeSymbol: "dsh-agent-approval#AgentApprovalSessionRecordsRequest",
|
|
400
424
|
schema: _agentApproval_sessionRecords_parameter_0$schema,
|
|
425
|
+
create: () => _agentApproval_sessionRecords_parameter_0$schema,
|
|
401
426
|
},
|
|
402
427
|
},
|
|
403
428
|
],
|
|
@@ -405,6 +430,7 @@ export const TYPERT = {
|
|
|
405
430
|
mode: "strict",
|
|
406
431
|
typeSymbol: "dsh-agent-approval#AgentApprovalSessionRecordsResult",
|
|
407
432
|
schema: sessionRecordsResultSchema,
|
|
433
|
+
create: () => sessionRecordsResultSchema,
|
|
408
434
|
},
|
|
409
435
|
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
410
436
|
},
|
|
@@ -419,6 +445,7 @@ export const TYPERT = {
|
|
|
419
445
|
mode: "strict",
|
|
420
446
|
typeSymbol: "dsh-agent-approval#AgentApprovalDirectoryResult",
|
|
421
447
|
schema: directoryResultSchema,
|
|
448
|
+
create: () => directoryResultSchema,
|
|
422
449
|
},
|
|
423
450
|
sourceLocation: { file: "index.js", line: 1, column: 1 },
|
|
424
451
|
},
|