dsh-plugin-tool-management 0.7.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 (36) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +16 -5
  3. package/README_EN.md +16 -5
  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 +17 -0
  21. package/lib/agents-md/service.js +41 -3
  22. package/lib/client.js +820 -375
  23. package/lib/compat/preset-reach.js +1 -1
  24. package/lib/compat/probe.js +8 -0
  25. package/lib/index.js +433 -10
  26. package/lib/mcp/state-section.js +90 -0
  27. package/lib/prompt-sections.js +148 -0
  28. package/lib/rules/archive-engine.js +99 -29
  29. package/lib/rules/archive.js +56 -28
  30. package/lib/rules/service.js +259 -39
  31. package/lib/skills/core.js +4 -1
  32. package/lib/subagents/catalog.js +89 -0
  33. package/lib/subagents/service.js +189 -20
  34. package/lib/subagents/tools.js +10 -3
  35. package/package.json +97 -97
  36. package/lib/rules/provider.js +0 -121
package/CHANGELOG.md CHANGED
@@ -10,6 +10,54 @@
10
10
 
11
11
  ---
12
12
 
13
+ ## [0.8.0] - 2026-09-15
14
+
15
+ ### 新增
16
+
17
+ - 场景锁定:锁定后 MCP / 技能 / 子智能体 / 记忆 / 提示词五个域整体只读;未启动不能上锁,锁定中不能关闭或切换,先解锁再改。
18
+ - 子智能体开关:停用的人设不注入上下文、模型不可见(文件不动);新建 / 导入 / 回收站恢复的人设自动启用,首次升级全部启用。
19
+ - 场景联动:启动场景时档案勾选的子智能体自动启用,退出按快照精确停回。
20
+ - 子智能体人设目录进入系统提示词:只列名字 + 描述,正文仅在委派时传给子代理。
21
+ - MCP 服务器状态与用户备注进入系统提示词:只列当前真正可用的 server,备注作为决策提示带给模型。
22
+ - 四个管理域补上导出(技能 / 子智能体 / 提示词 / 记忆):勾选条目打包 zip 写到指定目录,只读源文件。
23
+ - 提示词预设支持描述:只显示在插件界面,不写进 AGENTS.md。
24
+
25
+ ### 变更
26
+
27
+ - 导出弹窗重做:固定宽高、默认不勾选、条目分组折叠(技能按来源文件夹、记忆按场景、会话按工作区目录),组内同名条目全部展示。
28
+ - 导入入口统一:提示词补上与技能页同源的导入弹窗;四个导入弹窗一律用「文件要求」清单。
29
+ - 删除场景不再要求先清空:连它下面的全部记忆一起进同一条回收站条目,恢复按原路径整条放回;使用中的场景仍拒绝删除。
30
+ - 场景名与人设名可以改了:改名连带目录与档案绑定同步;保留场景、重名、正在使用的场景明确拒绝。
31
+ - 场景开关成为唯一入口:打开 = 进入场景(应用档案 + 启用),关闭 = 恢复全局默认;「退出模式」与开关走同一条路径。
32
+ - 记忆改为单一真相源 `enabled`:档案弹窗的勾选就是记忆自身的开关;新建与导入的记忆默认不开启。
33
+ - 提示词「应用」生效时机口径修正:下一轮对话即生效(宿主每轮重读 AGENTS.md),不再说「新会话生效」。
34
+ - 技能回收站弹窗重做:上下两块(目录 / 技能)各占一半、各自滚动,两组的后果差异写进界面;入口移到工具栏。
35
+ - MCP 新增默认级别改为全局;「Profile 级」更名「应用级」,级别下拉全局在上。
36
+ - 界面统一化:按钮四级语义、列表类弹窗固定尺寸且只允许列表层滚动、工具栏顺序固定、命名统一「新增 / 导入 / 导出 + 页名」;提示词 / 子智能体页补统计行。
37
+ - 备注输入框加 200 字上限,备注标签如实说明(会随请求发送给模型)。
38
+
39
+ ### 修复
40
+
41
+ - 进 / 退模式报 EPERM 且开关要点两次:索引与技能管理状态的原子写遇文件占用(EPERM/EACCES/EBUSY)自动重试。
42
+ - 退出场景模式后 MCP 服务器级与技能目录不回滚:快照的服务器级 / 来源级名单在读盘时被剥掉,现在原样保留。
43
+ - 列表类弹窗条目多时看不到滚动条:列表组被 flex 收缩后条目直接被裁掉;现在列表层正常滚动并带常驻细滚动条。
44
+ - 顶部「当前模式」横幅永远不显示:开关与按钮各写一个状态、互不同步,现在两者恒等。
45
+ - 长文本排版错位与截断丢失:标题截断补齐并加 `title` 提示。
46
+ - 历史页两个工作区分组标签区分无实际意义,统一为「已移除」。
47
+ - 兼容页把 semver 上界当受支持版本展示。
48
+ - 清理 CSS 死规则、未定义类名与 i18n 死键;滚动容器改为向上查找。
49
+
50
+ ### 移除
51
+
52
+ - 「切入此模式」按钮(开关承担)。
53
+ - 场景档案的 `memories` 段:老档案里的该字段被忽略,不做自动迁移。
54
+ - `memoryAllowed` / `computeMemoriesPlan`(单一真相源后不再需要)。
55
+
56
+ ### 说明
57
+
58
+ - 新建记忆默认不开启是行为变更:已有记忆的 `enabled` 原样保留,不受影响。
59
+ - 老数据里 `mode.scene` 与 `active` 可能不一致:不做一次性迁移,下次拨动任一场景开关时自然对齐。
60
+
13
61
  ## [0.7.0] - 2026-09-15
