dsh-plugin-tool-management 0.16.6 → 0.18.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 +115 -0
- package/README.md +20 -4
- package/README_EN.md +20 -4
- package/docs/images/1-EN.png +0 -0
- package/docs/images/1.png +0 -0
- package/docs/images/2-EN.png +0 -0
- package/docs/images/2.png +0 -0
- package/docs/images/3-EN.png +0 -0
- package/docs/images/3.png +0 -0
- package/docs/images/4-EN.png +0 -0
- package/docs/images/4.png +0 -0
- package/docs/images/5-EN.png +0 -0
- package/docs/images/5.png +0 -0
- package/docs/images/6-EN.png +0 -0
- package/docs/images/6.png +0 -0
- package/docs/images/7-EN.png +0 -0
- package/docs/images/7.png +0 -0
- package/docs/images/8-EN.png +0 -0
- package/docs/images/8.png +0 -0
- package/docs/update.md +59 -0
- package/lib/audit-log.js +6 -2
- package/lib/client.js +1615 -148
- package/lib/compat/capability-specs.js +321 -0
- package/lib/compat/host-probe.js +261 -0
- package/lib/compat/host-roots.js +168 -0
- package/lib/compat/probe-types.js +6 -0
- package/lib/compat/probe.js +54 -714
- package/lib/context-inject-contract.js +114 -0
- package/lib/context-inject-frame.js +147 -0
- package/lib/context-inject-select.js +127 -0
- package/lib/context-inject-surface.js +97 -0
- package/lib/context-inject.js +57 -459
- package/lib/host-names.js +150 -0
- package/lib/http-api.js +229 -0
- package/lib/hub.js +84 -11
- package/lib/imports/parsers.js +40 -15
- package/lib/index.js +235 -843
- package/lib/mcp/inspect-probe.js +199 -0
- package/lib/mcp/loader-token.js +26 -0
- package/lib/mcp/manager.js +267 -558
- package/lib/mcp/patch-yaml.js +207 -40
- package/lib/mcp/secret-guard.js +122 -16
- package/lib/mcp/tool-visibility.js +388 -0
- package/lib/memories/archive-engine.js +163 -16
- package/lib/memories/archive.js +10 -1
- package/lib/memories/discovery.js +261 -0
- package/lib/memories/export-plan.js +42 -0
- package/lib/memories/index-io.js +125 -12
- package/lib/memories/memories-types.js +1 -0
- package/lib/memories/service.js +167 -78
- package/lib/memories/snapshot.js +41 -260
- package/lib/op-registry.js +72 -8
- package/lib/ops/compat.js +17 -2
- package/lib/ops/prompts.js +18 -5
- package/lib/ops/quick-prompts.js +26 -0
- package/lib/ops/scene-records.js +157 -10
- package/lib/ops/scene-sync.js +71 -1
- package/lib/ops/sessions.js +63 -13
- package/lib/ops/snapshot.js +123 -24
- package/lib/ops/trash.js +45 -9
- package/lib/prompts/quick-service.js +211 -0
- package/lib/prompts/service.js +7 -2
- package/lib/request-gate.js +115 -56
- package/lib/scene-linkage.js +184 -0
- package/lib/scene-prompt-sync.js +46 -7
- package/lib/scenes/candidates.js +21 -3
- package/lib/sessions/archive-schemas.js +121 -0
- package/lib/sessions/path-key.js +46 -0
- package/lib/sessions/workspace.js +45 -168
- package/lib/settings-sidecars.js +143 -0
- package/lib/skills/core-types.js +8 -0
- package/lib/skills/core-util.js +81 -0
- package/lib/skills/core.js +97 -2297
- package/lib/skills/dir-watch.js +71 -0
- package/lib/skills/frontmatter.js +96 -0
- package/lib/skills/homes.js +14 -0
- package/lib/skills/import-pipeline.js +231 -0
- package/lib/skills/manager-state.js +800 -0
- package/lib/skills/official.js +269 -0
- package/lib/skills/provider-registration.js +89 -0
- package/lib/skills/service.js +4 -234
- package/lib/skills/skill-roots.js +287 -0
- package/lib/skills/skill-trash.js +265 -0
- package/lib/skills/system-trash.js +97 -0
- package/lib/skills/upload-pipeline.js +374 -0
- package/lib/slash-settings.js +25 -0
- package/lib/subagents/persona-parse.js +312 -0
- package/lib/subagents/persona-types.js +5 -0
- package/lib/subagents/persona-write.js +93 -0
- package/lib/subagents/run-provider.js +159 -0
- package/lib/subagents/service.js +20 -639
- package/lib/subagents/tool-filter.js +98 -0
- package/lib/token-config.js +240 -0
- package/lib/tool-table-switch.js +163 -0
- package/lib/tools/scene.js +40 -9
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,121 @@
|
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
## [0.18.0] - 2026-10-01
|
|
14
|
+
|
|
15
|
+
斜杠命令「工具」段 + 快捷提示词(含场景绑定)+ 兼容页两段开关与挂载实况。
|
|
16
|
+
|
|
17
|
+
### 新增
|
|
18
|
+
|
|
19
|
+
- **斜杠命令「工具」段**:对话输入框打 `/` 就能进场景、启停技能 / MCP 服务器 / 子智能体 / 提示词 / 记忆,点完菜单不关、接着点下一条。走宿主官方 `inputTriggers` 通道(不改官方包),只放可逆动作。
|
|
20
|
+
- 六个域各一行,点一行原地进入该域条目(面包屑「工具 › 技能」);启用项绿色对勾、停用项空心框,右侧灰字是条目自己的备注,域行右侧是当前态摘要。
|
|
21
|
+
- 条目按域内唯一的 `key` 定位(技能与 MCP 服务器会重名);点下去先叠本地乐观状态,写成功后按官方口让菜单重取一次候选。
|
|
22
|
+
- 每个外部技能目录多一行「目录名 · 目录」,开得也关得;列表全量给出不截断,技能按来源目录、记忆按场景分组,已启用的在前。
|
|
23
|
+
- 场景域不列两个恒开的保留场景;记忆域默认带上「全局」那一组并钉在最前面。
|
|
24
|
+
- 半截 token 直接按 Enter 会被拦下,不会当普通消息发给模型。
|
|
25
|
+
- **快捷提示词**:提示词页拆成「全局提示词」与「快捷提示词」两段。快捷词不注入上下文,在 `/` 的「快捷提示词」段点一下把正文原样贴进输入框(不自动发送);与预设两份存储(`hub/quick-prompts/`),每条一颗开关管它在不在 `/` 里。
|
|
26
|
+
- 新 op 8 条(list / create / update / toggle / remove + 回收站三条)逐条登记进 `op-registry`,写侧与五个管理域同一条门禁。
|
|
27
|
+
- 数据纪律与预设同级:删除进回收站、可勾选导出成 zip、随整机迁移快照走。
|
|
28
|
+
- **场景可以绑定一组快捷提示词**:「修改场景」里那颗下拉默认「当前启用的」= 不绑、进出不碰;勾了的进场景启用、其余停用,退出按快照还原。空表是合法值(= 进入后全部停用)。
|
|
29
|
+
- **兼容页「斜杠命令入口」一组**:两段各一颗勾选框(新 op `slash-settings`)+ 一枚「已生效 / 未生效」标签(挂载实况由客户端按段上报);功能总览同步多一行。
|
|
30
|
+
- **一条全局轻提示 `showPluginToast`**(右下角):斜杠命令是在对话页按下的,`Notice` 长在页签里、那时设置页根本没挂载。
|
|
31
|
+
|
|
32
|
+
### 修复
|
|
33
|
+
|
|
34
|
+
- **`scene_manager_switch` 退出场景的回执说「什么都没改」**:判据把"目标就是当前场景"的早退与"真的退掉一个场景"混成同一个形状,模型每次退出拿到的都是 `OK: already in scene「」`。
|
|
35
|
+
- **`/` 菜单进 / 出场景不应用、也不恢复档案**:「启用集合与当前模式恒等」这条原本靠每个调用方各调两个 op 维持,`/` 那一行只调了一个。现在收到服务端兜住,面板 / `/` / 模型工具都只发一次调用。
|
|
36
|
+
- **分组卡片点标题收不起来**(MCP 页 0.11.0 起、提示词页两处):写进"收起 = true"那张表里的值取反错了,每次点击都把同一个值写回去。
|
|
37
|
+
|
|
38
|
+
### 变更
|
|
39
|
+
|
|
40
|
+
- **档案摘要与切换回执补上「模型工具表」这一档**:`scene_manager_list` 多一格「工具表方案「X」」,切换回执多一句「切到方案「X」(关 N 条)」/「按进场景前的快照还原」;名单本来没变就一句都不说。模型侧不提快捷提示词。
|
|
41
|
+
- **`/` 的「工具 › 提示词」域里两类提示词都是启停行**,贴文字改由「快捷提示词」那一段常驻承担(两个源、两件事)。
|
|
42
|
+
- **提示词页两组换成技能那样的可折叠卡片**(卡片头 = 组名 + 条数);快捷那组卡片头给「全选 / 取消全选」,全局那组不给(单选)。
|
|
43
|
+
- **全局提示词的「应用 / 重新应用」两颗文字按钮换成一颗药丸开关**(在「编辑」左边):亮着的再点一次 = 重新写回 `AGENTS.md`。
|
|
44
|
+
- **「修改场景」弹窗分两模块**(基本信息 / 场景绑定),快捷提示词的勾选清单换成段卡片(段头计数 + 全选,段体按内容长)。
|
|
45
|
+
- **模型工具表里「提示词」这一组改口「全局提示词」**,两条工具的说明点明只管写进 `AGENTS.md` 的基线;没有为快捷提示词新增模型工具。
|
|
46
|
+
- **含下拉与勾选清单的字段外层 `label` 改 `div`**:嵌套 label 会把"点段头空白"转给勾选清单里第一颗复选框。
|
|
47
|
+
- **场景档案弹窗的段脚注撤了**(同一件事在段头计数、未定义提示与脚注各说一遍)。
|
|
48
|
+
- **「新增提示词」弹窗删掉「或从现有预设复制」那一格**(`agentsmd-create` 的 `from` 参数保留,只是界面不再给入口)。
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## [0.17.0] - 2026-09-30
|
|
53
|
+
|
|
54
|
+
对抗性审查收尾:三批(P0/P1/P2 表 19 条 + §5 脆弱性地图 F1–F12)与随后一轮复审(14 条发现 + 2 条替代项)全部处理完毕,逐条到终态;P0 / P1 每条都先复现坏行为再修。报告与终态处置表在 `review/`(本地工作稿,按 `.gitignore` 不入版本库)。
|
|
55
|
+
|
|
56
|
+
### 修复
|
|
57
|
+
|
|
58
|
+
- **记忆索引:一次读失败不再等于「整份配置被清空」**(P0-1):读失败(EACCES / EBUSY)曾被当成「没有索引」,随后任何一次写都会把空索引落盘,界面 5 秒轮询的读操作也会触发。现在只有 ENOENT 算新用户,其余读失败一律按「不可信」处理(拒写 + 界面按全部未启用显示)。
|
|
59
|
+
- **场景回收站:含子目录 / bundle 记忆的场景恢复不再必然失败**(P0-2):负载名拒收带 `/` 的名字,而场景记忆天生是目录树 —— 删除能成功、恢复必失败且不可再恢复;删除回滚失败还会把回收站条目整条删掉。现在负载名支持安全相对路径,恢复失败退回回收站,回滚没做完绝不清理条目。
|
|
60
|
+
- **记忆回收站恢复不再能写到记忆根之外**(P0-3):条目里的组名是磁盘数据,`../..` 能把正文写到记忆根外。现在与回收站列表同一道判据,并在落盘前核对落点是否在根内。
|
|
61
|
+
- **整机迁移快照不再导出明文凭据**(P0-4):默认导出只认 `key` / `token` / `secret` / `password` 四个参数名,`?api_key=` / `?access_token=` / `?sig=` 等全部漏掉。现在与 MCP 列表同一套打码,并补上非绝对地址的兜底;`$VAR` / `!!js` 这类间接引用改回原样保留。
|
|
62
|
+
- **MCP 体检不再回未打码的地址**(P0-5):它是免令牌的只读操作,却把配置里的 URL 原文回给客户端。现在地址一律打码后回(主机与路径保留),命令名仍明文(与 `mcpm-list` 口径一致)。
|
|
63
|
+
- **注入取数失败不再伪装成「已清空」**(P1-8 / F2):某个域抛异常时被当成「这轮没内容」,还向模型发一条假的「已清空」,界面显示成「未投递」。现在异常与真的空分开:抛异常的域这轮不发,「注入实况」新增「取数失败」状态,兼容页那一行同时承载装配失败与运行期失败。
|
|
64
|
+
- **读失败不再改名用户文件**(本版自查):上一批把读失败也接到「改名留存」那条处置上,而读失败常是瞬时的 —— 等于把「重试即可恢复」升级成「记忆全没了」。现在两条路分开:解析失败照旧改名留存,读失败只标记不可信、不动文件,下次读成功自动解除。
|
|
65
|
+
- **场景改名 / 删除→恢复不再丢记忆的索引条目**(P1-1):改名没搬每条记忆的启停 / 排序 / 标签 / 置顶 / 备注,这些条目被当悬空引用清掉 —— 用户显式停用的记忆会自己重新启用。现在改名按前缀整体迁移,删除时一并收进回收站、恢复时合并回来。
|
|
66
|
+
- **删除 / 恢复场景不再跟随目录链接搬走根外文件**(P1-2,已实测复现):`memories/<场景>` 若是指向根外的链接,列目录会列出链接目标的内容,删除会真的把根外文件搬进回收站。现在动手前核对落点是否在根内,遍历时跳过链接。
|
|
67
|
+
- **MCP 导出不再谎报「hub 目录写入失败」**(P1-3):它把一份 JSON 交给了只接受补丁格式的写入器,校验必然失败且错误被吞,界面给的诊断是错的。改用普通 JSON 写入。
|
|
68
|
+
- **停用的 MCP 工具不再能被调用**(P1-4):`mcp__<server>__<tool>` 对 `__` 有歧义,而守卫取第一个 `__`、列表取最后一个、场景档案又取第一个 —— serverName 含下划线时守卫查表不命中即放行,这是**执行侧**失效。现在三处共用同一个切分函数 `splitMcpToolName`。
|
|
69
|
+
- **重复 loader id 守卫不再只扫 MCP 行**(P1-5):导入一条非 MCP 条目就能撞出重复 id,而同 id 会让插件组装失败、DSH 起不来。现在扫全部 insert 子条目(顶层覆盖块不算)。
|
|
70
|
+
- **整机迁移的技能域从「永远不工作」到能用**(P1-6):导出侧读错返回结构,技能永远导出 0 项而界面显示「迁移完成」;导入侧又把 zip 喂给只认目录和 `.md` 的入口。现在导出按正确结构展开,导入改走能吃 zip 的链路。
|
|
71
|
+
- **`history-delete` 收敛到「只能删已归档会话」**(P1-7):批量删除一直求交归档集合,单删却直接删 —— 一个客户端 bug 就能永久删除任意已保存会话。现在单删也先确认在归档集合里(查不到归档状态即拒绝)。
|
|
72
|
+
- **场景绑定的预设正文有了与 AGENTS.md 相同的注入预算**(P2-1):AGENTS.md 分支有 64 KiB 截断,场景分支一点上限都没有。现在复用同一套截断与提示。
|
|
73
|
+
- **全局 AGENTS.md 与场景基线快照改为原子写**(P2-2 / P2-16):AGENTS.md 是宿主每步都重读的文件,中断可能留下半截内容进模型上下文;基线快照损坏会让「退出场景恢复 AGENTS.md」静默失效。现在两者原子替换,快照读不出来时如实报警。
|
|
74
|
+
- **编辑 / 删除 MCP 不再删掉手写 `config` 的覆盖块**(P2-6):补丁按条目 id 生效,手写配置是合法用法,删除时却被整块带走。现在只删纯块;「启停值读不出来」(如 `!!js …`)也不再被当成显式启用。
|
|
75
|
+
- **去重读的不再是「另一个文件」**(P2-19):全局指令路径有两条来源,去重时用了不是宿主实际读的那一份,同一份预设正文被注入两遍。现在由调用方把宿主实际读的那一份喂进来。
|
|
76
|
+
- **保存场景档案不再抹掉别的场景**(P2-3):档案切片在写队列外读、队列内写,窗口里另一个写者的改动会被陈旧整片回写覆盖。现在每次写显式声明改哪几片,档案另走逐场景增量。
|
|
77
|
+
- **场景名口径统一:命名用单段、定位用完整路径**(P2-4):多段名(`a/b`)能通过校验并被写进启用集合,但注入时两边对不上,表现为「开关点了、场景没生效」且零报错。现在命名路径必须单段(多段当场报错),定位路径按完整路径寻址。
|
|
78
|
+
- **备份名加上毫秒与进程内序号**(P2-5):时间戳只到秒,同一次操作连写两遍时后一份覆盖前一份,「保留 5 份」实际变成「保留 5 个秒」。两代格式都认,存量备份仍会被清理。
|
|
79
|
+
- **行级编辑不再改坏块标量**(P2-7):折叠空行会把 3+ 连续换行折成 1 个,而块标量(`!!js |`)的内容就是换行与缩进 —— 折一次等于改写用户手写的表达式。现在跳过块标量内部,认不出形状时退化为旧行为。
|
|
80
|
+
- **`tools.restrict` 缺失时不再静默**(P2-8):全局 tools 面没有 `restrict` 时直接返回,停用工具仍留在模型可见的工具表里,兼容页还报「ok」。现在与另一处同 id、同文案地上报。
|
|
81
|
+
- **整机迁移导入不再吞掉各域的「需要注意」**(P2-9):只取成功 / 跳过数,于是「这些密钥已是打码占位符,请重新填写」到不了界面。现在透传并渲染(记忆域带上跳过原因,上限 5 条)。
|
|
82
|
+
- **`mcpmRestart` 不再把服务器留在停用态**(P2-11):某些形状下(条目自带 `disabled: true`、靠覆盖块启用)恢复步骤会把生效值回落到条目自带值。现在恢复前比对一次,不等就显式写回。
|
|
83
|
+
- **令牌操作不再把「覆盖条目」当成「第二份补丁」**(P2-12):判据只对 insert 条目成立,而 0.1.7 bundle 挂载下令牌的写点就是覆盖条目 —— 那种安装下所有令牌操作被全量拒绝。现在按形状分类,写点优先取覆盖条目。
|
|
84
|
+
- **不可解析的超时值不再写成 `NaN`**(P2-13):手写补丁里 `toolCallTimeoutMs` 被读成字符串,`Number("30s")` 直接把 `NaN` 落盘。现在认不出来就整行不写,`0` 也不写。
|
|
85
|
+
- **「已知工具」侧车的读-改-写整段进写锁**(P2-15):两个并发写者各读旧表、各并进自己那台服务器,后写的整份覆盖先写的。现在锁内读 → 合并 → 落盘。
|
|
86
|
+
- **技能上传不再能从暂存目录逃出去**(P2-17):路径校验只挡「正好是 `..`」的段,而 Windows 会裁掉段尾的空格,`.. ` 等于 `..`。现在按段判「会不会被文件系统改写」,正常点文件(`.DS_Store`)照常放行。
|
|
87
|
+
- **子智能体列表不再列出管不动的隐藏人设**(P2-18):隐藏名(`.foo`)被判 hidden,列表里却出现一个「看得见、改不了、删不掉」的人设。现在列表侧与校验侧同一道谓词。
|
|
88
|
+
|
|
89
|
+
### 修复(复审)
|
|
90
|
+
|
|
91
|
+
- **`skill-trash-delete` 的路径穿越堵住**(F1,P0):`id` 直接拼进回收站目录路径,`id=".."` 就能把整个 `hub/trash` 交给系统回收站。现在走既有的单段名校验。
|
|
92
|
+
- **「读改写例外」不再被借道**(F2,P1):`tool-table` 免令牌的依据是「纯读」,而「保存方案 / 删除方案」走同一个操作名却会写侧车。现在写条件改为数据化声明:带写触发键就必须过令牌。
|
|
93
|
+
- **场景锁定对模型面生效**(F3,P1):冻结只包在界面那条入口上,锁着一个非活动场景时模型仍能改技能 / 记忆 / MCP / 子智能体 / 场景档案。现在两侧同一份判据;「锁着仍能解锁、仍能退出场景」用契约测试钉住。
|
|
94
|
+
- **打码 URL 不再被写回补丁**(F4,P1):新增 / 导入 MCP 拿到的是已打码的地址,写回时不做还原,`%3Credacted%3E` 真的落进补丁。现在所有写路径强制还原,还原不出来就报错要求重填。
|
|
95
|
+
- **打码链补上 userinfo 与 fragment**(F5,P1):`https://user:pass@host/…` 与 `…#access_token=abc` 原样输出,而这两种形态在托管服务里都常见。现在一并打码。
|
|
96
|
+
- **块标量识别按 YAML 规范补全**(F6,P1):识别只认 `|` / `>` 紧跟指示符的形态,`!!js |` / `&a |` / `|2-` 都不算,照样被折 = 改写手写表达式。现在按规范最小集补齐,另加「认不出的疑似块标量头 → 整份文件不折叠」。
|
|
97
|
+
- **注入通道的「取数失败」覆盖到域内部**(F7,P1):上一轮只堵住通道拿到异常那一层,而某个域自己就把 IO 错误吞成空串。现在域内部也把 IO 失败与真的空分开;文件不存在仍按正常空处理。
|
|
98
|
+
- **「首选」对模型真正生效**(F8,P1):界面与模型侧共用同一个分组函数,而 provider 那条路径没传 `preferred` —— 同名首选只影响界面显示。现在 provider 路径传上;首选来源处于停用时如实回报「已记录,但它不会生效」。
|
|
99
|
+
- **单删的归档判据取权威集合**(F9,P2):单删用有损投影(头部读不出来的会话被静默跳过),批量路径用权威集合 —— 同一份数据两条路结论相反。现在单删也取权威集合。
|
|
100
|
+
- **「只能删已归档」成为不变量**(F10,P2):级联删除按父子关系直接删、不问归档集合,删一个已归档父会话会连带删掉未归档的子会话。现在只吃已归档的子会话,读不出归档状态时什么都不级联。
|
|
101
|
+
- **记忆回收站恢复失败会回滚**(F11,P2):复制中途失败留下「半放回 + 目标已非空」,而条目还在 —— 下一次恢复撞「同名记忆已存在」,这条记忆再也恢复不了。现在失败时清掉落点并保留条目,可直接重试。
|
|
102
|
+
- **`.txt` 按内容嗅探,不再一律当纯文本**(F12,P2):改名成 `.txt` 的 JSONL / Markdown 转写会被整份折成一条 user 消息,而返回的是「导入成功」。现在先嗅探,认不出且行数不少时如实提示。
|
|
103
|
+
- **引用探测失败不再放行删除**(F13,P2):`refs()` 返回 `null` 时放行 —— 删掉被场景绑定的预设会静默让场景驱动失效。现在探测失败一律拒绝,并说明是「探测失败」而非「有引用」。
|
|
104
|
+
- **场景基线写失败不再被吞**(F14,P2):失败只写一行 `warn`,AGENTS.md 照旧切进场景态而没有退路,界面零提示。现在返回失败原因,与「AGENTS.md 未写入」分开上报。
|
|
105
|
+
|
|
106
|
+
### 新增
|
|
107
|
+
|
|
108
|
+
- **兼容探测表新增 `fs.patch-io`**(F5):补丁文件的读写要经 `ctx.fs` 升级沙箱策略,五个方法任一改名会让 19 处补丁写路径一起报错。现在钉在兼容页上;「参数语义变了」探不到,如实分开。
|
|
109
|
+
- **挂载心跳带上宿主进程身份**(F1):额外记 `pid` 与 `hostStartedAt`,`check:host` 据此直接给结论(写心跳的进程还在 → 这一轮确实挂上了;已不在 → 宿主重启过)。局限:进程号会被复用。
|
|
110
|
+
- **doctor 新增 `AGENTS.md` 增量刷新的 drift canary**(F3):官方改成事件驱动 / 改 digest 口径时旧正文会继续注入且零报错。现在加一组源码标记检查,缺失时直说影响面。
|
|
111
|
+
- **`hostRootCandidates()` 成为「宿主在哪」的唯一口径**(F10):运行时、doctor、host-deps 此前各写一份,doctor 还少了桌面版归档那条(桌面宿主上会报「找不到宿主」或比出假的「两份不同拷贝」)。现在三处共用一份。
|
|
112
|
+
- **`mcpmListView` 上报 MCP 工具前缀的漂移**(F6):前缀抽成 `MCP_TOOL_PREFIX`(唯一一处)并加一条 inform-only 上报。判据是「`mcp` 词根后换了分隔符」且至少两个同名根的工具 —— 第一版没排除本插件自己的 `mcp_manager_*`,会让这条在每台机器上误报,已自查改掉。
|
|
113
|
+
- **服务器名的 `__` 歧义会出声了**(N2):`serverName` 允许含 `__`,于是「`a` 的 `b__c`」与「`a__b` 的 `c`」在全名上同形。本轮不收紧校验,改为加一条 inform-only 上报,两种形状取更具体的那条只出一行;判据是纯函数且零误报,只上报、不阻断、不自动改名。
|
|
114
|
+
|
|
115
|
+
### 变更
|
|
116
|
+
|
|
117
|
+
- **两份 peer range 不再漂移,且明确「不设上界」**(F9 / §5.4):`probe.ts` 与 `package.json` 此前是两个写法(且前者 caret 隐含上界,与注释自相矛盾)。现在两处是同一个字符串并由契约测试钉住;无法用 range 消除的缺口(尚未枚举的新 rc 在 npm7+ 下仍会 ERESOLVE)写进注释。
|
|
118
|
+
- **契约测试共补 34 条不变量**(`test/contracts.test.mjs`,三批 18 条 + 复审 16 条):全部钉纯函数不变量与宿主契约,不加界面测试。
|
|
119
|
+
|
|
120
|
+
### 说明
|
|
121
|
+
|
|
122
|
+
- **实测**:`npm run build`、`npm run check:i18n`(zh/en 各 1501 键)、`npm run typecheck:client`、`npm run lint` 通过;`node --test test/contracts.test.mjs` **67/67**(33 既有 + 34 新增)、`test/client-exports.test.mjs` 1/1;`doctor.mjs` / `host-deps.mjs` 正常跑完。
|
|
123
|
+
- **先复现再下结论**:复审 14 + 2 条每条都先复现坏行为,修完再把修复回退掉重跑同一份探针 —— 只证明「改完是绿的」不足以说明探针在判别。回退后转红数:F9 / F10 5 项、F11–F14 10 项、N1 7 项、N2 2 项。
|
|
124
|
+
- **N1 在本机是 no-op(如实标注)**:本机 7 个已配置 serverName、105 条已知工具,无一含 `__`,停用表为空 —— 三种切法逐条比对 0 条不一致,这次统一切法是为将来修的。**残余风险**:两个真实服务器名互为 `__` 前缀时,守卫(候选必须窄,否则 fail-open)与显示侧仍可能给出不同答案,由 N2 的上报把它变成可见提示。
|
|
125
|
+
- **未做的验证**:按 `AGENTS.md`,功能验证由用户在真实环境完成 —— 本次未在真实宿主里点过界面。三处只做了静态核对:`mcpmListView` 的前缀漂移上报、`webServer.register` 失败的运行期上报、备份名的新格式。
|
|
126
|
+
- **本版仍未处理的部分**:两份报告里没有了。两处明确不做、记录在案:① §5.4 余下两条属持续维护成本(每出一个宿主 rc 需手工同步 5 处、桌面宿主缺「布局漂移」上报),记在适配矩阵里;② **F15 不收紧**(拒绝含 `__` 的 `serverName`)—— 今天放行 `__` 的 5 处校验一旦收紧,存量服务器会从「能管」变成「管不了」,改由 N1 + N2 处理。
|
|
127
|
+
|
|
13
128
|
## [0.16.6] - 2026-09-30
|
|
14
129
|
|
|
15
130
|
官方内置技能管理补全 web 侧:web 宿主照注的沙盒诊断技能接入技能页(可见、可停),Office 三件套按裁定在 web 上一并暴露;并补齐接管后缺失的 LibreOffice Kit 路径段。
|
package/README.md
CHANGED
|
@@ -41,7 +41,8 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
|
|
|
41
41
|
|
|
42
42
|
| 亮点 | 说明 |
|
|
43
43
|
| --------------------------- | ----------------------------------------------------------------------------------------- |
|
|
44
|
-
| 一键换场景 | 每个场景各配一套 MCP / 技能 / 人设 /
|
|
44
|
+
| 一键换场景 | 每个场景各配一套 MCP / 技能 / 人设 / 记忆(绑了的话还有快捷提示词),进入时整套切换、退出时还原;模型也能按你说的切 |
|
|
45
|
+
| 不离开对话就能管 | 在对话输入框打 `/` 出「工具」段:进场景、启停技能 / MCP / 子智能体 / 提示词 / 记忆,点一下就生效 |
|
|
45
46
|
| 记忆自动送到模型眼前 | 每个场景下写几段 `.md` 就是它的资料库,正文自动进上下文,不用每次复制粘贴 |
|
|
46
47
|
| 给 MCP 服务器写备注 | 「A 不可用时改用 B 兜底」这类话写进备注,模型每轮都看得到,会照做 |
|
|
47
48
|
| 单个工具也能关 | 一台服务器里可以只停某个工具,模型看不见也调不到;「重启」只重连,不改开关状态 |
|
|
@@ -75,10 +76,20 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
|
|
|
75
76
|
|
|
76
77
|
## 功能
|
|
77
78
|
|
|
79
|
+
### 斜杠命令(在对话里直接管)
|
|
80
|
+
|
|
81
|
+
- **打 `/` 出「工具」段**:六行 —— 场景 / 技能 / MCP 服务器 / 子智能体 / 提示词 / 记忆。点一行原地进入这一域的条目(顶栏面包屑点「工具」回上一级),再点一条直接生效。**点完菜单不关**,接着点下一条也行 —— 连点多个开关是主要用法。
|
|
82
|
+
- **状态看得见**:启用项图标位是绿色对勾、停用项是空心框,右侧灰字是条目自己的备注(场景说明 / 技能描述 / MCP 备注 / 人设描述 / 预设描述 / 记忆描述,超 40 字截断;没写备注才退回「已启用 / 未启用」);域行右侧给当前态摘要(`当前:工作`、`3 启用 / 1 停用`),不点进去也知道现在什么状况。点下去立刻翻转(本地乐观状态),写失败会翻回来并说明原因。
|
|
83
|
+
- **条目多也不挡路**:每个域全量列出,靠面板自己滚动;技能按来源目录分组、记忆按场景分组,组内已启用的排前面。每个外部技能目录另给一行「目录名 · 目录」,钉在本组最上面,点它就是启停整个来源(开着也列,所以也关得掉;关掉时它里面的技能整组收起,重新启用当场又摆回来)。场景域里两个恒开的保留项(「全局」与公共基线)不出现,但记忆域默认带上「全局」那几条,并把这一组钉在最前面 —— 它们不属于当前场景,却对任何对话都成立。
|
|
84
|
+
- **只放可逆动作**:进场景与各类启停。再点当前场景 = 退出场景(只注入全局与公共基线);只有全局提示词那一档关不掉(基线没有"全部不应用"这一态),点当前那一份只回一句「当前就是它」。增删改、导入导出、改配置仍各归各页。
|
|
85
|
+
- **走宿主官方通道**:用 DSH 的输入触发器接口注册(官方技能菜单同一条路),不 patch 官方包;宿主没有该服务时这个入口不出现,「兼容」页会照实说明。两段各一颗开关(「工具」/「快捷提示词」),在「兼容 → 注入」块的「斜杠命令入口」一组里,行末那枚标签说的是本次启动真挂上没;两段各挂各的源,关掉一个不影响另一个;两段都关掉后 `/` 菜单回到出厂样子(修改后重启 DSH 即可生效)。
|
|
86
|
+
- **「工具 › 提示词」里两类提示词都在,每一行都是启停**:全局那组 = 哪一份写进 `AGENTS.md`(单选,各带分组标题),快捷那组 = 这条还开不开着(与提示词页那颗药丸开关同一个动作、同一份状态)。这一域里连已经关着的快捷词也列 —— 管理那一层不该因为被管起来就找不到。
|
|
87
|
+
- **另起一段「快捷提示词」管取用**:只列开着的那几条,点一行把存好的那段话原样替换进输入框,**不自动发送**(发送键留给你),所以那一行不带对勾 —— 它不是启停。
|
|
88
|
+
|
|
78
89
|
### 场景与记忆
|
|
79
90
|
|
|
80
91
|
- **场景 = 分组,记忆 = `.md` 文件**:`memories/<场景>/<名>.md`,整篇正文自动注入上下文,文件名支持中文。
|
|
81
|
-
- **「启用」与「进入」是两件事**:启用决定注入按哪个场景走(单选,全关 = 只注入「全局」与 `_shared`);进入才按档案整套切换 MCP / 技能 /
|
|
92
|
+
- **「启用」与「进入」是两件事**:启用决定注入按哪个场景走(单选,全关 = 只注入「全局」与 `_shared`);进入才按档案整套切换 MCP / 技能 / 人设(绑了的话还有快捷提示词),并把绑定的提示词写进 `AGENTS.md`。**两者必须恒等,而这条恒等由服务端兜住**:`rules-set-active` 先把运行时切到位再写启用集合(切不动就一个字都不写),所以面板开关、`/` 菜单、模型工具哪个入口都只发一次调用就两轴齐动。
|
|
82
93
|
- **场景档案**:每个场景搭配 MCP 工具集 / 技能集 / 子智能体 / 记忆(任意组合)。语义是**勾的启用、没勾的停用**,整段没建 = 该域全部停用;退出按进场景前的快照还原。场景内这三个域的开关照常可用,改动会同步写进档案。
|
|
83
94
|
- **场景锁定**:锁定后 MCP / 技能 / 子智能体 / 记忆 / 提示词五个域的增删改整体只读(界面与服务端双侧拦截);场景自身的启停、MCP 重启、导出不受影响。
|
|
84
95
|
- **删除场景 = 连记忆一起删**:场景记录、档案与全部记忆进同一条回收站条目,恢复时按原路径整条放回;使用中的场景拒绝删除。改名会连带改目录与档案。
|
|
@@ -101,7 +112,7 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
|
|
|
101
112
|
- **工具级开关**:单个工具可独立停用(模型看不见也调不到),整台支持批量。
|
|
102
113
|
- **停着也能看清单**:没在跑的服务器仍显示上次见过的工具名与描述(标「上次运行时」);从没跑过的可以一键启动读取。
|
|
103
114
|
- **备注**:每台服务器可写一句给模型的提示,随状态段一起注入。曾经连上过、现在连不上的服务器会列出来并标注 —— 这样模型会说"它没连上,检查一下",而不是建议你去装一个。
|
|
104
|
-
- **密钥打码**:默认把凭据整值打码(`$VAR`、`!!js` 这类间接引用不动;URL
|
|
115
|
+
- **密钥打码**:默认把凭据整值打码(`$VAR`、`!!js` 这类间接引用不动;URL 的查询串、`user:pass@` 与 `#片段` 一并打码),看明文要令牌。打码值**不会被写回配置** —— 保存时你原样留着的字段会还原成已存的值,地址里没有可还原的原值时整次保存会被拒绝(静默丢掉查询串会留下一个"连得上但认证失败"的地址)。打码只管界面展示,详见「配置与安全」。
|
|
105
116
|
- **迁移与备份**:跨项目级 / 全局迁移失败自动回滚;支持 JSON 导出导入。
|
|
106
117
|
|
|
107
118
|
### 技能
|
|
@@ -118,7 +129,11 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
|
|
|
118
129
|
- **记得「最近一次应用的是哪份」**:就算你手改过 `AGENTS.md`,也答得出来源(会注明"此后文件有变")。
|
|
119
130
|
- 每条预设可写一句"这份是干什么的",只存在插件侧、不进 `AGENTS.md`。
|
|
120
131
|
- **被引用的不能删**(场景绑定 / 当前内容 / 退出场景要恢复的那一份),删除进回收站。
|
|
121
|
-
-
|
|
132
|
+
- **生效与否就是卡片左边那颗开关**:点亮 = 把这一份写进 `AGENTS.md`;已经亮着的那颗再点一次 = 重新写回(把被手改的文件拉回来)。基线没有"全部不应用"这一态,所以这颗开关关不掉 —— 想换一份就点亮另一份(单选)。
|
|
133
|
+
- 场景接管期间点亮另一份 = 把该场景改绑到那一份(同步写进场景档案);锁定时拒绝。
|
|
134
|
+
- **快捷提示词**(同页第二段):存一段常用的话,之后在对话框打 `/` 点一下就原样贴进输入框,可直接编辑再发送。它**不注入上下文**,卡片上那颗开关只管一件事 —— 这条还在不在 `/` 的「快捷提示词」段里出现(关掉时正文与备注都留着;同一颗开关在「工具 › 提示词」那一域里也拨得动)。只由你自己点出来;与全局基线分开存,删除进回收站,也能导出与随迁移快照带走。
|
|
135
|
+
- **场景可以绑定一组快捷提示词**:「修改场景」里「提示词预设」下面那颗下拉,默认「当前启用的(保持现状)」= 不绑、进出不碰;改成「按场景勾选」后,进入本场景只启用你勾的那几条、其余停用,**退出场景按进场景前的开关还原**。一条都不勾是"进入后全部停用",和"不绑"是两件事。
|
|
136
|
+
- **两组各自是一张可折叠卡片**(点卡片头收起 / 展开,打了字自动展开)。快捷那组的卡片头有一颗「全选 / 取消全选」,只作用于当前可见的那几条;全局那组没有 —— 那一档是单选,"全部应用"没有意义。
|
|
122
137
|
|
|
123
138
|
### 历史会话
|
|
124
139
|
|
|
@@ -170,6 +185,7 @@ dsh plugin --profile web add dsh-plugin-tool-management@latest
|
|
|
170
185
|
- **curl / 脚本**:带 `x-dsh-token`,或带浏览器 cookie。
|
|
171
186
|
- **HTTP 状态码**:除安全栅栏的 401 / 403 外,一律 HTTP 200 + `{ ok: false, error }` —— 脚本分流请以 `body.ok` 为准。
|
|
172
187
|
- **端口转发**:宿主缺 `connection` 服务时栅栏退到「Host 回环 + 同源」判定,本机进程伪造 `Host: localhost` 即可调用写 op。转发到局域网 / 公网的场景**务必配令牌** —— 陌生人注入 MCP 命令等同远程执行。「选择文件夹」弹窗用的 `dir-list` 能列出任意绝对路径(只读),同一条前提。
|
|
188
|
+
- **服务器名里的 `__`(起名建议)**:工具全名是 `mcp__<服务器名>__<工具名>`,所以服务器名里再出现 `__` 会让它**切不唯一** —— `mcp__a__b__c` 既可能是服务器 `a` 的工具 `b__c`,也可能是服务器 `a__b` 的工具 `c`;两个服务器名互为 `__` 前缀(`a` 与 `a__b`)同理。本轮**不收紧校验**(今天放行 `__` 的 5 处校验一旦收紧,存量服务器会从"能管"变成"管不了",而服务器本身照跑),改为在**兼容页**出一条提示。工具照常可用,只是界面上的勾选可能落不到停用表里那条键上 —— **起名时避开 `__` 就没有这个问题**。
|
|
173
189
|
|
|
174
190
|
## 常见问题
|
|
175
191
|
|
package/README_EN.md
CHANGED
|
@@ -41,7 +41,8 @@ In one line: **configure "work / writing / coding" each as a scene and switch th
|
|
|
41
41
|
|
|
42
42
|
| Highlight | What it means |
|
|
43
43
|
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
44
|
-
| One-click scene switch | Each scene carries its own MCP / skills / personas / memories; entering applies them, leaving restores. The model can switch them for you too |
|
|
44
|
+
| One-click scene switch | Each scene carries its own MCP / skills / personas / memories (plus a bound set of quick prompts, if you set one); entering applies them, leaving restores. The model can switch them for you too |
|
|
45
|
+
| Manage without leaving chat | Type `/` in the composer for a “Tools” section: enter a scene, toggle skills / MCP / subagents / prompts / memories — one click, done |
|
|
45
46
|
| Memories reach the model | A few `.md` files under a scene become its knowledge base — injected automatically, no copy-pasting |
|
|
46
47
|
| Notes for MCP servers | Write "if A is down, fall back to B" as a note; the model sees it every turn and acts on it |
|
|
47
48
|
| Disable a single tool | Keep a server but mute one tool: invisible and uncallable. "Restart" only reconnects and never flips your switches |
|
|
@@ -75,10 +76,20 @@ Then remind me to hard-refresh the browser.
|
|
|
75
76
|
|
|
76
77
|
## Features
|
|
77
78
|
|
|
79
|
+
### Slash commands (manage from the chat box)
|
|
80
|
+
|
|
81
|
+
- **Type `/` to get a “Tools” section**: six rows — scenes / skills / MCP servers / subagents / prompts / memories. Click a row to drop into that domain's items in place (the breadcrumb's “Tools” step goes back), click an item to apply it. **The menu stays open after a click** — keep toggling the next one; batch toggling is the main use.
|
|
82
|
+
- **State is visible**: enabled items carry a green check in the icon slot, disabled ones an empty box, and the grey text on the right is the item's own note (scene description / skill description / MCP note / persona description / preset description / memory description, clipped to 40 chars; rows without one fall back to “Enabled / Not enabled”). Each domain row shows a summary (`now: Work`, `3 on / 1 off`), so you know where you stand without opening it. The check flips the moment you click (optimistic); a failed write flips back and says why.
|
|
83
|
+
- **Long lists stay usable**: every domain lists all of its items and the panel scrolls; skills group by source directory, memories by scene, enabled rows first inside each group. Each external skill directory also gets one "directory name · directory" row pinned at the top of its group — clicking it toggles the entire source (it is listed while enabled too, so you can switch it off here; its skills collapse with it and come straight back when it is enabled again). The two always-on reserved scenes ("Global" and the shared baseline) don't appear under scenes, but the memories domain includes the global ones by default and pins that group at the top: they aren't in the current scene yet they hold in every conversation.
|
|
84
|
+
- **Only reversible actions**: entering a scene and the various toggles. Clicking the scene that's already active leaves it (only global and shared keep injecting); the one thing that can't be switched off is the global prompt — there is no "apply nothing" state for a baseline, so clicking the preset already in effect just says it is the current one. Create / delete / edit / import / export stay on their own pages.
|
|
85
|
+
- **Built on the host's official channel**: registered through DSH's input-trigger interface (the same one the official skills menu uses) — no patching of official packages. If the host lacks that service the entry simply never appears and the compatibility page says so. Each section gets its own checkbox (“Tools” / “Quick prompts”) inside the “Slash command entry” group under “Compatibility → Injection”, and the tag at the end of each row says whether it really mounted this startup. The two sections register independently, so switching one off leaves the other alone; turning both off restores the stock `/` menu (restart DSH for the slash-command change to take effect).
|
|
86
|
+
- **“Tools › Prompts” holds both kinds of prompt, and every row there is a switch**: the global group is which baseline is written into `AGENTS.md` (single choice), the quick group is whether that snippet is on at all — the same action and the same state as the pill switch on the Prompts page. Quick prompts that are switched off stay listed here: the place you manage things from should not hide an item the moment you manage it.
|
|
87
|
+
- **A separate “Quick prompts” section is for reuse**: only the enabled ones appear, and one click replaces the typed token with the saved text in the composer — **nothing is sent for you**; the send key stays yours. Those rows carry no check mark on purpose: clicking one inserts text, it doesn't toggle state.
|
|
88
|
+
|
|
78
89
|
### Scenes & memories
|
|
79
90
|
|
|
80
91
|
- **A scene = a group, a memory = a `.md` file**: `memories/<scene>/<name>.md`, the whole body is injected; file names may be non-ASCII.
|
|
81
|
-
- **"Enabled" and "entered" are two axes.** Enabled decides which scene the injection follows (single-select; none enabled = only `global` and `_shared` inject). Entering applies the scene's whole MCP / skills / personas set and writes its bound prompt into `~/.dsh/AGENTS.md` (5 generations of backups, restored on exit).
|
|
92
|
+
- **"Enabled" and "entered" are two axes.** Enabled decides which scene the injection follows (single-select; none enabled = only `global` and `_shared` inject). Entering applies the scene's whole MCP / skills / personas set and writes its bound prompt into `~/.dsh/AGENTS.md` (5 generations of backups, restored on exit). **They stay identical, and the server is what holds that invariant**: `rules-set-active` brings the runtime in line before it writes the enabled set — and writes nothing at all if the runtime refuses — so every entry point (the UI toggle, the `/` menu, the model tool) needs a single call.
|
|
82
93
|
- **Scene profile**: each scene combines MCP tools / skills / subagents / memories. The rule is *ticked = on, unchecked = off*, and a section that was never created means that whole domain is off. Leaving restores the pre-scene state verbatim. While a scene is active, the switches in those three domains still work and are written back into its profile; only locking freezes them.
|
|
83
94
|
- **Scene lock**: once locked, create/update/delete across MCP / skills / subagents / memories / prompts is read-only (UI disabled plus a server-side guard). Creating, renaming, binding a prompt, activating or entering a scene, the recycle bin, MCP restart and exports stay outside the frozen list. A scene must be running to lock, and a locked scene cannot be turned off until you unlock it.
|
|
84
95
|
- **Deleting a scene deletes its memories too**: record, profile and every memory land in one recycle-bin entry and come back as a whole. A running scene refuses deletion; renaming follows through to the directory and profiles.
|
|
@@ -102,7 +113,7 @@ Then remind me to hard-refresh the browser.
|
|
|
102
113
|
- **Per-tool switches**: disable individual tools (invisible to the model and blocked at call); whole servers support bulk.
|
|
103
114
|
- **Stopped servers still show their tools**: one that is not running keeps the names and descriptions last seen (marked "as of last run"); one that never ran can be probed with "start server to read tools".
|
|
104
115
|
- **Status and notes enter the context**: currently usable servers are listed, and **one that connected before but cannot right now is listed and labelled too** — so the model says "it is not connected, check it" instead of reading "configured but unreachable" as "not configured" and suggesting you install one. Servers that never connected are omitted; your notes travel along as decision hints.
|
|
105
|
-
- **Secret masking**: a credential is replaced **as a whole** by `••••••`, and only for keys that look sensitive; `$VAR` and `!!js` are indirections and stay readable, and a URL's query string
|
|
116
|
+
- **Secret masking**: a credential is replaced **as a whole** by `••••••`, and only for keys that look sensitive; `$VAR` and `!!js` are indirections and stay readable, and a URL's query string, its `user:pass@` userinfo and its `#fragment` are all masked. "Reveal" needs a token. A masked value is never written back into the patch file — on save the plugin restores the stored value for any field you left alone, and refuses the whole save when a URL has nothing to restore from (a silently stripped query string would leave an address that connects but fails authentication).
|
|
106
117
|
- **Migrate & back up**: cross-level migration rolls back on failure; JSON export/import.
|
|
107
118
|
|
|
108
119
|
### Skills
|
|
@@ -119,7 +130,11 @@ Then remind me to hard-refresh the browser.
|
|
|
119
130
|
- **It remembers the last applied preset**: even after you hand-edit `AGENTS.md`, the origin is still reported (flagged "the file changed since").
|
|
120
131
|
- Each preset can carry a one-line description that lives in a sibling `meta.json` — shown in this panel, never injected.
|
|
121
132
|
- **A referenced preset cannot be deleted** (scene binding / current `AGENTS.md` content / the copy to restore on scene exit); deletes go to the recycle bin.
|
|
122
|
-
- **
|
|
133
|
+
- **The switch on the left of a card is the answer to “is this one in effect”**: flip it on and that preset is written into `AGENTS.md`; clicking the one that is already on writes it again (undoing hand edits). There is no "apply nothing" state for a baseline, so this switch cannot be turned off — light up a different one instead (single choice).
|
|
134
|
+
- **While a scene drives the baseline, flipping another one rebinds that scene** to the chosen preset (written into the scene profile, realigned immediately); it is refused only while the scene is locked. The global baseline is restored from the snapshot on exit.
|
|
135
|
+
- **Quick prompts** (the second section on the same page): save a piece of text you keep typing, then hit `/` in the composer and click it — it lands verbatim in the input, ready to edit and send. It is **never injected**; its switch controls exactly one thing — whether the row still shows up in the `/` “Quick prompts” section (text and note survive when it's off; the same switch is reachable under “Tools › Prompts”). Stored apart from the baselines, deletable to the recycle bin, exportable and included in the migration snapshot.
|
|
136
|
+
- **A scene can bind a set of quick prompts**: a new dropdown under “Prompt preset” in “Edit scene”. The default, “The enabled ones (keep as is)”, means the scene does not touch this domain at all; switch it to “Pick per scene” and entering that scene enables exactly the checked ones and disables the rest, **leaving the scene restores the switches as they were before entering**. Checking nothing is "disable all inside this scene", which is the opposite of "not bound".
|
|
137
|
+
- **Both groups are collapsible cards** (click the header to fold, and a search query forces them open). The quick group's header carries a “Select all / Deselect all” button that applies to the currently visible rows only; the global group has none — that one is single choice, so "apply every baseline" has no meaning.
|
|
123
138
|
|
|
124
139
|
### Archived sessions
|
|
125
140
|
|
|
@@ -173,6 +188,7 @@ The plugin uses the host's own `@deepseek-ai/*` libraries at runtime — they mu
|
|
|
173
188
|
- **curl / scripts**: send `x-dsh-token`, or carry the browser cookie.
|
|
174
189
|
- **HTTP status convention**: except for the fence's 401 / 403, a missing token or a business failure is **HTTP 200 + `{ ok: false, error }`** — branch on `body.ok`, not on the status code.
|
|
175
190
|
- **Port forwarding**: when the host has no `connection` service the fence falls back to "loopback Host + same origin", which any local process can imitate with `Host: localhost`. If you forward the port to a LAN or the public internet, **configure a token** — a stranger injecting MCP commands is remote code execution. The `dir-list` call behind the folder picker lists any absolute path (read-only) under the same precondition.
|
|
191
|
+
- **`__` in a server name (naming advice)**: a tool's full name is `mcp__<server>__<tool>`, so an extra `__` inside a server name makes it **ambiguous** — `mcp__a__b__c` can be server `a`'s tool `b__c` or server `a__b`'s tool `c`; the same goes for two server names that are `__`-prefix related (`a` and `a__b`). This release deliberately **does not tighten validation** (the 5 places that accept `__` today would turn existing servers from "manageable" into "unmanageable" while the servers themselves keep running); instead the Host tab shows an informational note. The tools keep working — only a checkbox in the UI may fail to land on the key used in the disabled-tools table. **Avoid `__` when naming and none of this applies.**
|
|
176
192
|
|
|
177
193
|
## FAQ
|
|
178
194
|
|
package/docs/images/1-EN.png
CHANGED
|
Binary file
|
package/docs/images/1.png
CHANGED
|
Binary file
|
package/docs/images/2-EN.png
CHANGED
|
Binary file
|
package/docs/images/2.png
CHANGED
|
Binary file
|
package/docs/images/3-EN.png
CHANGED
|
Binary file
|
package/docs/images/3.png
CHANGED
|
Binary file
|
package/docs/images/4-EN.png
CHANGED
|
Binary file
|
package/docs/images/4.png
CHANGED
|
Binary file
|
package/docs/images/5-EN.png
CHANGED
|
Binary file
|
package/docs/images/5.png
CHANGED
|
Binary file
|
package/docs/images/6-EN.png
CHANGED
|
Binary file
|
package/docs/images/6.png
CHANGED
|
Binary file
|
package/docs/images/7-EN.png
CHANGED
|
Binary file
|
package/docs/images/7.png
CHANGED
|
Binary file
|
package/docs/images/8-EN.png
CHANGED
|
Binary file
|
package/docs/images/8.png
CHANGED
|
Binary file
|
package/docs/update.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
| 版本 | 发布 | 主题 |
|
|
6
6
|
| ---------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
7
|
+
| [0.18.0](#0180---2026-10-01) | 2026-10-01 | 斜杠命令「工具」段(对话里打 `/` 就能进场景、启停六个域,点完不关)+ 快捷提示词(`/` 里点一下贴进输入框;场景可绑定一组)+ 兼容页两段开关与挂载实况 + 提示页药丸开关与可折叠卡片 + 修好分组卡片收不起来、退出场景回执说「什么都没改」、`/` 进 / 出场景不跟着切档案 |
|
|
8
|
+
| [0.17.0](#0170---2026-09-30) | 2026-09-30 | 对抗性审查收尾(三批 19 条 + 复审 14 条 + 2 条替代项,全部处理):修好 3 处数据丢失与 2 处凭据外泄、停用 MCP 工具仍可调用等**执行侧**守卫失效、场景回收站与记忆索引的恢复问题;MCP 工具全名的切分收敛成一套规则、服务器名含 `__` 的歧义会出声提示 |
|
|
7
9
|
| [0.16.6](#0166---2026-09-30) | 2026-09-30 | 官方内置技能补全 web 侧:web 照注的沙盒诊断技能可见可停 + Office 三件套 web 也暴露 + 补上接管后缺失的 LibreOffice Kit 路径段(0.16.5 桌面已缺) |
|
|
8
10
|
| [0.16.5](#0165---2026-09-30) | 2026-09-30 | 桌面版误报 5 条「两份拷贝」修掉(身份逐包核对)+ 「全部可用」与红卡不再同屏 + 官方内置技能接入管理(桌面版注入的 4 个可启停;web 不出现) |
|
|
9
11
|
| [0.16.0](#0160---2026-09-29) | 2026-09-29 | 桌面版宿主身份误判修好(归档宿主按版本核对,带空格路径的宿主版本不再显示 unknown)+ 兼容页三张指标卡各删一行、适配版本改标 0.2.0-rc.2 + 四个域的行状态统一成名字后面的胶囊(已启用 / 未启用,停用类改灰)+ MCP 体检点挪到名字前 + 体检补端点探测 + 删除同步清引用 + 轮询不空转 + 子智能体补上「已启用」 |
|
|
@@ -26,6 +28,63 @@
|
|
|
26
28
|
|
|
27
29
|
---
|
|
28
30
|
|
|
31
|
+
## 0.18.0 - 2026-10-01
|
|
32
|
+
|
|
33
|
+
- **斜杠命令「工具」段**:对话输入框打 `/` 就能进场景、启停技能 / MCP 服务器 / 子智能体 / 提示词 / 记忆,点完菜单不关、接着点下一条。走宿主官方 `inputTriggers` 通道(不碰官方包),只放可逆动作,读写复用面板那批接口。
|
|
34
|
+
- **快捷提示词**:提示词页拆成「全局提示词」与「快捷提示词」两段;快捷词不注入上下文,在 `/` 的「快捷提示词」段点一下把正文原样贴进输入框(不自动发送),每条一颗开关管它在不在那里。
|
|
35
|
+
- **场景可以绑定一组快捷提示词**:「修改场景」里那颗下拉默认「当前启用的」= 不绑、进出不碰;勾了的进场景启用、其余停用,退出按快照还原。
|
|
36
|
+
- **兼容页多一组「斜杠命令入口」**:两段各一颗开关 + 一枚「已生效 / 未生效」标签(为什么没生效写在悬停里),功能总览同步多一行。
|
|
37
|
+
- **新增一条全局轻提示**:斜杠命令是在对话页按下的,面板内的提示条长在页签里、到不了那里。
|
|
38
|
+
- **提示词页两组换成可折叠卡片**;全局那段的两颗「应用 / 重新应用」文字按钮换成一颗药丸开关 —— 亮着的再点一次就是重新写回 `AGENTS.md`。
|
|
39
|
+
- **「修改场景」弹窗分两模块**(基本信息 / 场景绑定),快捷提示词的勾选清单换成段卡片(段头计数 + 全选,段体按内容长)。
|
|
40
|
+
- **模型侧说得更全一点**:工具表里「提示词」这一组改口「全局提示词」;档案摘要与切换回执补上「工具表方案」这一档(名单本来没变就一句都不说)。快捷提示词不提 —— 模型看不到也改不了。
|
|
41
|
+
- **修好三处**:分组卡片点标题收不起来(MCP 页从 0.11.0 起就这样);`scene_manager_switch` 每次退出场景都报成「什么都没改」;`/` 里进 / 出场景不跟着切档案(这条恒等改由服务端兜)。
|
|
42
|
+
- **数据纪律不降级**:快捷提示词删除进回收站、可勾选导出、随整机迁移快照走;场景锁定期间整体只读。
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 0.17.0 - 2026-09-30
|
|
47
|
+
|
|
48
|
+
- **记忆索引:一次读失败不再等于「整份配置被清空」**:读不到(杀软 / 索引器占住)时以前当成「没有索引」,随后任何一次写都会把空索引落盘 —— 打开面板就可能触发。现在只有文件真的不存在才算新用户,其余读失败一律拒写并如实显示。
|
|
49
|
+
- **场景回收站:含子目录 / bundle 记忆的场景恢复不再必然失败**:删除能成功、恢复必失败且不可再恢复;删除回滚失败还会永久删掉那些记忆。现在恢复失败会退回回收站,回滚没做完绝不清理条目。
|
|
50
|
+
- **回收站恢复不再能写到记忆根之外**:条目里的组名是磁盘数据,`../..` 能把正文写到记忆根外。现在与列表同一道判据,并在落盘前核对落点。
|
|
51
|
+
- **整机迁移快照不再导出明文凭据**:默认导出只认 `key` / `token` / `secret` / `password`,`?api_key=` / `?access_token=` / `?sig=` 这类常见写法全部漏掉。现在与 MCP 列表同一套打码。
|
|
52
|
+
- **MCP 体检不再回未打码的地址**:它是免令牌的只读操作,却把配置里的 URL 原文回给客户端。现在地址一律打码后回。
|
|
53
|
+
- **停用的 MCP 工具不再能被调用**:工具全名 `mcp__<服务器>__<工具>` 对 `__` 有歧义,判断「停用了吗」的地方取第一个 `__`,服务器名含下划线时查不到就当成没停用 —— 照常可调用。现在全插件只剩一套切分规则,执行侧拦截、列表页、场景档案的勾选键三处同源。
|
|
54
|
+
- **注入取数失败不再伪装成「已清空」**:某个域取数抛异常时以前被当成「这轮没内容」,还会向模型发一条假的「已清空」。现在异常与真的空分开,「注入实况」多一个「取数失败」状态。
|
|
55
|
+
- **场景改名 / 删除→恢复不再丢记忆的元数据**:改名没搬每条记忆的启停 / 排序 / 标签 / 置顶 / 备注,于是你显式停用的记忆会自己重新启用。现在改名按前缀整体迁移,删除时一并收进回收站、恢复时合并回来。
|
|
56
|
+
- **删除 / 恢复场景不再跟随目录链接搬走根外文件**(已实测复现):`memories/<场景>` 若是指向别处的链接,删除会真的把根外文件搬进回收站。现在动手前先核对落点。
|
|
57
|
+
- **单删会话收敛到「只能删已归档的」**:批量删除一直是这个口径,单删却直接删 —— 一个客户端 bug 就能永久删除任意已保存的会话。现在单删也先确认在归档列表里;级联删除同样只吃已归档的子会话。
|
|
58
|
+
- **编辑 / 删除 MCP 不再删掉你手写 `config` 的覆盖块**:补丁按条目 id 生效,手写配置是合法用法,删除时却被整块带走。现在只删「纯块」。
|
|
59
|
+
- **编辑 MCP 不再改坏补丁里的多行脚本**:折叠空行会动到块标量(`!!js |`)内部 —— 补丁照旧能读、照旧能跑,只是算出来的值变了。现在折叠跳过块标量内部。
|
|
60
|
+
- **重启 MCP 服务器不再把它留在停用态**:某些形状下恢复步骤会把生效值回落到条目自带值,重启完服务器是关着的。现在恢复前比对一次,不等就写回重启前的状态。
|
|
61
|
+
- **设置令牌不再被误判成「两份补丁」**:bundle 挂载下令牌的落点是一条覆盖条目,却被算成「第二条」—— 那种安装下所有令牌操作都被拒绝。现在按形状分开。
|
|
62
|
+
- **保存场景档案不再抹掉别的场景**:进场景时那段窗口里保存的另一个场景档案会被陈旧数据整片覆盖。现在每次写声明改哪几片,档案另走逐场景增量。
|
|
63
|
+
- **场景名口径统一**:多段名(`a/b`)能通过校验并被写进启用集合,但注入时两边对不上,表现为「开关点了、场景没生效」且零报错。现在新建 / 改名目标 / 启用集合必须单段,定位按完整路径。
|
|
64
|
+
- **全局 AGENTS.md 与场景基线快照改为原子写**:以前中断 / 断电可能留下半截内容进模型上下文;快照损坏会让「退出场景恢复」静默失效。现在原子替换,快照读不出来时如实报警。
|
|
65
|
+
- **整机迁移的技能域从「永远不工作」到能用**:导出侧读错返回结构,技能永远导出 0 项而界面显示「迁移完成」;导入侧又把 zip 喂给只认目录和 `.md` 的入口。现在两侧一起修好。
|
|
66
|
+
- **迁移导入的「需要注意」不再被吞掉**:只报成功 / 跳过数,「这些密钥已是打码占位符,请重新填写」这类要你动手的清单到不了界面。现在会跟着那行一起显示。
|
|
67
|
+
- **技能上传不再能从暂存目录逃出去**:路径校验只挡「正好是 `..`」,而 Windows 会裁掉段尾空格,`.. ` 等于 `..`。现在按段判「会不会被文件系统改写」。
|
|
68
|
+
- **兼容页新增「宿主文件读写」探测**;**`check:host` 新增「AGENTS.md 刷新契约」检查、挂载心跳带上进程身份**(直接判「这一轮插件挂上没」);**doctor 与宿主依赖工具不再各写一套「宿主在哪」**。
|
|
69
|
+
- **MCP 工具名前缀只有一处定义,并会在漂移时提示**;**服务器名含 `__` 时会出声提示**(只提示、不阻断,没有这类名字时一条都不报)。
|
|
70
|
+
|
|
71
|
+
### 复审那一轮(14 条发现 + 2 条替代项)
|
|
72
|
+
|
|
73
|
+
- **回收站条目 id 不再能路径穿越**:传 `..` 就能把整个 `hub/trash` 交给系统回收站。现在走同一道单段名校验。
|
|
74
|
+
- **「纯读」的名义不再能借来写盘**:`tool-table` 的「保存方案 / 删除方案」走同一个操作名却会写配置,带上就能免令牌改侧车。现在带写触发键就必须过令牌。
|
|
75
|
+
- **场景锁定对模型也生效了**:以前「冻结」只包在界面那条入口上,锁着场景时界面点不动、模型改得动。现在两侧同一份判据(锁着仍能解锁、仍能退出)。
|
|
76
|
+
- **打码地址不再被写回配置**:表单里填的是列表页给的已打码地址,写回时不做还原,真地址从此找不回来。现在所有写路径强制还原,还原不出来就报错让你重填;打码也补上了 `user:pass@` 与 `#access_token=` 两种写法。
|
|
77
|
+
- **编辑 MCP 不再改坏带 tag / anchor 的多行脚本**:`!!js |`、`&a |`、`|2-` 这些写法没被识别成块标量,照样被折。现在按 YAML 规范补齐,认不出形状时整份文件不折叠。
|
|
78
|
+
- **注入假「已清空」补完到域内部**:某些域自己就把读失败吞成空串,通道照样发那条假的「已清空」。现在域内部也把读失败与真的空分开。
|
|
79
|
+
- **「同名首选」对模型真正生效**:首选以前只影响界面显示,模型拿到的仍是按优先级选出的那份;把停用副本设为首选还会「两份都不生效」。现在两边同源,首选来源停用时如实告诉你「已记录,但它不会生效」。
|
|
80
|
+
- **单删会话的归档判据取权威来源**:以前用「读得出来的归档记录」,头部读不出来的已归档会话会被误报「未归档」。现在取权威集合。
|
|
81
|
+
- **记忆回收站恢复失败会回滚**:中途失败留下「一半已放回 + 目标已非空」,下一次恢复撞「同名记忆已存在」,这条记忆再也恢复不了。现在清掉落点、保留条目,可直接重试。
|
|
82
|
+
- **改名成 `.txt` 的转写不再被折成一条消息**:以前一律按纯文本解析,整份对话塞进一条 user 消息而结果报「导入成功」。现在先按内容嗅探,认不出就如实提示。
|
|
83
|
+
- **删预设前先确认没被引用**:探测失败时以前放行删除,删掉被场景绑定的预设会静默让场景驱动失效。现在探测失败一律拒绝。
|
|
84
|
+
- **退出场景「没有退路」时不再静默**:存基线失败时以前只写一行日志,AGENTS.md 照旧切进场景态而恢复不回原内容。现在单独报出来。
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
29
88
|
## 0.16.6 - 2026-09-30
|
|
30
89
|
|
|
31
90
|
- **web 上注入的沙盒诊断技能看得见、关得掉了**:官方宿主的沙盒技能门控只看 Windows(web 照样向每个会话注入),0.16.5 却把 web 挡在官方内置管理之外——页面不显示、会话照注入。现在 web 也物化官方技能、以更高优先级接管,停用即不注入。
|
package/lib/audit-log.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// ③ readonly 与失败/抛错的调用不记 —— 记的是「变更成功」,不是「有人试过」。
|
|
13
13
|
import { appendFile, readFile, stat, unlink, writeFile } from 'node:fs/promises';
|
|
14
14
|
import { hubPath } from './hub.js';
|
|
15
|
-
import { OP_REGISTRY } from './op-registry.js';
|
|
15
|
+
import { OP_REGISTRY, isReadCall } from './op-registry.js';
|
|
16
16
|
const AUDIT_FILE = 'audit.jsonl';
|
|
17
17
|
/** 轮转阈值:超过 512KB 保留最近 500 条。这页的本意是「最近改动」,不是无限期审计。 */
|
|
18
18
|
const ROTATE_OVER_BYTES = 512 * 1024;
|
|
@@ -64,9 +64,13 @@ export function recordAudit(entry) {
|
|
|
64
64
|
/**
|
|
65
65
|
* 一次 op 结果要不要记:写类 + 本次成功(`ok !== false`,与服务端「成功返回扁平 {ok:true,…}」
|
|
66
66
|
* 的口径一致;不返回 ok 的按成功处理)。
|
|
67
|
+
*
|
|
68
|
+
* 「两态 op」(`inject-settings` / `tool-table` / `scene-settings` / `mcpm-settings`)的读侧
|
|
69
|
+
* 不记:`isWriteClassOp` 只看 op 名,而那几个名字既读又写 —— 光打开一次兼容页就会被记成
|
|
70
|
+
* 一次改动,把真变更淹没。判据与写门禁同源(登记表的 `writeWhen`),不在这里另写一份。
|
|
67
71
|
*/
|
|
68
72
|
export function recordOpAudit(op, args, source, result) {
|
|
69
|
-
if (!isWriteClassOp(op) || AUDIT_SKIP.has(op))
|
|
73
|
+
if (!isWriteClassOp(op) || AUDIT_SKIP.has(op) || isReadCall(op, args))
|
|
70
74
|
return;
|
|
71
75
|
if (result && typeof result === 'object' && result.ok === false)
|
|
72
76
|
return;
|