dsh-prompt-customizer 0.9.2 → 2.1.2
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.en.md +49 -234
- package/README.md +45 -310
- package/build.mjs +27 -10
- package/client/client.js +2446 -1364
- package/client/client.js.map +4 -4
- package/docs/adr/0001-remove-catalog-pool.md +27 -0
- package/docs/adr/0002-hide-identity-name-source.md +23 -0
- package/docs/adr/0003-destructive-updates-allowed.md +18 -0
- package/docs/adr/0004-generalized-filter-model.md +17 -0
- package/docs/adr/0005-universal-prompt-takeover.md +109 -0
- package/docs/design/prompt-control-consensus.md +103 -0
- package/docs/guide.md +280 -0
- package/docs/images/prompt.png +0 -0
- package/docs/images/tool.png +0 -0
- package/docs/testing/feature-matrix.md +142 -0
- package/docs/upgrades/1.0.0-sqlite-breaking.md +26 -0
- package/docs/upgrades/1.4.0-generalized-model.md +23 -0
- package/docs/upgrades/1.4.1-web-preview-fixes.md +15 -0
- package/docs/upgrades/2.0.0-remove-workspace-level.md +16 -0
- package/docs/upgrades/2.0.1-context-fixes.md +6 -0
- package/docs/upgrades/2.0.10-import-and-skill.md +6 -0
- package/docs/upgrades/2.0.11-regression-fixes.md +7 -0
- package/docs/upgrades/2.0.12-generative-tool-tests.md +5 -0
- package/docs/upgrades/2.0.13-runtime-contract.md +8 -0
- package/docs/upgrades/2.0.14-tool-execution-guard.md +5 -0
- package/docs/upgrades/2.0.15-mask-pool-regression.md +5 -0
- package/docs/upgrades/2.0.16-regression-cleanup.md +6 -0
- package/docs/upgrades/2.0.17-unhide-source.md +5 -0
- package/docs/upgrades/2.0.18-unhide-cleanup.md +4 -0
- package/docs/upgrades/2.0.19-mcp-json-edit.md +4 -0
- package/docs/upgrades/2.0.2-generic-context-filter.md +6 -0
- package/docs/upgrades/2.0.20-preset-isolation.md +4 -0
- package/docs/upgrades/2.0.21-isolation-restore-test.md +4 -0
- package/docs/upgrades/2.0.22-source-immutability.md +3 -0
- package/docs/upgrades/2.0.3-skill-summary.md +6 -0
- package/docs/upgrades/2.0.4-tool-draft.md +5 -0
- package/docs/upgrades/2.0.5-tool-catalog-robustness.md +13 -0
- package/docs/upgrades/2.0.6-tool-restrict.md +6 -0
- package/docs/upgrades/2.0.7-tool-stability.md +5 -0
- package/docs/upgrades/2.0.8-catalog-row-stability.md +4 -0
- package/docs/upgrades/2.0.9-tool-and-write.md +8 -0
- package/docs/upgrades/2.1.0-universal-prompt-takeover.md +41 -0
- package/docs/upgrades/2.1.1-tool-shadow-detection.md +48 -0
- package/docs/upgrades/2.1.2-tool-catalog-scope.md +55 -0
- package/docs/upgrades/README.md +298 -0
- package/docs/upgrades/dsh-0.2.2-rc1.md +49 -0
- package/docs/upgrades/rc2-migration.md +70 -0
- package/lib/index.js +4697 -1701
- package/lib/index.js.map +4 -4
- package/package.json +7 -5
- package/scripts/e2e-report.json +221 -0
- package/scripts/e2e-terminal.mjs +210 -0
- package/scripts/simulate-rescan.mjs +184 -0
- package/scripts/smoke-host.mjs +1 -1
- package/scripts/verify-apply-all.mjs +64 -0
- package/scripts/verify-effect.mjs +153 -0
- package/scripts/verify-mcp-edit-ext.mjs +48 -0
- package/scripts/verify-mcp-edit.mjs +45 -0
- package/scripts/verify-panel-browser.mjs +298 -0
- package/scripts/verify-workspace-mcp.mjs +62 -0
- package/scripts/test-mcp-layering.mjs +0 -441
- package/scripts/test-mcp-tool-disable.mjs +0 -420
- package/scripts/test-rc2-runtime.mjs +0 -42
- package/scripts/test-skill-toggles.mjs +0 -100
package/docs/guide.md
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# 使用与实现指南
|
|
2
|
+
|
|
3
|
+
> 本文件保留原 README 的详细说明(会话阶段、界面、功能特性、工作原理、使用说明、配置位置、已知限制与开发)。产品概览见根目录 [README](../README.md),版本升级记录见 [docs/upgrades/README.md](upgrades/README.md)。
|
|
4
|
+
>
|
|
5
|
+
> **状态(2.1.2)**:本文是历史文档,与当前实现有漂移 —— ① 统一为单文件 SQLite `~/.dsh/prompt-customizer/prompt-customizer.db`,`config.yaml` / `catalog.yaml` 不读不迁移;② 工作区级提示词 / 工具层已移除(2.0.0);③ 跨预设累积池与手动重扫已删除(ADR-0001),下文「池子是见过才知道的并集」「catalog/rescan」等段落均已过时;④ **2.1.0 起清单与预览并入「同预设活动 agent」的真实装配**(ADR-0005),因此「预设预览按纯预设 scope 装配、不读取 agent 作用域条目」「预设预览右栏不会混入会话级内容」不再成立;⑤ 2.1.1 起同名遮蔽进只读遮蔽池;⑥ **2.1.2 起右栏可见工具目录改用 `ctx.tools.schemas(agent)`(与真实会话同源),不再只显示预设层工具**,只读池也如实列出插件纯新增的会话级工具。当前行为以 [ADR-0005](../adr/0005-universal-prompt-takeover.md) 与 [2.1.0](upgrades/2.1.0-universal-prompt-takeover.md) / [2.1.1](upgrades/2.1.1-tool-shadow-detection.md) / [2.1.2](upgrades/2.1.2-tool-catalog-scope.md) 升级记录为准。
|
|
6
|
+
|
|
7
|
+
## 会话阶段怎么流转
|
|
8
|
+
|
|
9
|
+
阶段不是固定三拍,而是由**持久会话事件**推导出来的:首个 durable 的 `tool/call` 或
|
|
10
|
+
`assistant/message` 触发晋级,一次 `compaction/end` 把晋级复位。面板上三个阶段部分
|
|
11
|
+
就分别对应这三种状态。
|
|
12
|
+
|
|
13
|
+
<table>
|
|
14
|
+
<tr align="center">
|
|
15
|
+
<td width="28%"><b>① 会话开始</b><br><code>bootstrap</code><br><b>引导期</b></td>
|
|
16
|
+
<td width="6%">→</td>
|
|
17
|
+
<td width="28%"><b>② 首个 durable 信号</b><br><code>tool/call</code> · <code>assistant/message</code><br><b>常驻期</b> <code>active</code></td>
|
|
18
|
+
<td width="6%">→</td>
|
|
19
|
+
<td width="32%"><b>③ 一次压缩</b><br><code>compaction/end</code><br><b>压缩受控期</b> <code>compaction</code></td>
|
|
20
|
+
</tr>
|
|
21
|
+
<tr>
|
|
22
|
+
<td colspan="5" align="center">
|
|
23
|
+
④ 压缩后再来一个 durable 信号 → <b>回到常驻期</b>;只要再来一次压缩,又会落回压缩受控期
|
|
24
|
+
</td>
|
|
25
|
+
</tr>
|
|
26
|
+
</table>
|
|
27
|
+
|
|
28
|
+
完整的转移关系(引导期也能不经常驻期直接进压缩受控期):
|
|
29
|
+
|
|
30
|
+
| 当前阶段 | 事件 | 去向 |
|
|
31
|
+
| ---------- | ---------------------------------------------- | -------------- |
|
|
32
|
+
| 引导期 | 首个 durable `tool/call` / `assistant/message` | **常驻期** |
|
|
33
|
+
| 引导期 | `compaction/end` | **压缩受控期** |
|
|
34
|
+
| 常驻期 | `compaction/end`(晋级复位) | **压缩受控期** |
|
|
35
|
+
| 压缩受控期 | 压缩之后新的 durable 信号 | **常驻期** |
|
|
36
|
+
| 任意 | 子代理会话(`delegationDepth > 0`) | 恒为**常驻期** |
|
|
37
|
+
| 任意 | 无会话的读取(清单、预览) | 恒为**常驻期** |
|
|
38
|
+
|
|
39
|
+
每个阶段各解析出什么 —— 面板的三个部分与配置字段一一对应:
|
|
40
|
+
|
|
41
|
+
| 面板里的部分 | 生效的段屏蔽 | 注入段的 `phase` | 生效的工具黑名单 |
|
|
42
|
+
| ------------------------- | -------------------- | -------------------------- | ---------------------------------------------------------- |
|
|
43
|
+
| 引导期提示词 / 引导期工具 | `sectionsBootstrap` | `bootstrap`(+ `always`) | `tools.bootstrap.exclude`,未配置则回落静态 |
|
|
44
|
+
| 常驻期提示词 / 常驻期工具 | `sections` | `active`(+ `always`) | `tools.exclude`(静态) |
|
|
45
|
+
| 压缩受控期提示词 / 工具 | `sectionsCompaction` | `compaction`(+ `always`) | `tools.compaction.exclude`,未配置则回落引导期,再回落静态 |
|
|
46
|
+
|
|
47
|
+
两点容易踩:
|
|
48
|
+
|
|
49
|
+
- **`always` 注入段三个阶段都在**,且各阶段的排序空间独立 —— 所以本插件产出的阶段条目排在 `always` 组之后(运行时按数组序后写覆盖前写,阶段序才压得住全局序)。
|
|
50
|
+
- **阶段视图是"这个状态会解析成什么",不是"会话曾经是什么"**。预设原生的阶段规则(zero-tool bootstrap、warmup 等)在同一时刻也在生效,并且可能在其它插件之后改动结果 —— 见[已知限制](#已知限制)。
|
|
51
|
+
|
|
52
|
+
## 界面
|
|
53
|
+
|
|
54
|
+
侧边栏点 **能力** 打开独立面板,顶层三个 tab:**SKILL**(技能集合管理)、**MCP**(Server 接入与工具级启停)、**提示词**(本节其余内容)。会话里 `/` 取技能与技能调用的工具行由 DSH 内核的 `@deepseek-ai/dsh-client-ui-skill` 提供 —— 本插件不重复注册(`skill` 命名空间 / 同名槽位键 / 同名斜杠源三处都归内核,重复注册会让内核插件的 apply 抛错)。
|
|
55
|
+
|
|
56
|
+
下面两张图是**提示词 tab**(截图截于 0.6.0 之前:顶部预设行当时还是纯文字 Tab,功能一致;SKILL / MCP 两个 tab 的截图待补)。
|
|
57
|
+
|
|
58
|
+
以下为**提示词 tab** 的细节 —— 侧边栏点 **能力 → 提示词** 打开独立面板。**第一行是 agent 预设 chips**(0.9.0 起无「全部 Agent」),每枚带图标、名称与该预设的定制项数(橙色数字 = 这个预设单独改过东西),点一下即切换编辑目标,进入面板时默认选中第一个可用预设。**第二行是定制头部**:模式切换(提示词 / 工具 / 配置)+ 阶段 Tab(引导期 / 压缩受控期 / 常驻期,左右两栏联动)+ 三态同步与中文提示词开关 + 保存 / 刷新 / 关闭。
|
|
59
|
+
|
|
60
|
+
**提示词模式**:左栏当前阶段的勾选列表(屏蔽 / 替换 / 注入 / 排序,底部三态过滤),右栏实时预览装配后的最终系统提示词:
|
|
61
|
+
|
|
62
|
+

|
|
63
|
+
|
|
64
|
+
**工具模式**:左栏该阶段的工具目录勾选列表,「本系统全部工具」池可把注册表里仍有的工具加回该阶段;右栏是模型可见目录(含「模型可见 / 注册表总数」对照):
|
|
65
|
+
|
|
66
|
+

|
|
67
|
+
|
|
68
|
+
## 功能特性
|
|
69
|
+
|
|
70
|
+
### 技能集合管理(SKILL tab)
|
|
71
|
+
|
|
72
|
+
- **技能包**:把散装技能归组(账本 `.bundles.json` 记规范名与目录名两套写法,目录名不一致也能命中);包可以有分类(最多 8 个、每个 ≤24 字符),改名会同步 `SKILL.md` frontmatter 里的 `name`,删除按规范名走,成员悬空时如实上报。
|
|
73
|
+
- **导入**:拖入 / 选择 ZIP 或文件夹,自动剥掉顶层文件夹、落成 `<技能根>/<名称>/SKILL.md`,并立刻归组到目标技能包;重名给明确错误,不带路径分隔的名字一律拒绝(不越界读技能根外的文件)。
|
|
74
|
+
- **开关(全局 / 预设两层)**:单个技能与整个技能包都能开关,预设层写自己那份账(规范名条目),只对该 agent 预设生效 —— 与「全局」层互不覆盖。
|
|
75
|
+
- **技能健康**:`/api/skill-health` 给出技能根的可读性与成员一致性体检。
|
|
76
|
+
- **技能从哪来(0.11.0 起读内核)**:面板列表直接是 `ctx.skills.list({ cwd })` 的结果 —— 文件系统各根(`<工作区>/.dsh/skills`、`<工作区>/.agents/skills`、`~/.dsh/skills`、`~/.agents/skills`,工作区按「最近的含 `.git` 祖先」判定)+ `bundled`(随安装)+ `runtime`(office 包)+ 插件自注册 provider。顺序、去重、优先级全由内核按 scope 链与 cwd 决定,插件不再自扫、不再取「所有会话的并集」。
|
|
77
|
+
- **与内核分工**:会话里的 `/` 技能源与技能工具行由 DSH 内核的 `@deepseek-ai/dsh-client-ui-skill` 负责,本插件不重复注册(重复注册会让内核 apply 抛错并拖垮整条客户端插件加载链);本插件提供的是「能力」面板里的管理面(导入 / 归组 / 开关 / 体检)与它背后的宿主路由。
|
|
78
|
+
|
|
79
|
+
### MCP Server 接入(MCP tab)
|
|
80
|
+
|
|
81
|
+
- **一键接入**:粘贴 JSON / DSH 原生 YAML(`mcpServers` 形态)/ `mcp-client` 行片段,面板先给待写入预览,再写进预设组合或 profile patch —— **写前备份**,重名 server 跳过,非法 serverName / 非布尔 `enabled` 直接拒绝。
|
|
82
|
+
- **预设专属 Server 行**:直接在面板里新增 / 删除某个 agent 预设自带的 Server 行(写进该预设声明行的 `config.plugins`,经 DSH 的 `configEditor` 落盘 profile patch)。
|
|
83
|
+
- **分层遮蔽**:全局行 + 预设层两本账(预设层分「继承全局」与「自带」两侧,各记各的账);预设自带的同名 Server 优先于继承条目;全局关闭 = 一票否决,预设层不能反开(返回 409 并给出说明)。
|
|
84
|
+
- **工具级启停**:按最长匹配把工具归到所属 Server(`my` 与 `my_server` 各自成组),可整台 Server 关掉,也可只关其中几个工具;装配过滤、状态路由、原生目录三处同源。
|
|
85
|
+
- **推荐清单**:`/api/mcp-recommended` 给出常见 MCP Server 的配置模板,照抄即可接入。
|
|
86
|
+
- **MCP Server 只有一种来源:Cordis 组合行**。内核没有「读某个目录下 `mcp.json`」的约定(全仓库 grep `mcps` 零命中),所以 0.10.x 曾加过的 `mcps/` 四目录层在 **0.11.0 已移除** —— 面板的列表、启停、增删全部作用于组合行(`mcp-client` 行 / profile patch),不再由插件代读目录、代挂行。
|
|
87
|
+
|
|
88
|
+
### 提示词段
|
|
89
|
+
|
|
90
|
+
- **屏蔽**:按名字 + 来源从装配结果里移除该段。被屏蔽的行不会消失,仍可编辑、恢复 —— 屏蔽只意味着不注入模型。
|
|
91
|
+
- **替换**:编辑该段文本,编辑框预填当前生效文本(动态段会尽力解析出真实内容再回显)。
|
|
92
|
+
- **注入**:每个阶段里「+ 注入」展开表单,按名称 + 文本新建一段,带 `手动` 徽标,随时可删除。
|
|
93
|
+
- **排序**:行首抓手拖动排序,或用行内 ↑/↓ 箭头逐格挪。顺序以 0 起始的连续虚拟下标存储,不会出现重复或小数 order,也不需要手填数字。**未手动排序时默认按宿主注册的规范 `order` 排列**(与模型实收顺序一致,如 `tool:apply_patch` 落在 `tool:edit` 之后),新见到的段按 order 落位、不再追加到尾部。
|
|
94
|
+
- **拖拽**:把「本系统全部提示词」池里的行拖进列表 = 加入当前阶段(带上池里原文);把行拖回池 = 从当前阶段移除(注入进来的撤销注入,原生段转为屏蔽);把行拖到头部某个**阶段按钮**上 = 复制到那个阶段。拖动中有插入位置提示(行上下的蓝色线),投放区高亮;列表比视口长时,把指针拖到列表上/下边缘会自动滚动(越靠边越快),所以池在折叠区里、目标行在视口外也照样能拖到。
|
|
95
|
+
- **每阶段独立**:引导期屏蔽写 `sectionsBootstrap`,压缩受控期写 `sectionsCompaction`,常驻期写 `sections`;三份名单互不继承、互不影响,排序空间也互不干扰,因此「引导期只留 5 段、常驻期全开」可以分别表达 —— 在一个阶段屏蔽 / 恢复某段,绝不会改变它在其它阶段的状态。从「本系统全部提示词」池把段**拖入**当前阶段即成为当前阶段的独立副本(带原文写入本阶段注入条目)—— 加入阶段只有拖拽这一条路径,池里的行不再挂按钮,界面因此干净一半。(勾选「三态同步」后三态共用同一份列表,见下。)
|
|
96
|
+
- **强制覆盖(`forceSections`,默认开)**:只有当前预设 / 当前阶段存在实际段策略(屏蔽 / 替换 / 注入 / 排序)时才包装宿主装配入口,按本插件结果重建最终 sections —— 此时预设插件自身的阶段裁段(如 liangshen 引导期 20→1)与 persona 的 `complete: true` 整段接管会被绕过;没有段定制时保持宿主原样(包括 minimal 的 complete persona)。设为 `false` 退回瀑布流内过滤(此时完整段接管仍会压制段级定制)。
|
|
97
|
+
- **工具提示词段(`tool:*`)**:工具的第一部分是注册在 `systemPrompt` 里的工具提示词段,会以普通段的形式出现在提示词清单里,可照常屏蔽 / 替换 / 排序;工具页的 `description` 是第二部分(只读),参数 JSON Schema 是第三部分(不可编辑)。一个 `tool:*` 段可能服务多个工具(如 `tool:jobs` 对应 `job_kill/job_list/job_output`),工具页会给出关联提示。
|
|
98
|
+
- **中文提示词开关(面板头部工具栏,刷新按钮旁)**:开启 = 把名字对得上内置译本(`lib/zh/`,25 条目)的段一次性覆盖为中文;关闭 = 清掉这些段的替换文本,回归英文原文。两个方向都写入编辑草稿,与手动编辑同一条保存路径;开关状态从配置探测,不新增字段。自定义段与对不上名字的段不受影响,段数与注入不增不减。`{{...}}` 提示词变量(如 persona 的 `{{model}}` / `{{cwd}}`)、机器路径与代码块逐字保留;`tools:sdk` 只替换前导散文,TS 代码块取自原文。**`tools:sdk` 与 `context:file-reference` 是函数译本**:按该行原文决定译不译(原文为空 = 该段的守卫已把它抹掉,就放弃替换,绝不用译本把一段被守卫消掉的内容复活);开关开启时从「本系统全部提示词」池把段拖进某阶段,也优先取译本 —— 加入即中文,一步接管。
|
|
99
|
+
- **三态同步(头部开关,默认关)**:勾选瞬间即把另外两态覆写为**常驻期的并集行集**(写入编辑草稿,点「保存」生效),之后三个阶段共用同一份段列表与文本 —— 增加 / 删除 / 排序 / 勾选 / 编辑文本都一次写全三个阶段,不再逐阶段各点一遍。行序以常驻期为骨架,只存在于另外两态的段追加在尾部并补进常驻期(同名段以它原生所在那一阶段的行为准);三份屏蔽名单也统一为同一份。动态段(运行时才生成正文,取不到原文)无法凭空建进别的阶段,列表里会给出说明。工具两栏的隐藏 / 显示与加回同样对三个阶段一起生效(只作用于同名的那一项)。
|
|
100
|
+
|
|
101
|
+
### 工具目录
|
|
102
|
+
|
|
103
|
+
- **勾选 = 该阶段对模型可见**(`exclude`):取消勾选即在**该阶段**隐藏这个工具,勾回来就恢复,被隐藏的行半透明原位保留。没有白名单模式 —— 它会让 `exclude` 整体失效,一次勾选就能悄悄关掉该阶段其它所有工具,而表达能力并不比反选更多。
|
|
104
|
+
- **「加回」名单(`add`)**:被该阶段裁掉、但**注册表里仍有**的工具,可从「本系统全部工具」池加入该阶段 —— 装配时在过滤**之后**从注册表查回 schema 追加(`exclude` 优先:同一名字两边都在 = 隐藏)。注册表里根本没有的工具(别的预设独有)加不进来,界面会明确说明。
|
|
105
|
+
- **阶段目录**:引导期与压缩受控期各有独立的 exclude / add 名单,运行时优先级为 **压缩受控期 > 引导期 > 静态** —— 压缩后仍未晋级且配了压缩目录就用它,否则未晋级时用引导目录,其余情况用静态过滤。
|
|
106
|
+
- **拖拽**:把池里的工具拖进列表 = 让它在当前阶段出现(加回或从黑名单放出来);把行拖回池 = 从当前阶段拿掉(已加回的撤销加回,原生工具则该阶段隐藏);拖到头部某个**阶段按钮**上 = 复制到那个阶段,**隐藏 / 启用状态一起带过去**,源阶段不动。加回阶段同样只有拖拽这一条路径。
|
|
107
|
+
- **扩充的天花板是注册表**:只能把注册表里已有的工具加回某个阶段;要让一个全新工具出现,得改预设的组成,不是这里。
|
|
108
|
+
- **顺序**:左栏启用列表、「本系统全部工具」池、右栏模型可见目录都按**宿主最终目录顺序**排列(预设配了 `toolOrder` 就用它,否则字母序)—— 不再按注册表枚举序 / 浏览先后乱排。
|
|
109
|
+
- **同名工具分开显示**:若别的插件在会话作用域注册了与原生同名的工具(如 better-edit 的 `read` / `edit`、apply-patch-edit 的 `apply_patch`),列表会出现**同名两行**:插件提供的那个在启用列表(标「会话级」,**可勾选开关** —— 取消即真正从模型目录移除,靠装配后过滤 `assembly.tools` 实现,因为 `restrict` 管不到作用域内注册的工具),原生那个进只读「已遮蔽」池(标「插件遮蔽」,**无法反开**)。
|
|
110
|
+
- **执行器包装(PTC 的 `run_code`)**:作为「执行器包装」锁定行出现在启用列表,勾选框禁用(它不是可单独开关的普通工具)。
|
|
111
|
+
- **只读「已遮蔽」池**:只放注册表里有、但当前不可见的 —— 被别的插件 `restrict` 掉的、被别的插件同名顶掉的原生工具、被本插件 MCP 账本遮蔽的。不可勾选、不可反开(要恢复请回到对应插件 / MCP Tab)。
|
|
112
|
+
- **工具的三部分分开**:提示词段(`tool:*`,在提示词 Tab 编辑)、工具描述(工具页只读展示)、参数 JSON Schema(不可编辑);工具页只负责工具显隐,不把 description / Schema 混入提示词编辑。
|
|
113
|
+
- 只影响面向模型的目录;工具本身与路由照常工作。
|
|
114
|
+
|
|
115
|
+
### 模型视角预览
|
|
116
|
+
|
|
117
|
+
预览分两种口径:
|
|
118
|
+
|
|
119
|
+
- **编辑目标预设预览**:提示词模式看最终系统提示词,工具模式看模型可见目录;随头部阶段 Tab 联动切换。2.1.0 起提示词清单与预览同时来自「该预设 + 同预设活动 agent」的真实装配(ADR-0005)——插件在 agent 作用域动态注册的段也会出现在清单与右栏;工具目录仍按纯预设装配计算。无活动会话 / 无同预设活动 agent 时退回纯预设装配。
|
|
120
|
+
- **当前会话(只读)**:`/session` 路由用最新活动根会话自己的 agent scope 跑真实装配,展示模型此刻真正看到的提示词、运行时上下文与工具目录。2.1.0 起它与预设编辑预览的 live 视图是**两条并列的真实装配入口**:预设预览只并入**同预设**活动 agent 的段,只读视图按最新根会话展示;两者都会列出 agent/created 时动态注册的段与 agent 作用域 `tools.restrict` 的遮蔽。
|
|
121
|
+
|
|
122
|
+
工具视图给出「模型可见 / 完整目录」的对照 —— PTC、Code Mode 这类预设会把整套目录包装成单个 `run_code`,只看注册表会误判。启用列表里的「会话级」(插件提供的工具)与「执行器包装」(`run_code`)是模型实际可见、本插件锁定的项;底部只读「已遮蔽」池放的是「注册表里有、当前不可见」的「插件遮蔽」「本插件遮蔽」项(无法反开)。同名工具会分别出现在启用列表(插件提供)与已遮蔽池(原生)两处。
|
|
123
|
+
|
|
124
|
+
### 提示词变量
|
|
125
|
+
|
|
126
|
+
宿主只注册 `provider` / `model` / `cwd` 三个变量,段文本里引用别的 `{{name}}` 会直接让整次装配失败。本插件经官方扩展点追加两类变量:
|
|
127
|
+
|
|
128
|
+
- **内置系统事实**:`date` / `time` / `datetime` / `weekday` / `hostname` / `platform` / `arch` / `username` / `home` / `shell` / `locale` / `node_version`,每次装配现算。
|
|
129
|
+
- **全量环境变量**:`process.env` 的每个键映射为 `env_<小写,非法字符归并为 _>`,如 `PATH` → `{{env_path}}`、`USER.NAME` → `{{env_user_name}}`。
|
|
130
|
+
|
|
131
|
+
**黑名单(`envBlocklist`)**:env 里常有密钥,进了提示词就会随请求发给模型,所以命中黑名单的键不注册。预填条目覆盖常见凭据类键(含 `SECRET` / `TOKEN` / `PASSWORD` / `API_KEY` / `*_DSN` 等),条目支持 `*` 通配、大小写不敏感;面板的环境变量黑名单卡片可随时增删,卡里的折叠列表给出当前实际注册的变量清单。黑名单变化在下次装配生效(面板改动或直接改 `config.yaml` 都一样)。
|
|
132
|
+
|
|
133
|
+
**导出 / 导入随行**:导出预设时当前黑名单随行写入文件;导入端按并集并入(只增不减),与快照库语义一致。
|
|
134
|
+
|
|
135
|
+
严格渲染的代价:段里引用了一个未注册的名字(如被黑名单挡下的键),**整段装配失败**而不是留空 —— 面板清单里没列出的名字不要用。
|
|
136
|
+
|
|
137
|
+
### 配置快照与 agent 预设
|
|
138
|
+
|
|
139
|
+
- **保存当前配置**:把当前作用域的完整定制(含每阶段屏蔽名单、每阶段排序、阶段工具目录)存成一份可复用的配置快照。
|
|
140
|
+
- **应用**:同名段被覆盖、快照名单之外的当前段被默认屏蔽;快照里当前系统匹配不上的段默认跳过(跨系统导入不凭空建段),快照里没有的阶段字段保留你当前的值,不会被抹掉。同一时间只有一份在用。
|
|
141
|
+
- **导出 / 导入**:配置快照以 JSON 往返(Tauri 桌面走原生对话框,Web 走下载 / 文件选择),同名预设会被跳过。顺序以相对形式存储(每段记住它跟随谁),快照因此可跨不同段集合移植。
|
|
142
|
+
- **存为 agent 预设**:整体**复制**当前编辑目标的预设目录(组成文件、伴生脚本、技能目录一并带走)到用户预设根,再把当前定制写进它的覆盖项。新预设随即出现在头部预设 Tab 里 —— 它是一个真正可切换的 agent 预设,而不只是一份配置副本。
|
|
143
|
+
|
|
144
|
+
### 跨预设的注册表池
|
|
145
|
+
|
|
146
|
+
「本系统全部提示词 / 本系统全部工具」不随编辑目标切换:它是一个**跨预设、只增不减的并集**(同名后见到者赢,新名追加),存放在 `catalog.yaml` 这个派生缓存里,删掉会自行重建。
|
|
147
|
+
|
|
148
|
+
池子的内容来自三处:
|
|
149
|
+
|
|
150
|
+
- **当前 scope 的注册表**(你正在编辑的那个预设);
|
|
151
|
+
- **同预设活动 agent 的会话级段 / 工具**:当编辑目标正好是同预设活动 agent 所属预设时,清单与预览在请求时按该 agent 的真实装配现 merge(`tool:subagent`、`context:file-reference`、`tool:undo_last_edit` 等任意段名),按 `{name, source}` 去重、同名不同源分列,并打「会话级」标记;切换到其它预设时保持纯预设列表,避免跨预设混入(ADR-0005);
|
|
152
|
+
- **浏览过的其它预设**:只在某个预设里注册的段 / 工具(如 `tools:ptc-only`、`raw-html-v2:vcp`)随你切换编辑目标逐步并进来 —— 这部分按需增长,是本插件的取舍(逐个挂载预设 tree 慢到十几秒,不值得每次开面板都跑)。
|
|
153
|
+
|
|
154
|
+
真实会话装配那次也会把看到的段 / 工具并进登记表,作为没有活 agent 时的兜底。`catalog/rescan` 同样会读取同预设活动 agent 的视图,避免重扫把只在 agent 作用域注册的条目清掉。池里的段按宿主 `order` 排列(与模型实收一致);工具池只列能按阶段开关的预设工具,不可控项见工具页签的只读「完整目录 / 已遮蔽」。
|
|
155
|
+
|
|
156
|
+
## 工作原理
|
|
157
|
+
|
|
158
|
+
一次改动从面板到模型的完整链路:
|
|
159
|
+
|
|
160
|
+
<table>
|
|
161
|
+
<tr align="center">
|
|
162
|
+
<td width="19%"><b>① 侧边栏面板</b><br>左栏勾选列表 / 右栏预览<br><i>只改内存草稿</i></td>
|
|
163
|
+
<td width="3%">→</td>
|
|
164
|
+
<td width="19%"><b>② 插件自有路由</b><br><code>/config</code> · <code>/config/apply</code><br><code>/preview</code> · <code>/inventory</code> · <code>/presets</code></td>
|
|
165
|
+
<td width="3%">→</td>
|
|
166
|
+
<td width="19%"><b>③ config.yaml</b><br>全局字段 + <code>overrides[预设]</code><br><i>mtime 懒加载,手改即时生效</i></td>
|
|
167
|
+
<td width="3%">→</td>
|
|
168
|
+
<td width="34%"><b>④ 装配瀑布流</b><br><code>system-prompt/assemble</code> 钩子按会话推导阶段,<br>解析出生效配置并过滤</td>
|
|
169
|
+
</tr>
|
|
170
|
+
<tr>
|
|
171
|
+
<td colspan="9" align="center"><b>④ 内部依次是</b>:<code>effectiveConfig(overrides[会话所属预设])</code>(0.9.0 起无全局基底)→ 段:屏蔽 → 替换 → 注入 → 按 order 排序;工具:<code>pickToolsFilter</code>(压缩 > 引导 > 静态)→ <code>applyToolFilter</code></td>
|
|
172
|
+
</tr>
|
|
173
|
+
<tr>
|
|
174
|
+
<td colspan="9" align="center">
|
|
175
|
+
<b>⑤ 交卷前还有一手</b>:宿主在瀑布流<b>之后</b>,若存在 <code>complete: true</code> 的段就把整份 sections 还原成那一条 —— 这就是面板会对这类预设亮黄标的原因(工具目录不受影响;当前阶段有实际段策略且 <code>forceSections</code> 开启时,本插件已在装配入口重建 sections,接管被绕过,不再亮黄标;没有段策略时保持 complete 原样)
|
|
176
|
+
</td>
|
|
177
|
+
</tr>
|
|
178
|
+
<tr>
|
|
179
|
+
<td colspan="9" align="center"><b>⑥ 模型收到</b>:最终系统提示词 + 可见工具目录;右栏预览读的就是这一份结果</td>
|
|
180
|
+
</tr>
|
|
181
|
+
</table>
|
|
182
|
+
|
|
183
|
+
代码地图:
|
|
184
|
+
|
|
185
|
+
| 路径 | 作用 |
|
|
186
|
+
| --------------------------------- | -------------------------------------------------------------------------------- |
|
|
187
|
+
| `lib/index.js` | 宿主端:装配钩子、五条 HTTP 路由、agent 预设 fork、遗留字段一次性清理 |
|
|
188
|
+
| `lib/effective.js` | 纯函数:字段级 override 合并、阶段选取(注入段 / 工具目录)、黑名单过滤 |
|
|
189
|
+
| `lib/promotion.js` | 由 durable 事件推导 `{promoted, boundary}`,压缩复位、子代理恒已晋级 |
|
|
190
|
+
| `lib/vars.js` | 提示词变量:内置系统事实 + env 全量映射 / 黑名单,装配入口按签名懒同步 |
|
|
191
|
+
| `lib/sectionOps.mjs` | **面板与单测共用**的阶段状态纯函数(名单写回目标、注入身份、重排、逐阶段持久化) |
|
|
192
|
+
| `lib/store.js` / `lib/catalog.js` | 原子写 + last-good 回落的配置存储;跨预设段/工具累积登记表 |
|
|
193
|
+
| `src/client/` | 面板(React,无 JSX 语法糖依赖,`h()` 直写),构建进 `client/client.js` |
|
|
194
|
+
|
|
195
|
+
关键约定:阶段逻辑只有一份实现 —— `lib/sectionOps.mjs` 既被 tsdown 打进浏览器包,也被
|
|
196
|
+
`node --test` 直接 import 跑单测,所以「测试通过」和「界面行为」之间不存在第二套代码。
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
## 使用说明
|
|
200
|
+
|
|
201
|
+
侧边栏点 **能力**,在面板顶部选 **提示词** tab。第一行是 agent 预设 chips(0.9.0 起「全部 Agent」已移除——提示词必须按具体预设修改),选中某个预设后改动只对该预设生效,预设未定制的字段 = 官方默认;chips 上的橙色数字告诉你它已经单独改了几项。第二行是定制头部:模式切换(提示词 / 工具 / 配置)、阶段 Tab(引导期 / 压缩受控期 / 常驻期 —— 左栏列表与右栏预览联动切换同一个阶段)、三态同步与中文提示词开关、保存 / 刷新 / 关闭。
|
|
202
|
+
|
|
203
|
+
### 提示词模式
|
|
204
|
+
|
|
205
|
+
左栏列出当前阶段的段:
|
|
206
|
+
|
|
207
|
+
- **勾选框**:该阶段是否注入模型(`未屏蔽` / `已屏蔽` 徽标);被停用的行半透明原位保留,随时勾回
|
|
208
|
+
- **编辑**:按阶段替换该段文本,替换过的行带 `已替换` 徽标与「还原」按钮
|
|
209
|
+
- **↑/↓**:调整该阶段内的顺序;`#N` 是它当前的虚拟下标
|
|
210
|
+
- `系统` / `手动` 徽标标明段的来源,只有 `手动` 段可以删除
|
|
211
|
+
- **「+ 注入」**:展开表单按名称 + 文本新建一段(阶段锁定为当前 Tab)
|
|
212
|
+
- **底部三态过滤**:全部 / 已启用 / 已停用,只统计当前阶段
|
|
213
|
+
|
|
214
|
+
「本系统全部提示词」只读池收在列表末尾的折叠区:**把行拖进上面的列表**即加入当前阶段,**拖到头部阶段按钮**即加入那个阶段(行上不再有按钮)。右栏实时预览当前阶段装配后的最终系统提示词 —— 编辑草稿的效果同步呈现,面板会标注「预览尚未保存草稿」。
|
|
215
|
+
|
|
216
|
+
勾选头部的**三态同步**后,三个阶段共用同一份段列表与文本(常驻期为骨架,另外两态独有的段追加在尾部并补进常驻期):切哪个阶段 Tab 看到的都是同一份列表,增删 / 排序 / 勾选 / 编辑文本一次写全三态 —— 适合「三个阶段要一样的提示词」;不勾选则三态各管各的,适合「引导期只留几段、晋级后全开」。
|
|
217
|
+
|
|
218
|
+
### 工具模式
|
|
219
|
+
|
|
220
|
+
左栏列出该阶段进入过滤的目录 ∪ 你加回的工具:勾选 = 该阶段对模型可见,取消 = 在该阶段隐藏。「本系统全部工具」池收在折叠区:**把行拖进列表**即让它在当前阶段出现,**拖到阶段按钮**即复制到那个阶段(隐藏状态一起带过去),**拖回池**即从当前阶段拿掉。想看模型真正拿到几个工具,看右栏预览的「模型可见 / 注册表总数」对照。
|
|
221
|
+
|
|
222
|
+
### 配置模式
|
|
223
|
+
|
|
224
|
+
左栏是**配置快照库**(保存当前配置 / 导入 / 应用 / 导出 / 删除,正在使用的那份带「使用中」标记);右栏是**存为 agent 预设**(整体 fork 当前编辑目标的预设目录并写入当前定制)与**全局设置**:强制覆盖开关、环境变量黑名单(增删条目、查看当前实际注册的变量清单)、提示词变量参考、恢复初始状态(清空全部定制并关闭 `forceSections`,与卸载插件等效,无需重启,点击需二次确认)。
|
|
225
|
+
|
|
226
|
+
### 编辑目标与保存
|
|
227
|
+
|
|
228
|
+
预设 Tab 决定改动落在哪。提示词与工具模式共享同一份未保存草稿,**保存**按钮一次落盘;切到配置模式或切换编辑目标会丢弃草稿(脏草稿先弹确认)。也就是说:写坏的东西不点保存就不会进文件。
|
|
229
|
+
|
|
230
|
+
## 配置存放位置
|
|
231
|
+
|
|
232
|
+
- `~/.dsh/prompt-customizer/config.yaml` —— 唯一权威配置。首次启动时若该文件不存在而旧版 `settings.yaml` 里有对应段落,会自动迁移一次(主文档原样保留,可回滚)。手工编辑即时生效,无需重启。
|
|
233
|
+
- `~/.dsh/prompt-customizer/catalog.yaml` —— 跨预设的段 / 工具累积登记表,纯派生缓存,删掉会随浏览重建。
|
|
234
|
+
- 技能侧:技能根目录下的 `.bundles.json`(技能包账本,记规范名与目录名两套写法)与技能开关账本(全局层 + 各预设层)。
|
|
235
|
+
- MCP 侧:`$DSH_HOME` 下本插件目录里的 `preset-masks.json`(分层遮蔽账本)与 `tool-disable.json`(工具级启停账本);预设自带 Server 行写在该 agent 预设声明行的 `config.plugins` 里,由 DSH 的 `configEditor` 原子写回 profile 的 `cordis.patch.yml`(全局 Server 仍由本插件直接编辑该 patch,写前备份)。
|
|
236
|
+
- mcps 目录侧(内核不读,本插件代读并挂载):全局 `~/.agents/mcps/**/mcp.json`,工作区 `<工作区>/.dsh/mcps/**/mcp.json` 与 `<工作区>/.agents/mcps/**/mcp.json`。只读这些文件,不写;工作区层的 Server 只在该工作区的会话里可见。
|
|
237
|
+
|
|
238
|
+
## 已知限制
|
|
239
|
+
|
|
240
|
+
下面都是实测结论。面板在相关情况下会直接给出黄色警示,不需要你猜:
|
|
241
|
+
|
|
242
|
+
- **有些预设的提示词不由段组成。** 若某个段以 `complete: true` 注册(dsh-persona 的「整段接管」),宿主会在装配瀑布流**之后**把整份 sections 还原成那一条段。当前阶段有实际段策略且 `forceSections`(默认开)时,本插件在装配入口绕开该机制,段级定制照常生效;没有段策略时保持 complete 原样;设为 `false` 时,本插件的屏蔽 / 替换 / 注入 / 排序对这类预设无效(工具过滤不受影响),面板会写明「最终系统提示词由 `deployment:persona` 段整段接管」。
|
|
243
|
+
- **丢弃段的原因不止一种**。除了 `complete` 接管,也存在预设用自己的规则在特定阶段裁段(实测某预设引导期 20 段 → 1 段,而注册表里并没有 complete 段)。所以面板还做了一次机制无关的比对:把本插件产出的段名与最终装配逐名核对,不符时提示「产出 N 段,模型只见 M 段」。
|
|
244
|
+
- **预览的伪会话可能降级**。阶段视图由一次合成会话驱动,个别预设插件会在这种会话上抛错;此时该阶段回退为无会话装配并标注「已降级」,即那个阶段看到的是不带原生阶段裁剪的结果。
|
|
245
|
+
- **替换动态生成的段会固定其内容**。像 `app:web-surface` 这类段在装配时实时生成(嵌入当前 Web 端口等)。替换后文本冻结为你编辑时的值,不再跟随运行时变化;想保持跟随请改用屏蔽。
|
|
246
|
+
- **动态段文本解析是尽力而为**。面板读取动态段时会尝试调用其生成函数(只传最小上下文)来回显真实内容;依赖更复杂上下文、一调就抛的段会显示 `<动态生成>`,其余功能不受影响。另外,带 `{{model}}` / `{{cwd}}` 之类变量的段在列表里显示的是**未替换的模板**,右栏预览里才是替换后的最终文本。
|
|
247
|
+
- **导出依赖宿主允许下载**。Web 回退走浏览器下载:若宿主 webview 静默丢弃下载,面板仍会提示「导出成功」而文件没有落地。导入(文件选择)不受影响。
|
|
248
|
+
- **池子是「见过才知道」的并集**。当前 scope 与**同预设活动 agent** 作用域的段 / 工具当场就能列出来;但**只在别的预设里注册**的段 / 工具要等你切到那个编辑目标才进池(逐个挂载预设 tree 太慢,不做预热)。池子对「某个名字属于哪个阶段」没有权威信息 —— 加入阶段时按当前 Tab 落,之后可以随意拖动改位置。
|
|
249
|
+
- **工具目录的扩充以注册表为天花板**,见前文「扩充的天花板是注册表」。
|
|
250
|
+
- **「当前会话」的判定**:面板是进程级单例,客户端拿不到渲染期的当前会话 id,因此以**最新创建的根会话**为准(`session.header.createdAt` 降序,子代理 `delegationDepth > 0` 不计入);多会话来回切换时,面板可能仍显示最新那个会话的技能集合与「当前会话」视图。无会话时退回启动 cwd 的全局视图。可写根集合仍只在「插件挂载时」与「新会话创建时(`agent/created`)」重算。
|
|
251
|
+
- **工具显隐的边界**:本插件的阶段工具过滤分两层 —— 继承的全局工具走 `tools.restrict`(只收窄、取交集),作用域内注册的工具(插件提供的 `read` / `edit` / `apply_patch` 等)走**装配后过滤 `assembly.tools`**(按名字从模型函数表移除),所以两类都能被本插件按阶段隐藏。但 ① 别的插件 `restrict` 掉的全局工具、② 被别的插件同名顶掉(遮蔽)的原生工具,本插件**无法反开**(restrict 不可反向、遮蔽由对方在会话作用域注册决定);这两类留在只读「已遮蔽」池。③ PTC / code-mode 下 `run_code` 程序内部可调工具来自 toolSet,本插件按名隐藏 `assembly.tools` 只影响模型可见的函数表,不影响程序内部绑定。
|
|
252
|
+
- **mcps 目录只读挂载**:面板不改写这些 `mcp.json`;要让某台 Server 成为持久全局配置,仍走「添加 MCP Server」(写 profile patch)。工作区层的 Server 工具名带 8 位路径哈希后缀(如 `mcp__codegraph-e5f6a7b8__*`),这是同名隔离的代价。
|
|
253
|
+
|
|
254
|
+
## 开发
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
npm install
|
|
258
|
+
npm run check # typecheck + build + 全量单测
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
两侧都由 [esbuild](https://esbuild.github.io/) 一次构建(`node build.mjs`):
|
|
262
|
+
|
|
263
|
+
- `lib/index.js` —— 宿主半身,ESM、自包含,只留 `node:*` 内建依赖;`@deepseek-ai/*` 一律走 `vendor/`(内置叶子模块)或构建期内联,`assertHostExternals()` 会在构建末尾把违规的裸导入直接判失败;
|
|
264
|
+
- `client/client.js` —— 浏览器半身,`__ModuleLoader__` factory bundle;`react*` 与 `@deepseek-ai/*` 走宿主模块表,其余全部内联。
|
|
265
|
+
|
|
266
|
+
浏览器半身改动别只靠单测(历史上「点 MCP tab 闪退」就是这么漏出去的:单测全绿,真渲染才炸)。两道针对性检查:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# 1) 静态护栏:从宿主 ui-primitives 导入的名字必须真实存在(防 undefined 组件)
|
|
270
|
+
node --test test/client-primitives.test.mjs
|
|
271
|
+
|
|
272
|
+
# 2) 真浏览器:起一个 dsh web,再用真实 Chrome 点一遍面板并截图
|
|
273
|
+
dsh web --port 3099 --no-open # 从输出里取出带 token 的 URL
|
|
274
|
+
node scripts/verify-panel-browser.mjs --url "<带 token 的 URL>" \
|
|
275
|
+
--expect-skills <技能名,...> --expect-mcp <serverName,...> --out ./verify-shots
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
`--headless` 可切无头;脚本只用 Node 内建能力(`fetch` + `WebSocket` 驱动 CDP),不引第三方依赖。
|
|
279
|
+
|
|
280
|
+
阶段性与可测的纯逻辑集中在 `vendor/prompt-customizer/`(提示词策略 / 清单登记表 / 阶段投影)与 `vendor/skill-manager/`:同一份纯函数既被两侧打包使用,也被 `node --test` 直接覆盖,测试即上线代码。`npm run check` = 构建 + 全量单测 + 两半 smoke。
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# 终测:功能点矩阵与自动化覆盖
|
|
2
|
+
|
|
3
|
+
> **状态(2.1.0)**:本文件记录的是 1.x / 2.0.x 时期的终端级与行为级验证结果(2026-11-07),**不作为 2.1.0 的当前验证结论**。当前门禁是 `npm run check`(构建 + 全量单测 + 宿主 / 客户端 smoke)与 `test/universal-prompt-takeover.test.mjs`(ADR-0005 组合场景)。`scripts/verify-effect.mjs` 的旧 `replace` 字典、`level=workspace`、`scripts/e2e-terminal.mjs` 的工作区级断言已与 1.4.0 / 2.0.0 之后的代码不相容,属历史脚本,运行前须按当前 `/config/apply` 契约更新;`docs/guide.md` 同样保留作历史材料,现状以 `docs/adr/0005-universal-prompt-takeover.md` 与 `docs/upgrades/2.1.0-universal-prompt-takeover.md` 为准。
|
|
4
|
+
|
|
5
|
+
> 自动化脚本:`scripts/e2e-terminal.mjs`(终端级,走真实 HTTP + dsh-auth 握手)。
|
|
6
|
+
> 运行:先起一个实例 `dsh web --no-open --port <N>`,再
|
|
7
|
+
> `node scripts/e2e-terminal.mjs --url "http://127.0.0.1:<N>/?token=<TOKEN>" [--destructive]`。
|
|
8
|
+
> `--destructive` 会先 `GET /backup` 整库备份、测试后 `POST /restore` 恢复,保护真实数据。
|
|
9
|
+
|
|
10
|
+
结果(2026-11-07,web profile,MCP `anysearch` + `codegraph`):
|
|
11
|
+
- 单测 `npm test`:**136 passed / 0 failed**。
|
|
12
|
+
- E2E(`--destructive`):**43/43 passed**,含备份→写入→恢复一致性。
|
|
13
|
+
|
|
14
|
+
## A. 提示词定制(预设级)
|
|
15
|
+
| 功能 | 覆盖 | 结果 |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| inventory 清单(段/工具/阶段) | `test/*` + E2E `GET /inventory` | PASS |
|
|
18
|
+
| config 读/写(forceSections、envBlocklist、presets) | `test/store` `test/reset-route` + E2E `GET /config`、`/config/set`、`/config/unset` | PASS |
|
|
19
|
+
| 三阶段 preview(bootstrap/compaction/active) | `test/ordering` `test/rc2-preview` + E2E `GET /preview?phase=` | PASS |
|
|
20
|
+
| 草稿预览 POST /preview | `test/session-preview` | PASS(单测) |
|
|
21
|
+
| 段 屏蔽/替换/注入/拖拽排序 | `test/ordering` `test/sectionOps` | PASS |
|
|
22
|
+
| 工具目录按阶段 隐藏/加回 | `test/tool-shadow` `test/tool-visibility` | PASS |
|
|
23
|
+
| config/apply 预设级写入 + 还原 | E2E `POST /config/apply`(target) | PASS |
|
|
24
|
+
| export 当前预设定制(只读) | `test/export-route` + E2E `GET /export` | PASS |
|
|
25
|
+
| 恢复初始 /config/reset | `test/reset-route` | PASS |
|
|
26
|
+
|
|
27
|
+
## B. 两级(预设级 / 工作区级)
|
|
28
|
+
| 功能 | 覆盖 | 结果 |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| config/apply `level=workspace` 写 `workspaceOverrides[cwd]` | `test/workspace-override` + E2E | PASS |
|
|
31
|
+
| 合并语义 工作区>预设(同名后者胜) | `test/workspace-override` `mergeOverrideLayers` | PASS |
|
|
32
|
+
| 运行时按会话 cwd 叠加工作区 override | `buildSessionPreview`/`resolveTarget`(单测 + 实机) | PASS |
|
|
33
|
+
| 顶部统一「预设级/工作区级」切换(三 tab 共用) | 实机 UI(截图) | PASS |
|
|
34
|
+
| 移除「当前会话」独立模式 | 实机 UI | PASS |
|
|
35
|
+
|
|
36
|
+
## C. SKILL 技能管理
|
|
37
|
+
| 功能 | 覆盖 | 结果 |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| list / bundles / loose 清单 | `test` skill 系列 + E2E `GET /api/skill-manager/list` | PASS |
|
|
40
|
+
| 全局 / 预设级开关 | `test/skill-toggles` + E2E `PUT /skill-toggles/presets/:id/skills/:name` | PASS |
|
|
41
|
+
| **工作区级开关(新)** | `test`(skill-toggles workspace)+ E2E `PUT /skill-toggles/workspaces/:cwd/skills/:name` + `GET /workspaces` | PASS |
|
|
42
|
+
| 技能健康检查 | E2E `GET /api/skill-health` | PASS |
|
|
43
|
+
| 技能包 CRUD / 安装 / 删除 | 单测(文件系统相关,E2E 未做破坏性文件操作) | 单测 PASS |
|
|
44
|
+
|
|
45
|
+
## D. MCP 管理
|
|
46
|
+
| 功能 | 覆盖 | 结果 |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| mcp-status(服务器/工具/遮蔽/工作区关闭/工具禁用镜像) | `test/mcp-*` + E2E `GET /api/triad/mcp-status` | PASS |
|
|
49
|
+
| 注册 Server 呈现(anysearch 4 工具、codegraph 1 工具) | 实机 UI 截图 + E2E | PASS |
|
|
50
|
+
| 预设级 遮蔽(mask) | `test` + E2E `PUT /mcp-masks/:preset/:server` | PASS |
|
|
51
|
+
| 预设级 工具级启停 | `test/mcp-tool-disable` + E2E | PASS |
|
|
52
|
+
| 工作区级 server 关闭 | `test/mcp-workspace-scope` + E2E `PUT .../workspace/:cwd/servers/:server` | PASS |
|
|
53
|
+
| **工作区级 工具级启停(新)** | `test/mcp-workspace-scope`(新增用例)+ E2E `PUT .../workspace/:cwd/tools` + `status` | PASS |
|
|
54
|
+
| mcp-config 启停 / 移除 | `test` + UI | PASS(单测/UI) |
|
|
55
|
+
| mcp-presets 添加/移除专属 Server | `test` + UI | PASS(单测/UI) |
|
|
56
|
+
| mcp-preview 粘贴校验 | `test` | PASS(单测) |
|
|
57
|
+
|
|
58
|
+
## E. 备份 / 恢复
|
|
59
|
+
| 功能 | 覆盖 | 结果 |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| 整库备份 `GET /backup`(docs + catalog) | `test/backup-route` + E2E | PASS |
|
|
62
|
+
| 整库恢复 `POST /restore` 且覆盖一致 | `test/backup-route` + E2E(恢复后 overrides 与备份一致) | PASS |
|
|
63
|
+
| 配置页「完整备份/恢复」卡片 | 实机 UI | PASS |
|
|
64
|
+
|
|
65
|
+
## F. 配置页
|
|
66
|
+
| 功能 | 覆盖 | 结果 |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| 环境变量黑名单(envBlocklist,`{{env:...}}`) | 实机 UI + 备份含该字段 | PASS |
|
|
69
|
+
| 强制覆盖 forceSections | E2E `config/set` + UI | PASS |
|
|
70
|
+
| 完整备份/恢复 | E2E + UI | PASS |
|
|
71
|
+
| 配置快照库(保存/应用/导入/导出/删除) | UI(保留,底层 presets/activePreset 不清理) | PASS |
|
|
72
|
+
| 恢复初始状态 | `test/reset-route` + UI | PASS |
|
|
73
|
+
| 自适应卡片网格排版 | 实机 UI | PASS |
|
|
74
|
+
|
|
75
|
+
## G. 存储 / 版本
|
|
76
|
+
| 功能 | 覆盖 | 结果 |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| 单文件 SQLite(WAL,node:sqlite) | `test/*`(DB 版) | PASS |
|
|
79
|
+
| 破坏式:旧 YAML/JSON 不读不迁移 | `test/include-migration` 等 | PASS |
|
|
80
|
+
| 版本 1.0.0 + 升级文档 | `docs/upgrades/1.0.0-sqlite-breaking.md` | PASS |
|
|
81
|
+
|
|
82
|
+
## 未纳入自动化(说明)
|
|
83
|
+
- 技能包安装/删除、MCP 添加专属 Server 会写真实文件系统(技能根、profile patch),E2E 不做破坏性文件操作,仅单测/手动覆盖。
|
|
84
|
+
- `codegraph` 依赖本机 `codegraph` 命令;某些启动环境 PATH 缺失时该 Server 显示「等待注册」,属环境问题,不影响插件逻辑。
|
|
85
|
+
|
|
86
|
+
## H. 行为级验证(真的生效,非只看接口 200)
|
|
87
|
+
脚本:`scripts/verify-effect.mjs`(对比宿主**真实装配**前后:`/preview` 的最终 `text`+`tools`、`/session` 活动会话真实视图;写入前备份、测后恢复)。
|
|
88
|
+
|
|
89
|
+
结果(web profile,活动会话 cwd=`D:\dsh-pulgn`):**13/13 通过**。
|
|
90
|
+
|
|
91
|
+
| 场景 | 观测 | 结果 |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| 预设级·隐藏段 | `/preview(active)` 最终 `sections` 去除该段;`text` 13522→13472 | PASS |
|
|
94
|
+
| 预设级·替换段文本 | 最终 `text` 含替换标记 `__E2E_MODIFIED_TEXT__` | PASS |
|
|
95
|
+
| 预设级·隐藏工具(MCP 工具级) | `/preview.tools`(=宿主交给模型的工具声明)不再含 `mcp__anysearch__batch_search` | PASS |
|
|
96
|
+
| 工作区级·隐藏段 | 活动会话 `/session` 最终 `sections` 27→26;`text` 15714→15664 | PASS |
|
|
97
|
+
| 工作区级·隐藏工具 | 活动会话 `/session.tools` 不再含该 MCP 工具 | PASS |
|
|
98
|
+
| 以上各项还原 | 隐藏/替换撤销后,段与工具均回到最终装配/会话视图 | PASS |
|
|
99
|
+
|
|
100
|
+
> 结论:在工作区隐藏/修改提示词、隐藏/启用工具,**确实改变了模型最终收到的系统提示词与工具声明**(隐藏即从最终装配移除;替换即进入最终文本;再次放回即恢复)。
|
|
101
|
+
|
|
102
|
+
## 2.1.0 当前验证(ADR-0005,全域系统提示词接管)
|
|
103
|
+
|
|
104
|
+
> 以下来自本机 `npm run check`(2026-11-09):全量单测 **164/164 通过**、构建产物重建、宿主 / 客户端 smoke 全绿。真宿主 E2E 由使用者自行校验;上节 A–H 的 2026-11-07 结果均为历史存档。
|
|
105
|
+
|
|
106
|
+
| 场景 | 覆盖 | 结果 |
|
|
107
|
+
|---|---|---|
|
|
108
|
+
| 会话级段进入 `/inventory` / `/preview`,同名不同源分列,`{kind:'agent'}` 身份稳定 | `test/universal-prompt-takeover.test.mjs` | PASS |
|
|
109
|
+
| 屏蔽会话级段后 `/preview.text` 与 `/session.sections` 都不含它,撤销恢复 | 同上 | PASS |
|
|
110
|
+
| 任意段名的 agent 段可枚举(非 `tool:*` 特判) | 同上 | PASS |
|
|
111
|
+
| 切到别的预设不串台;无活动 agent 退回纯预设不抛错 | 同上 | PASS |
|
|
112
|
+
| 工具目录不受 live 提示词视图影响(D6) | 同上 | PASS |
|
|
113
|
+
| 段按宿主规范 order 排序(含 agent 链 order) | `test/ordering.test.mjs` | PASS |
|
|
114
|
+
| 预览正文并入同预设活动 agent、工具目录仍纯预设 | `test/rc2-preview.test.mjs`、`test/source-model.test.mjs` | PASS |
|
|
115
|
+
| 无明确编辑目标时退回纯预设、不读累积池 | `test/runtime-catalog.test.mjs` | PASS |
|
|
116
|
+
| 反例 | 把 `liveBase.sections` 换回空数组、或让 `stableSourceOf` 返回带 session id 的原始 agent source,上述组合用例必须失败 | 已写入新测试文件头注释 |
|
|
117
|
+
|
|
118
|
+
## 2.1.1 当前验证(同名遮蔽探测)
|
|
119
|
+
|
|
120
|
+
> 来自本机 `npm run check`(2026-11-09):全量单测 **170/170 通过**、构建产物重建、宿主 / 客户端 smoke 全绿。真宿主 E2E 由使用者自行校验。
|
|
121
|
+
|
|
122
|
+
| 场景 | 覆盖 | 结果 |
|
|
123
|
+
|---|---|---|
|
|
124
|
+
| `definitions` 缺席 / agent `definitions` 缺该 name / `inPreset=false`(`schemas` 未挂原生)时同名遮蔽仍进池 | `test/tool-shadow-universal.test.mjs` ①②③ | PASS |
|
|
125
|
+
| 0.2.1 `restrict` 场景(agent 视图仍含插件工具)仍进池 | 同上 ④ | PASS |
|
|
126
|
+
| 任意工具名(`apply_patch` / `edit` / `plugin:custom`)都进池,非样例特判 | 同上 ⑤ | PASS |
|
|
127
|
+
| 遮蔽行 source 标继承层、`shadowedBy` 指向 agent 工具、`keySuffix='shadowed'` | 同上 ①③ + `test/tool-shadow.test.mjs` | PASS |
|
|
128
|
+
| 不误判 agent 新增 / 同一注册不拆行 / 跨预设不串台 / 无活动 agent 不抛错 / 工具目录状态不变 | 同上 ⑥ | PASS |
|
|
129
|
+
| 反例 | 判定换回单点 `presetDefs.get(name) !== liveDefs.get(name)` 时 ①②③ 必须失败;为 `read` 写死特判时 ⑤ 必须失败 | 已写入新测试文件头注释并实测 |
|
|
130
|
+
|
|
131
|
+
## 2.1.2 当前验证(工具目录与真实会话同源)
|
|
132
|
+
|
|
133
|
+
> 来自本机 `npm run check`(2026-11-09):全量单测 **175/175 通过**、构建产物重建、宿主 / 客户端 smoke 全绿。真宿主 E2E 由使用者自行校验。
|
|
134
|
+
|
|
135
|
+
| 场景 | 覆盖 | 结果 |
|
|
136
|
+
|---|---|---|
|
|
137
|
+
| 右栏可见工具目录 = agent scope 注册视图(含 `apply_patch` / `undo_last_edit`),计数与右栏同源 | `test/tool-catalog-scope.test.mjs` ① | PASS |
|
|
138
|
+
| 无 live agent 回落纯预设装配;右栏与 `/session` 同源 | 同上 ②③ | PASS |
|
|
139
|
+
| PTC 塌缩防护(`assemble().tools` 只剩 `run_code` 时仍用 `schemas(agent)`) | 同上 ④ | PASS |
|
|
140
|
+
| 纯新增 agent 工具不伪造 `masked-shadow`、`read` 仍是真同名遮蔽 | 同上 ⑤ | PASS |
|
|
141
|
+
| 只读池纳入 `locked-agent`(会话级徽标)、`stateBadge` 四态 | `test/tool-mask-pool.test.mjs` | PASS |
|
|
142
|
+
| 反例 | 主源换回 `toolSchemasOf(ctx, scopeKey, true)`(presetScopeKey)时 ①③④ 必须失败 | 实测 ①③④ 全红、②⑤ 仍绿 |
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# 1.0.0 —— 破坏式:自有存储迁移到 SQLite
|
|
2
|
+
|
|
3
|
+
> 破坏式更新:**不再兼容旧版 JSON / YAML 存储**。旧文件原样保留但**不读取、不迁移**。
|
|
4
|
+
|
|
5
|
+
## 变更
|
|
6
|
+
|
|
7
|
+
- 插件自有存储从多份 `config.yaml` / `catalog.yaml`(以及后续账本)统一为**单文件
|
|
8
|
+
SQLite**:`~/.dsh/prompt-customizer/prompt-customizer.db`(WAL)。
|
|
9
|
+
使用 Node 内建 `node:sqlite`,**无新增依赖**。
|
|
10
|
+
- 表结构见 `vendor/prompt-customizer/db.js`:
|
|
11
|
+
- `doc(key, json)`:小型整份文档(`config`、工作区 overrides、各 MCP / 技能账本)。
|
|
12
|
+
- `catalog_section` / `catalog_tool`:跨预设「全部提示词 / 全部工具」池,按行规范化存储。
|
|
13
|
+
|
|
14
|
+
> 注:这两张表已在 1.4.1 删除(ADR-0001),当前 DB 只有 `doc(key, json)` 与账本,不存在目录池表。
|
|
15
|
+
- `ledger(domain, scope, name, value)`:按条目读写的名单(预留)。
|
|
16
|
+
- 迁移范围:`config`、`catalog`、新增的**工作区级 override**、MCP `preset-masks` / `tool-disable` / `workspace-close`、技能 `preset-toggles` / `hidden-toggles` **全部进 DB**。宿主配置文件(`cordis.patch.yml` / `.mcp.json`)与技能根下的 `.bundles.json` 仍保持文件(不属于本插件账本)。
|
|
17
|
+
- **两级自定义**:预设级(`overrides[preset]`,只覆盖该预设作用域可见项)→ 工作区级(`workspaceOverrides[cwd]`,作用于该工作区所有会话、可覆盖会话里全部段/工具,且**覆盖预设级**)。面板顶部一个「预设级 / 工作区级」切换,SKILL / MCP / 提示词三 tab 共用。SKILL 工作区级为按 cwd 的技能/技能包开关(`skills/workspace-toggles`,优先级 工作区>预设>全局);MCP 工作区级可整台 server 关闭(`mcp/workspace-close`)与逐工具启停(`mcp/workspace-tool-disable`)。
|
|
18
|
+
- 配置 API 不变(`createConfigStore` 的 `raw / readResolved / writeSection / setField`),
|
|
19
|
+
但底层由文件换成 DB 的 `doc('config')`。
|
|
20
|
+
- 旧版 `~/.dsh/settings.yaml` 的历史段**不再一次性迁移**;`config.yaml` / `catalog.yaml`
|
|
21
|
+
不再读写。
|
|
22
|
+
|
|
23
|
+
## 升级须知
|
|
24
|
+
|
|
25
|
+
- 首次启动会新建空的 `prompt-customizer.db`;用户需**重新配置**(旧定制不迁移)。
|
|
26
|
+
- 想回退:装回 0.x 版本即可(旧文件仍在原位、未被删除)。
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 1.4.0 — 通用过滤模型(破坏式)
|
|
2
|
+
|
|
3
|
+
对齐 DSH `0.2.2-rc.1`。旧配置/快照**不迁移**。
|
|
4
|
+
|
|
5
|
+
> 本文记录 1.4.0 当时的行为,保留作历史材料。其中「工作区级」「预设级只叠通用会话项」已被后续版本修订:工作区级在 2.0.0 移除;会话级段的并入口径在 2.1.0 改为「同预设活动 agent 的真实装配」([ADR-0005](../adr/0005-universal-prompt-takeover.md))。
|
|
6
|
+
|
|
7
|
+
## 变更
|
|
8
|
+
- 三阶段由唯一 `PHASES` 描述表驱动,字段名/状态映射/工具目录不再三处手抄。
|
|
9
|
+
- 段、工具、运行时上下文身份统一为 `{name, source}`;`source` 为注册层
|
|
10
|
+
`global` / `preset(id)` / `agent(session)` / `executor` / `workspace`。
|
|
11
|
+
- 名单(sections/contexts/tools exclude/add)存结构化 EntryRef;旧 name-only 名单忽略。
|
|
12
|
+
- `replace` 改为阶段化 `replacements: [{name, source?, phase, text}]`,只替换已存在段。
|
|
13
|
+
- 工作区级 = 预设候选超集 + 工作区 override:可隐藏但不可消失。
|
|
14
|
+
- 预设级只叠“通用会话项”(不属于任何已声明预设的 agent 条目),不叠具体会话的专属项。
|
|
15
|
+
- 运行时上下文按阶段独立显隐。
|
|
16
|
+
- `envBlocklist` 可配置、默认空;date/time/weekday 用 Intl 按宿主 locale/TZ。
|
|
17
|
+
- MCP:全局行读 `configEditor.entries()`;热重载用 `ctx.mcpManager.watch()` /
|
|
18
|
+
`mcp-manager/status`;工作区 `.mcp.json` 按 cwd 匹配的 agent scope 挂载;
|
|
19
|
+
删除第三方探活与自动改写。
|
|
20
|
+
- 中文提示词整功能、SectionView、sectionOps、旧 rescan 文案等死代码全部删除。
|
|
21
|
+
|
|
22
|
+
## 不再支持
|
|
23
|
+
- 旧 `replace` 字典、旧字符串名单、旧 catalog/目录池、旧中文提示词翻译、旧快照阶段键。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 1.4.1 — Web 预览/编辑运行时修复
|
|
2
|
+
|
|
3
|
+
> **2.1.0 修订([ADR-0005](../adr/0005-universal-prompt-takeover.md))**:本页记录 1.4.1 当时的修复,保留作历史材料。第 1 条「预设预览不再读取当前会话的 agent 作用域条目」已被取代 —— 有同预设活动 agent 时 `/preview` 会并入其真实装配;`sessionOverlay` 字段仍不产生。`catalog_section` / `catalog_tool` 表(第 2 条)已随 ADR-0001 删除,当前 DB 不存在这两张表。
|
|
4
|
+
|
|
5
|
+
## 修复
|
|
6
|
+
- 预设预览不再读取当前会话的 agent 作用域条目:`/preview` 返回纯预设 `baseSections` / `baseTools` / `baseContexts`,不再产生 `sessionOverlay`。
|
|
7
|
+
- 删除旧 `catalog_section` / `catalog_tool` DDL 与所有旧目录查询,避免旧 SQLite 文件触发 `no such table: catalog_section`。
|
|
8
|
+
- 运行时上下文只返回 `baseContexts`,上下文显隐写回配置时只保留 `{name, source}`,不再混入 `text` / `blocked`。
|
|
9
|
+
- 删除“左栏已并入当前会话”“会话变量尚未绑定”等过期提示。
|
|
10
|
+
- 保留工具阶段名单、提示词屏蔽/替换/注入和三态同步的保存路径。
|
|
11
|
+
|
|
12
|
+
## 验证
|
|
13
|
+
- `npm run build`、`npm test`(141/141)、host/client smoke 全绿。
|
|
14
|
+
- 真实 web 预设矩阵:standard 24段/54工具/7上下文,ptc 25段/53工具/7上下文,minimal 9段/24工具/1上下文,cordis 24段/56工具/7上下文;三阶段一致。
|
|
15
|
+
- 浏览器实测:预设级引导期屏蔽段、工具可见性、上下文显隐保存后刷新仍保持;工作区级 ptc 的 `tools:ptc-only` 出现在 base 列表。
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# 2.0.0 — 移除工作区级提示词/工具层
|
|
2
|
+
|
|
3
|
+
## 破坏式变更
|
|
4
|
+
- 只保留**单预设编辑**:提示词 / 工具定制按 `overrides[presetId]` 保存和生效。
|
|
5
|
+
- 删除工作区级提示词/工具的 UI、查询参数、运行时装配与备份内容。
|
|
6
|
+
- `workspaceOverrides` 字段休眠:保留在 DB 中,不读、不写、不显示、不进备份;恢复备份也不删除既有休眠数据。
|
|
7
|
+
- 单预设编辑器提供导入 / 导出;设置页提供全部预设备份包与手动空 overrides 清理。
|
|
8
|
+
- 工作区概念继续用于 MCP、技能扫描和 cwd,不受影响。
|
|
9
|
+
|
|
10
|
+
## 代码归档
|
|
11
|
+
- 工作区级相关源码保留在原目录,但不再被入口、路由或构建装配接线;恢复时手动接线。
|
|
12
|
+
- 对应的旧测试移到 `test/archive/`,不进入测试门禁。
|
|
13
|
+
|
|
14
|
+
## 验证
|
|
15
|
+
- `npm run build`、`npm test`、host/client smoke 全绿。
|
|
16
|
+
- web 面板无“预设级 / 工作区级”切换与工作区选择器;单预设编辑、导入导出、清理按钮可见。
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# 2.0.1 — 运行时上下文修复
|
|
2
|
+
|
|
3
|
+
- `tool:<name>:depth` 这类工具拥有的运行时上下文:工具不在当前候选目录或当前文本为空时不再显示,消除 `tool:subagent:depth` / `tool:subagent_fork:depth` 的残留项。
|
|
4
|
+
- 运行时上下文显隐改为编辑草稿:勾选只更新“预览含未保存草稿”,点「保存」一次写入;不再点一下立即刷新。
|
|
5
|
+
- `PromptContext` 的 `name/order/text/interpolate/required` 是宿主全部公开字段;插件不伪造 provider 元数据。
|
|
6
|
+
- 三阶段(引导期 / 常驻期 / 压缩受控期)使用同一套宿主 `assemble` 上下文;默认三阶段都返回,只有宿主显式 `suppressRuntimeContext()` 或 persona `includeRuntimeContext:false` 时才抑制可选上下文。
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# 2.0.10 — 导入原子与技能摘要/健康补齐
|
|
2
|
+
|
|
3
|
+
- 新增 `/api/prompt-customizer/config/batch`:导入预设时 `envBlocklist` 与 `presets` 一次写入,第二次校验失败不会留下半套修改。
|
|
4
|
+
- `kernel-skills` 将已获取的真实技能摘要按 `scope + cwd + name` 持久化,重启后禁用 bundled/virtual 技能仍能回填原摘要。
|
|
5
|
+
- `skill-health` 将 kernel 中不在文件系统根内的 bundled/office/plugin 技能计入 healthy。
|
|
6
|
+
- 2.0.9 起的工作区技能状态与保存写队列继续保留。
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# 2.0.11 — 回归修复
|
|
2
|
+
|
|
3
|
+
- `/presets` 只返回全局基底状态,不再把 workspace override 混入 preset 级 `skills`;workspace 状态由 `/workspaces` 单独提供。
|
|
4
|
+
- 技能摘要缓存键改为 `preset + cwd + name`(预设不可得时回落会话 id),跨会话恢复 office/plugin 禁用技能摘要。
|
|
5
|
+
- 完整目录保留同名 agent `locked-agent` 遮蔽行,同时不重复 `masked-plugin` 预设行。
|
|
6
|
+
- `skill-health` 路由捕获异常并返回 500,不再出现 unhandled rejection/悬挂响应;mask stub 不再当作真实 bundle 成员。
|
|
7
|
+
- 刷新时 `/config` 失败不再被 preview 成功覆盖。
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# 2.0.13 — DSH 运行时契约对齐
|
|
2
|
+
|
|
3
|
+
- 工具目录按 `ctx.tools.definitions(scope)` 的注册定义识别来源,`locked-agent` 与 `masked-plugin` 行保留 `keySuffix`,同名遮蔽在 inventory/session 两条路径一致。
|
|
4
|
+
- `latestRootAgent` 改为复用按 `session.header.createdAt` 降序的 `listRootAgents`,不再假设 `agents.roots()[0]` 是最新会话。
|
|
5
|
+
- agent 来源匹配按 `source.kind='agent'` 跨会话匹配,预设配置不再绑定某个 session id。
|
|
6
|
+
- 工具可见性测试按宿主 `restrict` 契约拒绝 agent-local/未知名字;生成式 24 工具用例覆盖任意数量工具。
|
|
7
|
+
|
|
8
|
+
> 2.1.0 沿用:本页第 3 条「agent 来源按 `source.kind` 跨会话匹配」是 [ADR-0005](../adr/0005-universal-prompt-takeover.md) D4(清单身份稳定化)的前提。
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# 2.0.15 — 工具屏蔽池恢复
|
|
2
|
+
|
|
3
|
+
- 修复 `catalogTools` 因 base 同名过滤丢掉 `masked-plugin` / `masked-own` 行,导致工具面板「已遮蔽」池为空的问题。
|
|
4
|
+
- 保留 base 的 `hidden/controllable` 行用于阶段反选,同时保留 masked 行供只读池解释;两者按 `state` / `keySuffix` 区分。
|
|
5
|
+
- 新增回归:预设 base 有 `masked-tool`、agent 视图缺失时,inventory 必须返回 `masked-plugin` 行。
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# 2.0.16 — 回归清理
|
|
2
|
+
|
|
3
|
+
- 屏蔽池逻辑抽成 `src/client/prompt/tool-pool.ts` 的纯函数,新增任意同名 base + masked 状态测试;同名 base 不再吞掉 `masked-plugin` / `masked-own`。
|
|
4
|
+
- `/presets?workspace=` 返回独立的 `workspaceSkills`/`workspaceBundles`,workspace 级视图可显示 workspace 独有技能,不污染 preset 级状态。
|
|
5
|
+
- 技能摘要缓存增加跨 cwd 的宽 key 回退;DSH tool source 用 definition 对象身份识别同名遮蔽。
|
|
6
|
+
- 恢复/重置/导入/清理等配置写入口统一走 `enqueueWrite`;`silentSync` 加序号,旧 workspace 响应不再覆盖新状态。
|