14
62
 
15
63
  ### 新增
package/README.md CHANGED
@@ -37,8 +37,9 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
37
37
  | 能力 | 说明 |
38
38
  |---|---|
39
39
  | 场景记忆 | 启用场景里的 `.md` 正文**自动进系统提示词**,下一个请求即生效 |
40
- | 场景档案 | 每个场景自由搭配 **MCP 工具集 / 技能集 / 子智能体 / 记忆**;可「切入模式」一键收窄 |
40
+ | 场景档案 | 每个场景自由搭配 **MCP 工具集 / 技能集 / 子智能体 / 记忆**;打开场景即应用,关闭按快照恢复 |
41
41
  | 场景提示词 | 场景绑一份提示词预设,切换场景直接改写 `~/.dsh/AGENTS.md`(关掉自动恢复) |
42
+ | 场景锁定 | 锁住一个场景 = **五个管理域整体只读**(勾没勾的都不能动);未启动不能上锁,锁定中关不掉,先解锁再改 |
42
43
  | MCP 工具级开关 | 单台服务器里**单个工具**可独立启停:模型看不见也调不到 |
43
44
  | 重启语义 | 重启只重连,**不改变启停状态** |
44
45
  | 密钥安全 | 密钥默认打码;「显示密钥」与导出**必须带令牌**——没配 `token` 就不给明文 |
@@ -47,7 +48,9 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
47
48
  | AGENTS.md 预设 | 多套全局基线,一键应用,保留 5 代备份 |
48
49
  | 归档会话 | 按项目分组、批量恢复 / 删除、保留期清理;工作区登记被删后可重建 |
49
50
  | 对话导入导出 | 接管 Claude Code / Cursor / Codex / 任意文本;导出 Markdown / JSONL |
50
- | 子智能体 | 一个文件一个人设,即用即弃不进 History,自动继承场景记忆 |
51
+ | 导入导出成对 | 技能 / 子智能体 / 提示词 / 记忆都有导出:勾选条目 → 打包 zip 到指定目录(只读源文件) |
52
+ | 子智能体 | 一个文件一个人设,**启停开关**决定是否注入上下文;即用即弃不进 History,自动继承场景记忆 |
53
+ | 上下文可见性 | 人设目录与「当前可用的 MCP server + 你的备注」进入系统提示词,模型自己知道有什么可用 |
51
54
  | 前缀缓存友好 | 注入段只由「启用场景 + 文件内容」决定,逐字节稳定 |
