dsh-plugin-tool-management 0.1.3 → 0.5.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 +108 -38
- package/README_EN.md +161 -37
- package/cordis.patch.yml +11 -0
- package/docs/Changelog.md +471 -0
- package/docs/images/MCP.png +0 -0
- package/docs/images//344/274/232/350/257/235.png +0 -0
- package/docs/images//345/234/272/346/231/257.png +0 -0
- package/docs/images//345/255/220/346/231/272/350/203/275/344/275/223.png +0 -0
- package/docs/images//346/212/200/350/203/275.png +0 -0
- package/docs/images//346/217/220/347/244/272/350/257/215.png +0 -0
- package/docs/images//350/256/260/345/277/206.png +0 -0
- package/lib/approval-policy.js +46 -0
- package/lib/client.js +2288 -256
- package/lib/hub.js +94 -0
- package/lib/imports/upload.js +286 -0
- package/lib/index.js +586 -113
- package/lib/rules/archive-engine.js +191 -0
- package/lib/rules/archive.js +140 -0
- package/lib/rules/provider.js +121 -0
- package/lib/rules/service.js +2166 -0
- package/lib/skills/core.js +366 -23
- package/lib/skills/service.js +36 -10
- package/lib/subagents/service.js +333 -0
- package/lib/subagents/tools.js +62 -0
- package/package.json +20 -12
- package/screenshots.json +9 -0
package/README.md
CHANGED
|
@@ -3,36 +3,47 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/dsh-plugin-tool-management)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](package.json)
|
|
6
|
-
[](https://github.com/ouli-1242/dsh-plugin-tool-management)
|
|
7
|
-
|
|
8
|
-
**简体中文** · [English](README_EN.md)
|
|
6
|
+
[](https://github.com/ouli-1242/dsh-plugin-tool-management)
|
|
7
|
+
[](https://dsh.market/)
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
**简体中文** · [English](README_EN.md) · [Changelog](docs/Changelog.md)
|
|
10
|
+
|
|
11
|
+
**DeepSeek Harness 的 MCP 服务、技能与记忆管理插件。** 一个设置面板管好五件事:
|
|
11
12
|
|
|
12
13
|
- **MCP**:连接了哪些服务、每个服务有哪些工具、哪些工具该让模型用——增删改查、启停、重启,全部即改即生效;
|
|
13
14
|
- **Skills**:本机各处的技能(DSH / Agents / Codex / Claude / 项目级 / 你自己指定的任意目录)一目了然,逐个或整组启停、创建、导入、回收;
|
|
14
15
|
- **AGENTS.md**:管理多套全局指令基线预设,一键「应用」写入 `~/.dsh/AGENTS.md`,新会话生效、当前会话不变;
|
|
15
|
-
- **History
|
|
16
|
+
- **History**:已归档会话统一管理,按项目分组、批量恢复/删除,对话导入/导出,保留期自动清理;
|
|
17
|
+
- **场景记忆**:`~/.dsh/tool-management/memories/<场景>/` 下一个文件夹 = 一个场景、一个 `.md` = 一条记忆——**新建场景**(带描述)、往里放 `.md`(文件名支持中文)、开关场景;启用场景里的记忆正文**整篇自动进入系统提示词**,不用每次重复解释。保留场景 `global`(界面「全局」)恒定注入任何对话。
|
|
16
18
|
|
|
17
19
|
不手改 `cordis.patch.yml`,不碰任何技能源文件,重启与升级后配置依旧。
|
|
18
20
|
|
|
19
21
|
---
|
|
20
22
|
|
|
21
|
-
<!-- 图片占位 1:MCP 管理页截图 → docs/images/
|
|
23
|
+
<!-- 图片占位 1:MCP 管理页截图 → docs/images/MCP.png -->
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
27
|
+
<!-- 图片占位 2:Skills 管理页截图 → docs/images/技能.png -->
|
|
22
28
|
|
|
23
|
-

|
|
24
30
|
|
|
25
|
-
<!-- 图片占位
|
|
31
|
+
<!-- 图片占位 3:AGENTS.md 预设页截图 → docs/images/提示词.png -->
|
|
26
32
|
|
|
27
|
-

|
|
28
34
|
|
|
29
|
-
<!-- 图片占位
|
|
35
|
+
<!-- 图片占位 4:History 归档会话页截图 → docs/images/会话.png -->
|
|
30
36
|
|
|
31
|
-

|
|
32
38
|
|
|
33
|
-
<!-- 图片占位
|
|
39
|
+
<!-- 图片占位 5:场景记忆页截图 → docs/images/场景.png -->
|
|
34
40
|
|
|
35
|
-

|
|
42
|
+
<!-- 图片占位 6:记忆页截图 → docs/images/记忆.png -->
|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
<!-- 图片占位 7:子智能体页截图 → docs/images/子智能体.png -->
|
|
46
|
+

|
|
36
47
|
|
|
37
48
|
## 核心亮点
|
|
38
49
|
|
|
@@ -44,14 +55,20 @@
|
|
|
44
55
|
| 写入保护 | 每次改写补丁前自动留 `.bak` 时间戳备份(保留 5 份);重复 loader id 写前拦截、跨级迁移失败自动回滚 |
|
|
45
56
|
| 备份恢复 | JSON 导入支持 `overwrite` 覆盖同 id 条目,不再只能跳过 |
|
|
46
57
|
| 技能来源 | 接入 `~/.agents` / `~/.codex` / `~/.claude` 三个官方不加载的技能目录,并支持**自定义任意技能目录**(只读接入、重叠拒绝) |
|
|
47
|
-
| 技能操作 | 创建技能、ZIP/文件夹导入、插件回收站(恢复 / 永久删除 /
|
|
58
|
+
| 技能操作 | 创建技能、ZIP/文件夹导入、插件回收站(恢复 / 永久删除 / 系统回收站兜底)、系统编辑器打开源文件。**删除只对项目级来源开放**:DSH 技能与导入技能(`~/.dsh/skills/`、`~/.dsh/tool-management/skills/`)**不可删除**,只能停用 |
|
|
59
|
+
| 技能来源命名 | `DSH 技能` = 官方 `~/.dsh/skills/`;**`导入技能`** = 插件导入/新建的落点 `~/.dsh/tool-management/skills/`(优先级高于 DSH 技能,同名时遮蔽官方那份) |
|
|
48
60
|
| 即时刷新 | 技能目录由后台线程监听,编辑器里改完技能页面自动刷新 |
|
|
49
61
|
| AGENTS.md 预设 | 多套全局指令基线预设库:新建 / 导入 / 编辑 / 应用 / 删除;「应用」写入 `~/.dsh/AGENTS.md`(新会话生效,当前会话不变) |
|
|
50
62
|
| 会话归档管理 | History 页按项目分组展示已归档会话:搜索、全选、批量恢复 / 永久删除、保留期自动清理(改保留期后倒计时以修改时间为基准重置) |
|
|
51
63
|
| 对话导入 / 导出 | 从 Claude Code / Cursor(JSONL)、Codex(Markdown)、任意文本无痛接管对话;导出可选会话范围,目录默认桌面,支持 Markdown / JSONL |
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
64
|
+
| 场景记忆自动生效 | 记忆 = `~/.dsh/tool-management/memories/<场景>/<name>.md`;勾选启用的场景,其目录树内所有 `.md` 正文**自动进入系统提示词**(per-agent `systemPrompt` 段),模型无需任何工具调用,切换后**下一个请求即生效**;保留场景 **`global`(界面「全局」)恒定注入任何对话** |
|
|
65
|
+
| 记忆导入 | 记忆页「导入记忆」:`.md` / `.zip`(可多选、可拖入);zip 内目录名即场景,裸 `.md` 落到弹窗所选场景(留空 = 保留场景「全局」);zip 内 `<场景>/<名>/SKILL.md` 按 **bundle** 导入(同层文件作附件);同名跳过并列出名单,**为此补出来的场景也会在结果里列出** |
|
|
66
|
+
| 场景启用开关 | 场景是**显式记录**(带描述、顺序),目录名支持中文;「启用场景」多选开关全局持久化在 `rules-index.json` 的 `active`;**无配置时全部启用**,`global` 与 `_shared/` 恒常生效 |
|
|
67
|
+
| 场景档案(自由搭配) | 每个场景可勾选自己的 **MCP 工具集 / 技能集 / 子智能体绑定 / 记忆**(任意组合;清单只列实时存在的条目,勾=启用/未勾=停用;MCP 还支持两级:不勾服务器=整台停用,勾了服务器但一个工具都不勾=该服务器全停)。**记忆段只影响注入**(没勾的记忆不进提示词,文件原样保留)。勾了工具/技能段的场景可「设为当前模式」:应用档案前先落盘快照、退出按快照**原文**恢复;仅记忆 / 仅子智能体的场景不显示模式按钮;进入后下一请求生效 |
|
|
68
|
+
| 轻量子智能体 | `~/.dsh/tool-management/agents/<人设>.md` 一个文件一个人设(frontmatter 可选:`description` / `provider` + `model` / `tools` 白名单 / `toolsDeny` 黑名单,正文=人设提示词,缺省自动派生);页头「导入」支持 `.md` / `.zip`(同名跳过并列出名单);模型经 `subagent_list` / `subagent_run` 调用——子代理带人设运行、只回传结果、即用即弃(不进 History);**自动继承当前启用场景的记忆段**;场景档案可绑定「本场景可用哪些人设」(绑定外调用直接拒绝);运行默认需确认,设置可关 |
|
|
69
|
+
| 前缀缓存友好 | 段文本只由「启用场景 + 文件内容」决定,逐字节稳定;场景切换 / 编辑记忆只变化一次,其余请求缓存照常命中(不违反"零注入层"——那条只禁每轮动态变化的内容) |
|
|
70
|
+
| 模型工具 | **14 个**:`skill_mcp_manager_*` 管 MCP(4),`skill_manager_*` 管技能(3),`agentsmd_list` / `agentsmd_apply` 管 AGENTS.md 预设库(2,模型只能查与切换,不能新建/删除,以免误删用户预设),`rule_manager_*` 管场景记忆(3,创建前需用户确认,可在设置中关闭),`subagent_list` / `subagent_run` 调用人设子智能体(2,运行前默认需确认,设置 `requireConfirmForModelSubagentRun` 可关)。**三个确认门都识别会话审批策略**:`approval=never`(完全权限)下确认卡不可能弹出,插件视为「用户已预先批准」直接放行并记 `confirm-bypass` 日志(与官方子代理工具在完全权限下的行为一致) |
|
|
71
|
+
| 界面 | 独立的 `dsm-*` 设计系统,**七栏**(场景 / MCP / 技能 / 子智能体 / 提示词 / 记忆 / 会话)页头同构、段卡片统一;勾选类界面(档案四段 / 人设工具黑白名单)共用同一套排版,长列表都有筛选框;人设的模型与工具限制收在「高级选项」折叠区(已配置则自动展开);通知分两级(成功 = 浮层,警告/错误 = 页内横幅);档案弹窗固定高度,加减段不跳动 |
|
|
55
72
|
|
|
56
73
|
## 快速开始
|
|
57
74
|
|
|
@@ -66,7 +83,7 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
|
|
|
66
83
|
dsh plugin --profile web remove dsh-plugin-tool-management
|
|
67
84
|
```
|
|
68
85
|
|
|
69
|
-
装完硬刷新浏览器(Cmd/Ctrl+Shift-R),设置里出现
|
|
86
|
+
装完硬刷新浏览器(Cmd/Ctrl+Shift-R),设置里出现 **工具** 面板(场景 / MCP / 技能 / 子智能体 / 提示词 / 记忆 / 会话 七栏)即安装成功(客户端改动由 DSH 热加载,无需重启)。
|
|
70
87
|
|
|
71
88
|
也可以直接对任意 DSH 会话说:
|
|
72
89
|
|
|
@@ -90,31 +107,58 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
|
|
|
90
107
|
|
|
91
108
|
- **看全貌**:按来源分组列出所有技能——项目级、运行时、内置、插件自带,以及四个用户目录(`~/.dsh` / `~/.agents` / `~/.codex` / `~/.claude`,后三个由本插件接入)和你自己添加的自定义目录。
|
|
92
109
|
- **启停**:单个技能、整个来源、整个项目,随时切换;实现是 override provider 的遮蔽策略,源文件一个字节都不动,换机或重装只要复制状态文件。
|
|
110
|
+
- **移除来源**:与「停用来源」不同——停用仍会扫描并列出该来源的技能(只是不可调用),**移除则连目录都不再扫描**:技能从列表消失,也不参与同名优先级,模型侧(provider 候选)同样看不到。文件与目录**一个字节都不动**,随时可恢复;保留给用户的 `dsh`(官方 DSH 技能目录)与 `hub`(导入技能落点)以及项目级来源不可移除,界面上不显示该按钮。
|
|
111
|
+
- **同名技能自选**:多处出现同名技能时,默认按来源优先级自动取一个生效(其余显示「被覆盖」,无开关);想改用某来源的版本,点该行「启用这个」即设为**同名首选**并启用——首选只写进状态文件(`preferredSkills`),不动任何源文件;赢家行可「取消首选」回到自动。来源整体停用时「启用这个」会被拦截并提示先启用该来源。
|
|
93
112
|
- **自定义目录**:点「添加目录」输入绝对路径,该目录即成为只读技能来源——适合管理散落在仓库、网盘同步目录里的技能合集;与已有来源重叠的路径会被拒绝,避免遮蔽失效。
|
|
94
|
-
- **创建与导入**:表单直接创建;ZIP、`.md`、技能文件夹拖进来就能装;删除先进回收站,可恢复,永久删除前还会尝试移入系统回收站兜底。
|
|
95
|
-
|
|
96
|
-
### 管 AGENTS.md 预设
|
|
97
|
-
|
|
98
|
-
- **预设库**:新建、导入、编辑多套全局指令基线(如不同团队的 coding standard 或不同角色的行为规范)。
|
|
99
|
-
- **应用即写入**:「应用」把选中预设写入 `~/.dsh/AGENTS.md`,**新会话生效、当前会话不变**;编辑后点「重新应用」即可同步最新内容,删除前请先切换到其他预设。
|
|
100
|
-
|
|
101
|
-
### 管历史会话
|
|
102
|
-
|
|
103
|
-
- **按项目分组**:归档会话按工作区自动分组展示,搜索标题 / 会话 ID / 项目路径快速定位;工作区目录已不存在的会话会打上 ⚠ 标记。
|
|
104
|
-
- **批量操作**:「全选」后批量恢复或永久删除;恢复的会话回到工作区列表,删除会连同其子代理子会话一并清理。
|
|
105
|
-
- **保留期**:顶部下拉选择自动清理周期(0 = 永久保留),到期自动清除;修改保留期后,所有会话的倒计时以修改时间为基准重新计算。
|
|
106
|
-
- **导入对话**:无痛接管其他工具的会话——Claude Code / Cursor 的 JSONL、Codex 的 Markdown、以及任意文本格式,导入后即可继续对话。
|
|
113
|
+
- **创建与导入**:表单直接创建;ZIP、`.md`、技能文件夹拖进来就能装;删除先进回收站,可恢复,永久删除前还会尝试移入系统回收站兜底。
|
|
114
|
+
|
|
115
|
+
### 管 AGENTS.md 预设
|
|
116
|
+
|
|
117
|
+
- **预设库**:新建、导入、编辑多套全局指令基线(如不同团队的 coding standard 或不同角色的行为规范)。
|
|
118
|
+
- **应用即写入**:「应用」把选中预设写入 `~/.dsh/AGENTS.md`,**新会话生效、当前会话不变**;编辑后点「重新应用」即可同步最新内容,删除前请先切换到其他预设。
|
|
119
|
+
|
|
120
|
+
### 管历史会话
|
|
121
|
+
|
|
122
|
+
- **按项目分组**:归档会话按工作区自动分组展示,搜索标题 / 会话 ID / 项目路径快速定位;工作区目录已不存在的会话会打上 ⚠ 标记。
|
|
123
|
+
- **批量操作**:「全选」后批量恢复或永久删除;恢复的会话回到工作区列表,删除会连同其子代理子会话一并清理。
|
|
124
|
+
- **保留期**:顶部下拉选择自动清理周期(0 = 永久保留),到期自动清除;修改保留期后,所有会话的倒计时以修改时间为基准重新计算。
|
|
125
|
+
- **导入对话**:无痛接管其他工具的会话——Claude Code / Cursor 的 JSONL、Codex 的 Markdown、以及任意文本格式,导入后即可继续对话。
|
|
107
126
|
- **导出对话**:按会话范围(全部 / 仅归档 / 按工作区)导出,每个会话一个 Markdown 或 JSONL 文件;导出目录默认桌面,旁边带「选择文件夹」按钮弹出目录树,逐级浏览选中后自动回填绝对路径。
|
|
108
127
|
|
|
128
|
+
### 管场景(场景页)
|
|
129
|
+
|
|
130
|
+
> 场景 = 分组维度,记忆(`.md`)= 内容;场景可挂「档案」:MCP 工具集 / 技能集 / 子智能体绑定 / 记忆,四段自由搭配。
|
|
131
|
+
> 数据统一收在 `~/.dsh/tool-management/`(目录结构、旧路径自动搬迁、缓存设计见 [Changelog](docs/Changelog.md))。
|
|
132
|
+
|
|
133
|
+
- **场景是显式记录**:`memories/<场景>/` 是它的记忆目录,场景本身带**描述**与顺序(存在 `rules-index.json` 的 `scenes` 切片)。`~/.dsh/tool-management/memories/办公/流程.md` 即"办公"场景下的一条记忆。场景名支持中文等任意 Unicode(≤64 字符,不含 `/ \ < > : " | ? *`,不以 `.` 开头,**单个路径段**);`global` 是保留场景(界面显示「全局」),`_shared/` 是历史保留的公共场景。
|
|
134
|
+
- **新建场景**:点「新建场景」填名字与一句描述(也可以自己在 `memories/` 下 `mkdir`,效果一样,下次读取会补上记录)。**空场景也合法**——可以先把场景建好、之后再往里放记忆。卡片上还有「改描述」随时补说明。
|
|
135
|
+
- **每个 `.md` 就是一条记忆**:一句话或一段话都行,不用写 frontmatter,整篇正文都会注入。往场景文件夹里丢文件就生效,也可以点卡片上的「新建记忆」在页面里写——**文件名支持中文**(如 `站会流程.md`)。
|
|
136
|
+
- **开关场景**:场景卡片右侧的开关就是启用/停用(与 Skills 页同一套组件和布局)。其目录树内**所有 `.md` 的正文会自动进入系统提示词**——模型不需要做任何动作,也不用每次重复解释。切换**下一个请求即生效**,无需重开会话或重载插件。
|
|
137
|
+
- **默认全部启用**:没有任何配置时所有场景都生效("丢进去就有用");场景多了再在页面上收窄。`global`(「全局」)与 `_shared/` 恒常生效,卡片上没有开关。
|
|
138
|
+
- **全局记忆**:保留场景 `global` 的记忆**任何对话都注入**(不吃场景开关),适合"放之四海皆准"的偏好与约定。新建记忆时场景留空即落到这里。
|
|
139
|
+
- **导入记忆**:页头「导入记忆」支持 `.md` 与 `.zip`(可多选、可拖入)。zip 内带目录时**目录名即场景**(`工作/standup.md` → 场景 `工作`);**直接拖入文件夹同理**(按文件夹层级落场景,多级目录保留为 `A/B`);裸 `.md` 落到弹窗里选的场景——**留空 = 保留场景「全局」**。zip 内 `<场景>/<名>/SKILL.md` 按 **bundle** 导入(落 `<场景>/<名>/`,**同层文件作附件**;附件名非法 / 空 / 单个 >8 MB / 合计 >16 MB 逐条跳过并回报)。文件按原文落盘,**同名自动跳过并列出名单**(不覆盖既有记忆)。所有被丢弃的内容都会**回报原因**(含 zip 内超限条目),不做静默丢弃;导入时引用到的场景若还不存在会**自动补一条场景记录并在结果里列出**(不静默造数据)。
|
|
140
|
+
- **记忆 = 一个 Markdown 文件**:`<场景>/<name>.md`(flat)或 `<场景>/<name>/SKILL.md`(bundle,可带附件)。新建时选场景(下拉里是已存在的场景,要去「场景」页先建)、填名称(= 文件名)、描述与正文,frontmatter 全部可选,缺失时插件自动派生。**归属不存在的场景会被明确拒绝**(`场景不存在`),不再静默造场景。
|
|
141
|
+
- **bundle 附件**:形态选 bundle 时可直接**添加附件**(多选,单个 ≤8 MB、单次 ≤16 MB / 32 个);附件存在记忆目录里,**不会进入提示词**(只有 `SKILL.md` 正文注入),编辑时可逐个移除。flat 是单文件,没有目录可放附件。
|
|
142
|
+
- **启停与回收**:逐条启停(每行右侧开关,停用的记忆仍留在磁盘上,只是不进提示词)、编辑、移入回收站;页头「回收站」可以**恢复**或**永久删除**已删记忆,删除前有二次确认。`enabled` 等状态存在侧车索引里,绝不回写记忆文件。
|
|
143
|
+
- **注入预算可见**:页头下方常驻一条预算条(已用 / 上限字节),超限变红并标「已超限」。默认上限 64 KiB;**某条记忆放不下时只跳过它**、继续装后面放得下的小记忆,段尾会附一份「未注入(超出预算)」清单——模型与用户都能看到哪些记忆这次没进提示词,而不是静默丢失。
|
|
144
|
+
- **不再改写 `~/.dsh/AGENTS.md`**:原"始终层"已下线,公共基线改由 `_shared/` 承担,统一走系统提示词段。
|
|
145
|
+
- **场景档案(四段自由搭配)**:卡片上「档案」打开编辑器,四段各自独立"添加/移除"——**MCP 工具集**(两级勾选:先勾服务器,「添加」时按当前运行时状态预勾;不勾=整台停用,勾了但一个工具都不勾=该服务器全停)、**技能集**(勾选器只列实时发现的条目,预勾当前启用状态,勾=启用/未勾=停用)、**子智能体绑定**(勾人设名单,全不选=不限制)、**记忆**(场景卡片列出每个场景的记忆与已勾条数,点「选记忆」进场景内明细;**只影响注入**——没勾的记忆不进系统提示词,文件与内容一律不动)。编辑器顶部有筛选框,长列表不用靠滚动找;弹窗固定高度,加减段不跳动。勾了工具/技能段的场景出现「设为当前模式」按钮:**进入模式 = 快照当前启停 → 先落盘快照 → 应用勾选集 → 记忆收窄到该场景**;「退出模式」按快照**原文**恢复(模式期间写进去的整台停用键随之消失)。运行中手动改动不会偷偷回写,点「保存到场景」才落盘。进入后下一请求生效。任一步失败自动回滚并如实上报(回滚未完成会写进错误文本,不谎报「已回滚」)。
|
|
146
|
+
- **子智能体(人设)**:`~/.dsh/tool-management/agents/<人设>.md`,一个文件一个人设——frontmatter 可选(`description` 何时调用,**一句话即可** / `provider` + `model` 指定模型路由(**两者是一对**:跨来源换模型必须都填,如 `provider: sensenova` + `model: sensenova-6.8-flash-lite`;只填 `model` 会落在主会话的来源上) / `tools` 工具白名单 / `toolsDeny` 工具黑名单,缺省自动派生),正文就是人设提示词。页面上这些都在「**高级选项**」折叠区里(已经在用模型/工具限制的人设自动展开):模型是**下拉选择**(宿主 LLM 目录里的 `provider · model` 对,目录里没有的可切「自定义」手填),工具白/黑名单是**勾选器**——候选是**全部 Agent 预设工具名的并集**并标注「当前会话可见 / 其它预设里可用」,因为人设可能在任何预设下被复用,只列当前会话的工具会让换预设后的子代理启动失败(官方 `toolFilter` 对未知名直接拒绝启动)。页头「导入」支持 `.md` 与 `.zip`(zip 内任意层级的 `.md` 都按文件名导入,**同名自动跳过并列出名单**)。模型用 `subagent_list` 看清单、`subagent_run{agent, task}` 调用:子代理**带人设独立运行**、自动继承当前启用场景的记忆段、只把最终输出回传主模型(≤16 KiB),跑完即弃不进 History。场景档案里绑定「本场景可用哪些人设」(绑定外调用报"人设不可用");运行默认弹确认(花的是真 token),设置 `requireConfirmForModelSubagentRun: false` 可关,完全权限(`approval=never`)下视为已预先批准直接放行(见 FAQ)。**治理边界**:以上约束只覆盖 `subagent_run` 这一条通道——DSH 官方的 `subagent` / `subagent_fork` 是宿主能力,无确认门、也不认这套人设,任何模式下都不受本插件约束(见 FAQ「两条子代理通道」)。
|
|
147
|
+
|
|
109
148
|
### 让模型和脚本参与管理
|
|
110
149
|
|
|
111
150
|
| 入口 | 能做什么 |
|
|
112
151
|
|---|---|
|
|
113
|
-
| `/mcp`、`/skills`、`/agents-md` | 聊天框查看当前状态 |
|
|
114
152
|
| `skill_mcp_manager_list / set_enabled / restart / add` | 模型查询与操作 MCP 服务 |
|
|
115
153
|
| `skill_manager_list / set_enabled / create` | 模型查询与操作技能(创建前会征求你同意) |
|
|
154
|
+
| `agentsmd_list / agentsmd_apply` | 模型查询 AGENTS.md 预设库、切换当前预设(写入 `~/.dsh/AGENTS.md`,新会话生效);**不提供新建/删除**,避免模型误删你的预设 |
|
|
155
|
+
| `rule_manager_list / read / write` | 模型查询与读写场景记忆(写入前会征求你同意,可在设置中关闭确认) |
|
|
156
|
+
| `subagent_list / subagent_run` | 模型列出人设、按人设运行一次性子代理(只回传结果、跑完即弃;运行前默认需确认,可在设置中关闭) |
|
|
116
157
|
| `POST /dsh-plugin-tool-management/api` | 脚本调用的 HTTP API(`{op, args}` 协议) |
|
|
117
158
|
|
|
159
|
+
> v0.4 起**不再注册斜杠命令**(曾有 `/mcp`、`/skills`、`/agents-md`、`/scene-memory`):
|
|
160
|
+
> 它们只能输出纯文本快照、既不能操作也容易与面板状态不一致,面板里每一项都有等价入口。
|
|
161
|
+
|
|
118
162
|
## 配置与安全
|
|
119
163
|
|
|
120
164
|
插件 loader 行支持以下可选字段(`dsh plugin add` 会自动插入,一般无需手写):
|
|
@@ -132,10 +176,16 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
|
|
|
132
176
|
|---|---|
|
|
133
177
|
| MCP 服务器定义 | `profiles/<profile>/cordis.patch.yml`(项目级)或 `~/.dsh/cordis.patch.yml`(全局),改写前自动 `.bak` |
|
|
134
178
|
| 服务器备注 / 页面设置 / 工具停用列表 / 导出 | DSH 主目录下的旁路 JSON(`skill-mcp-manager-*.json`) |
|
|
135
|
-
| 技能启停策略 / 自定义目录 | `~/.dsh/tool-management/state.json` |
|
|
179
|
+
| 技能启停策略 / 同名首选表 / 自定义目录 | `~/.dsh/tool-management/state.json`(`sources` / `enabledSkills` / `disabledSkills` / `preferredSkills` / `customRoots`) |
|
|
136
180
|
| 技能回收站 / 导入暂存 | `~/.dsh/tool-management/trash`、`uploads` |
|
|
137
|
-
|
|
|
181
|
+
| 插件新建/导入的技能 | `~/.dsh/tool-management/skills/<技能>/`(官方 `~/.dsh/skills/` 仍作为来源列出,只读接入) |
|
|
182
|
+
| AGENTS.md 预设库 / 应用结果 | `~/.dsh/tool-management/agents-md/<预设 id>/AGENTS.md`;「应用」写入 `~/.dsh/AGENTS.md` |
|
|
138
183
|
| 归档会话账本 / 保留期 | 插件目录 `data/history-archived-at.json`、`data/history-retention.json` |
|
|
184
|
+
| 记忆文件(真源) | `~/.dsh/tool-management/memories/<场景>/<name>.md`(flat)或 `<场景>/<name>/SKILL.md`(bundle);场景名可含中文;**保留场景 `global`(界面「全局」)的记忆任何对话都注入**;`memories/` 根层的裸 `.md` 不属于任何场景,**不会注入**(体检会报 `noScene`) |
|
|
185
|
+
| 记忆索引 / 场景记录 / 启用场景 | `~/.dsh/tool-management/rules-index.json`(`enabled`/排序/标签 + `scenes` 场景记录(label/描述/顺序)+ `active` 启用场景集合(`null` = 全部启用)+ `archives` 场景档案勾选集 + `mode` 当前模式快照) |
|
|
186
|
+
| 人设文件(真源) | `~/.dsh/tool-management/agents/<人设>.md`(frontmatter 可选,正文 = 人设提示词) |
|
|
187
|
+
| 页面设置 / 确认开关 | `~/.dsh/dsh-plugin-tool-management-settings.json`(`requireConfirmForModelSubagentRun` 等) |
|
|
188
|
+
| 记忆回收站 | `~/.dsh/tool-management/rules-trash/<trashId>/`(删除记忆先进这里,可恢复) |
|
|
139
189
|
| 运行日志 | `~/.dsh/dsh-plugin-tool-management.log`(滚动) |
|
|
140
190
|
|
|
141
191
|
## 常见问题
|
|
@@ -147,17 +197,37 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
|
|
|
147
197
|
| 改坏了配置 DSH 起不来 | 同目录取最近的 `cordis.patch.yml.bak-<时间戳>` 恢复。 |
|
|
148
198
|
| 页面数据不刷新 | 等待页面自动轮询(默认 5 秒);或手动点「刷新」。 |
|
|
149
199
|
| 镜像源装不到最新版 | 加 `--registry=https://registry.npmjs.org` 稍后再试。 |
|
|
200
|
+
| 完全权限(`approval=never`)下还需要确认吗? | **不需要,也不会弹卡**:三个确认门(`rule_manager_write` / `skill_manager_create` / `subagent_run`)在 never 会话里被视作「用户已预先批准」,直接放行,并在 `~/.dsh/dsh-plugin-tool-management.log` 记一条 `confirm-bypass` 留痕。想让它们重新问一次,就把访问模式切回「工作区内修改」;只想关掉某一项,用插件设置里的 `requireConfirmForModel*` 开关。 |
|
|
201
|
+
| `subagent_run` 报「spawn provider 不可用」 | **条件式**:宿主自带 `spawn` provider(最新版无需装包、无需挂载),只有宿主确实没注册、且本插件也挂载不了 `@deepseek-ai/dsh-subagent-spawn-in-process` 时才会出现(错误文本里带原始原因,多见于旧版或特定 profile)。此时在宿主 profile 里挂载该包后重启 DSH——本插件不把它写进 `cordis.patch.yml`,以免缺包的宿主整棵树起不来(取舍见该文件注释)。 |
|
|
202
|
+
| 场景里只绑了 A 人设,为什么模型还是跑起了没绑定的子代理? | **子代理有两条通道**。本插件的 `subagent_run` 走确认门 + 场景人设绑定;DSH 官方的 `subagent` / `subagent_fork` 是宿主能力,**没有确认门、也没有「用哪个人设」的概念**,因此任何模式下都不受本插件的确认与绑定约束(实测:同一条消息里官方 `subagent` 无审批卡直接返回,紧接着的 `subagent_run` 才弹卡;`subagent_fork` 同样无卡)。本插件的治理只覆盖 `subagent_run`;要收紧官方那两个通道得由宿主侧约定或后续版本把它们纳入插件前裁决。 |
|
|
150
203
|
|
|
151
204
|
## 开发
|
|
152
205
|
|
|
153
206
|
```bash
|
|
154
207
|
npm install
|
|
155
|
-
npm
|
|
156
|
-
npm run
|
|
157
|
-
npm run
|
|
208
|
+
npm run build # 构建(tsc + 同步客户端 bundle)
|
|
209
|
+
npm run build:client # 只同步 src/client.js → lib/client.js
|
|
210
|
+
npm run lint # 语法自检(node --check 两个产物)
|
|
211
|
+
npm run check:i18n # 中英词典键集合 + 占位符对齐
|
|
212
|
+
npm test # 构建 + i18n 自检 + 全部语义契约测试(node --test test/*.test.mjs,76 例)
|
|
158
213
|
```
|
|
159
214
|
|
|
160
|
-
|
|
215
|
+
> 本项目的验证方式是**直接跑一遍真实行为**(验收证据与已知问题见 [Changelog](docs/Changelog.md)),而不是断言代码当前怎么实现——
|
|
216
|
+
> 后者只是把实现抄一遍,必然通过。例外是十组**语义契约**测试(`npm test`,跑 `lib/` 产物,共 76 例):
|
|
217
|
+
> `archive.test.mjs`(引擎状态机:勾=启用、空段可持久化、失败回滚与如实上报)、
|
|
218
|
+
> `import.test.mjs`(导入展开、落点规划与限额回报)、
|
|
219
|
+
> `approval-policy.test.mjs`(never 审批策略探测;用真实 cordis + 真实 `ApprovalService` 复现读取链)、
|
|
220
|
+
> `subagent-scene.test.mjs`(场景绑定必须在子代理运行**之前**拒绝)、
|
|
221
|
+
> `subagent-persona.test.mjs`(人设 frontmatter 往返:`provider`/`model`/`toolsDeny` 读写不丢;目录不存在时创建)、
|
|
222
|
+
> `hub-layout.test.mjs`(统一数据目录:旧布局搬移不覆盖、保留场景 global 恒在且不可删、记忆必须归属已存在场景、档案记忆段只影响投影)、
|
|
223
|
+
> `skills-delete.test.mjs`(哪些技能可以删:用户级来源不可删、只读来源仍只读)、
|
|
224
|
+
> `skills-state.test.mjs`(技能状态文件读取韧性:缺键自愈、类型错仍 fail-closed)、
|
|
225
|
+
> `client-exports.test.mjs`(**客户端导出契约**:只求值 factory 不跑 `apply` 也能拿到 `dict`/`pages`;禁止把导出写在 `apply` 方法体里)、
|
|
226
|
+
> `client-render.test.mjs`(**装配与渲染**:假 ctx 跑完整 `apply`,断言注册了 `settings.section`,并递归渲染整棵组件树不抛错)。
|
|
227
|
+
> 它们断言语义契约而非实现抄写;真实行为验收仍以浏览器/宿主实测为准,契约测试不能替代。
|
|
228
|
+
> 另有 `npm run check:i18n`(中英词典键集合 + 占位符对齐)与 `node scripts/i18n-debt.mjs`(还剩多少硬编码中文,当前 113 条:提示词页 38 / 会话页 75)。
|
|
229
|
+
|
|
230
|
+
结构:宿主端 `src/index.ts`(Cordis 对象插件,`lib/index.js` 为发布产物;`lib/` 全部由 `npm run build` 生成、**不入版本库**,克隆后先构建);数据目录常量与搬移 `src/hub.ts`;技能核心 `src/skills/core.js`(纯 Node);AGENTS.md 预设库 `src/agents-md/service.ts`;归档会话管理 `lib/history/`(`workspace.js` / `projcache.js` / `tombstone.js`);对话导入解析 `src/imports/parsers.js`;场景记忆服务 `src/rules/`(`service.ts` 发现/CRUD/索引/两相扫描段渲染、`provider.ts` per-agent `systemPrompt` 段注册;模块路径与 `rules-*` op 名保留为内部协议,用户可见的页面与目录名已改为「场景记忆」/`memories/`);浏览器端 `src/client.js`(ModuleLoader CJS bundle,`dsm-*` 设计系统,经同源 API 与宿主通信)。运行时依赖仅 `fflate`(ZIP 解压)。
|
|
161
231
|
|
|
162
232
|
发布:`npm version patch && npm publish`(`prepublishOnly` 自动构建)。
|
|
163
233
|
|
package/README_EN.md
CHANGED
|
@@ -3,36 +3,47 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/dsh-plugin-tool-management)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](package.json)
|
|
6
|
-
[](https://github.com/ouli-1242/dsh-plugin-tool-management)
|
|
7
|
-
|
|
8
|
-
[简体中文](README.md) · **English**
|
|
6
|
+
[](https://github.com/ouli-1242/dsh-plugin-tool-management)
|
|
7
|
+
[](https://dsh.market/)
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
[简体中文](README.md) · **English** · [Changelog](docs/Changelog.md)
|
|
10
|
+
|
|
11
|
+
**An MCP server, skills & memory manager for DeepSeek Harness.** One settings panel keeps five things under control:
|
|
11
12
|
|
|
12
13
|
- **MCP**: which servers are configured, what tools each one exposes, and which tools the model may call — add, edit, remove, toggle, restart; every change takes effect immediately;
|
|
13
14
|
- **Skills**: every skill on the machine (DSH / Agents / Codex / Claude / project-level / any directory you add) at a glance — toggle individually or per source, create, import, recycle;
|
|
14
15
|
- **AGENTS.md**: keep multiple global instruction baselines as presets, apply one with a click to write `~/.dsh/AGENTS.md` — new sessions pick it up, current sessions stay unchanged;
|
|
15
|
-
- **History**: archived sessions in one place — grouped by project, batch restore / delete, import & export transcripts, retention-based auto-cleanup
|
|
16
|
+
- **History**: archived sessions in one place — grouped by project, batch restore / delete, import & export transcripts, retention-based auto-cleanup;
|
|
17
|
+
- **Scene Memory**: under `~/.dsh/tool-management/memories/<scene>/`, one folder = one scene and one `.md` = one memory — **create scenes** (with a description), drop `.md` files in (non-ASCII names are fine), toggle scenes; the bodies of memories in an enabled scene are **injected into the system prompt in full**, so you never re-explain them. The reserved scene `global` ("Global" in the UI) is injected into every conversation.
|
|
16
18
|
|
|
17
19
|
No hand-editing of `cordis.patch.yml`, and skill source files are never touched. Configuration survives restarts and upgrades.
|
|
18
20
|
|
|
19
21
|
---
|
|
20
22
|
|
|
21
|
-
<!-- Image slot 1: MCP management page screenshot → docs/images/
|
|
23
|
+
<!-- Image slot 1: MCP management page screenshot → docs/images/MCP.png -->
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
27
|
+
<!-- Image slot 2: Skills management page screenshot → docs/images/技能.png -->
|
|
22
28
|
|
|
23
|
-

|
|
24
30
|
|
|
25
|
-
<!-- Image slot
|
|
31
|
+
<!-- Image slot 3: AGENTS.md presets page screenshot → docs/images/提示词.png -->
|
|
26
32
|
|
|
27
|
-

|
|
28
34
|
|
|
29
|
-
<!-- Image slot
|
|
35
|
+
<!-- Image slot 4: History archived sessions page screenshot → docs/images/会话.png -->
|
|
30
36
|
|
|
31
|
-

|
|
32
38
|
|
|
33
|
-
<!-- Image slot
|
|
39
|
+
<!-- Image slot 5: Scene memory page screenshot → docs/images/场景.png -->
|
|
34
40
|
|
|
35
|
-

|
|
42
|
+
<!-- Image slot 6: Memory page screenshot → docs/images/记忆.png -->
|
|
43
|
+

|
|
44
|
+
|
|
45
|
+
<!-- Image slot 7: Subagents page screenshot → docs/images/子智能体.png -->
|
|
46
|
+

|
|
36
47
|
|
|
37
48
|
## Highlights
|
|
38
49
|
|
|
@@ -44,14 +55,20 @@ No hand-editing of `cordis.patch.yml`, and skill source files are never touched.
|
|
|
44
55
|
| Write protection | Every patch rewrite keeps a timestamped `.bak` backup (last 5); duplicate loader ids are rejected before write; failed cross-level migration rolls back |
|
|
45
56
|
| Backup / restore | JSON import supports `conflict: 'overwrite'` to replace entries with the same id, not just skip them |
|
|
46
57
|
| Skill sources | Hooks up `~/.agents` / `~/.codex` / `~/.claude` (three directories official DSH does not load) plus **any custom skill directory** you add (read-only, overlapping paths rejected) |
|
|
47
|
-
| Skill operations | Create skills, import ZIP / folders, plugin recycle bin (restore / permanent delete with OS-trash fallback), open the source file in the system editor |
|
|
58
|
+
| Skill operations | Create skills, import ZIP / folders, plugin recycle bin (restore / permanent delete with OS-trash fallback), open the source file in the system editor. **Deletion is project-level only**: DSH skills and imported skills (`~/.dsh/skills/`, `~/.dsh/tool-management/skills/`) cannot be deleted — disable them instead |
|
|
59
|
+
| Skill source names | `DSH skills` = the official `~/.dsh/skills/`; **`Imported skills`** = where this plugin puts what you create/import, `~/.dsh/tool-management/skills/` (higher priority, so a same-named copy shadows the official one) |
|
|
48
60
|
| Live refresh | Skill directories are watched from a background thread — edits made in an editor show up automatically |
|
|
49
61
|
| AGENTS.md presets | Multiple global instruction baselines as presets — create / import / edit / apply / delete; "Apply" writes `~/.dsh/AGENTS.md` (new sessions pick it up, current sessions stay unchanged) |
|
|
50
62
|
| Archived session management | History page groups archived sessions by project: search, select-all, batch restore / permanent delete, retention-based auto-cleanup (changing the retention resets the countdown from the change time) |
|
|
51
63
|
| Transcript import / export | Seamlessly take over conversations from Claude Code / Cursor (JSONL), Codex (Markdown), or any text; export picks the session scope, defaults to the desktop, in Markdown / JSONL |
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
64
|
+
| Scene memory auto-injected | A memory is `~/.dsh/tool-management/memories/<scene>/<name>.md`; every `.md` inside an enabled scene has its body **injected into the system prompt automatically** (per-agent `systemPrompt` section), with no tool call from the model and effect on the **very next request**; the reserved scene **`global`** ("Global" in the UI) is injected into every conversation. |
|
|
65
|
+
| Memory import | "Import memory" on the Memory page: `.md` / `.zip` (multi-select, drag-and-drop); inside a zip a directory name is the scene, and a bare `.md` lands in the scene picked in the dialog (leave it empty = the reserved scene "Global"); `<scene>/<name>/SKILL.md` inside a zip is imported as a **bundle** (sibling files become attachments); same names are skipped and listed, **including scenes created just for this import** |
|
|
66
|
+
| Scene enable switch | A scene is an **explicit record** (with a description and order); the multi-select switch persists globally in `rules-index.json`'s `active`; **all scenes enabled by default**, `global` and `_shared/` always on |
|
|
67
|
+
| Scene profile (four free-form sections) | Each scene can select its own **MCP tool set / skill set / subagent bindings / memories** in any combination (the lists show only what exists right now; checked = enabled, unchecked = disabled; MCP has two levels: not checking a server disables it entirely, checking a server but none of its tools stops that whole server). **The memory section only affects injection** (an unchecked memory stays out of the prompt while the file is left exactly as it is). A scene with a tool or skill section also gets "Set as active mode": applying the profile persists a snapshot first, and exiting restores it **verbatim**; a scene with only memories or only subagents shows no mode button; the change takes effect on the next request |
|
|
68
|
+
| Lightweight subagents | `~/.dsh/tool-management/agents/<persona>.md` — one file per persona (optional frontmatter: `description` / `provider` + `model` / `tools` allowlist / `toolsDeny` denylist; the body is the persona prompt and is derived automatically when missing); the page header's "Import" takes `.md` / `.zip` (same names skipped and listed); the model calls them through `subagent_list` / `subagent_run` — the child runs with the persona, returns only its result, and is discarded (it never enters History); it **inherits the memories of the currently enabled scenes automatically**; a scene profile can bind "which personas are available in this scene" (calls outside the binding are refused); running asks for confirmation by default, which can be turned off in settings |
|
|
69
|
+
| Prefix-cache friendly | Section text depends only on enabled scenes + file contents, so it is byte-stable; switching scenes or editing a memory changes it exactly once, every other request keeps hitting the cache (this does not violate the "no injection layer" rule — that one only bans per-turn dynamic content) |
|
|
70
|
+
| Model tools | **14**: `skill_mcp_manager_*` for MCP (4), `skill_manager_*` for skills (3), `agentsmd_list` / `agentsmd_apply` for the AGENTS.md preset library (2 — the model may only list and switch, never create or delete, so it cannot wipe your presets), `rule_manager_*` for scene memories (3; creating asks for your consent, can be turned off in settings), `subagent_list` / `subagent_run` for persona subagents (2; running asks for your consent by default, turn off with `requireConfirmForModelSubagentRun`). **All three confirm gates respect the session approval policy**: under `approval=never` (full access) no card can appear, so the plugin treats it as "the user has pre-approved" and passes through, logging `confirm-bypass` — matching the official subagent tools' behaviour under full access |
|
|
71
|
+
| UI | Its own `dsm-*` design system, **seven columns** (Scenes / MCP / Skills / Subagents / Prompts / Memory / Sessions) with a uniform page header and shared section cards; every checkbox-style surface (the four profile sections, the persona tool allow/deny lists) uses one layout, and long lists all have a filter box; a persona's model and tool limits live in an "Advanced options" fold-out (auto-expanded once configured); notices come in two levels (success = toast, warning/error = in-page banner); the profile dialog has a fixed height so adding or removing sections never makes it jump |
|
|
55
72
|
|
|
56
73
|
## Getting started
|
|
57
74
|
|
|
@@ -66,7 +83,7 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
|
|
|
66
83
|
dsh plugin --profile web remove dsh-plugin-tool-management
|
|
67
84
|
```
|
|
68
85
|
|
|
69
|
-
Hard-refresh the browser (Cmd/Ctrl+Shift-R) after installing —
|
|
86
|
+
Hard-refresh the browser (Cmd/Ctrl+Shift-R) after installing — a **Tools** panel appears in Settings with seven tabs (Scenes / MCP / Skills / Subagents / Prompts / Memory / Sessions), which means the install worked (client changes are hot-loaded by DSH, no restart needed).
|
|
70
87
|
|
|
71
88
|
You can also tell any DSH session:
|
|
72
89
|
|
|
@@ -90,31 +107,104 @@ Then remind me to hard-refresh the browser.
|
|
|
90
107
|
|
|
91
108
|
- **See everything**: skills are grouped by source — project, runtime, built-in, plugin-shipped, the four user directories (`~/.dsh` / `~/.agents` / `~/.codex` / `~/.claude`; the last three are hooked up by this plugin) and any custom directories you added.
|
|
92
109
|
- **Toggle**: individual skills, whole sources or whole projects — implemented as an override-provider shadow policy, so not a single byte of the source file changes; moving machines is just copying the state file.
|
|
110
|
+
- **Remove a source**: unlike disabling one — a disabled source is still scanned and listed (its skills simply cannot be called) — **removing means the directory is not scanned at all**: its skills disappear from the list, drop out of the same-name priority, and become invisible to the model too (provider candidates). Not a single byte is touched on disk, and it can be restored at any time. The reserved `dsh` (official DSH skills) and `hub` (the plugin's own import target) sources, and project-level sources, cannot be removed and show no button.
|
|
93
111
|
- **Custom directories**: click "Add directory", enter an absolute path, and that directory becomes a read-only skill source — ideal for skill collections living in repos or synced folders; overlapping paths are rejected to keep the shadow policy sound.
|
|
94
|
-
- **Create / import / recycle**: create from a form; drag in a ZIP, a `.md` file or a skill folder; deleted skills go to the plugin recycle bin first, and permanent delete still tries the OS trash as a last safety net.
|
|
95
|
-
|
|
96
|
-
### Managing AGENTS.md presets
|
|
97
|
-
|
|
98
|
-
- **Preset library**: create, import and edit multiple global instruction baselines (e.g. different teams' coding standards or role behaviors).
|
|
99
|
-
- **Apply = write**: "Apply" writes the selected preset to `~/.dsh/AGENTS.md` — **new sessions pick it up, current sessions stay unchanged**; "Re-apply" syncs the latest content after editing; switch to another preset before deleting.
|
|
100
|
-
|
|
101
|
-
### Managing archived sessions
|
|
102
|
-
|
|
103
|
-
- **Grouped by project**: archived sessions are grouped by workspace automatically; search by title / session ID / project path; sessions whose workspace folder no longer exists are flagged with ⚠.
|
|
104
|
-
- **Batch operations**: "Select all" then batch-restore or permanently delete; restored sessions return to the workspace list, and deletion cascades to their subagent sessions.
|
|
105
|
-
- **Retention**: pick the cleanup period from the dropdown (0 = keep forever); the expiry baseline is the later of the archive time and the last retention change, so changing the retention resets the countdown.
|
|
106
|
-
- **Import conversations**: take over sessions from other tools — Claude Code / Cursor JSONL, Codex Markdown, and arbitrary text — and keep chatting right after import.
|
|
112
|
+
- **Create / import / recycle**: create from a form; drag in a ZIP, a `.md` file or a skill folder; deleted skills go to the plugin recycle bin first, and permanent delete still tries the OS trash as a last safety net.
|
|
113
|
+
|
|
114
|
+
### Managing AGENTS.md presets
|
|
115
|
+
|
|
116
|
+
- **Preset library**: create, import and edit multiple global instruction baselines (e.g. different teams' coding standards or role behaviors).
|
|
117
|
+
- **Apply = write**: "Apply" writes the selected preset to `~/.dsh/AGENTS.md` — **new sessions pick it up, current sessions stay unchanged**; "Re-apply" syncs the latest content after editing; switch to another preset before deleting.
|
|
118
|
+
|
|
119
|
+
### Managing archived sessions
|
|
120
|
+
|
|
121
|
+
- **Grouped by project**: archived sessions are grouped by workspace automatically; search by title / session ID / project path; sessions whose workspace folder no longer exists are flagged with ⚠.
|
|
122
|
+
- **Batch operations**: "Select all" then batch-restore or permanently delete; restored sessions return to the workspace list, and deletion cascades to their subagent sessions.
|
|
123
|
+
- **Retention**: pick the cleanup period from the dropdown (0 = keep forever); the expiry baseline is the later of the archive time and the last retention change, so changing the retention resets the countdown.
|
|
124
|
+
- **Import conversations**: take over sessions from other tools — Claude Code / Cursor JSONL, Codex Markdown, and arbitrary text — and keep chatting right after import.
|
|
107
125
|
- **Export conversations**: pick a session scope (all / archived only / by workspace); each session becomes a Markdown or JSONL file; the export directory defaults to the desktop, and the adjacent "Select" button opens a directory tree to browse and fill in the absolute path.
|
|
108
126
|
|
|
127
|
+
### Managing scene memory (the Scene Memory page)
|
|
128
|
+
|
|
129
|
+
> This page merges the former "Rules" and "Scenes" pages: **a scene is the grouping dimension, a memory (`.md`) is the content.**
|
|
130
|
+
> The data folder also moved to **`~/.dsh/tool-management/memories/`** — existing files are moved in automatically (see "Upgrade note" below).
|
|
131
|
+
|
|
132
|
+
- **A scene is an explicit record** (name + description, stored in the `scenes` slice of `rules-index.json`); `memories/<scene>/` holds its memories: `~/.dsh/tool-management/memories/办公/流程.md` is one memory in the "办公" scene. Scene names accept any Unicode (≤64 chars, no `/ \ < > : " | ? *`, must not start with a dot, **a single path segment**); `global` is the reserved always-on scene ("Global" in the UI) and `_shared/` is the legacy shared scene.
|
|
133
|
+
- **New scene**: "New scene" asks for a name and a one-line description (or just `mkdir` under `memories/` — a record is filled in on the next read). **An empty scene is perfectly valid**, so you can create scenes first and add memories later; the card also has "Edit" for the description.
|
|
134
|
+
- **Every `.md` is one memory**: a sentence or a paragraph, no frontmatter needed, and the whole body is injected. Drop a file into the scene folder and it takes effect, or use "New memory" on the card to write it on the page — **file names can be Chinese** (e.g. `站会流程.md`). A memory whose scene does not exist is **rejected outright** (`scene not found`) instead of silently creating one.
|
|
135
|
+
- **Toggle a scene**: the switch on the right of each scene card enables/disables it (same component and layout as the Skills page). Every `.md` inside an enabled scene is **injected into the system prompt automatically**; the model needs no tool call and you never have to explain again. Toggling takes effect on the **very next request**, with no new session and no plugin reload.
|
|
136
|
+
- **All scenes are enabled by default**: with no configuration at all, every scene is live ("drop it in and it works"); narrow the set in the UI once you have many scenes. `global` ("Global") and `_shared/` are always on (their cards have no switch).
|
|
137
|
+
- **One memory = one Markdown file**: `<scene>/<name>.md` (flat) or `<scene>/<name>/SKILL.md` (bundle, with attachments). When creating, fill in the scene (pick an existing one or **type a new scene name** — its folder is created for you), the name (= file name), description and body — frontmatter is entirely optional and derived automatically when missing.
|
|
138
|
+
- **Bundle attachments**: with the bundle form you can **add attachments** right in the dialog (multi-select, ≤8 MB each, ≤16 MB / 32 files per upload); they live in the memory folder and are **never injected into the prompt** (only the `SKILL.md` body is), and you can remove them one by one while editing. The flat form is a single file, so it has nowhere to put attachments.
|
|
139
|
+
- **Toggle & recycle**: enable/disable each memory (the switch on the right of every row — a disabled memory stays on disk and is simply left out of the prompt), edit, and move to trash; the "Trash" button in the page header can **restore** or **permanently delete** removed memories, with a confirmation step before the permanent delete. `enabled` and friends live in the sidecar index and are never written back to your files.
|
|
140
|
+
- **Injection budget is visible**: a budget bar (used / max bytes) sits under the summary and turns red with an "Over budget" label. Default cap 64 KiB; when one memory does not fit it is **skipped** while smaller ones behind it are still included, and the section tail carries a "not injected (over budget)" list — both the model and you can see what was left out instead of losing it silently.
|
|
141
|
+
- **`~/.dsh/AGENTS.md` is no longer written**: the old "always layer" is gone; the shared baseline now lives in `_shared/` and flows through the system-prompt section.
|
|
142
|
+
- **Scene profile (four free-form sections)**: the "Profile" button opens an editor where **MCP tools**, **skills**, **subagent bindings** and **memories** are added/removed independently. For memories the editor lists each scene as a card (description + how many of its memories are checked) and "Pick memories" drills into that scene; check semantics are the same as the other sections (**unchecked = not injected for that scene; files and content are never touched**). Sections with a defined-but-empty selection disable that whole domain. Every section body has a filter box, and the dialog keeps a fixed height so adding/removing sections never makes it jump. A scene with MCP/skill sections also gets a "Set as active mode" button: entering takes a runtime snapshot, persists it first, applies the selections and narrows memory injection to that scene; exiting restores the snapshot **verbatim**. Failures roll back and are reported honestly (an incomplete rollback is written into the error text rather than claimed as "rolled back").
|
|
143
|
+
- **Subagents (personas)**: `~/.dsh/tool-management/agents/<persona>.md`, one file per persona — frontmatter is optional (`description` for when to call it, **one sentence is enough**; `provider` + `model` for the model route (**a pair**: switching providers requires both, e.g. `provider: sensenova` + `model: sensenova-6.8-flash-lite`; a bare `model` resolves against the main session's provider); `tools` allowlist; `toolsDeny` denylist), and the body is the persona prompt. On the page all of this sits in an **Advanced options** fold-out (auto-expanded when the persona already uses a model or tool restriction): the model is a **dropdown** (the `provider · model` pairs from the host LLM catalogue, with a "Custom" entry to type one it does not list), and the tool allow/deny lists are **pickers** whose candidates are the **union of tool names across all agent presets**, tagged "available in this session" vs "available in other presets" — a persona can be reused under any preset, and listing only this session's tools would make the child fail to start after a preset switch (the official `toolFilter` rejects unknown names outright).
|
|
144
|
+
|
|
145
|
+
#### Caching and refresh (§5.2)
|
|
146
|
+
|
|
147
|
+
| Situation | Is the prefix stable? | Result |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| Scene set unchanged, memory files unchanged | byte-for-byte stable | ✅ prompt prefix cache hits |
|
|
150
|
+
| Enabling/disabling a scene (explicit action) | changes once | ⚠️ that session re-warms once — acceptable |
|
|
151
|
+
| Editing a memory (page or editor) | changes once | ⚠️ same, and it takes effect on the **next request** |
|
|
152
|
+
| Timestamps / counts / relative time in the section | changes every request | ❌ forbidden (and absent from the implementation) |
|
|
153
|
+
|
|
154
|
+
The implementation uses a **two-phase scan with a fingerprint cache**: each assembly only walks
|
|
155
|
+
directories with `stat` to build a fingerprint (no body reads) and reuses the previous rendering
|
|
156
|
+
when it is unchanged; only a changed fingerprint (scene toggle, file edit, enable/disable) triggers
|
|
157
|
+
reading bodies and re-rendering. **`fs.watch` is deliberately not used** — recursive watching is
|
|
158
|
+
unreliable on Windows, and a silently dead watcher would return stale content forever; the
|
|
159
|
+
fingerprint probe costs sub-milliseconds and buys "always fresh, never silently stale".
|
|
160
|
+
|
|
161
|
+
#### Upgrade note: the data folder moved (v0.4)
|
|
162
|
+
|
|
163
|
+
Since v0.4 **all plugin data lives under one directory**, `~/.dsh/tool-management/`
|
|
164
|
+
(easier to inspect and back up):
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
~/.dsh/tool-management/
|
|
168
|
+
├─ memories/<scene>/<name>.md | <scene>/<name>/SKILL.md memory bodies (source of truth)
|
|
169
|
+
├─ agents/<persona>.md subagent personas
|
|
170
|
+
├─ agents-md/<preset id>/AGENTS.md AGENTS.md preset library
|
|
171
|
+
├─ skills/ skills created/imported by the plugin
|
|
172
|
+
├─ trash/ skill trash; rules-trash/ = memory trash
|
|
173
|
+
├─ rules-index.json enable/order/scene records/profiles/mode
|
|
174
|
+
└─ state.json skill enable policy and custom roots
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Old locations are moved in automatically on first start** (move only, never delete, never
|
|
178
|
+
overwrite an existing target, once per process, failures do not block startup):
|
|
179
|
+
|
|
180
|
+
| Old location | New location |
|
|
181
|
+
|---|---|
|
|
182
|
+
| `~/.dsh/scene-memory/<scene>/…` | `~/.dsh/tool-management/memories/<scene>/…` |
|
|
183
|
+
| `~/.dsh/scene-memory/<root>.md` (the old global memory) | `~/.dsh/tool-management/memories/global/<root>.md` |
|
|
184
|
+
| `~/.dsh/rules/…` (pre-v0.3) | as the two rows above |
|
|
185
|
+
| `~/.dsh/subagents/<persona>.md` | `~/.dsh/tool-management/agents/<persona>.md` |
|
|
186
|
+
| plugin dir `data/agents-md-presets/` | `~/.dsh/tool-management/agents-md/` |
|
|
187
|
+
|
|
188
|
+
The move uses `rename` (instant on one volume) and leaves the source folder as an empty shell you can
|
|
189
|
+
delete once you are satisfied. `~/.dsh/skills/` (the official DSH skill directory) is **not** moved: it
|
|
190
|
+
stays listed as a switchable source, while skills **created or imported by the plugin** now land in
|
|
191
|
+
`tool-management/skills/` (the hub copy wins when both define the same name).
|
|
192
|
+
|
|
109
193
|
### Let the model and scripts help
|
|
110
194
|
|
|
111
195
|
| Entry point | What it does |
|
|
112
196
|
|---|---|
|
|
113
|
-
| `/mcp`, `/skills`, `/agents-md` | Check the current state from the chat box |
|
|
114
197
|
| `skill_mcp_manager_list / set_enabled / restart / add` | Let the model query and operate MCP servers |
|
|
115
198
|
| `skill_manager_list / set_enabled / create` | Let the model query and operate skills (creating asks for your consent) |
|
|
199
|
+
| `agentsmd_list / agentsmd_apply` | Let the model list the AGENTS.md preset library and switch the active preset (writes `~/.dsh/AGENTS.md`, effective for new sessions); **no create or delete**, so the model cannot wipe your presets |
|
|
200
|
+
| `rule_manager_list / read / write` | Let the model query and write scene memories (writes ask for your consent; can be disabled in settings) |
|
|
201
|
+
| `subagent_list / subagent_run` | Let the model list personas and run a one-shot persona subagent (result only, discarded afterwards; running asks for your consent by default, can be disabled in settings) |
|
|
116
202
|
| `POST /dsh-plugin-tool-management/api` | HTTP API for scripts (`{op, args}` protocol) |
|
|
117
203
|
|
|
204
|
+
> v0.4 **no longer registers slash commands** (there used to be `/mcp`, `/skills`, `/agents-md`,
|
|
205
|
+
> `/scene-memory`): they could only print a text snapshot, could not operate anything, and drifted from
|
|
206
|
+
> the panel state. Every one of them has an equivalent entry in the settings panel.
|
|
207
|
+
|
|
118
208
|
## Configuration & security
|
|
119
209
|
|
|
120
210
|
Optional fields on the plugin loader row (`dsh plugin add` inserts it automatically):
|
|
@@ -134,8 +224,14 @@ Why a token: the cross-site protection (POST-only + custom header + same-origin
|
|
|
134
224
|
| Server notes / page settings / disabled tools / export | Sidecar JSON files under the DSH home (`dsh-plugin-tool-management-*.json`) |
|
|
135
225
|
| Skill toggle policy / custom directories | `~/.dsh/tool-management/state.json` |
|
|
136
226
|
| Skill recycle bin / import staging | `~/.dsh/tool-management/trash`, `uploads` |
|
|
137
|
-
|
|
|
227
|
+
| Skills created/imported by the plugin | `~/.dsh/tool-management/skills/<skill>/` (the official `~/.dsh/skills/` stays listed as a source, read-only) |
|
|
228
|
+
| AGENTS.md presets / applied file | `~/.dsh/tool-management/agents-md/<preset id>/AGENTS.md`; "Apply" writes `~/.dsh/AGENTS.md` |
|
|
138
229
|
| Archived session ledger / retention | Plugin dir `data/history-archived-at.json`, `data/history-retention.json` |
|
|
230
|
+
| Memory files (source of truth) | `~/.dsh/tool-management/memories/<scene>/<name>.md` (flat) or `<scene>/<name>/SKILL.md` (bundle); scene names may be non-ASCII; the reserved scene **`global`** (shown as "Global") is injected into every conversation; a bare `.md` in the `memories/` root belongs to no scene and is **never injected** (the checkup reports `noScene`) |
|
|
231
|
+
| Memory index / scene records / enabled scenes | `~/.dsh/tool-management/rules-index.json` (`enabled` / order / tags + `scenes` records (label/description/order) + `active` enabled-scene set (`null` = all) + `archives` profile selections + `mode` snapshot) |
|
|
232
|
+
| Persona files (source of truth) | `~/.dsh/tool-management/agents/<persona>.md` (frontmatter optional, body = persona prompt) |
|
|
233
|
+
| Page settings / confirm switches | `~/.dsh/dsh-plugin-tool-management-settings.json` (`requireConfirmForModelSubagentRun` etc.) |
|
|
234
|
+
| Memory recycle bin | `~/.dsh/tool-management/rules-trash/<trashId>/` (deleted memories land here and can be restored) |
|
|
139
235
|
| Runtime log | `~/.dsh/dsh-plugin-tool-management.log` (rolling) |
|
|
140
236
|
|
|
141
237
|
## FAQ
|
|
@@ -147,17 +243,45 @@ Why a token: the cross-site protection (POST-only + custom header + same-origin
|
|
|
147
243
|
| Broken config, DSH won't boot | Restore the newest `cordis.patch.yml.bak-<timestamp>` next to it. |
|
|
148
244
|
| Page data not refreshing | Wait for the automatic polling (default 5s) or click "Refresh". |
|
|
149
245
|
| Latest version not found on a mirror | Add `--registry=https://registry.npmjs.org` and retry later. |
|
|
246
|
+
| Do the confirmations still apply in full access (`approval=never`)? | **No, and no card appears.** The three confirm gates (`rule_manager_write` / `skill_manager_create` / `subagent_run`) treat a `never` session as "the user has pre-approved", so they pass straight through and write a `confirm-bypass` line to `~/.dsh/dsh-plugin-tool-management.log`. Switch the access mode back to "workspace write" to get asked again, or turn off a single gate with the matching `requireConfirmForModel*` setting. |
|
|
247
|
+
| `subagent_run` reports "spawn provider unavailable" | **Conditional**: the host ships a `spawn` provider (recent versions need no extra package and no mount). It only appears when the host really registers none *and* this plugin cannot mount `@deepseek-ai/dsh-subagent-spawn-in-process` either — the message carries the original reason, and it is mostly an older version or a specific profile. Mount that package in the host profile and restart DSH: this plugin deliberately keeps it out of `cordis.patch.yml` so a host without the package still boots. |
|
|
248
|
+
| The scene binds only persona A, so why did an unbound subagent still run? | **There are two subagent channels.** This plugin's `subagent_run` goes through its confirm gate and the scene persona binding; DSH's own `subagent` / `subagent_fork` are host capabilities with **no confirm gate and no notion of this plugin's personas**, so they honour neither in any mode (verified live: in one message the official `subagent` returned with no approval card while the following `subagent_run` did prompt; `subagent_fork` likewise ran card-free). This plugin's governance covers `subagent_run` only — tightening the official pair would take a host-side convention or a later version that brings them into the plugin's pre-execute gate. |
|
|
150
249
|
|
|
151
250
|
## Development
|
|
152
251
|
|
|
153
252
|
```bash
|
|
154
253
|
npm install
|
|
155
|
-
npm
|
|
156
|
-
npm run
|
|
157
|
-
npm run
|
|
254
|
+
npm run build # build (tsc + sync client bundle)
|
|
255
|
+
npm run build:client # sync src/client.js → lib/client.js only
|
|
256
|
+
npm run lint # syntax self-check (node --check on both artifacts)
|
|
257
|
+
npm test # build + all semantic-contract tests (node --test test/*.test.mjs)
|
|
158
258
|
```
|
|
159
259
|
|
|
160
|
-
|
|
260
|
+
> Changes are verified by **actually exercising the real behaviour** (evidence and known issues live in
|
|
261
|
+
> [Changelog](docs/Changelog.md)) instead of asserting what the code currently does — the latter
|
|
262
|
+
> just copies the implementation and passes by construction. The exception is ten groups of
|
|
263
|
+
> **semantic-contract** tests (`npm test`, run against the built `lib/`, 76 cases):
|
|
264
|
+
> `archive.test.mjs` (engine state machine), `import.test.mjs` (ZIP expansion, landing plans, limit
|
|
265
|
+
> reporting), `approval-policy.test.mjs` (never-policy detection, driving a real cordis context and
|
|
266
|
+
> a real `ApprovalService`), `subagent-scene.test.mjs` (scene binding must reject *before* a
|
|
267
|
+
> subagent runs), `subagent-persona.test.mjs` (persona frontmatter round-trip: `provider`,
|
|
268
|
+
> `model` and `toolsDeny` survive a UI save; creating a persona with no directory present),
|
|
269
|
+
> `hub-layout.test.mjs` (unified data directory: legacy layouts move without overwriting, the
|
|
270
|
+
> reserved `global` scene always exists and cannot be deleted, a memory must belong to an existing
|
|
271
|
+
> scene, and the profile memory section only affects projection), `client-exports.test.mjs`
|
|
272
|
+
> (client export contract: evaluating the factory alone — without running `apply` — must already
|
|
273
|
+
> expose `dict`/`pages`; exports written inside the `apply` method body are rejected), and
|
|
274
|
+
> `client-render.test.mjs` (assembly and rendering: a fake ctx drives the whole `apply`, asserts
|
|
275
|
+
> `settings.section` is registered, then renders the entire component tree without throwing). They
|
|
276
|
+
> assert contracts, not
|
|
277
|
+
> implementation copies; real-behaviour
|
|
278
|
+
> acceptance still happens
|
|
279
|
+
> in the browser/host and these tests do not replace it.
|
|
280
|
+
> `npm run check:i18n` additionally checks the zh/en dictionaries for key-set and placeholder
|
|
281
|
+
> drift, and `node scripts/i18n-debt.mjs` reports how much hard-coded Chinese is left (113 lines
|
|
282
|
+
> today: 38 on the prompts page, 75 on the sessions page).
|
|
283
|
+
|
|
284
|
+
Layout: host half `src/index.ts` (object-form Cordis plugin, `lib/index.js` is the shipped artifact); data-directory constants and migration `src/hub.ts`; skill core `src/skills/core.js` (pure Node); AGENTS.md presets `src/agents-md/service.ts`; archived session management `lib/history/` (`workspace.js` / `projcache.js` / `tombstone.js`); transcript import parsing `src/imports/parsers.js`; scene-memory store `src/rules/` (`service.ts` discovery/CRUD/index/checkup/two-phase section render, `provider.ts` per-agent `systemPrompt` section registration; the module path and `rules-*` op names stay as internal protocol, while the user-visible page and folder became “Scene Memory” / `memories/`); browser half `src/client.js` (ModuleLoader CJS bundle, `dsm-*` design system, talks to the host through the same-origin API). The only runtime dependency is `fflate` (ZIP extraction).
|
|
161
285
|
|
|
162
286
|
Publish: `npm version patch && npm publish` (`prepublishOnly` builds automatically).
|
|
163
287
|
|
package/cordis.patch.yml
CHANGED
|
@@ -32,6 +32,17 @@
|
|
|
32
32
|
#
|
|
33
33
|
# 冲突告警:不要同时安装独立的 @michengai/dsh-archive-manager——两个补丁都
|
|
34
34
|
# 禁用官方 workspace 行并插入替换,会导致重复服务注册、启动失败。
|
|
35
|
+
#
|
|
36
|
+
# spawn provider(子智能体)挂载:本文件**故意不**插入
|
|
37
|
+
# `@deepseek-ai/dsh-subagent-spawn-in-process` 行。取舍理由:
|
|
38
|
+
# 1) insert 行在启动期解析:换台没有该包的宿主会因单行加载失败拖垮整棵插件树,
|
|
39
|
+
# 而缺 provider 时受影响面只有一个 subagent_run 调用;
|
|
40
|
+
# 2) 该行与本插件运行时的 ctx.plugin 兜底挂载存在双挂载窗口(同名 provider 重复注册)。
|
|
41
|
+
# 改由 src/subagents/service.ts 走官方通道:ctx.subagents.list() 探测到 spawn 即跳过;
|
|
42
|
+
# 缺失才经 createRequire + apply(ctx, {providerName:'spawn'}) 挂载;失败把原因原样抛给模型。
|
|
43
|
+
# 该包在 package.json 声明为**可选** peerDependency(peerDependenciesMeta.optional)——
|
|
44
|
+
# 宿主/profile 自带时可以照常挂载。设计 §3.2 字面要求「挂载声明进 cordis.patch.yml」,
|
|
45
|
+
# 这里按上述风险裁定为有意偏离(记录见 docs/审查/2026-09-13-场景档案v2双轴评审.md)。
|
|
35
46
|
- id: workspace
|
|
36
47
|
disabled: true
|
|
37
48
|
- id: session-projection-cache
|