dsh-plugin-tool-management 0.6.0 → 0.8.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +179 -0
  2. package/README.md +117 -221
  3. package/README_EN.md +116 -220
  4. package/docs/images/1/345/234/272/346/231/257.png +0 -0
  5. package/docs/images/1/345/234/272/346/231/257_en.png +0 -0
  6. package/docs/images/2MCP.png +0 -0
  7. package/docs/images/2MCP_en.png +0 -0
  8. package/docs/images/3/346/212/200/350/203/275.png +0 -0
  9. package/docs/images/3/346/212/200/350/203/275_en.png +0 -0
  10. package/docs/images/4/345/255/220/346/231/272/350/203/275/344/275/223.png +0 -0
  11. package/docs/images/4/345/255/220/346/231/272/350/203/275/344/275/223_en.png +0 -0
  12. package/docs/images/5/346/217/220/347/244/272/350/257/215.png +0 -0
  13. package/docs/images/5/346/217/220/347/244/272/350/257/215_en.png +0 -0
  14. package/docs/images/6/350/256/260/345/277/206.png +0 -0
  15. package/docs/images/6/350/256/260/345/277/206_en.png +0 -0
  16. package/docs/images/7/344/274/232/350/257/235.png +0 -0
  17. package/docs/images/7/344/274/232/350/257/235_en.png +0 -0
  18. package/docs/images/8/345/205/274/345/256/271.png +0 -0
  19. package/docs/images/8/345/205/274/345/256/271_en.png +0 -0
  20. package/docs/update.md +56 -38
  21. package/lib/agents-md/service.js +84 -5
  22. package/lib/client.js +1488 -475
  23. package/lib/compat/preset-reach.js +425 -0
  24. package/lib/compat/probe.js +8 -0
  25. package/lib/http-fence.js +21 -0
  26. package/lib/hub.js +160 -2
  27. package/lib/index.js +687 -47
  28. package/lib/mcp/override-blocks.js +195 -0
  29. package/lib/mcp/state-section.js +90 -0
  30. package/lib/prompt-sections.js +148 -0
  31. package/lib/rules/archive-engine.js +99 -29
  32. package/lib/rules/archive.js +56 -28
  33. package/lib/rules/service.js +332 -35
  34. package/lib/skills/core.js +15 -1
  35. package/lib/skills/service.js +3 -0
  36. package/lib/subagents/catalog.js +89 -0
  37. package/lib/subagents/service.js +384 -41
  38. package/lib/subagents/tools.js +18 -5
  39. package/package.json +97 -96
  40. package/screenshots.json +10 -10
  41. package/docs/Changelog.md +0 -144
  42. package/lib/rules/provider.js +0 -121