52
55
  | 兼容体检 | 「兼容」页一屏看清宿主能力、每个动作走原生还是适配、哪些降级 |
53
56
  | 模型工具 | **14 个**(`skill_mcp_manager_*` / `skill_manager_*` / `agentsmd_*` / `rule_manager_*` / `subagent_*`) |
@@ -83,15 +86,20 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
83
86
  - **场景 = 分组,记忆 = `.md` 文件**。`memories/<场景>/<名>.md`,整篇正文自动进系统提示词,文件名支持中文。
84
87
  - **单选启用**:同时只启用一个场景(其余置灰),关掉全部 = 只注入「全局」与 `_shared`。新场景默认不启动。
85
88
  - **场景绑提示词**:切换场景直接改写 `~/.dsh/AGENTS.md`(覆盖前 5 代备份,关掉自动恢复基线)。
86
- - **场景档案**:每个场景搭配 MCP 工具集 / 技能集 / 子智能体 / 记忆(任意组合);可「切入模式」一键应用并收窄注入,退出按快照原文恢复。
89
+ - **场景档案**:每个场景搭配 MCP 工具集 / 技能集 / 子智能体 / 记忆(任意组合);打开场景即应用并收窄注入,关闭按快照原文恢复(开关是唯一入口)。
87
90
  - **导入**:`.md` / `.zip`(目录名 = 场景,bundle 带附件),同名跳过绝不覆盖,超限逐条回报。
91
+ - **导出**:勾选记忆打包成 zip,保留「场景/名称」层级;bundle 型连目录里的附件一起打进去。只读源文件。
88
92
  - **注入预算**:默认 64 KiB,放不下的跳过并列出清单。删除进回收站。
93
+ - **场景锁定**:锁定后 MCP / 技能 / 子智能体 / 记忆 / 提示词整体只读,界面禁用 + 服务端守卫双侧拦截;未启动不能上锁,锁定中不能关闭,先解锁再改。
94
+ - **删除场景 = 连记忆一起删**:场景记录、档案与全部记忆进同一条回收站条目,恢复按原路径整条放回;使用中的场景拒绝删除。场景名可改(连带目录与档案,记忆正文不动)。
89
95
 
90
96
  ### 子智能体
91
97
 
92
98
  - **一个文件一个人设**:`agents/<人设>.md`,frontmatter 全可选。
93
99
  - **工具限制按 Agent 预设**:每个预设一份白/黑名单(互相排斥),运行期按当前预设生效——堵掉旧「全体并集」名单换预设后子代理起不来的坑。
94
100
  - **即用即弃**:`subagent_run` 带人设运行、只回传结果、不进 History,自动继承场景记忆。场景可绑定可用人设。
101
+ - **启停开关**:停用的人设不注入上下文、模型不可见(文件不动);新建 / 导入 / 恢复自动启用。启动场景时档案勾选的人设自动启用,退出按快照精确停回。
102
+ - **人设目录进系统提示词**:只列名字 + 描述,模型知道有哪些人设可委派;人设名可改,场景绑定自动跟着改。
95
103
 
96
104
  ### MCP 服务
97
105
 
@@ -99,17 +107,19 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
99
107
  - **工具级开关**:单个工具可独立停用(模型看不见也调不到),整台支持批量。
100
108
  - **密钥打码**:默认 `••••••`,「显示密钥」要令牌。
101
109
  - **迁移与备份**:跨项目级/全局迁移失败自动回滚;JSON 导出导入。
110
+ - **状态与备注进系统提示词**:只列当前真正可用的 server,你的备注作为决策提示带给模型;级别分「全局 / 应用级」,新增默认全局。
102
111
 
103
112
  ### 技能
104
113
 
