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.
- package/CHANGELOG.md +179 -0
- package/README.md +117 -221
- package/README_EN.md +116 -220
- package/docs/images/1/345/234/272/346/231/257.png +0 -0
- package/docs/images/1/345/234/272/346/231/257_en.png +0 -0
- package/docs/images/2MCP.png +0 -0
- package/docs/images/2MCP_en.png +0 -0
- package/docs/images/3/346/212/200/350/203/275.png +0 -0
- package/docs/images/3/346/212/200/350/203/275_en.png +0 -0
- package/docs/images/4/345/255/220/346/231/272/350/203/275/344/275/223.png +0 -0
- package/docs/images/4/345/255/220/346/231/272/350/203/275/344/275/223_en.png +0 -0
- package/docs/images/5/346/217/220/347/244/272/350/257/215.png +0 -0
- package/docs/images/5/346/217/220/347/244/272/350/257/215_en.png +0 -0
- package/docs/images/6/350/256/260/345/277/206.png +0 -0
- package/docs/images/6/350/256/260/345/277/206_en.png +0 -0
- package/docs/images/7/344/274/232/350/257/235.png +0 -0
- package/docs/images/7/344/274/232/350/257/235_en.png +0 -0
- package/docs/images/8/345/205/274/345/256/271.png +0 -0
- package/docs/images/8/345/205/274/345/256/271_en.png +0 -0
- package/docs/update.md +56 -38
- package/lib/agents-md/service.js +84 -5
- package/lib/client.js +1488 -475
- package/lib/compat/preset-reach.js +425 -0
- package/lib/compat/probe.js +8 -0
- package/lib/http-fence.js +21 -0
- package/lib/hub.js +160 -2
- package/lib/index.js +687 -47
- package/lib/mcp/override-blocks.js +195 -0
- package/lib/mcp/state-section.js +90 -0
- package/lib/prompt-sections.js +148 -0
- package/lib/rules/archive-engine.js +99 -29
- package/lib/rules/archive.js +56 -28
- package/lib/rules/service.js +332 -35
- package/lib/skills/core.js +15 -1
- package/lib/skills/service.js +3 -0
- package/lib/subagents/catalog.js +89 -0
- package/lib/subagents/service.js +384 -41
- package/lib/subagents/tools.js +18 -5
- package/package.json +97 -96
- package/screenshots.json +10 -10
- package/docs/Changelog.md +0 -144
- package/lib/rules/provider.js +0 -121
package/docs/update.md
CHANGED
|
@@ -1,54 +1,72 @@
|
|
|
1
1
|
# 版本更新概要
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
逐条细节、边界与已知限制见 [Changelog](./Changelog.md);功能说明见 [README](../README.md) / [README_EN](../README_EN.md)。
|
|
5
|
-
|
|
6
|
-
> 版本号 = npm 上实际发布的发布号(`npm view dsh-plugin-tool-management versions`)。
|
|
7
|
-
> 日期 = npm 发布时刻(**UTC**);本地时间(UTC+8)比它晚 8 小时。
|
|
8
|
-
> 开发期的内部编号 `v0.3` / `v0.4` 没有单独发布,内容随 v0.5.0 一起出去。
|
|
3
|
+
每个版本大致改了什么——想知道「升上去会变什么」看这里就够了。逐条细节见 [Changelog](../CHANGELOG.md),功能说明见 [README](../README.md) / [README_EN](../README_EN.md)。
|
|
9
4
|
|
|
10
5
|
| 版本 | 发布 | 主题 |
|
|
11
6
|
|---|---|---|
|
|
12
|
-
| [
|
|
13
|
-
| [
|
|
14
|
-
| [
|
|
15
|
-
| [
|
|
7
|
+
| [0.8.0](#080---2026-09-15) | 2026-09-15 | 场景锁定 + 子智能体开关 + 四域导出 |
|
|
8
|
+
| [0.7.0](#070---2026-09-15) | 2026-09-15 | 回收站全量 + 预设注入可见性 + 密钥令牌化 |
|
|
9
|
+
| [0.6.0](#060---2026-09-14) | 2026-09-14 | 宿主兼容体检 + 兼容页 |
|
|
10
|
+
| [0.5.1](#051---2026-09-13) | 2026-09-13 | 场景档案默认不勾选 + 场景页排版重做 |
|
|
11
|
+
| [0.5.0](#050---2026-09-13) | 2026-09-13 | 数据目录统一 + 场景显式化 + 界面重做 |
|
|
12
|
+
| [0.2.0](#020---2026-09-12) | 2026-09-12 | 五域合并进一个「工具」面板 |
|
|
16
13
|
|
|
17
14
|
---
|
|
18
15
|
|
|
19
|
-
##
|
|
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
|
+
|
|
32
|
+
## 0.7.0 - 2026-09-15
|
|
33
|
+
|
|
34
|
+
- 回收站扩到子智能体 / 场景 / 提示词预设(删除都进回收站,可恢复)。
|
|
35
|
+
- 子智能体工具限制按 Agent 预设(每预设一份白/黑名单)。
|
|
36
|
+
- 兼容页「预设注入边界」五列标签(绿/红/灰框)。
|
|
37
|
+
- 明文密钥改为一律要令牌(没配 `token` 就不给明文)。
|
|
38
|
+
- MCP「整理补丁」重新上线(删多余启停块,状态不变)。
|
|
39
|
+
|
|
40
|
+
## 0.6.0 - 2026-09-14
|
|
20
41
|
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
- **安全与界面**:插件 HTTP 路由接上宿主鉴权栅栏(Host/Origin 判定 + browser-session cookie;`token` 作为脚本与局域网部署的逃生门);AGENTS.md 预设「应用」改为保留最近 **5 代**备份;全站 24 处弹窗的「取消 / 关闭」统一只在右上角;英文界面不再露中文(面板跟随宿主语言,会话页与 AGENTS.md 页接入词典)。
|
|
42
|
+
- 新增「兼容」页(第 8 栏)+ doctor/host-deps 脚本。
|
|
43
|
+
- 兼容判定从源码文本比对改为模块实体 + 能力探测。
|
|
44
|
+
- 归档会话不再丢工作区归属(登记被删后重建分组 + 一键重新登记)。
|
|
45
|
+
- 技能来源权限语义修正(默认来源必须读取但技能可删)。
|
|
46
|
+
- 场景可绑提示词预设,切换场景直接改写 AGENTS.md(关掉自动恢复)。
|
|
47
|
+
- 场景启用改单选,新场景默认不启动。
|
|
28
48
|
|
|
29
|
-
##
|
|
49
|
+
## 0.5.1 - 2026-09-13
|
|
30
50
|
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
- 客户端契约测试补上「档案弹窗默认勾选」「记忆段只认本场景的记忆」「场景页不列全局」等用例;两份 README 的测试组清单同步校正。
|
|
51
|
+
- 场景档案弹窗新加段默认不勾选。
|
|
52
|
+
- 档案「记忆」段只列本场景的记忆。
|
|
53
|
+
- 场景页排版重做(卡片只留名字+描述+动作)。
|
|
54
|
+
- 保留场景「全局」不再出现在场景页与档案弹窗。
|
|
36
55
|
|
|
37
|
-
##
|
|
56
|
+
## 0.5.0 - 2026-09-13
|
|
38
57
|
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
58
|
+
- 数据全部收进 `~/.dsh/tool-management/`(旧位置自动搬入)。
|
|
59
|
+
- 场景升级为显式记录;根层裸 `.md` 不再注入。
|
|
60
|
+
- 新增「导入技能」来源 + 「移除来源」操作。
|
|
61
|
+
- 场景档案新增第 4 段「记忆」。
|
|
62
|
+
- 修掉三个真故障:整页白屏、导出静默丢失、Skills 页锁死。
|
|
63
|
+
- 斜杠命令全部下线。
|
|
45
64
|
|
|
46
|
-
##
|
|
65
|
+
## 0.2.0 - 2026-09-12
|
|
47
66
|
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
- **History**:归档会话按项目分组、搜索、全选、批量恢复 / 永久删除、保留期自动清理;支持从 Claude Code / Cursor(JSONL)、Codex(Markdown)、任意文本导入;导出 Markdown / JSONL。
|
|
67
|
+
- 五域合并进一个「工具」面板:MCP / Skills / AGENTS.md 预设 / History。
|
|
68
|
+
- MCP 工具级启停、重启只重连、密钥打码、补丁备份。
|
|
69
|
+
- Skills 接入 ~/.agents / ~/.codex / ~/.claude + 自定义目录。
|
|
70
|
+
- History 按项目分组、批量操作、保留期清理、对话导入导出。
|
|
53
71
|
|
|
54
|
-
>
|
|
72
|
+
> 0.1.1 / 0.1.2 / 0.1.3 无独立记录(仅 git tag)。
|
package/lib/agents-md/service.js
CHANGED
|
@@ -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
|
|
6
|
+
// ~/.dsh/AGENTS.md,下一轮对话生效(宿主每个 agent/pre-step 都会 stat 并重读该文件)。
|
|
7
7
|
//
|
|
8
8
|
// id 即目录名:字符集口径见 `./preset-id.ts`(用户裁定「什么都能写」,只留
|
|
9
9
|
// 文件系统安全约束);`__last-applied__` 是备份槽,不算用户预设。
|
|
@@ -13,7 +13,10 @@ import { mkdir, readdir, readFile, rename, rm, stat, writeFile } from 'node:fs/p
|
|
|
13
13
|
import { join } from 'node:path';
|
|
14
14
|
import { createHash } from 'node:crypto';
|
|
15
15
|
import { isValidPresetId, LAST_APPLIED_PRESET_ID, normalizePresetId } from './preset-id.js';
|
|
16
|
+
import { listTrashEntries, moveOutOfTrash, moveToTrash, purgeTrashEntry, readTrashEntry } from '../hub.js';
|
|
16
17
|
const FILENAME = 'AGENTS.md';
|
|
18
|
+
/** 描述侧车:与 AGENTS.md 同目录,避免把「只给使用者看」的文字注入提示词。 */
|
|
19
|
+
const META_FILE = 'meta.json';
|
|
17
20
|
const LAST_APPLIED_ID = LAST_APPLIED_PRESET_ID;
|
|
18
21
|
/** 新建预设的初始正文(空模板);用户也可以直接粘贴自己的内容。 */
|
|
19
22
|
const BLANK_TEMPLATE = '# AGENTS.md\n\n(DSH 全局指令基线预设,待编辑)\n';
|
|
@@ -35,6 +38,38 @@ export function createAgentsMdService(_ctx, deps) {
|
|
|
35
38
|
return null;
|
|
36
39
|
}
|
|
37
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
|
+
}
|
|
38
73
|
// 幂等初始化:仅当库完全无预设且全局 AGENTS.md 存在时,拷贝全局为 default
|
|
39
74
|
// 预设(首次运行引导)。用户已 create/apply 过任何预设则不插手,避免把
|
|
40
75
|
// 当前生效内容误存成 default 与真正生效的预设冲突。
|
|
@@ -83,6 +118,7 @@ export function createAgentsMdService(_ctx, deps) {
|
|
|
83
118
|
return {
|
|
84
119
|
id,
|
|
85
120
|
active: globalHash !== null && contentHash !== null && globalHash === contentHash,
|
|
121
|
+
description: await readDescription(id),
|
|
86
122
|
};
|
|
87
123
|
}));
|
|
88
124
|
presets.sort((a, b) => a.id.localeCompare(b.id));
|
|
@@ -141,13 +177,14 @@ export function createAgentsMdService(_ctx, deps) {
|
|
|
141
177
|
}
|
|
142
178
|
await mkdir(dir, { recursive: true });
|
|
143
179
|
await writeFile(join(dir, FILENAME), content, 'utf8');
|
|
180
|
+
await writeDescription(safeId, options?.description);
|
|
144
181
|
return { ok: true, id: safeId };
|
|
145
182
|
}
|
|
146
183
|
/**
|
|
147
184
|
* 保存预设:正文写入 + 可选**改名**(目录改名,内容随目录一起走)。
|
|
148
185
|
* 改名冲突(目标已存在)直接拒绝,不合并、不覆盖。
|
|
149
186
|
*/
|
|
150
|
-
async function update(id, content, nextId) {
|
|
187
|
+
async function update(id, content, nextId, description) {
|
|
151
188
|
const bad = idError(id);
|
|
152
189
|
if (bad)
|
|
153
190
|
return { ok: false, error: '非法 id:' + bad };
|
|
@@ -179,6 +216,7 @@ export function createAgentsMdService(_ctx, deps) {
|
|
|
179
216
|
}
|
|
180
217
|
}
|
|
181
218
|
await writeFile(join(deps.presetsDir, targetId, FILENAME), String(content ?? ''), 'utf8');
|
|
219
|
+
await writeDescription(targetId, description);
|
|
182
220
|
return { ok: true, id: targetId, ...(targetId === safeId ? {} : { renamedFrom: safeId }) };
|
|
183
221
|
}
|
|
184
222
|
/**
|
|
@@ -285,6 +323,10 @@ export function createAgentsMdService(_ctx, deps) {
|
|
|
285
323
|
return { ok: false, error: message(e) };
|
|
286
324
|
}
|
|
287
325
|
}
|
|
326
|
+
/**
|
|
327
|
+
* 删除预设 = **移入回收站**(整个 `agents-md/<id>/` 目录搬走)。
|
|
328
|
+
* 备份槽 `__last-applied__` 不可删;正在生效的预设由调用方先拦(见 index.ts)。
|
|
329
|
+
*/
|
|
288
330
|
async function remove(id) {
|
|
289
331
|
const safeId = String(id ?? '').trim();
|
|
290
332
|
if (safeId === LAST_APPLIED_ID)
|
|
@@ -299,11 +341,47 @@ export function createAgentsMdService(_ctx, deps) {
|
|
|
299
341
|
catch {
|
|
300
342
|
return { ok: false, error: '预设不存在:' + safeId };
|
|
301
343
|
}
|
|
302
|
-
await
|
|
344
|
+
const moved = await moveToTrash('agents-md', safeId, [{ from: dir, dest: 'preset' }]);
|
|
345
|
+
if (moved.ok === false)
|
|
346
|
+
return { ok: false, error: '移入回收站失败:' + moved.error };
|
|
303
347
|
return { ok: true, id: safeId };
|
|
304
348
|
}
|
|
349
|
+
async function trashList() {
|
|
350
|
+
return { ok: true, trash: await listTrashEntries('agents-md') };
|
|
351
|
+
}
|
|
352
|
+
/** 从回收站恢复预设:同 id 已存在时**拒绝**(绝不覆盖)。 */
|
|
353
|
+
async function trashRestore(id) {
|
|
354
|
+
const entry = await readTrashEntry('agents-md', String(id ?? '').trim());
|
|
355
|
+
if (!entry)
|
|
356
|
+
return { ok: false, error: '回收站条目不存在:' + String(id ?? '').trim() };
|
|
357
|
+
const bad = idError(entry.name);
|
|
358
|
+
if (bad)
|
|
359
|
+
return { ok: false, error: '回收站里的 id 不合法:' + bad };
|
|
360
|
+
const target = join(deps.presetsDir, entry.name);
|
|
361
|
+
try {
|
|
362
|
+
await stat(target);
|
|
363
|
+
return { ok: false, error: '无法恢复,同 id 预设已存在:' + entry.name };
|
|
364
|
+
}
|
|
365
|
+
catch { /* 可用 */ }
|
|
366
|
+
try {
|
|
367
|
+
await mkdir(deps.presetsDir, { recursive: true });
|
|
368
|
+
await moveOutOfTrash('agents-md', entry.id, 'preset', target);
|
|
369
|
+
}
|
|
370
|
+
catch (e) {
|
|
371
|
+
return { ok: false, error: '恢复失败:' + message(e) };
|
|
372
|
+
}
|
|
373
|
+
await purgeTrashEntry('agents-md', entry.id);
|
|
374
|
+
return { ok: true, id: entry.name };
|
|
375
|
+
}
|
|
376
|
+
async function trashDelete(id) {
|
|
377
|
+
const clean = String(id ?? '').trim();
|
|
378
|
+
const gone = await purgeTrashEntry('agents-md', clean);
|
|
379
|
+
if (!gone)
|
|
380
|
+
return { ok: false, error: '回收站条目不存在:' + clean };
|
|
381
|
+
return { ok: true, id: clean };
|
|
382
|
+
}
|
|
305
383
|
// 从外部文本内容(如导入的 .md 文件)建预设:id 校验 + 重复检查 + 写 AGENTS.md。
|
|
306
|
-
async function importPreset(id, content) {
|
|
384
|
+
async function importPreset(id, content, description) {
|
|
307
385
|
const bad = idError(id);
|
|
308
386
|
if (bad)
|
|
309
387
|
return { ok: false, error: '非法 id:' + bad };
|
|
@@ -316,7 +394,8 @@ export function createAgentsMdService(_ctx, deps) {
|
|
|
316
394
|
catch { /* 不存在,继续 */ }
|
|
317
395
|
await mkdir(dir, { recursive: true });
|
|
318
396
|
await writeFile(join(dir, FILENAME), String(content ?? ''), 'utf8');
|
|
397
|
+
await writeDescription(safeId, description);
|
|
319
398
|
return { ok: true, id: safeId };
|
|
320
399
|
}
|
|
321
|
-
return { list, read, create, update, apply, restore, getCurrent, remove, importPreset };
|
|
400
|
+
return { list, read, create, update, apply, restore, getCurrent, remove, trashList, trashRestore, trashDelete, importPreset };
|
|
322
401
|
}
|