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
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# ADR-0001:移除目录累积池与手动重扫
|
|
2
|
+
|
|
3
|
+
- 状态:已采纳(2026-11-08)
|
|
4
|
+
|
|
5
|
+
## 背景
|
|
6
|
+
早期无法一次性拿到“全部提示词段/工具”,于是用“目录累积池(catalog_*)+ 手动重扫”来凑全量:
|
|
7
|
+
每次装配把见到的段/工具并入池子,重扫时整体替换。池子只增不减,且是**跨预设全局**的。
|
|
8
|
+
|
|
9
|
+
## 问题
|
|
10
|
+
- 全局池会把**别的预设独有**的段/工具串进当前预设(如 `tools:ptc-only` 串到一般预设)。
|
|
11
|
+
- 池子里的历史条目可能早已不存在,需要手动重扫清理。
|
|
12
|
+
- 清单/预览不再等于该预设的真实装配(“有就有”退化为“见过就有”)。
|
|
13
|
+
|
|
14
|
+
## 决策
|
|
15
|
+
- 删除“目录累积池 + 手动重扫”。清单只来自**当前预设真实装配**(动态枚举;2.1.0 起 + 同预设活动 agent,见 ADR-0005),有就有、没有就没有;
|
|
16
|
+
首次运行/插件后注册的段同样通过真实装配枚举得到。
|
|
17
|
+
|
|
18
|
+
> **2.1.0 修订(ADR-0005)**:这里的“当前预设真实装配”已被修订为「当前预设 **+ 同预设活动 agent** 的真实装配」——插件在 `agent/created` 里注册到 agent 作用域的段,只有用该 agent 自己的 scope 再跑一次真实装配才能枚举到。本 ADR 的其余结论(删除累积池 / 手动重扫、预设隔离、动态枚举、不保留跨预设历史条目)全部保留;只是不再用「跨预设历史池」凑齐全量,而是用同预设活动 agent 的真实装配。
|
|
19
|
+
|
|
20
|
+
## 后果
|
|
21
|
+
- 好处:预设天然隔离;清单与模型输入一致;无需手动维护。
|
|
22
|
+
- 代价:不再保留“跨预设历史条目”这种能力(本就是权宜)。
|
|
23
|
+
- 彻底移除:DB 迁移 `DROP TABLE IF EXISTS catalog_section / catalog_tool`;备份/恢复不再含 catalog 字段;
|
|
24
|
+
删除 `catalog.js` 及其测试(单用户,无兼容补丁)。
|
|
25
|
+
|
|
26
|
+
## 备选
|
|
27
|
+
- 给池子加“预设归属”过滤:仍保留全局池复杂度,且运行时归属不可靠 → 弃用。
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# ADR-0002:段/工具的隐藏身份采用“名字 + 来源”
|
|
2
|
+
|
|
3
|
+
- 状态:已采纳(2026-11-08)
|
|
4
|
+
|
|
5
|
+
## 背景
|
|
6
|
+
同名不同源很常见:某插件遮蔽了原生 `apply_patch` 并注册同名工具;提示词段也可能由不同 provider 注册同名项。
|
|
7
|
+
原先按“名字”去重/隐藏,会把不同来源的同名条目当成一个。
|
|
8
|
+
|
|
9
|
+
## 决策
|
|
10
|
+
- 段与工具的隐藏/显隐身份 = **名字 + 来源(source/provider)**。
|
|
11
|
+
- 工具页按来源分列同名工具:**遮蔽池显示原生**条目、**启用列表显示插件自带**条目。
|
|
12
|
+
- 旧配置中只有名字的隐藏名单**不迁移、忽略**(D9)。
|
|
13
|
+
|
|
14
|
+
> **2.1.0 注(ADR-0005)**:本 ADR 的「名字 + 来源」身份与「同名不同源分列」在 2.1.0 首次真正落到**提示词段**(此前只在工具页分列):插件在 agent 作用域用与宿主 global 段同名的 `tool:read` 遮蔽时,清单会分「global / agent」两行,各自独立屏蔽。「来源缺失需降级标注」仍是已知限制。
|
|
15
|
+
|
|
16
|
+
## 后果
|
|
17
|
+
- 好处:同名不同源可分别控制与展示;遮盖关系清晰。
|
|
18
|
+
- 代价:需要来源信息;若某处来源缺失,需降级并标注“来源未知”。
|
|
19
|
+
- 兼容:旧名单忽略,可能使旧定制失效。
|
|
20
|
+
|
|
21
|
+
## 备选
|
|
22
|
+
- 仅按名字:无法区分同名不同源 → 否。
|
|
23
|
+
- 仅按 provider 内部 id:宿主未必稳定暴露 → 用“名字+来源”折中。
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# ADR-0003:允许破坏式更新,不保留前向兼容
|
|
2
|
+
|
|
3
|
+
- 状态:已采纳(2026-11-08)
|
|
4
|
+
|
|
5
|
+
## 背景
|
|
6
|
+
本插件为单用户自用;历史遗留形状(如仅按名字的隐藏名单、目录池 catalog、旧快照结构)
|
|
7
|
+
对“按来源区分同名工具/段、预览=真实装配”等正确性目标形成阻碍。
|
|
8
|
+
|
|
9
|
+
## 决策
|
|
10
|
+
- **不为前向兼容写迁移/兼容补丁**。必要时可直接改变数据形状与语义;升级后可丢弃旧数据。
|
|
11
|
+
- 已按此执行:彻底移除 catalog;后续“名字+来源”身份、预览=真实装配均按最优形状实现,
|
|
12
|
+
不兼容旧配置(旧隐藏名单忽略)。
|
|
13
|
+
|
|
14
|
+
> **2.1.0 注**:继续沿用破坏式、不迁移旧数据的决策;「预览 = 真实装配」的数据源口径由 [ADR-0005](0005-universal-prompt-takeover.md) 修订为「该预设 + 同预设活动 agent 的真实装配」。
|
|
15
|
+
|
|
16
|
+
## 后果
|
|
17
|
+
- 好处:实现更简单、语义更正确;无需维护多套兼容分支。
|
|
18
|
+
- 代价:升级后旧定制可能失效(可接受,单用户)。
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ADR-0004:通用过滤模型(PHASES + name+source)
|
|
2
|
+
|
|
3
|
+
- 状态:已采纳(2026-11-08)
|
|
4
|
+
|
|
5
|
+
## 决策
|
|
6
|
+
1. 三阶段只由 `model.js` 的 `PHASES` 描述表定义;字段名、状态映射、工具字段全部派生,禁止三处手写。
|
|
7
|
+
2. 段/工具/运行时上下文的身份统一为 `{name, source}`;`source` 是注册层(global / preset(id) / agent(session) / executor / workspace),宿主能提供 provider 时再附带。
|
|
8
|
+
3. 配置名单存结构化条目;旧 name-only 名单忽略。
|
|
9
|
+
4. 预设级 = 所选预设逐阶段真实装配 + 同预设活动 agent 的 agent 作用域真实装配(2.1.0 / ADR-0005);工作区级已于 2.0.0 移除。
|
|
10
|
+
|
|
11
|
+
> **2.1.0 修订(ADR-0005)**:决策 4 的「通用会话项」口径已改为「**同预设活动 agent** 的真实装配条目」——只有编辑目标所属预设的活动 agent 的会话级段 / 上下文才并入清单与预览,切到别的预设不混入;工作区级已在 2.0.0 移除。本 ADR 的其余决策(三阶段唯一描述表、`{name, source}` 身份、旧 name-only 名单忽略、`replacements` 阶段化)全部保留。
|
|
12
|
+
5. `replace` 改为阶段化 `replacements`(只替换已存在段)。
|
|
13
|
+
|
|
14
|
+
## 后果
|
|
15
|
+
- 旧配置不兼容,直接丢弃(ADR-0003)。
|
|
16
|
+
- 宿主不暴露段/上下文的 provider;来源只能按 global/预设/agent 装配差异推导为“注册层”。
|
|
17
|
+
- 同名不同源可分行显示与独立操作。
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# ADR-0005:全域系统提示词接管(会话级段纳入可编辑清单)
|
|
2
|
+
|
|
3
|
+
- 状态:已采纳(2026-11-09)
|
|
4
|
+
- 版本:2.1.0
|
|
5
|
+
- 修订:ADR-0001 的「清单只来自当前预设真实装配」口径;`docs/design/prompt-control-consensus.md` 的 D1 / D3 / D4 预览口径
|
|
6
|
+
- 依赖:ADR-0002(名字 + 来源)、ADR-0004(PHASES + `{name, source}` 通用过滤模型)、2.0.13 运行时契约(agent 来源按 kind 跨会话匹配)
|
|
7
|
+
|
|
8
|
+
## 背景
|
|
9
|
+
|
|
10
|
+
### 宿主契约(事实,不是本插件的选择)
|
|
11
|
+
|
|
12
|
+
- `ctx.systemPrompt.section(section)` / `context(context)` 把内容注册在**调用方的 scope**:「Register an ordered prompt section in the calling context's scope. A scoped section shadows a global section with the same name」(`deepseek-harness/docs/subsystems/system-prompt.md`)。
|
|
13
|
+
- `PromptSection` / `PromptContext` 的字段只有 `name`、`order`、`text`(静态串或每次装配求值的 provider)、`interpolate`、`complete` / `required`;**没有 `source` / `provider` / `phase`**。宿主不把「这段是哪个插件注册的」暴露给 waterfall 消费方。
|
|
14
|
+
- `system-prompt/assemble` 瀑布流从 0.2.1-rc.2 起只携带 `sections` / `contexts` / `variables`(`PromptPresentation`),「tool declarations remain provider-owned」;工具 `description` 走 `GenerateOptions.tools`,不是系统提示词 token。
|
|
15
|
+
- `systemPrompt.layers` 是单向作用域链(`global` / `peek(scope)` / `chainLayers(scope)` / `merge(scope, ...)`),**没有「列出所有已注册作用域」的 API**。
|
|
16
|
+
|
|
17
|
+
### 缺陷(2.0.22 现状)
|
|
18
|
+
|
|
19
|
+
工具插件可以在 `agent/created` 里用 `agent.ctx.systemPrompt.section()` 把指引注册到 **agent 自有作用域**。实测 `dsh-hashline-edit@0.2.0` 就在 `dsh/index.ts` 的 `installAgentTools` 里注册了三段动态 `text` provider 的命名段:`tool:read`(1100) / `tool:apply_patch`(1350) / `tool:undo_last_edit`(1360),前两段还遮蔽宿主的全局同名段。
|
|
20
|
+
|
|
21
|
+
2.0.22 的 `/api/prompt-customizer/inventory` 与 `/preview` 走 `buildPreview`,只跑**纯预设 scope** 装配,并且把 live 段写成空数组:
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
mergeAgentScopedSections(baseView.sections ?? [], [], previewDenied, previewReplacements, sectionOrder)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
这是 ADR-0001 删除累积池后为「预设隔离」做的取舍,`test/runtime-catalog.test.mjs`、`test/source-model.test.mjs` 还把它钉成了断言(后者直接用 `tool:undo_last_edit` 当 agent-only 段的例子)。后果:
|
|
28
|
+
|
|
29
|
+
1. 只在该 agent 作用域注册的段(如 `tool:undo_last_edit`)在**可编辑清单里根本不存在**;只读 `/session` 才列得出来,而客户端从不请求它。
|
|
30
|
+
2. 同名段(`tool:read` / `tool:apply_patch`)清单里显示的是宿主 global/preset 的原文,不是插件文本。
|
|
31
|
+
3. 即使勾了屏蔽:UI 写 `{name, source:{kind:'global'|'preset'}}`,运行时该段被 `sourceForEntry` 标成 `{kind:'agent', id:<sessionId>}`;`model.js:entryMatches` 要求 `sourceKey` 相等,只对 `agent ↔ agent` 按 kind 放行 —— **名单命不中,模型照样收到插件的指引**。
|
|
32
|
+
4. 工具 schema 的 `description` 是另一条独立通道,段级隐藏原则上看不见;禁用整工具也不会删掉这三段(两条注册互相独立)。
|
|
33
|
+
|
|
34
|
+
结论:2.0.22 **不能**捕获并隐藏这类插件的提示词。这不是运行时过滤能力缺失——`applySectionPolicy` 对带 agent 来源的段同样按 `{name, source}` 过滤,`forceSections` 包装也会把过滤结果覆盖回最终 `sections`——缺的只是「UI 发现 / 枚举」这一环。
|
|
35
|
+
|
|
36
|
+
## 目标 / 非目标
|
|
37
|
+
|
|
38
|
+
**目标**
|
|
39
|
+
|
|
40
|
+
- 只要贡献者把内容注入系统提示词(global / preset / agent / executor 任意作用域、静态串或动态 provider、首次运行或插件后注册),就要能在**预设编辑面板**里被枚举,并屏蔽 / 替换 / 注入 / 排序。
|
|
41
|
+
- 屏蔽后,真实会话装配里该段确实消失(最终 `system/message` 正文不含它),达到对每一个系统提示词 token 的精确掌控。
|
|
42
|
+
- 泛例:按契约对任意注册项求解,不硬编码段名、不认插件名(延续 ADR-0004 / 2.0.2 / 2.0.9 / 2.0.13 的方向)。
|
|
43
|
+
|
|
44
|
+
**非目标**
|
|
45
|
+
|
|
46
|
+
- 不接管工具 schema 的 `description` / 参数 JSON Schema:它们走 `GenerateOptions.tools`,不是系统提示词 token;本插件仍只做「工具显隐」,不做签名编辑。
|
|
47
|
+
- 不接管不并入系统提示词的 user-role 消息、工具结果、LLM 请求体里另加的文本。
|
|
48
|
+
- 不提供「无活动会话时枚举 agent 作用域段」——宿主没有这个 API,插件必须自己把段注册在预设 / 全局层才能无会话也可控。
|
|
49
|
+
- 不改动工具目录 / `tools.restrict` / 遮蔽池链路(2.0.5–2.0.18 的回归约束),不恢复跨预设累积池。
|
|
50
|
+
|
|
51
|
+
## 决策
|
|
52
|
+
|
|
53
|
+
- **D1 双数据源**:`buildPreview` 在「编辑目标 == 同预设活动 agent」时,额外跑一次该 agent 自己 scope 的真实装配(`collectLivePromptView`)。复用同一份 `hint`(含 `promptCustomizerPatch` 草稿、名义阶段、`promptCustomizerPreset` / `PromptScope`),只覆盖 `scope` / `agent`,保证两份装配走同一份生效配置、同一阶段、同一草稿。一次 `promptCustomizerBase: true` 装配同时给出预过滤清单(`promptCustomizerBaseView`)与过滤后的正文(`sections`)。
|
|
54
|
+
- **D2 清单 = 预设 base ∪ agent base**:经 `mergePromptEntries` 按 `{name, source}` 去重,agent 视图优先;同名不同源**分两行**(ADR-0002),由 `mergeAgentScopedSections` 装饰 `blocked` / `replaced` 并给 agent 来源打 `scope: 'agent'`(客户端「会话级」徽标)。`sectionOrder` 取「预设作用域链 ∪ 同预设 agent 作用域链」,否则 agent 段的规范 order 取不到会被排到清单尾部。
|
|
55
|
+
- **D3 预览正文同源**:有 live 视图时,`sections` / `text` / `contexts` / `emitted` / `takenOverBy` 都取自 agent 真实装配(过滤后),右栏显示的就是模型此刻真正看到的系统提示词;`baseSections` / `baseContexts` 取两份 base 视图的并集。无活动会话时整体退回纯预设装配。
|
|
56
|
+
- **D4 身份稳定化**:运行时 `sourceForEntry` 给 agent 来源带 session id,但配置按预设存、必须跨会话命中。`stableSourceOf` 把**清单与预览里**的 agent 来源统一收敛成 `{ kind: 'agent' }`(不带 id);`entryMatches` 已对 `agent ↔ agent` 按 kind 匹配(2.0.13),所以 UI 写入的名单、草稿 `entryKey`、运行时候选三者身份一致且跨会话稳定。
|
|
57
|
+
- **D5 隔离不破**:只用 `liveAgentForPreset(ctx, 编辑预设 id)`,绝不拿 `latestRootAgent` 顶替;编辑 A 预设不会混入 B 预设会话的会话级段。`latestRootAgent` 仍只用于工具 catalog 与无会话兜底。
|
|
58
|
+
- **D6 工具数据源分离**:`finalTools` / `buildToolUnion` / `catalogTools` 仍按纯预设装配计算;提示词与工具两条链路互不干扰,避免推翻 2.0.x 的工具目录回归约束。
|
|
59
|
+
|
|
60
|
+
> **2.1.2 修订**:D6 的「右栏工具目录按纯预设装配」已被证明是错的——宿主真实会话装配的 `scope` 是 live Agent 自身([2.1.2 升级记录](../upgrades/2.1.2-tool-catalog-scope.md)),预设装配只显示预设层工具(实测 38 vs 真实 50)。右栏 `tools` / `registryTools` / `registryTotal` 已改为 `ctx.tools.schemas(agent)` 与 `/session` 同源;`buildToolUnion` / `tools.restrict` / 阶段过滤 / 遮蔽池结构仍不变,D6 的「不动工具目录回归约束」这部分继续成立。
|
|
61
|
+
- **D7 失败回退**:agent 装配抛错时 `warnOnce` 并退回纯预设装配,绝不因可选视图让 `/inventory` / `/preview` 500。
|
|
62
|
+
- **D8 `/session` 定位**:`/session`(`buildSessionPreview`)与 `buildPreview` 的 live 视图是**两条并列的真实装配入口**——前者回答「模型此刻真正看到什么」(只读),后者是编辑目标预设的清单 / 预览数据源。两者都把 agent 来源稳定化为 `{kind:'agent'}`。
|
|
63
|
+
|
|
64
|
+
## 行为规格
|
|
65
|
+
|
|
66
|
+
| 场景 | 行为 |
|
|
67
|
+
|---|---|
|
|
68
|
+
| 有同预设活动 agent | 清单列出预设段 + 该 agent 作用域段;agent 段带 `source:{kind:'agent'}` 与「会话级」徽标;右栏预览 = 该 agent 真实装配的系统提示词正文 |
|
|
69
|
+
| 同名不同源 | 分两行(宿主 global 行 + 插件 agent 行),各自独立屏蔽 / 替换 / 排序 |
|
|
70
|
+
| 屏蔽一个 agent 段 | 配置写 `overrides[preset].sections = [{name, source:{kind:'agent'}}]` → `applySectionPolicy` 在装配瀑布流里过滤 → `forceSections` 包装覆盖回最终 `sections` → 真实会话 / `/session` 的 `sections` 与 `text` 都不含它 |
|
|
71
|
+
| 切到别的预设 | 不混入其它预设会话的会话级段(纯预设列表) |
|
|
72
|
+
| 无活动会话 / agent 装配失败 | 退回纯预设装配;此时只能控制预设 / 全局层注册的段 |
|
|
73
|
+
| 三阶段 | 三份名单互不继承;`buildPreview` 的名义阶段同时作用于两份装配,草稿 patch 也同时叠加 |
|
|
74
|
+
| 工具 description | 不在段清单里,不单独隐藏;只能整工具显隐(既有能力) |
|
|
75
|
+
| `forceSections: false` + `complete:true` | 宿主整段接管会压制段级定制(既有已知限制,不因本 ADR 改变) |
|
|
76
|
+
|
|
77
|
+
## 影响模块
|
|
78
|
+
|
|
79
|
+
- `vendor/prompt-customizer/index.js`:`stableSourceOf` / `mergePromptEntries` / `collectLivePromptView`(新增);`buildPreview`(D1–D6)、`buildInventory`(清单注释)、`buildSessionPreview`(D8 身份稳定化)、路由与文件头注释。
|
|
80
|
+
- `src/client/`:零逻辑改动——`SectionsPane` 已有「会话级」徽标与 `agentScopedHint`,`phase-ops.ts:phaseRows` 会把 `baseSections` ∩ `sections` 的行渲染成可交互行。
|
|
81
|
+
- `src/client/prompt/locales.ts`:`agentScopedHint` 文案随本 ADR 更新(「预览装配看不到它」不再成立)。
|
|
82
|
+
- 测试:`test/runtime-catalog.test.mjs`、`test/source-model.test.mjs` 反转旧断言并新增「枚举 → 屏蔽 → 真实装配消失」组合用例。
|
|
83
|
+
- 文档:本 ADR、`docs/design/prompt-control-consensus.md`、`docs/guide.md`、`docs/upgrades/README.md` + `2.1.0-*.md`、`README.md`、`GLOSSARY.md`、`docs/testing/feature-matrix.md`。
|
|
84
|
+
|
|
85
|
+
## 已知限制
|
|
86
|
+
|
|
87
|
+
1. **无活动会话**:宿主没有枚举任意作用域的 API,插件在 `agent/created` 注册的段只能等会话存在后才可枚举。这是宿主契约边界,不是可实现而暂未实现的缺口。
|
|
88
|
+
2. **宿主 `layers` 缺席**:`sourceForEntry` 退化为按名字差异近似推导,配置里带 source 而候选 source 为 `undefined` 或不同 kind 时不命中(ADR-0004:14 的既有代价)。
|
|
89
|
+
3. **动态 `text` provider**:清单 / 预览用宿主已求值的文本,不二次调用 provider(避免 `forceSections` 重复执行);替换 / 注入会冻结动态文本(guide 已知限制)。
|
|
90
|
+
4. **contexts 口径**:`PromptContext` 在宿主里是 user-role 快照,本插件按「并入系统提示词的可控部分」处理(设计共识 D7);预览的 contexts 仍按 `previewContextsDenied` 手动过滤。
|
|
91
|
+
5. **工具 description 通道未纳入**:若日后要「保留工具但隐藏说明」,需新接缝改写 `result.tools[].description` 或接管 `systemPrompt.tools(provider)`,并重新评估模型调用契约;本次明确不做。
|
|
92
|
+
|
|
93
|
+
## 验证与反例
|
|
94
|
+
|
|
95
|
+
- **反例(会让本 ADR 的实现判定为失败)**:把 `buildPreview` 里 `liveBase.sections` 换回空数组,或把 `stableSourceOf` 改成返回原始带 id 的 agent source,新增用例必须失败。
|
|
96
|
+
- 必测组合:① 同预设活动 agent 的会话级段出现在 `/inventory.sections` 且 `source.kind === 'agent'` / `scope === 'agent'`;② 同名不同源分两行;③ 对 agent 段写入带 `{kind:'agent'}` 的屏蔽名单后,`/preview.text` 与 `/session.sections` 都不含它,撤销后恢复;④ 换一个不同名字 / 不同插件的 agent 段同样可枚举(证明不是样例特判);⑤ 切到别的预设不串台;⑥ 无活 agent 时退回纯预设且不抛错;⑦ 工具目录的行数 / 状态与变更前一致(证明 D6)。
|
|
97
|
+
|
|
98
|
+
## 与既有 ADR 的关系
|
|
99
|
+
|
|
100
|
+
- **ADR-0001**:删除累积池 / 手动重扫、预设隔离、动态枚举,全部保留;仅把「清单只来自**当前预设**真实装配」修订为「当前预设 **+ 同预设活动 agent** 的真实装配」。代价(不再保留跨预设历史条目)不变。
|
|
101
|
+
- **ADR-0002 / ADR-0004**:身份 `{name, source}`、同名不同源分列、PHASES 唯一表、不按名字硬编码——本次全部沿用,正是靠它们才能泛化。
|
|
102
|
+
- **2.0.13 运行时契约**:agent 来源按 `source.kind` 跨会话匹配,是 D4 能成立的前提。
|
|
103
|
+
|
|
104
|
+
## 备选
|
|
105
|
+
|
|
106
|
+
- 恢复「跨预设累积池 + 手动重扫」来凑齐全量:会把别的预设串进当前预设、池子只增不减、清单不再等于真实装配 → 否(ADR-0001 已否)。
|
|
107
|
+
- 让插件改在全局 / 预设层注册段:需要改所有第三方插件,不属本插件职责 → 否。
|
|
108
|
+
- 把整个 `buildPreview` 的 scope 直接换成 agent:会连带改变 `sourceForTool` 与 `result.tools` 过滤,推翻 2.0.5–2.0.18 的工具目录回归约束 → 否(改选 D6 双数据源分离)。
|
|
109
|
+
- 按固定段名清单(`tool:*`)特判捕获:只对当前样例成立,换插件 / 换段名即失效 → 否(违反 ADR-0004:31 与「修的是类,不是样例」)。
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# 提示词 / 工具 / 上下文 控制模型 — 设计共识
|
|
2
|
+
|
|
3
|
+
> 状态:设计共识(实现前)。日期:2026-11-08。术语见根目录 `GLOSSARY.md`。
|
|
4
|
+
> 兼容性:**允许破坏式更新,不保留前向兼容**(见 ADR-0003)。
|
|
5
|
+
|
|
6
|
+
> **2.1.0 修订(ADR-0005)**:本文件是实现前的设计共识,保留作历史材料。其中 D1「预览 = 该预设(+工作区)实际发给模型的系统提示词」、D3「严格预设隔离:清单与预览只来自该预设真实装配,禁止并集/跨预设混入」、D4「动态枚举」的**预览数据源口径**已由 [ADR-0005](../adr/0005-universal-prompt-takeover.md) 修订为「该预设 + 同预设活动 agent 的真实装配」;「工作区级」已在 2.0.0 移除。其余决策(D2 只渲染 sections、D5 名字+来源、D6 工具页/提示词页职责独立、D7–D10)不变。当前实现以 `vendor/prompt-customizer/index.js` 与 ADR-0005 为准,本文件不再描述现状。
|
|
7
|
+
|
|
8
|
+
## 1. 背景与问题
|
|
9
|
+
|
|
10
|
+
面板现能定制“预设级/工作区级”的提示词段与工具显隐,但存在若干问题:
|
|
11
|
+
|
|
12
|
+
1. **禁用技能卡片信息丢失**:被“全局/预设/工作区”禁用的技能,在面板里显示成桩信息
|
|
13
|
+
(`disabled by dsh-prompt-customizer for preset "..."`、`0 文件`),而不是原有内容。
|
|
14
|
+
2. **提示词预览混入工具格式**:右侧“提示词预览”把工具声明/schema/签名也渲染进去。
|
|
15
|
+
3. **跨预设串台(未彻底)**:一般预设里仍能出现 ptc 专属的**系统提示词段**(列表与正文都有),
|
|
16
|
+
但实际并未注入模型——说明预览/清单不是该预设的“真实装配”。
|
|
17
|
+
4. **同名不同源工具无法区分**:某个插件遮蔽了原生 `apply_patch` 并注册同名工具后,面板把它们
|
|
18
|
+
当成同一个;期望“遮蔽池显示原生、启用列表显示插件自带”。
|
|
19
|
+
5. **重复的权宜设计**:历史上用“目录累积池 + 手动重扫”来凑齐全量,现已可从真实装配动态枚举,
|
|
20
|
+
该设计应删除(已在 1.1.3 移除,本设计确认其为正式方向)。
|
|
21
|
+
|
|
22
|
+
## 2. 目标 / 非目标
|
|
23
|
+
|
|
24
|
+
**目标**
|
|
25
|
+
- 面板对“系统提示词段(含并入系统提示词的 host contexts)”与“工具”的展示与控制,严格反映
|
|
26
|
+
**当前预设(叠加工作区)的真实装配**:有就有、没有就没有,不多不少。
|
|
27
|
+
- 禁用技能卡片与启用时**信息完全一致**,仅状态为“已停用”。
|
|
28
|
+
- 同名不同源的段/工具按“名字+来源”分别展示与控制。
|
|
29
|
+
- 动态枚举:首次运行/插件后注册的段,出现即可控,无需手动重扫。
|
|
30
|
+
|
|
31
|
+
**非目标**
|
|
32
|
+
- 不接管“不并入系统提示词”的真正运行时上下文(会话消息、工具结果等)。
|
|
33
|
+
- 不提供工具签名/schema 的编辑(只能控工具显隐)。
|
|
34
|
+
- 不做“按固定名单匹配段”的实现(不硬编码段名)。
|
|
35
|
+
|
|
36
|
+
## 3. 决策(Decisions)
|
|
37
|
+
|
|
38
|
+
- **D1 真实装配预览**:所有级别的“提示词预览”= 该预设(+工作区)实际发给模型的**系统提示词**,
|
|
39
|
+
只含系统提示词段,不含工具声明/schema/签名。无活动会话时,跑一次该预设的真实装配作为预览。
|
|
40
|
+
- **D2 预览只渲染 sections**:以**段形式**注册的工具指引文本(如 `tool:read` 段)属提示词内容并进预览;工具声明里的 `description` 走 `GenerateOptions.tools`,不是系统提示词 token,不进预览;工具签名/声明不进预览。(2.1.0 消歧,见 ADR-0005)
|
|
41
|
+
- **D3 严格预设隔离**:清单与预览只来自该预设真实装配,禁止并集/跨预设混入(修复 ptc 段串台)。
|
|
42
|
+
- **D4 动态枚举、不按名字匹配**:从真实装配动态枚举所有段(含首次运行注册/插件注册),基于实际结果,
|
|
43
|
+
不依赖固定名单。
|
|
44
|
+
- **D5 身份 = 名字 + 来源**:段与工具的隐藏/显隐以“名字+来源”为标识;同名不同源区分对待。
|
|
45
|
+
- **D6 工具页 vs 提示词页职责独立**:工具页只控“工具是否可用”;提示词页只控“段(含工具描述文本)”
|
|
46
|
+
显隐。禁用工具不自动隐藏其描述段。
|
|
47
|
+
- **D7 运行时上下文(并入系统提示词的部分)可显隐**:允许拦截 host `contexts` 中并入系统提示词的部分;
|
|
48
|
+
真正 user-role 上下文不管。范围与提示词段一致:预设级+工作区级、三阶段独立、受“三态同步”。
|
|
49
|
+
- **D8 技能禁用卡片全量还原**:描述/文件数/路径/正文与启用时一致,仅状态为“已停用”。
|
|
50
|
+
- **D9 旧隐藏名单忽略**:改为“名字+来源”后,旧配置中只有名字的隐藏名单不迁移、忽略。
|
|
51
|
+
- **D10 移除目录池/重扫**:不再累积、不再手动重扫;清单只来自真实装配。并**彻底移除** `catalog_*` 表与
|
|
52
|
+
备份/恢复中的 catalog 字段(无兼容补丁)。
|
|
53
|
+
|
|
54
|
+
## 4. 行为规格
|
|
55
|
+
|
|
56
|
+
### 4.1 技能卡片(SKILL)
|
|
57
|
+
- 启用与禁用卡片除“开关/已停用”外,描述、文件数、路径/来源、可查看正文等**完全一致**。
|
|
58
|
+
- 禁用仅表示“模型侧不可用 + 开关为关”,不影响面板展示的真实元数据。
|
|
59
|
+
|
|
60
|
+
### 4.2 提示词页(段)
|
|
61
|
+
- 左栏:动态枚举当前预设真实装配里的系统提示词段(含并入系统提示词的 contexts),每条带来源标签、
|
|
62
|
+
可勾选显隐;同名不同源分列。
|
|
63
|
+
- 右栏:该预设真实系统提示词正文(仅 sections,不含工具 schema/签名)。
|
|
64
|
+
- 首次运行/插件后注册的段:出现即可控(动态枚举,无需重扫)。
|
|
65
|
+
|
|
66
|
+
### 4.3 工具页
|
|
67
|
+
- 按“名字+来源”列出工具:遮蔽池显示被隐藏/禁用的条目(含被遮蔽的**原生** `apply_patch`),
|
|
68
|
+
启用列表显示当前可见条目(含插件自带的同名 `apply_patch`)。
|
|
69
|
+
- 只控工具可用性;不涉及 schema 编辑。
|
|
70
|
+
|
|
71
|
+
### 4.4 预览
|
|
72
|
+
- 预览 = 真实装配结果(该预设 + 工作区);有活动会话用会话真实结果,无会话跑一次该预设装配。
|
|
73
|
+
- 只渲染系统提示词段;上下文中的 user-role 快照不计入系统提示词正文(但其中并入系统提示词的部分可控)。
|
|
74
|
+
|
|
75
|
+
### 4.5 三态与层级
|
|
76
|
+
- 段、工具、运行时上下文的显隐在 bootstrap/compaction/active 三阶段独立;
|
|
77
|
+
- “三态同步”开启时,三者改动均三阶段一起生效。
|
|
78
|
+
- 预设级 + 工作区级都可控;工作区级覆盖预设级。
|
|
79
|
+
|
|
80
|
+
## 5. 影响模块(预估)
|
|
81
|
+
- `vendor/prompt-customizer/index.js`:装配过滤(sections/contexts/tools)、inventory、preview 数据源改为真实装配;
|
|
82
|
+
移除剩余目录池耦合;引入“名字+来源”身份。
|
|
83
|
+
- `src/kernel-skills.ts`:禁用技能的真实元数据还原(不被闸门桩替换)。
|
|
84
|
+
- `src/skill-toggles.ts`:闸门桩与真实元数据的关系(面板展示用真实源)。
|
|
85
|
+
- `src/client/prompt/*`(Panel / PreviewPane / PresetsPane / types):段/工具/上下文清单与预览渲染、三态同步。
|
|
86
|
+
- `src/client/skills/*`(SkillsView / 卡片):禁用技能卡片渲染真实元数据。
|
|
87
|
+
|
|
88
|
+
## 6. 待实现时核实的技术问题(事实,不属用户决策)
|
|
89
|
+
- host `system-prompt/assemble` 返回的 `sections` / `contexts` 是否携带 `source/provider/scope`,
|
|
90
|
+
以及“并入系统提示词”的 contexts 的可识别方式。
|
|
91
|
+
- 工具注册表是否暴露 provider/source,用于“名字+来源”区分同名工具。
|
|
92
|
+
- 闸门 provider 桩条目如何在不影响模型可用性的前提下,为面板提供“真实技能元数据”。
|
|
93
|
+
|
|
94
|
+
## 7. 测试计划
|
|
95
|
+
- 单测:预设隔离(ptc 段不出现在一般预设清单/正文);预览只含 sections(无工具 schema/签名);
|
|
96
|
+
同名不同源工具分别列出;禁用技能卡片还原真实元数据;上下文显隐与三态同步。
|
|
97
|
+
- 实机:切换 standard/ptc/minimal,核对预览=真实系统提示词;禁用技能卡片信息;同名工具遮蔽展示。
|
|
98
|
+
|
|
99
|
+
## 8. 分阶段落地
|
|
100
|
+
1. 预览/清单真实化 + 严格预设隔离 + 预览只 sections(修 ptc 串台、混入工具格式)。
|
|
101
|
+
2. 技能禁用卡片全量还原。
|
|
102
|
+
3. 身份“名字+来源”(工具先做,段同名后补)+ 同名工具分源展示。
|
|
103
|
+
4. 运行时上下文(并入系统提示词部分)显隐 + 三态同步涵盖。
|