105
114
  - **来源一览**:项目级 / DSH / Agents / Codex / Claude / 自定义目录,按来源分组。
106
115
  - **两组权限相反**:默认来源(DSH / 导入技能)必须读取但技能可删;外部目录可停用/移除但技能只读。
107
116
  - **移除 ≠ 停用**:移除 = 连目录都不扫(文件零改动,可恢复);停用 = 仍列出但不可调用。
108
- - **同名自选 / 自定义目录 / ZIP 导入 / 回收站**。
117
+ - **同名自选 / 自定义目录 / ZIP 导入导出 / 回收站**。
109
118
 
110
119
  ### 提示词预设
111
120
 
112
- - 多套 `~/.dsh/AGENTS.md` 基线,一键应用(新会话生效,当前会话不变),保留 5 代备份。
121
+ - 多套 `~/.dsh/AGENTS.md` 基线,一键应用(宿主每轮重读该文件,下一轮对话生效),保留 5 代备份。
122
+ - **描述**:每条预设可写一句「这份是干什么的」,只显示在插件界面里;它存在同目录的 `meta.json`,不进 AGENTS.md,也就不会被注入提示词。
113
123
  - 新建即可写正文,编辑可改 id(= 目录改名,场景绑定自动跟着改)。正在生效的不能删;删除进回收站。
114
124
 
115
125
  ### 历史会话
@@ -135,6 +145,7 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
135
145
  | MCP 定义 | `cordis.patch.yml`(改前自动 `.bak`) |
136
146
  | 技能策略 / 自定义目录 | `~/.dsh/tool-management/state.json` |
137
147
  | 技能 / 记忆 / 人设 / 预设 | `~/.dsh/tool-management/{skills,memories,agents,agents-md}/` |
148
+ | 子智能体启停 | `~/.dsh/tool-management/agents-index.json` |
138
149
  | 回收站 | `~/.dsh/tool-management/trash/` |
139
150
  | 归档账本 / 保留期 | `~/.dsh/tool-management/history-*.json` |
140
151
  | 记忆索引 / 场景 / 档案 | `~/.dsh/tool-management/rules-index.json` |
package/README_EN.md CHANGED
@@ -37,8 +37,9 @@ Hard-refresh the browser (Cmd/Ctrl+Shift-R) afterwards — a **Tools** panel in
37
37
  | Capability | Description |
38
38
  |---|---|
39
39
  | Scene memory | `.md` bodies in an enabled scene are **injected into the system prompt**, effective on the next request |
40
- | Scene profile | Every scene freely combines **MCP tools / skills / subagents / memories**; "Enter mode" narrows injection in one click |
40
+ | Scene profile | Every scene freely combines **MCP tools / skills / subagents / memories**; opening a scene applies it, closing restores from the snapshot |
41
41
  | Scene prompt | A scene can bind a prompt preset; switching scenes rewrites `~/.dsh/AGENTS.md` (auto-restores on exit) |
42
+ | Scene lock | Locking a scene freezes **all five domains read-only** (bound entries or not); a scene must be running to lock, and a locked scene can't be turned off — unlock first |
42
43
  | Per-tool switches | **Individual tools** inside one MCP server can be disabled: invisible to the model, blocked at call time |
43
44
  | Restart semantics | Restart only reconnects — it **never flips the enabled state** |
44
45
  | Secret safety | Secrets masked by default; "Reveal" & export **require a token** — no `token` configured means no plaintext |
@@ -47,7 +48,9 @@ Hard-refresh the browser (Cmd/Ctrl+Shift-R) afterwards — a **Tools** panel in
47
48
  | AGENTS.md presets | Multiple global baselines, one-click apply, 5-generation backup |
48
49
  | Archived sessions | Grouped by project, batch restore / delete, retention cleanup; rebuildable after workspace deletion |
49
50
  | Transcript import/export | Take over Claude Code / Cursor / Codex / any text; export Markdown / JSONL |