package/package.json CHANGED
@@ -1,96 +1,97 @@
1
- {
2
- "name": "dsh-plugin-tool-management",
3
- "version": "0.6.0",
4
- "description": "DSH plugin: one settings panel for MCP servers, Skills, AGENTS.md presets, archived sessions and scene memories — plus scene memory injected into the system prompt and one-shot persona subagents. Settings UI + HTTP API + 14 model tools (skill_mcp_manager_*, skill_manager_*, agentsmd_*, rule_manager_*, subagent_*). Install with one command: dsh plugin --profile web add dsh-plugin-tool-management@latest",
5
- "repository": {
6
- "type": "git",
7
- "url": "https://github.com/ouli-1242/dsh-plugin-tool-management"
8
- },
9
- "type": "module",
10
- "main": "lib/index.js",
11
- "exports": {
12
- ".": "./lib/index.js",
13
- "./client": "./lib/client.js",
14
- "./workspace": "./lib/history/workspace.js",
15
- "./projcache": "./lib/history/projcache.js",
16
- "./package.json": "./package.json"
17
- },
18
- "files": [
19
- "lib",
20
- "cordis.patch.yml",
21
- "README.md",
22
- "README_EN.md",
23
- "LICENSE",
24
- "screenshots.json",
25
- "docs"
26
- ],
27
- "engines": {
28
- "node": ">=18"
29
- },
30
- "publishConfig": {
31
- "registry": "https://registry.npmjs.org",
32
- "access": "public"
33
- },
34
- "scripts": {
35
- "build": "tsc -p tsconfig.json && node scripts/sync-client.mjs",
36
- "build:client": "node scripts/sync-client.mjs",
37
- "prepublishOnly": "npm run build",
38
- "lint": "node --check lib/client.js && node --check lib/index.js",
39
- "check:i18n": "node scripts/check-i18n.mjs src/client.js",
40
- "check:host": "node scripts/host-deps.mjs && node scripts/doctor.mjs",
41
- "host-deps": "node scripts/host-deps.mjs --fix",
42
- "doctor": "node scripts/doctor.mjs",
43
- "test": "npm run build && npm run check:i18n && node --test test/archive.test.mjs test/import.test.mjs test/approval-policy.test.mjs test/subagent-scene.test.mjs test/subagent-persona.test.mjs test/hub-layout.test.mjs test/skills-state.test.mjs test/skills-delete.test.mjs test/skills-source-remove.test.mjs test/client-exports.test.mjs test/client-render.test.mjs test/compat-probe.test.mjs test/compat-fallback.test.mjs"
44
- },
45
- "keywords": [
46
- "dsh",
47
- "deepseek-harness",
48
- "skill",
49
- "skills",
50
- "mcp",
51
- "mcp-server",
52
- "plugin",
53
- "cordis"
54
- ],
55
- "dsh": {
56
- "bundle": {
57
- "patch": "./cordis.patch.yml"
58
- },
59
- "client": {
60
- "platform": "web",
61
- "inject": [
62
- "@deepseek-ai/dsh-client-locale"
63
- ]
64
- }
65
- },
66
- "peerDependencies": {
67
- "@deepseek-ai/cordis": "^4.0.1",
68
- "@deepseek-ai/dsh-tools": ">=0.1.5-rc.2 <0.2.0-0",
69
- "@deepseek-ai/dsh-workspace": ">=0.1.5-rc.2 <0.2.0-0",
70
- "@deepseek-ai/dsh-spill-local": ">=0.1.5-rc.2 <0.2.0-0",
71
- "@deepseek-ai/dsh-session-projection-cache": ">=0.1.5-rc.2 <0.2.0-0",
72
- "@deepseek-ai/dsh-storage-domain": ">=0.1.5-rc.2 <0.2.0-0",
73
- "@deepseek-ai/dsh-subagent-spawn-in-process": ">=0.1.5-rc.2 <0.2.0-0",
74
- "react": "^18.2.0"
75
- },
76
- "peerDependenciesMeta": {
77
- "@deepseek-ai/dsh-subagent-spawn-in-process": {
78
- "optional": true
79
- }
80
- },
81
- "devDependencies": {
82
- "@deepseek-ai/cordis": "^4.0.1",
83
- "@deepseek-ai/dsh-session-projection-cache": "^0.1.5-rc.2",
84
- "@deepseek-ai/dsh-spill-local": "^0.1.5-rc.2",
85
- "@deepseek-ai/dsh-storage-domain": "^0.1.5-rc.2",
86
- "@deepseek-ai/dsh-tools": "^0.1.5-rc.2",
87
- "@deepseek-ai/dsh-user-approval": "^0.1.5-rc.2",
88
- "@deepseek-ai/dsh-workspace": "^0.1.5-rc.2",
89
- "@types/node": "^24.0.0",
90
- "typescript": "^6.0.0"
91
- },
92
- "license": "MIT",
93
- "dependencies": {
94
- "fflate": "^0.8.3"
95
- }
96
- }
1
+ {
2
+ "name": "dsh-plugin-tool-management",
3
+ "version": "0.8.0",
4
+ "description": "DSH plugin: one settings panel for MCP servers, Skills, AGENTS.md presets, archived sessions and scene memories — plus scene memory injected into the system prompt and one-shot persona subagents. Settings UI + HTTP API + 14 model tools (skill_mcp_manager_*, skill_manager_*, agentsmd_*, rule_manager_*, subagent_*). Install with one command: dsh plugin --profile web add dsh-plugin-tool-management@latest",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/ouli-1242/dsh-plugin-tool-management"
8
+ },
9
+ "type": "module",
10
+ "main": "lib/index.js",
11
+ "exports": {
12
+ ".": "./lib/index.js",
13
+ "./client": "./lib/client.js",
14
+ "./workspace": "./lib/history/workspace.js",
15
+ "./projcache": "./lib/history/projcache.js",
16
+ "./package.json": "./package.json"
17
+ },
18
+ "files": [
19
+ "lib",
20
+ "cordis.patch.yml",
21
+ "README.md",
22
+ "README_EN.md",
23
+ "CHANGELOG.md",
24
+ "LICENSE",
25
+ "screenshots.json",
26
+ "docs"
27
+ ],
28
+ "engines": {
29
+ "node": ">=18"
30
+ },
31
+ "publishConfig": {
32
+ "registry": "https://registry.npmjs.org",
33
+ "access": "public"
34
+ },
35
+ "scripts": {
36
+ "build": "tsc -p tsconfig.json && node scripts/sync-client.mjs",
37
+ "build:client": "node scripts/sync-client.mjs",
38
+ "prepublishOnly": "npm run build",
39
+ "lint": "node --check lib/client.js && node --check lib/index.js",
40
+ "check:i18n": "node scripts/check-i18n.mjs src/client.js",
41
+ "check:host": "node scripts/host-deps.mjs && node scripts/doctor.mjs",
42
+ "host-deps": "node scripts/host-deps.mjs --fix",
43
+ "doctor": "node scripts/doctor.mjs",
44
+ "test": "npm run build && npm run check:i18n && node --test test/archive.test.mjs test/import.test.mjs test/approval-policy.test.mjs test/subagent-scene.test.mjs test/subagent-persona.test.mjs test/hub-layout.test.mjs test/skills-state.test.mjs test/skills-delete.test.mjs test/skills-source-remove.test.mjs test/client-exports.test.mjs test/client-render.test.mjs test/compat-probe.test.mjs test/compat-fallback.test.mjs test/preset-reach.test.mjs test/rules-toggle-args.test.mjs"
45
+ },
46
+ "keywords": [
47
+ "dsh",
48
+ "deepseek-harness",
49
+ "skill",
50
+ "skills",
51
+ "mcp",
52
+ "mcp-server",
53
+ "plugin",
54
+ "cordis"
55
+ ],
56
+ "dsh": {
57
+ "bundle": {
58
+ "patch": "./cordis.patch.yml"
59
+ },
60
+ "client": {
61
+ "platform": "web",
62
+ "inject": [
63
+ "@deepseek-ai/dsh-client-locale"
64
+ ]
65
+ }
66
+ },
67
+ "peerDependencies": {
68
+ "@deepseek-ai/cordis": "^4.0.1",
69
+ "@deepseek-ai/dsh-tools": ">=0.1.5-rc.2 <0.2.0-0",
70
+ "@deepseek-ai/dsh-workspace": ">=0.1.5-rc.2 <0.2.0-0",
71
+ "@deepseek-ai/dsh-spill-local": ">=0.1.5-rc.2 <0.2.0-0",
72
+ "@deepseek-ai/dsh-session-projection-cache": ">=0.1.5-rc.2 <0.2.0-0",
73
+ "@deepseek-ai/dsh-storage-domain": ">=0.1.5-rc.2 <0.2.0-0",
74
+ "@deepseek-ai/dsh-subagent-spawn-in-process": ">=0.1.5-rc.2 <0.2.0-0",
75
+ "react": "^18.2.0"
76
+ },
77
+ "peerDependenciesMeta": {
78
+ "@deepseek-ai/dsh-subagent-spawn-in-process": {
79
+ "optional": true
80
+ }
81
+ },
82
+ "devDependencies": {
83
+ "@deepseek-ai/cordis": "^4.0.1",
84
+ "@deepseek-ai/dsh-session-projection-cache": "^0.1.5-rc.2",
85
+ "@deepseek-ai/dsh-spill-local": "^0.1.5-rc.2",
86
+ "@deepseek-ai/dsh-storage-domain": "^0.1.5-rc.2",
87
+ "@deepseek-ai/dsh-tools": "^0.1.5-rc.2",
88
+ "@deepseek-ai/dsh-user-approval": "^0.1.5-rc.2",
89
+ "@deepseek-ai/dsh-workspace": "^0.1.5-rc.2",
90
+ "@types/node": "^24.0.0",
91
+ "typescript": "^6.0.0"
92
+ },
93
+ "license": "MIT",
94
+ "dependencies": {
95
+ "fflate": "^0.8.3"
96
+ }
97
+ }
package/screenshots.json CHANGED
@@ -1,10 +1,10 @@
1
- [
2
- "docs/images/1场景.png",
3
- "docs/images/2MCP.png",
4
- "docs/images/3技能.png",
5
- "docs/images/4子智能体.png",
6
- "docs/images/5提示词.png",
7
- "docs/images/6记忆.png",
8
- "docs/images/7会话.png",
9
- "docs/images/8兼容.png"
10
- ]
1
+ [
2
+ "docs/images/1场景.png",
3
+ "docs/images/2MCP.png",
4
+ "docs/images/3技能.png",
5
+ "docs/images/4子智能体.png",
6
+ "docs/images/5提示词.png",
7
+ "docs/images/6记忆.png",
8
+ "docs/images/7会话.png",
9
+ "docs/images/8兼容.png"
10
+ ]
package/docs/Changelog.md DELETED
@@ -1,144 +0,0 @@
1
- # Changelog
2
-
3
- `dsh-plugin-tool-management` 的**版本变更记录**:每个版本改了什么、有哪些已知限制。
4
-
5
- - 只要「大致内容」→ [版本更新概要](./update.md)
6
- - 功能说明与用法 → [README](../README.md) / [README_EN](../README_EN.md)
7
- - 版本号 = npm 上实际发布的发布号;**日期 = npm 发布时刻(UTC)**,本地时间(UTC+8)比它晚 8 小时。
8
- - 开发期的过程记录(根因分析、逐条实测数据、评审条目)不在这里,见 git 提交历史。
9
-
10
- ---
11
-
12
- ## v0.6.0(2026-09-14)
13
-
14
- **主题:宿主兼容体检。** 插件不再靠「比对官方源码文本」判断能不能动宿主数据,改为「查模块实体 + 探能力」,并把结果做成设置页里的「兼容」页;同时修掉归档会话的工作区归属、技能来源权限语义两类真缺陷。
15
-
16
- ### 新增
17
-
18
- - **「工具 → 兼容」页(第 8 个页签,只读)**:宿主版本与要求范围、插件适配版本、能力可用数、**每个宿主动作走哪条路径**(宿主原生入口 / 插件适配层 / 不可用)、已降级能力与原因、模块实体是否与宿主同一份、阻塞项清单,以及命令行体检入口。数据来自新 op `compat-status`,页面可「重新检查」。
19
- - **`node scripts/doctor.mjs`**:命令行版同一份体检,打印模块实体归属与宿主能力探测结果。
20
- - **`node scripts/host-deps.mjs`(`--fix` / `--restore`)**:把插件用的 `@deepseek-ai/*` 逐包改为指向宿主安装的 junction(原始副本备份到 `.host-deps-backup/`)。两边的包不是同一份物理模块时,`instanceof` / `===` / symbol 查找都不成立,「适配宿主实现」只能退化成猜。
21
- - **归档分组可重建**:工作区登记被 DSH 删除后(删登记不删目录、不删会话),归档列表按会话目录自动重建分组,标「工作区已移除」/「未登记的工作区」;目录仍在时给一个「重新登记为工作区」按钮(只在用户确认后调用宿主自己的接口,**只新增登记,不动文件与会话**)。
22
- - **恢复归档顺带恢复归属**:恢复会话后按会话目录把它挂回工作区记账(新增登记 / 复用已有登记 / 挂回会话),响应里带回 `registered` / `attached` / `skipped`,界面按结果显示一句话结论。此前恢复出来的会话在宿主侧没有归属,只会掉进「未分组」。
23
- - **场景可绑定一份提示词预设**:场景表单里选一个(单值字段 = 天然单选)。绑定前校验预设存在(不存在直接拒绝,不留悬空绑定),预设事后被删则场景卡片标「预设不存在」。**切换场景会直接改写 `~/.dsh/AGENTS.md`**(见下条)。
24
- - **切换场景直接改写 `~/.dsh/AGENTS.md`**(同日,**反转**本轮早先「只注入一段、不碰文件」的决定 —— 用户裁定:「切换场景,对应的提示词直接把 AGENTS.md 直接修改」):启用/切换场景、改绑预设、编辑"正在驱动基线的那份预设"的正文,四个动作都会把那份预设**真写进全局基线**,与「提示词」页的「应用」同一条路(覆盖前多代备份到 `agents-md/__last-applied__/`);**关掉场景时按原文恢复"进场景之前"的基线**(那份可能是用户手写的,不一定对应任何预设)——快照存 hub 的 `scene-baseline.json`,恢复后清空,连续切场景不会覆盖快照。相应地,`tool-management:scene-prompt` 注入段**已删除**(真改文件后再注入一遍会让同一份正文进上下文两次,且用户手改基线后还会被重新注入);绑定关系只保留只读投影,用于页面「生效中」标记与"文件是否已同步"的判断(内容一致时**不写盘**)。同步逻辑提成独立模块 `src/scene-prompt-sync.ts`,可在临时目录上用真实服务端到端验证。
25
- - **提示词预设库:新建即可写正文、编辑可改 id**:新建弹窗是「id + 正文文本框」(外加「或从现有预设复制」下拉,选中后把那份正文填进文本框,仍可继续改),不再是那个容易被当成搜索框的「复制来源」文本输入;编辑弹窗同样有 id 与正文两个字段。**改 id = 目录改名**(正文随目录一起走,目标已存在则拒绝、不合并),改名成功后宿主顺手把场景绑定一起改名(新增 op `rules-rebind-prompt`),不留悬空绑定。
26
- - **「生效中」以场景绑定的那份为准**:场景启用且绑了提示词预设时,**提示词页把场景绑的那份标成「生效中」**(用户裁定:「场景启动了,提示词内生效中的应该是场景选择的那个」),页面顶部写明来源(`当前:life(场景「A」)`);切换场景会把它写进 `AGENTS.md`,所以「文件里是它」这个降级标记只在用户手改过基线、或写入失败时才会出现。
27
- - **正在生效的提示词预设不能删除**(用户裁定):提示词页把「生效中」那行的**删除按钮禁用**并给出原因(悬停可见),宿主侧 `agentsmd-remove` 也**拒绝**删除它——生效 = 启用的场景绑定了它,否则 = 文件内容就是它;两者都不是的预设照常可删(被场景覆盖、只躺在文件里的那份也允许删)。删除按钮只是提示,真正的门在宿主:模型调用或旧页面缓存都会被挡住;被挡住时界面会把宿主返回的原因显示成错误条(`doRemove` 此前丢弃了响应,是静默失败)。判定失败时放行并记 warn——删预设不动 `~/.dsh/AGENTS.md`,最坏只是少一份副本。
28
- - **技能导入弹窗新增「选择文件夹」**;人设的**工具白/黑名单按官方 Agent 预设分组**展示(同一工具属于多个预设时在对应分组各出现一次,勾选状态共享),不再把所有非当前会话工具统一标成「当前会话不可见」。
29
-
30
- ### 变更
31
-
32
- - **兼容判定换底座**:删除「按源码文本比对官方实现」的门禁(上游改一行注释就会让归档/恢复/删除整体拒绝服务)。现在按能力路由——**有原生入口走原生、没有走受检适配层、都不行才拒绝**;拒绝信息写明**缺什么能力、后果、怎么修**,并且**永远发生在任何写入之前**。宿主本来就没有的可选原生槽位不算降级(由插件自己顶上)。
33
- - **技能来源权限语义修正**(两组来源的权限正好相反):默认来源 `DSH 技能`(`~/.dsh/skills/`)与 `导入技能`(`~/.dsh/tool-management/skills/`)**必须读取**——不可移除、**也不可停用**(停用等于「读出来但不可调用」,与「路径不能不读取」冲突);但**里面的技能可以删**(进回收站,可原样恢复)。外部 Agent 目录与自定义目录相反:**可以停用或移除**(不再读取),但里面的技能**只读、不能删**。旧版本写过的 `sources.hub` / `removedSources` 残留策略位在读取时被丢弃。
34
- - **用户数据搬出插件目录**:归档账本 `history-archived-at.json`、保留期 `history-retention.json`、工作区登记快照 `history-workspaces.json` 移入 `~/.dsh/tool-management/`(旧位置是插件目录 `data/`,启动时自动搬入,只搬不删、绝不覆盖)。npm 安装下 `dsh plugin update` 会整体替换插件目录,账本放那里会连累保留期基线。
35
- - **归档服务改为独立门面**:`cordis.patch.yml` **只插入本插件**——不再禁用官方 `workspace` / `session-projection-cache`,不再插入竞争 provider,也不按包名推断兼容性。归档时刻改由官方持久化事件打点;宿主自带删除屏障时不包裹投影缓存,缺屏障时才包裹并在卸载后原样还原。
36
- - **弹窗按钮统一**:全插件 24 处弹窗的「取消 / 关闭」只留在右上角(外加 Esc 与点遮罩),底部只留主操作。
37
- - **语言跟随宿主**:客户端显式注入 `locale`(`dsh.client.inject` 精简为 `@deepseek-ai/dsh-client-locale`),面板与页签名不再恒为中文;**会话页**与 **AGENTS.md(提示词)页**整页接入中英词典(新增约 100 条词条)。`check:i18n` 新增一项检查:**代码里以字面量引用的键必须都在词典里**(挡住「界面直接显示原始键名」)。
38
- - **AGENTS.md 预设「应用」保留 5 代备份**:写入 `__last-applied__/AGENTS.md.bak-<时间戳>`,按时间轮转只留最近 5 份(旧机器读取的 `__last-applied__/AGENTS.md` 照旧维护)。单槽位备份下连点两次「应用」会永久覆盖用户手写的原始内容。
39
- - **提示词预设 id 口径放宽**(用户裁定「id 应该什么都能写」):不再限定小写字母/数字/连字符,中文、空格、下划线、点都可以。id 即目录名,因此只保留文件系统硬约束——不含 `/ \` 与 `< > : " | ? *`、不以点开头、不以点或空格结尾、不是 `.`/`..`、不是 Windows 保留设备名(`con`/`nul`/`com1`…)、不含控制字符、≤64 字符,以及一个保留字 `__last-applied__`(「应用」的备份槽)。口径收在新的单一模块 `src/agents-md/preset-id.ts`,AGENTS.md 预设库与场景绑定(`scenes[].prompt`)共用,避免两处漂移;导入预设的 id 也不再被压成 slug。
40
- - **场景启用改单选**:除保留场景「全局」外**同时只能启用一个场景** —— 服务端拒绝多选(`error.rules.singleSceneOnly`,旧的 `all:true` 形态一并拒绝),界面把其余场景的开关**置灰**并说明被谁占用;`rules-create-scene` 会把历史默认 `active = null`(旧语义「全部启用」)**收敛成显式数组**,因此**新场景默认不启动**,并把 `collapsedActive` 回传界面如实提示;「切入此模式」现在会**同时启用该场景**(档案、记忆、提示词一起生效)。存量 `active = null` 且多个场景在场的状态**仍按旧语义读**(记忆段注入全部),场景页给一条显式「收敛为单选」按钮,而不是静默改写注入范围。
41
- - **模型/脚本入口语义收紧**:`history-retention-set` 拒绝小数(原来 1.5 被静默取整成 1)并在错误里回显收到的值;`rules-set-active` 必须显式传 `all:true` 或 `scenes:[…]`(无参不再静默把注入范围清成空);`mcpm-set-enabled` 的停用分支幂等(不再每点一次就往 `cordis.patch.yml` 追加一条重复项);`skill_manager_create` 的落点与界面「创建技能」一致(都落 hub);`history-import` 改为经宿主 `agents.create` 创建会话并回读校验,导入失败如实报错(会话 id 形态变为 `session-<uuid>`)。
42
- - **写操作门禁**:HTTP 路由先过宿主的 `connection.requestRejection`(Host 必须是回环 / LAN IP 字面量,叠加 browser-session cookie);宿主服务不在场时退回**本地判定**(只要求回环 Host + 非跨站 Fetch + Origin 与 Host 同源,**不含 cookie 鉴权**,比宿主栅栏弱)。`mcpm-reveal` / `mcpm-export` 这类会吐明文密钥的 op 额外要求请求带 `Origin` 头。显式配置的 `token` 是脚本 / 局域网的逃生门:令牌正确即视为已授权(并跳过栅栏)。
43
-
44
- ### 修复
45
-
46
- - **进出场景模式会静默改写技能策略(数据污染)**:快照与目标状态用的是**生效状态**,写回的却是**显式策略记录**,两者不等价 → 进出一次模式就会把用户从未启用的技能写成启用、把显式启用的改写成显式停用。现在扫描一次同时给出「生效 / 被同名覆盖 / 全量键」,快照只取生效项,写回时跳过被覆盖的副本、且**已经处于目标状态的技能不再写**。修复后同一实验下状态文件与基线逐字节一致。
47
- - **导入技能里删掉的技能拿不回来**:回收站元数据把非项目级来源记成了项目级,恢复时被判「原项目不在活动工作区」而拒绝。现在按作用域分岔,用户级来源按 key 重新解析路径(不信任元数据里的旧路径)。
48
- - **技能回收站显示字面量 `undefined`**:项目级来源缺名称/路径时不再拼空值,统一回退到来源显示名。
49
- - **面板不随宿主语言切换**、**会话页与 AGENTS.md 页整页硬编码中文**、**两个词条键写错导致界面露出原始键名**(`mcp.field.entryId` → `mcp.detail.entryId`)。
50
- - **`subagent_run` 的确认门早于参数校验**:人设不存在时不再先弹确认卡(批准后才报错),直接让工具体给出真实错误。
51
- - **删除链路的前置实现检查**:删除序列依赖官方声明为 private 的方法,此前失败点可能落在链路中段、留下「转录已删但归档标记还在」的部分状态。现在在任何破坏性步骤(含写屏障)之前校验所需方法,缺失即快速失败并提示更新插件。
52
- - **英文界面下兼容页的结论条仍是中文**:`compat-status` 的 `summary` 由服务端拼中文,英文界面直接照抄。现改为**客户端按当前语言拼**(新增 `compat.summary.ok` / `compat.summary.degraded` 两条词条),服务端那份 `summary` 只留给日志;并加一条本地化回归断言:英文词典下渲染兼容页,结论条不得出现中文字符(只锁"不许露中文",不锁措辞)。
53
- > 仍未本地化:降级项的 `label` / `detail` 与阻塞项文本仍由 `src/compat/probe.ts` 输出中文。宿主一切正常时页面上看不到它们(多数机器就是这个状态),一旦真降级,英文界面会中英混排。
54
- - **`history-workspace-register` 漏了 token 门禁**:它会新增一条宿主工作区登记,属写操作却不在 `WRITE_OPS` 里 —— 配置了 `token` 时它不校验 `x-dsh-token`(仍受宿主栅栏约束)。现补入清单,与其它写 op 一致。
55
- - **两处与实际行为不符的界面文案**:AGENTS.md「应用」的说明补上「备份**保留最近 5 代**」;创建技能的确认卡原写 `DSH_HOME/skills`,而该工具已改为落 `~/.dsh/tool-management/skills/`(与界面「创建技能」同根)。
56
-
57
- ### 已知限制(本版)
58
-
59
- - **浏览器交互验收仍未跑**(宿主要 launch token)。能进 CI 的是导出契约、装配与渲染、语义契约三层,**挡不住交互行为**;破坏性路径(归档 → 恢复 → 永久删除 → 保留期清理)仍需人工在实机点一次。
60
- - **与 `@michengai/dsh-archive-manager` 未做双安装验证**,不宣称与任意版本共存。归档兼容层仍是**有限兼容层**,不是零侵入:本地恢复/删除访问经检查的宿主内部状态;宿主缺自带删除屏障时会包裹投影缓存的 `put` / `write`(卸载后还原)。
61
- - **依赖去重只处理「两边都有」的包**;只有插件侧存在的包会报 `SKEW` 且**不被改动**。生产布局(`profiles/<name>/node_modules/<plugin>`)不需要跑 `--fix`,开发 `link:` 布局才需要。
62
- - **能力探测的版本指纹**取自 `@deepseek-ai/dsh-workspace` 的 `package.json`;官方拆包或改名时指纹退化为 `unknown`(此时仍按能力判断,不按版本)。能力评估有 5 秒 TTL,兼容页与写路由最多滞后 5 秒。
63
- - **硬编码中文未清零**:`node scripts/i18n-debt.mjs` 当前报 **214 条**(提示词页 15 条 + 199 条散落在未按页统计的组件与共享壳中;会话页已清零)。该脚本按页面函数分区统计,因此「按页」只能覆盖它认得的页面。
64
- - **官方 Config schema 缺失**:插件仍以 `{name, inject, apply}` 形式加载,`config.*` 裸读,没有加载期校验与默认值。
65
- - **场景提示词的三个边界**:① 保留场景「全局」也可手工绑定提示词(写在 `rules-index.json` 的 `scenes.global.prompt`),但它只在**没有任何场景启用**时生效,界面暂不暴露该入口;② 场景提示词**不计入记忆字节预算**(预算只管记忆段),体量由你自己控制;③ 历史 `active = null` 的多场景状态要你点一次「收敛为单选」才进入单选语义。
66
- - 其它长期边界见下方「长期约束与边界」。
67
-
68
- ---
69
-
70
- ## v0.5.1(2026-09-13)
71
-
72
- - **场景档案弹窗:新加的段默认一项都不勾**——MCP 工具集 / 技能集 / 子智能体绑定是空集,记忆段只预勾本场景里已启用的那几条;「全选」= 本场景全部。段脚注写明代价:空段 = 该域全部停用(子智能体段例外,空段 = 不限制)。
73
- - **档案弹窗「记忆」段只列被编辑场景自己的记忆**:宿主侧按记忆所属场景取档案,列别的场景(含「全局」)勾了不起作用,属陷阱 → 改为与本弹窗其余三段同构的平铺勾选行;记忆描述按 80 字截断,全文进悬浮提示。
74
- - **场景页排版重做**:卡片只留「名字 / 标签 / 开关 + 一行描述 + 动作行」,数量收进页首「当前模式」条(只在真的进入模式后出现);描述上限 60 字;「切入此模式」升为卡片主按钮。
75
- - **保留场景「全局」不再出现在场景页与档案弹窗**:它恒定注入、不是可切换的预设,MCP / 技能 / 人设各有专页;标记「任何对话都注入」压成「常驻」。
76
- - 客户端契约测试补上「档案弹窗默认勾选」「记忆段只认本场景的记忆」「场景页不列全局」等用例;两份 README 的测试组清单同步校正。
77
-
78
- **已知限制(未变)**:浏览器交互验收未跑;硬编码中文欠账未清零;官方 Config schema 缺失。
79
-
80
- ## v0.5.0(2026-09-13)
81
-
82
- **破坏性 / 结构性变更**
83
-
84
- - **插件产生的文件全部收进 `~/.dsh/tool-management/`**:记忆、人设、AGENTS.md 预设、新建/导入的技能、回收站、索引与配置。旧位置(`~/.dsh/scene-memory/`、更旧的 `~/.dsh/rules/`、`~/.dsh/subagents/`、插件目录 `data/agents-md-presets/`)首次启动**自动搬入**,纪律四条:**只搬不删**(源目录留空壳)、**绝不覆盖**(目标同名则跳过)、**每进程一次**、**失败不阻断**。`~/.dsh/skills/`(官方技能目录)**不搬**,仍作为可切换来源。
85
- - **场景从「恰好有这个名字的目录」升级为显式记录**(`rules-index.json` 的 `scenes` 切片:`label` / `description` / `order` / `createdAt`)。**空场景合法**;保留场景 `global`(界面「全局」)恒定存在、不可删除;`memories/` 根层的裸 `.md` **不再注入**并在体检里报 `noScene`;场景名单个路径段。
86
- - **斜杠命令全部下线**:`/mcp`、`/skills`、`/agents-md`、`/scene-memory`——它们只能输出纯文本快照,既不能操作也容易与面板状态不一致。
87
-
88
- **新增 / 变更**
89
-
90
- - **技能来源**:新增插件自有来源 **「导入技能」**(`~/.dsh/tool-management/skills/`,新建 / 导入的落点,优先级高于 `~/.dsh/skills/`,同名时遮蔽官方那份);新增 **「移除来源」**——与「停用来源」不同,移除是**连目录都不再扫描**(技能从列表消失、不参与同名优先级、模型侧候选也不产出),**源文件一个字节都不动**,可一键恢复读取。
91
- - **界面**:工具页七栏(场景 / MCP / 技能 / 子智能体 / 提示词 / 记忆 / 会话);场景档案编辑器新增第 4 段「记忆」(勾选只影响注入,文件不动);人设的模型与工具限制收进「高级选项」折叠区(模型下拉 + 工具白/黑名单勾选器);勾选区拉高(弹窗上限 620 → 720 px,段体改为下限优先);四个表单的辅助提示去冗余(删 6 条、改短 4 条)。
92
- - **i18n**:MCP 页与共享状态层从硬编码中文改为词典取词;七个页面的副标题统一为同一句式。
93
-
94
- **修复**
95
-
96
- - **工具页整页白屏**:`sceneLabel` 定义在 `MemoryPage` 闭包里却被 `ScenesPage` 调用 → `ReferenceError` 被 slot 边界吞成日志。
97
- - **导出静默丢失**:`module.exports._pages` / `DICT` 写在 `apply` 方法体末尾,`apply` 提前返回就永不执行 → 改为在 factory 作用域落地。
98
- - **Skills 页被锁死**:校验器要求状态文件里记录每个来源,新增 `hub` 来源后旧文件被判非法 → fail-closed 全停用 + 锁定写入(文件其实完好)。改为校验归一化后的文档:**缺键自愈、类型错仍拒绝**。
99
- - 人设目录不存在时创建失败;旧布局迁移把场景目录多套一层;`skill-create` 不传 root 时落错目录。
100
-
101
- **已知限制(未变)**:浏览器交互验收未跑(宿主要 launch token);硬编码中文欠账未清零;官方 Config schema 缺失。
102
-
103
- ## v0.2.0 及更早(2026-09-12)
104
-
105
- - 五个域合并进一个「工具」设置面板:**MCP / Skills / AGENTS.md 预设 / History(归档会话)**。
106
- - **MCP**:单个工具可独立启停(模型看不见也调不到)、重启只重连**不改变启停状态**、密钥(`env` / `headers`)默认打码、改写补丁前自动留时间戳 `.bak`(保留 5 份)、重复 loader id 写前拦截、跨级迁移失败自动回滚。
107
- - **Skills**:接入 `~/.agents` / `~/.codex` / `~/.claude` 与自定义目录(只读接入、重叠路径拒绝);创建 / ZIP 与文件夹导入 / 回收站 / 系统编辑器打开源文件;技能目录后台监听,编辑器改完页面自动刷新。
108
- - **AGENTS.md 预设库**:多套全局指令基线,一键「应用」写入 `~/.dsh/AGENTS.md`(新会话生效,当前会话不变)。
109
- - **History**:归档会话按项目分组、搜索、全选、批量恢复 / 永久删除、保留期自动清理;从 Claude Code / Cursor(JSONL)、Codex(Markdown)、任意文本导入;导出 Markdown / JSONL。
110
-
111
- > 对 **0.1.1 / 0.1.2 / 0.1.3** 没有可查的记录,因此不拆分它们的差异。开发期内部编号 `v0.3`、`v0.4` 未单独发布,内容随 v0.5.0 一起发布。
112
-
113
- ---
114
-
115
- ## 长期约束与边界
116
-
117
- 跨版本有效,改代码前先读。
118
-
119
- ### 非干扰原则(红线)
120
-
121
- 任何时候不得为插件功能改写 DSH 原生文件的语义、不得给原生段改名或改序、不得让注入内容破坏前缀缓存契约。违反任意一条即视为架构回归。
122
-
123
- - **前缀缓存友好**:注入段文本只由「启用场景 + 文件内容」决定,逐字节稳定;场景切换或编辑记忆只变化一次。段内不得出现时间戳、计数、相对时间等每轮变化的内容。
124
- - **数据落点**:插件**不在自己的安装目录存用户数据**(npm 安装会整体替换该目录);用户数据一律在 `~/.dsh/tool-management/`。稳态零写入,唯一会「覆盖」的是运行期手改这些文件——请在停止 `dsh web` 后再改。
125
- - **生效方式**:插件由宿主启动时加载 `lib/`,**改动需重启 `dsh web`**(patch 热重载不会重新 import 插件模块);`lib/` 不入版本库,克隆后先 `npm run build`。
126
-
127
- ### 治理与兼容边界
128
-
129
- - **子代理有两条通道**:本插件的 `subagent_run` 走确认门与场景人设绑定;DSH 官方的 `subagent` / `subagent_fork` 是宿主能力,**没有确认门、也不认这套人设**。本插件的治理只覆盖 `subagent_run`。
130
- - **归档兼容层**:官方目前没有完整的公开归档扩展接口,实际执行的是受检适配层(访问经检查的内部状态)。它是**有限兼容层**,不等于零侵入,也不等于与官方实现解耦。
131
- - **契约测试的边界**:契约测试断言语义契约而非实现抄写,替代不了真实行为验收;浏览器交互与破坏性路径仍需人工在实机确认。
132
- - **尚未验证**:与 `@michengai/dsh-archive-manager` 的双安装;官方工具在 `never` 会话下的行为;服务器「后加载」场景;`subagent_run` 参数不可见时的线上抓包复核。
133
-
134
- ### 升级 DSH 之后(按序执行)
135
-
136
- ```bash
137
- node scripts/doctor.mjs # 1. 模块实体是否同一份 + 宿主能力是否齐备
138
- node scripts/host-deps.mjs --fix # 出现「两份拷贝」时执行(改动的是 node_modules,不动源码)
139
- npm test # 2. 契约测试(13 组,跑 lib/ 产物)
140
- # 3. 打开 设置 → 工具 → 兼容:确认宿主版本、降级项、每个动作走哪条路径
141
- # 4. 破坏性路径人工回归:归档 → 恢复 → 永久删除 → 保留期清理
142
- ```
143
-
144
- 宿主缺某个包时,插件会拒绝受影响的动作并说明原因,不会「猜着写」。
@@ -1,121 +0,0 @@
1
- // dsh-plugin-tool-management —— 规则「自动在场层」投影(systemPrompt 段注册)。
2
- //
3
- // 变更单 01 的核心:把规则从"投影为 skill 目录条目(模型按需 load)"改为
4
- // **投影为 system prompt 段(自动在场)**。前者即使命中,模型也要自己决定看不看,
5
- // 正是用户抱怨的"每次都要解释"。
6
- //
7
- // 官方接口语义(@deepseek-ai/dsh-system-prompt):
8
- // - `section({ name, order, text })` 在**调用者的 scope** 注册;scoped 段遮蔽同名全局段。
9
- // - `text` 可以是**每次装配时求值的 provider 函数** → 切换启用场景后**下一个请求即生效**,
10
- // 无需重开会话、无需重载插件。
11
- // - `renderPrompt` 会**删除空段** → 无启用场景/空目录时返回 `''`,不产生空标题。
12
- //
13
- // 为什么注册两处(全局 + per-agent):
14
- // 全局注册覆盖所有 agent(含子 agent);per-agent 注册保证即使插件 ctx 自带 scope
15
- // (全局段对某些 agent 不可见)也能命中 —— 两者同名,scoped 遮蔽全局,不会重复注入。
16
- //
17
- // 缓存契约(§5.2):段文本是**会话级恒定**的(只由启用场景与文件内容决定),
18
- // 因此前缀逐字节稳定 → 前缀缓存可命中;禁止在段里放时间戳/计数/相对时间。
19
- const SECTION_NAME = 'tool-management:scene-memory';
20
- /**
21
- * §5.1 硬约束 2:官方 `SECTION_ORDERS` 里 2901–4999 是空档(TOOL_REPORT 2900 →
22
- * TOOLS_SDK 5000),取 **3000** —— 语义上是"工具能力说明之后、输出与 SDK 约定之前",
23
- * 且远离任何既有段。**不要**用官方已有数值(同号按名称排序,虽确定但难读,日后易撞)。
24
- */
25
- const SECTION_ORDER = 3000;
26
- const GLOBAL_KEY = '@global';
27
- /** 取 scope 上的 systemPrompt 服务(Cordis 的 ctx.get 可能抛错,全部吞掉)。 */
28
- function systemPromptOf(scope) {
29
- if (!scope)
30
- return undefined;
31
- try {
32
- if (typeof scope.get === 'function')
33
- return scope.get('systemPrompt');
34
- return scope.systemPrompt;
35
- }
36
- catch {
37
- return undefined;
38
- }
39
- }
40
- /** 注册全局 + agent-scope 的场景记忆段与场景提示词段。 */
41
- export function createRuleProviderRegistrar(ctx, facade) {
42
- const registrations = new Map();
43
- const install = (scope, key) => {
44
- if (!scope || registrations.has(key))
45
- return;
46
- const systemPrompt = systemPromptOf(scope);
47
- if (!systemPrompt || typeof systemPrompt.section !== 'function')
48
- return;
49
- try {
50
- const dispose = systemPrompt.section({
51
- name: SECTION_NAME,
52
- order: SECTION_ORDER,
53
- // 每次装配重读活动场景 → 切换启用状态后下一个请求即生效。
54
- // ⚠️ 硬约束 1:必须**同步返回 string**(不能是 Promise)——异步读取会破坏 renderPrompt。
55
- text: () => facade.renderActiveScenes(),
56
- });
57
- registrations.set(key, { scope, dispose: typeof dispose === 'function' ? dispose : () => { } });
58
- }
59
- catch (e) {
60
- // 同层重名注册会抛错:降级为"该段不注入",不影响其余 scope。
61
- console.error(`[dsh-plugin-tool-management] ${SECTION_NAME} section registration failed:`, String((e && e.message) || e));
62
- }
63
- };
64
- const uninstall = (key) => {
65
- const entry = registrations.get(key);
66
- if (!entry)
67
- return;
68
- registrations.delete(key);
69
- try {
70
- entry.dispose();
71
- }
72
- catch { /* ignore */ }
73
- };
74
- // ① 全局:插件 ctx 的 scope(覆盖所有 agent)
75
- install(ctx, GLOBAL_KEY);
76
- // ② per-agent:与既有 install/uninstall 生命周期一致(agent/created、agent/disposed)
77
- const on = ctx && ctx.on;
78
- let stopCreated;
79
- let stopDisposed;
80
- if (typeof on === 'function') {
81
- stopCreated = on('agent/created', (payload) => {
82
- const agent = payload && payload.agent;
83
- if (agent && agent.id != null)
84
- install(agent.ctx, String(agent.id));
85
- });
86
- stopDisposed = on('agent/disposed', (payload) => {
87
- const agent = payload && payload.agent;
88
- if (agent && agent.id != null)
89
- uninstall(String(agent.id));
90
- });
91
- }
92
- // 已存在的 agent(插件热加载场景):补注册。
93
- try {
94
- const agents = typeof ctx.get === 'function' ? ctx.get('agents') : undefined;
95
- if (agents && typeof agents.list === 'function') {
96
- for (const agent of agents.list()) {
97
- if (agent && agent.id != null)
98
- install(agent.ctx, String(agent.id));
99
- }
100
- }
101
- }
102
- catch { /* agents 服务不可用 → 仅靠事件 */ }
103
- return {
104
- invalidate: () => {
105
- for (const entry of registrations.values()) {
106
- try {
107
- entry.scope?.emit?.('system-prompt/change');
108
- }
109
- catch { /* 宿主无该事件 → 忽略 */ }
110
- }
111
- },
112
- dispose: () => {
113
- if (typeof stopCreated === 'function')
114
- stopCreated();
115
- if (typeof stopDisposed === 'function')
116
- stopDisposed();
117
- for (const key of [...registrations.keys()])
118
- uninstall(key);
119
- },
120
- };
121
- }