50
- | Subagents | One file per persona, run-and-discard, never enters History, inherits scene memories |
51
+ | Import pairs with export | Skills / subagents / prompts / memories all export too: pick items → zip into a directory you choose (read-only on sources) |
52
+ | Subagents | One file per persona, with an **on/off toggle** deciding whether it is injected; run-and-discard, never enters History, inherits scene memories |
53
+ | Context visibility | The persona catalog and "currently usable MCP servers + your notes" enter the system prompt, so the model knows what is available |
51
54
  | Prefix-cache friendly | Section text depends only on enabled scenes + file contents, byte-stable |
52
55
  | Compatibility check | The **Host** tab shows host capabilities, per-action routing, and degradations at a glance |
53
56
  | Model tools | **14** (`skill_mcp_manager_*` / `skill_manager_*` / `agentsmd_*` / `rule_manager_*` / `subagent_*`) |
@@ -83,15 +86,20 @@ The model can manage everything above via 14 tools (see highlights); scripts use
83
86
  - **A scene = a group, a memory = a `.md` file**. `memories/<scene>/<name>.md`, the whole body is injected, file names can be non-ASCII.
84
87
  - **Single-choice toggle**: only one scene at a time (others greyed out); turning all off = only `global` and `_shared` inject. New scenes start off.
85
88
  - **Scene-bound prompt**: switching scenes rewrites `~/.dsh/AGENTS.md` (5-gen backup, auto-restore on exit).
86
- - **Scene profile**: every scene combines MCP tools / skills / subagents / memories (any mix); "Enter mode" applies and narrows in one click, exit restores verbatim.
89
+ - **Scene profile**: every scene combines MCP tools / skills / subagents / memories (any mix); opening a scene applies and narrows injection, closing restores verbatim (the toggle is the only entry).
87
90
  - **Import**: `.md` / `.zip` (dir name = scene, bundles carry attachments), same names skipped never overwritten, over-limit items reported.
91
+ - **Export**: pick memories and zip them, keeping the `scene/name` layout; bundle memories bring their attachments along. Sources are read-only.
88
92
  - **Injection budget**: default 64 KiB, oversized memories skipped with a list. Deletes go to recycle bin.
93
+ - **Scene lock**: once locked, MCP / skills / subagents / memories / prompts are read-only — UI disabled plus a server-side guard; a scene must be running to lock, and a locked scene can't be closed until unlocked.
94
+ - **Deleting a scene deletes its memories too**: the scene record, profile and every memory go into one recycle-bin entry, restored as a whole; a running scene refuses deletion. Scene names are renameable (dir and profile follow, memory bodies untouched).
89
95
 
90
96
  ### Subagents
91
97
 
92
98
  - **One file per persona**: `agents/<persona>.md`, frontmatter entirely optional.
93
99
  - **Tool limits per Agent preset**: each preset gets its own allow/deny list (mutually exclusive), effective at runtime by the current preset — fixes the old "union of all presets" list that broke subagents after a preset switch.
94
100
  - **Run and discard**: `subagent_run` runs with the persona, returns only the result, never enters History, inherits scene memories. Scenes can bind which personas are available.
101
+ - **On/off toggles**: a disabled persona is not injected and invisible to the model (file untouched); newly created / imported / restored personas start enabled. Starting a scene auto-enables the personas its profile binds; exit restores precisely from the snapshot.
102
+ - **Persona catalog enters the system prompt**: names + descriptions only, so the model knows what it can delegate to; personas are renameable, scene bindings follow.
95
103
 
96
104
  ### MCP servers
97
105
 
@@ -99,17 +107,19 @@ The model can manage everything above via 14 tools (see highlights); scripts use
99
107
  - **Per-tool switches**: disable individual tools (invisible to the model, blocked at call), whole-server batch.
100
108
  - **Secret masking**: defaults to `••••••`, "Reveal" needs a token.
101
109
  - **Migrate & back up**: cross-project/global migration rolls back on failure; JSON export/import.
110
+ - **Status & notes enter the system prompt**: only currently usable servers are listed, and your notes travel along as decision hints; levels are "global / app", new servers default to global.
102
111
 
103
112
  ### Skills
104
113
 
105
114
  - **Sources at a glance**: project / DSH / Agents / Codex / Claude / custom dirs, grouped by source.
106
115
  - **Opposite permissions**: default sources must be read but skills can be deleted; external dirs can be disabled/removed but skills are read-only.
107
116
  - **Remove ≠ disable**: remove = directory not scanned at all (files untouched, restorable); disable = still listed but not callable.
108
- - **Same-name picker / custom dirs / ZIP import / recycle bin**.
117
+ - **Same-name picker / custom dirs / ZIP import & export / recycle bin**.
109
118
 
110
119
  ### Prompt presets
111
120
 
112
- - Multiple `~/.dsh/AGENTS.md` baselines, one-click apply (new sessions only, current unchanged), 5-gen backup.
121
+ - Multiple `~/.dsh/AGENTS.md` baselines, one-click apply (the host re-reads that file every turn, so it takes effect on the next turn), 5-gen backup.
122
+ - **Description**: one line saying what a preset is for — shown in this panel only. It lives in a sibling `meta.json`, never in AGENTS.md, so it is never injected into prompts.
113
123
  - Create with body inline, edit can change id (= dir rename, scene bindings follow). Active preset can't be deleted; deletes go to recycle bin.
114
124
 
115
125
  ### Archived sessions
@@ -135,6 +145,7 @@ The plugin uses the host's own `@deepseek-ai/*` libraries at runtime — they mu
135
145
  | MCP definitions | `cordis.patch.yml` (auto `.bak` before rewrite) |
136
146
  | Skill policy / custom dirs | `~/.dsh/tool-management/state.json` |
137
147
  | Skills / memories / personas / presets | `~/.dsh/tool-management/{skills,memories,agents,agents-md}/` |
148
+ | Subagent toggles | `~/.dsh/tool-management/agents-index.json` |
138
149
  | Recycle bin | `~/.dsh/tool-management/trash/` |
139
150
  | Archive ledger / retention | `~/.dsh/tool-management/history-*.json` |
140
151
  | Memory index / scenes / profiles | `~/.dsh/tool-management/rules-index.json` |
Binary file
Binary file
package/docs/update.md CHANGED
@@ -4,6 +4,7 @@
4
4
 
5
5
  | 版本 | 发布 | 主题 |
6
6
  |---|---|---|
7
+ | [0.8.0](#080---2026-09-15) | 2026-09-15 | 场景锁定 + 子智能体开关 + 四域导出 |
7
8
  | [0.7.0](#070---2026-09-15) | 2026-09-15 | 回收站全量 + 预设注入可见性 + 密钥令牌化 |
8
9
  | [0.6.0](#060---2026-09-14) | 2026-09-14 | 宿主兼容体检 + 兼容页 |
9
10
  | [0.5.1](#051---2026-09-13) | 2026-09-13 | 场景档案默认不勾选 + 场景页排版重做 |
@@ -12,6 +13,22 @@
12
13
 
13
14
  ---
14
15
 
16
+ ## 0.8.0 - 2026-09-15
17
+
18
+ - **场景锁定**:锁住后 MCP / 技能 / 子智能体 / 记忆 / 提示词整体只读(勾没勾的都不能动);未启动不能上锁,锁定中关不掉也切不走。
19
+ - **子智能体开关**:默认只把启用的人设注入上下文;启动场景时档案勾选的人设自动启用,退出按快照精确停回。
20
+ - **四个管理域补上导出**(技能 / 子智能体 / 提示词 / 记忆):导出弹窗分组折叠、默认不勾选、固定尺寸;记忆按场景分组、技能按来源文件夹分组。
21
+ - **导入入口统一**:提示词补上与技能页同源的拖拽弹窗;四个导入弹窗一律「文件要求」清单。
22
+ - **删除场景 = 连它下面的全部记忆一起进回收站**(含未启用与 bundle 附件),恢复时整条按原路径放回。
23
+ - **场景名、人设名现在可以改**(改名连带目录搬迁与绑定同步)。
24
+ - **提示词预设支持描述**:只显示在插件界面里,存 `meta.json`,绝不写进 AGENTS.md。
25
+ - 子智能体人设目录与 MCP 服务器备注进入系统提示词(模型知道有哪些人设可委派、哪些 server 可用)。
26
+ - 修复:进/退模式报 EPERM、开关要点两次(Windows 文件占用时 rename 自动重试)。
27
+ - 修复:退出场景模式后 MCP 服务器级与技能目录不回滚(快照字段在读盘时被剥掉)。
28
+ - 技能回收站重做:弹窗内上下两块(目录 / 技能)、各占一半、各自滚动;「删除记录」与「永久删除」统一为红色。
29
+ - MCP 新增默认级别改为全局;「Profile 级」改名「应用级」,全局排在上面。
30
+ - 界面统一化:按钮四级语义、弹窗固定尺寸只允许列表层滚动、命名统一「新增 / 导入 / 导出 + 页名」。
31
+
15
32
  ## 0.7.0 - 2026-09-15
16
33
 
17
34
  - 回收站扩到子智能体 / 场景 / 提示词预设(删除都进回收站,可恢复)。
@@ -3,7 +3,7 @@
3
3
  // DSH 全局指令基线只有一个文件 ~/.dsh/AGENTS.md(USER_GLOBAL_FILE 固定),
4
4
  // 没有内置的「多份全局 AGENTS.md 切换」机制。本服务在 hub 内维护一个
5
5
  // 预设库(每套一个子目录 + AGENTS.md),「应用」= 把选中预设内容写入
6
- // ~/.dsh/AGENTS.md,新会话生效(当前会话不变,DSH 本身如此)。
6
+ // ~/.dsh/AGENTS.md,下一轮对话生效(宿主每个 agent/pre-step 都会 stat 并重读该文件)。
7
7
  //
8
8
  // id 即目录名:字符集口径见 `./preset-id.ts`(用户裁定「什么都能写」,只留
9
9
  // 文件系统安全约束);`__last-applied__` 是备份槽,不算用户预设。
@@ -15,6 +15,8 @@ import { createHash } from 'node:crypto';
15
15
  import { isValidPresetId, LAST_APPLIED_PRESET_ID, normalizePresetId } from './preset-id.js';
16
16
  import { listTrashEntries, moveOutOfTrash, moveToTrash, purgeTrashEntry, readTrashEntry } from '../hub.js';
17
17
  const FILENAME = 'AGENTS.md';
18
+ /** 描述侧车:与 AGENTS.md 同目录,避免把「只给使用者看」的文字注入提示词。 */
19
+ const META_FILE = 'meta.json';
18
20
  const LAST_APPLIED_ID = LAST_APPLIED_PRESET_ID;
19
21
  /** 新建预设的初始正文(空模板);用户也可以直接粘贴自己的内容。 */
20
22
  const BLANK_TEMPLATE = '# AGENTS.md\n\n(DSH 全局指令基线预设,待编辑)\n';
@@ -36,6 +38,38 @@ export function createAgentsMdService(_ctx, deps) {
36
38
  return null;
37
39
  }
38
40
  }
41
+ // ── 描述(「只给使用者看」)────────────────────────────────────────────────
42
+ // 存在预设目录的 `meta.json` 里,**不写进 AGENTS.md**:那个文件的正文会被原样注入
43
+ // 系统提示词,把「这份预设是干什么的」写进去等于凭空给模型加了一段说明。
44
+ // 读写都 best-effort:描述坏掉/写不进去不该让「保存预设」失败(正文才是本体)。
45
+ async function readDescription(id) {
46
+ try {
47
+ const raw = await readFile(join(deps.presetsDir, id, META_FILE), 'utf8');
48
+ const parsed = JSON.parse(raw);
49
+ return typeof parsed.description === 'string' ? parsed.description : '';
50
+ }
51
+ catch {
52
+ return '';
53
+ }
54
+ }
55
+ /**
56
+ * 写描述。`undefined` = 不动(老调用方 / 只想改正文时不该顺手把描述抹掉),
57
+ * 空串 = 明确清空(连文件一起删,避免留一个空壳 meta.json)。
58
+ */
59
+ async function writeDescription(id, description) {
60
+ if (description === undefined)
61
+ return;
62
+ const text = String(description).trim();
63
+ const file = join(deps.presetsDir, id, META_FILE);
64
+ try {
65
+ if (text === '') {
66
+ await rm(file, { force: true });
67
+ return;
68
+ }
69
+ await writeFile(file, JSON.stringify({ description: text }, null, 2) + '\n', 'utf8');
70
+ }
71
+ catch { /* 描述写不进去不该让保存失败 */ }
72
+ }
39
73
  // 幂等初始化:仅当库完全无预设且全局 AGENTS.md 存在时,拷贝全局为 default
40
74
  // 预设(首次运行引导)。用户已 create/apply 过任何预设则不插手,避免把
41
75
  // 当前生效内容误存成 default 与真正生效的预设冲突。
@@ -84,6 +118,7 @@ export function createAgentsMdService(_ctx, deps) {
84
118
  return {
85
119
  id,
86
120
  active: globalHash !== null && contentHash !== null && globalHash === contentHash,
121
+ description: await readDescription(id),
87
122
  };
88
123
  }));
89
124
  presets.sort((a, b) => a.id.localeCompare(b.id));
@@ -142,13 +177,14 @@ export function createAgentsMdService(_ctx, deps) {
142
177
  }
143
178
  await mkdir(dir, { recursive: true });
144
179
  await writeFile(join(dir, FILENAME), content, 'utf8');
180
+ await writeDescription(safeId, options?.description);
145
181
  return { ok: true, id: safeId };
146
182
  }
147
183
  /**
148
184
  * 保存预设:正文写入 + 可选**改名**(目录改名,内容随目录一起走)。
149
185
  * 改名冲突(目标已存在)直接拒绝,不合并、不覆盖。
150
186
  */
151
- async function update(id, content, nextId) {
187
+ async function update(id, content, nextId, description) {
152
188
  const bad = idError(id);
153
189
  if (bad)
154
190
  return { ok: false, error: '非法 id:' + bad };
@@ -180,6 +216,7 @@ export function createAgentsMdService(_ctx, deps) {
180
216
  }
181
217
  }
182
218
  await writeFile(join(deps.presetsDir, targetId, FILENAME), String(content ?? ''), 'utf8');
219
+ await writeDescription(targetId, description);
183
220
  return { ok: true, id: targetId, ...(targetId === safeId ? {} : { renamedFrom: safeId }) };
184
221
  }
185
222
  /**
@@ -344,7 +381,7 @@ export function createAgentsMdService(_ctx, deps) {
344
381
  return { ok: true, id: clean };
345
382
  }
346
383
  // 从外部文本内容(如导入的 .md 文件)建预设:id 校验 + 重复检查 + 写 AGENTS.md。
347
- async function importPreset(id, content) {
384
+ async function importPreset(id, content, description) {
348
385
  const bad = idError(id);
349
386
  if (bad)
350
387
  return { ok: false, error: '非法 id:' + bad };
@@ -357,6 +394,7 @@ export function createAgentsMdService(_ctx, deps) {
357
394
  catch { /* 不存在,继续 */ }
358
395
  await mkdir(dir, { recursive: true });
359
396
  await writeFile(join(dir, FILENAME), String(content ?? ''), 'utf8');
397
+ await writeDescription(safeId, description);
360
398
  return { ok: true, id: safeId };
361
399
  }
362
400
  return { list, read, create, update, apply, restore, getCurrent, remove, trashList, trashRestore, trashDelete, importPreset };