dsh-paoding 0.2.2 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +27 -32
  2. package/README_en.md +27 -32
  3. package/bin/dsh-paoding.mjs +73 -11
  4. package/docs/architecture.md +41 -34
  5. package/docs/architecture_en.md +65 -42
  6. package/docs/configuration.md +159 -65
  7. package/docs/configuration_en.md +161 -66
  8. package/docs/images/1.png +0 -0
  9. package/docs/installation.md +100 -237
  10. package/docs/installation_en.md +112 -252
  11. package/docs/orchestration.md +34 -38
  12. package/docs/orchestration_en.md +34 -38
  13. package/package.json +8 -5
  14. package/plugins/paoding-config-ui/api-core.mjs +215 -18
  15. package/plugins/paoding-config-ui/index.mjs +414 -154
  16. package/plugins/paoding-config-ui/lib/base.css +1083 -42
  17. package/plugins/paoding-config-ui/lib/client.js +2266 -252
  18. package/plugins/paoding-config-ui/package.json +2 -2
  19. package/plugins/paoding-config-ui/runtime-inventory.mjs +27 -26
  20. package/presets/orchestrator/agent.cordis.yml +19 -9
  21. package/presets/orchestrator/preset.yml +3 -2
  22. package/presets/orchestrator/restrict.mjs +2 -1
  23. package/tools/install.mjs +9 -4
  24. package/tools/lib/alloc.mjs +60 -29
  25. package/tools/lib/cli.mjs +127 -278
  26. package/tools/lib/compose.mjs +261 -95
  27. package/tools/lib/config.mjs +266 -86
  28. package/tools/lib/host.mjs +55 -24
  29. package/tools/lib/skills.mjs +72 -45
  30. package/tools/lib/state.mjs +172 -40
  31. package/tools/lib/upgrade.mjs +170 -0
  32. package/tools/lib/util.mjs +7 -0
  33. package/tools/lib/version.mjs +233 -0
  34. package/tools/lib/workspaces.mjs +74 -0
  35. package/tools/lib/yaml.mjs +92 -15
  36. package/docs/images/2.png +0 -0
  37. package/docs/images/3.png +0 -0
  38. package/docs/images/4.png +0 -0
  39. package/docs/images/5.png +0 -0
  40. package/docs/images/6.png +0 -0
  41. package/install.sh +0 -31
  42. package/tools/lib/wizard.mjs +0 -516
@@ -4,44 +4,45 @@
4
4
 
5
5
  # 配置
6
6
 
7
- dsh-paoding 把「按角色分工的编排 preset」做成**配置驱动**:你手编(或让交互向导 / Web 配置 UI 帮你写)一个 YAML 配置文件,安装器(`tools/install.mjs`,CLI 与配置 UI 共用同一生成管线 `collectState` / `generateAndInstall`)在安装时据此重写目标 preset —— `~/.dsh/.agent-presets/orchestrator/agent.cordis.yml`,覆盖角色 allow、角色 persona、主 agent 白名单(`config.allow` 注入)、主 agent persona 的技能行/内联与人设追加。
7
+ dsh-paoding 把「按角色分工的编排 preset」做成**配置驱动**:你手编(或在「庖丁配置」面板里点选)一个 YAML 配置文件,生成器(`tools/`,面板「保存并应用」与仓库内兜底 CLI 共用同一生成管线 `collectState` / `generateAndInstall`)在应用时据此重写目标 preset —— `~/.dsh/.agent-presets/orchestrator/agent.cordis.yml`,覆盖角色 allow、角色 persona、主 agent 白名单(`config.allow` 注入)、主 agent persona 的技能行/内联与人设追加。
8
8
 
9
- 配置文件描述的是**声明式意图**。目标文件每次都由「源码 preset + 本配置文件」重新生成:改配置 → 重跑安装 = 幂等同步,不会累积手工补丁。
9
+ 配置文件描述的是**声明式意图**。目标文件每次都由「源码 preset + 本配置文件」重新生成:改配置 → 在面板点「保存并应用」= 幂等同步,不会累积手工补丁。
10
10
 
11
11
  ## 1. 配置文件
12
12
 
13
13
  ### 1.1 位置与优先级
14
14
 
15
- 配置文件默认位置是 `$DSH_HOME/dsh-paoding.config.yml`;`$DSH_HOME` 未设置时默认为 `~/.dsh`。CLI 参数 `--config <file>` 可指定任意其它路径。
15
+ 配置文件默认位置是 `$DSH_HOME/dsh-paoding.config.yml`;`$DSH_HOME` 未设置时默认为 `~/.dsh`。环境变量 `DSH_PAODING_CONFIG` 可给面板改路径;仓库内兜底 CLI 的 `--config <file>` 参数也可指定任意其它路径。
16
+
17
+ 改完配置怎么应用(下文「重新应用」均指第一行):
16
18
 
17
19
  | 场景 | 行为 |
18
20
  |---|---|
19
- | 交互向导(`./install.sh`) | 检测并分配后,确认时把选择**持久化**到配置文件(默认 `~/.dsh/dsh-paoding.config.yml`,以 `0o600` 权限写入);向导重启时会以既有配置作为种子值 |
20
- | `./install.sh --auto` | 非交互应用:有配置文件则应用,没有则用智能默认(≈ 静态 preset 现状,零回归);改配置后重跑即幂等应用 |
21
- | `./install.sh --dry-run` | 只打印检测报告与将生成的 allow / persona 变化,不写任何文件(含配置文件);适合先预览再动手 |
22
- | `./install.sh --auto --config <file>` | 用指定文件替代默认位置 |
23
- | Web 配置 UI(设置 → 庖丁配置) | 面板「保存并应用」写入 preset 并把分配保存到配置文件,等价于 `--auto` + 向导保存 |
21
+ | Web 面板(左侧栏「庖丁配置」入口) | **主路径**:打开面板会把既有配置加载为当前值,点「保存并应用」写入 preset 并把分配保存到配置文件(默认 `~/.dsh/dsh-paoding.config.yml`,以 `0o600` 权限写入)。手编过配置文件的话,先开面板再应用即可 |
22
+ | 首装自动化 | 插件启动时发现 preset 缺失或版本标记不符,自动按配置文件应用一次(无配置则写基础模板)——日常无需手动触发 |
23
+ | 兜底 CLI(仅限克隆仓库的开发者) | `node tools/install.mjs --auto`:有配置文件则幂等应用,没有则写基础模板;`--dry-run` 只打印检测报告与将生成的 allow / persona 变化,不写任何文件(含配置文件),适合先预览再动手;`--config <file>` 用指定文件替代默认位置 |
24
24
 
25
- 配置文件**存在但解析失败**是硬错误(直接报错退出);**不存在**则视为无配置(走智能默认或向导)。`profile`、`roles` 等顶层键的语义见下节。
25
+ 配置文件**存在但解析失败**是硬错误(直接报错退出);**不存在**则视为无配置(写基础模板)。`profile`、`roles` 等顶层键的语义见下节。
26
26
 
27
- CLI 参数优先级:`--profile` 显式给出时覆盖配置文件里的 `profile` 键,否则以配置文件为准,再否则默认 `web`。
27
+ 兜底 CLI 的参数优先级:`--profile` 显式给出时覆盖配置文件里的 `profile` 键,否则以配置文件为准,再否则默认 `web`。
28
28
 
29
29
  ### 1.2 顶层键
30
30
 
31
- 以下键名与 `tools/install.mjs` 的 `normalizeConfig` 一致(配置文件 schema 的唯一权威来源)。
31
+ 以下键名与 `tools/lib/config.mjs` 的 `normalizeConfig` 一致(配置文件 schema 的唯一权威来源;`tools/install.mjs` 仅转出口)。
32
32
 
33
33
  | 顶层键 | 类型 | 语义 |
34
34
  |---|---|---|
35
35
  | `profile` | string | 检测时纳入哪个 profile 的 patch 层(`$DSH_HOME/profiles/<profile>/cordis.patch.yml`);缺省 `web` |
36
- | `roles` | map | `toolName` → `{ persona?, name?, tools[], model?, provider? }`。对内置三角色(`search_external` / `design` / `implement`):覆盖 persona 与 allow 意图,并可配 `name` 显示名(只替换该角色默认 persona 首行身份句的主语,见 2.4)与专用模型(`model` / `provider`,见 2.5);其它键名 = **自定义角色**:生成全新 `delegation-<toolName>` 块并把 toolName 注入主 agent 的 `config.allow`(详见第 2、6 节) |
36
+ | `roles` | map | `toolName` → `{ persona?, name?, tools[], model?, provider?, background_mode? }`。对内置三角色(`search_external` / `design` / `implement`):覆盖 persona 与 allow 意图,并可配 `name` 显示名(只替换该角色默认 persona 首行身份句的主语,见 2.4)、专用模型(`model` / `provider`,见 2.5)与会话模式(`background_mode`,见 2.6);其它键名 = **自定义角色**:生成全新 `delegation-<toolName>` 块并把 toolName 注入主 agent 的 `config.allow`(详见第 2、6 节) |
37
37
  | `roles_remove` | string[] | 整条删除的内置角色 toolName 列表(只认 `search_external` / `design` / `implement`,其它名字忽略并告警;缺省 = `[]`)。删除 = 委派行 / 工具面 / 角色 persona / 主 agent 侧委派指引全部不再生成(详见 2.3) |
38
38
  | `skills` | map | `skill` → 分配给该技能的角色 toolName 列表;安装时把 `Available skills: …` 引导句写进这些角色 persona 的尾部(详见第 7 节) |
39
- | `main_agent_extra` | string[] | 追加到主 agent 白名单的工具(host 工具,如 `mcp__codegraph__codegraph_explore`、`memory_search`、`mnemon_*`);与检测库存求交,未检测到则不注入 |
39
+ | `main_agent_extra` | string[] | 追加到主 agent 白名单的工具(host 工具,如 `mcp__codegraph__codegraph_explore`、`memory_search`、`mnemon_*`);按「preset 自带工具面 ∪ 检测库存」对账,两头都不占的名字不注入 |
40
40
  | `main_agent_remove` | string[] | 从主 agent 白名单裁掉的基础工具(如 goal 工具族、`exit_plan_mode`);不在当前 allow 的名字警告并跳过;移除结果为空列表直接报错 |
41
41
  | `main_agent_skills` | string[] | 主 agent 技能软引导(默认通道):每技能在 persona 末尾写一行紧凑技能行 + `Read full rules:` 路径 |
42
42
  | `main_agent_skills_inline` | string[] | 主 agent 技能硬内联(可选):选中技能 SKILL.md 全文内联进 persona,每轮固定生效 |
43
43
  | `main_agent_persona_extra` | string \| null | 主 agent persona 尾部追加文本。`null` / 缺省 = 用默认常量;`''` = 不追加任何内容;其它字符串 = 覆盖默认 |
44
- | `main_agent_name` | string \| null | 主 agent 名称(一改两处:部署 preset 显示名与 persona 身份行 `You are the <name> agent powered by the {{model}} model.`)。trim 后 1–60 字符、不可含换行;空 / 缺省 = 保持默认(详见第 5 节) |
44
+ | `main_agent_display_name` | string \| null | 主 agent 显示名,**只改部署 preset 显示名**(GUI 预设选择器里那个名字),不动 persona 身份行。约束:trim 后 1–60 字符、不可含换行;空 / 缺省 = 默认「编排模式 (Orchestrator)」(工作区预设用派生名,详见 5.1) |
45
+ | `workspaces` | map | 工作区目录绝对路径 → 该工作区的专属配置条目,字段与顶层同构(`profile` 除外);每个条目单独生成一份预设 `orchestrator-<slug>`,与全局预设互不影响(详见第 9 节) |
45
46
 
46
47
  `roles` 语义细节:
47
48
 
@@ -50,18 +51,18 @@ CLI 参数优先级:`--profile` 显式给出时覆盖配置文件里的 `profi
50
51
  - `roles.<toolName>.name`:仅对内置三角色生效的可选 `string | null` 显示名(缺省 `null` = 用该角色内置默认身份)。只替换该角色**默认** persona 首行身份句的主语——design 默认 `You are the design agent.`,配 `name: UI 设计` 后为 `You are the UI 设计 agent.`,句子其余文字不动;约束、边界与示例见 2.4。
51
52
  - `roles.<toolName>.model`:该角色的专用模型 id(可选 `string`)。配置后,该角色派出的每个子 agent 都固定用这个模型,不再随主 agent 会话当前模型走;缺省 = 不注入 `agentOptions`,子 agent 继承主 agent 的模型(详见 2.5)。
52
53
  - `roles.<toolName>.provider`:该角色模型所在的 provider 路由(可选 `string`)。须与 `model` 成对配置才生效,只配 `provider` 会被安装器告警并忽略;只配 `model` 时沿用主 agent 的 provider 路由(详见 2.5)。
54
+ - `roles.<toolName>.background_mode`:该角色的会话模式(可选 `'one-shot' | 'continuable'`,缺省 `one-shot`)——一次性用完即弃,或可续:子会话跨轮保留,主 agent 用 `send_message` 就地续修。内置角色与自定义角色同语义;continuable 的前置、代价与面板路径见 2.6。
53
55
  - `roles` 下键名不在三角色内 = 自定义角色(见第 6 节);请勿把静态角色 `search_internal_deep` 写进 `roles`(见 2.2)。
54
56
  - 内置角色可**整体删除**:`roles_remove` 键只认三角色名,删除效果、与 `roles` 键的一致性及恢复路径见 2.3。
55
57
 
56
- `main_agent_extra` 缺省 / 为空时回落到「按本次检测的智能默认」(检测到的 codegraph、`memory_search` 等归主 agent)——这也是不写任何配置时主 agent 仍能直接调 codegraph 工具的原因。
58
+ `main_agent_extra` **键缺失**(老配置 / 未写过该键)时回落到「按本次检测的智能默认」(检测到的 codegraph、`memory_search` 等归主 agent);**显式 `main_agent_extra: []` 表示明确不要 host 工具,不再回落**——fresh 首装落盘的基础模板即显式 `main_agent_extra: []` 形态,默认不含任何 host 工具(codegraph 等需在配置或面板里显式开启才可用)。
57
59
 
58
60
  ### 1.3 完整最小示例
59
61
 
60
- 一个覆盖全部常用键的配置文件(键序与安装器写出的 `serializeConfig` 一致):
62
+ 一个覆盖全部常用键的配置文件(键序与面板写出的 `serializeConfig` 一致):
61
63
 
62
64
  ```yaml
63
- # dsh-paoding(庖丁)安装配置 —— 可手编;改后重跑 ./install.sh --auto 应用。
64
- # 交互向导 / 配置 UI 也会写本文件(0o600)。
65
+ # dsh-paoding(庖丁)安装配置 —— 可手编;改后在侧栏底部「庖丁配置」入口应用,或重跑 node tools/install.mjs --auto
65
66
 
66
67
  profile: web # 检测时扫描 profiles/<profile>/cordis.patch.yml
67
68
 
@@ -83,7 +84,7 @@ roles: # toolName -> { persona?, tools[] }
83
84
  design: # 只改 persona、tools 留空 = 保留静态 allow
84
85
  persona: |-
85
86
  You are the design agent. Produce UI/UX designs and specs; never implement final code.
86
- code-reviewer: # 自定义角色(toolName 匹配 /^[a-z][a-z0-9_]*$/)
87
+ code-reviewer: # 自定义角色(toolName 匹配 /^[a-z][a-z0-9_-]{1,31}$/)
87
88
  persona: |-
88
89
  You are the code-reviewer agent. Review diffs and files for bugs, security
89
90
  issues and style regressions; report a prioritized list with file:line.
@@ -105,7 +106,7 @@ main_agent_remove: # 裁基础工具(实测四项约省 ≈0.8k tokens/
105
106
  - exit_plan_mode
106
107
  main_agent_skills: # 软引导:persona 技能行 + 主 agent 用 read 按需加载
107
108
  - caveman
108
- main_agent_skills_inline: [] # 硬内联(空 = 不用);与 skills 同列时只内联不写软行
109
+ main_agent_skills_inline: [] # 硬内联(空 = 不用);与 `main_agent_skills` 同列时只内联不写软行
109
110
  main_agent_persona_extra: |- # null/缺省 = 默认 codegraph 规则;'' = 不追加;其他 = 覆盖
110
111
  Never call codegraph_* tools without passing projectPath = {{cwd}}.
111
112
 
@@ -116,7 +117,7 @@ skills: # skill -> 分配给的角色(写进角色 persona 的
116
117
 
117
118
  对上例的几点说明:
118
119
 
119
- - `roles.search_external` 的 tools 是**意图**:若 tavily 未启用,安装器会把 5 个 `mcp__tavily__*` 剔除,保留其余(`--dry-run` 的 removed 列表会给出原因)。
120
+ - `roles.search_external` 的 tools 是**意图**:若 tavily 未启用,生成器会把 5 个 `mcp__tavily__*` 剔除,保留其余(「预览生成」的 removed 列表会给出原因)。
120
121
  - `roles.design` 未写 `tools` → 保留静态 allow,只换 persona。
121
122
  - `roles.code-reviewer` 安装后生成 `delegation-code-reviewer` 委派块,主 agent 白名单加入 `code-reviewer`,对话里直接调该 toolName 即可委派。
122
123
  - `main_agent_persona_extra` 里的 `{{cwd}}` / `{{model}}` 是 DSH 运行时替换的占位符,必须原样保留。
@@ -143,6 +144,7 @@ roles:
143
144
  operation: report the failure compactly so the orchestrator can re-delegate.
144
145
  tools:
145
146
  - read
147
+ - read_image
146
148
  - write
147
149
  - edit
148
150
  - glob
@@ -168,11 +170,11 @@ roles:
168
170
 
169
171
  - **不要**把 `search_internal_deep` 写进配置文件 `roles` 键 —— 非三角色键名会被当作**自定义角色**处理,安装器会再生成一个重复的 `delegation-search-internal-deep` 块,与静态块冲突。
170
172
  - 同理它也**不在** `roles_remove` 可删名单内(该键只认三角色名,见 2.3)——它刻意保留为静态角色,不在任何配置键 / UI 里,本键也删不掉它。
171
- - 想调整它的 persona / 工具面:直接编辑 `presets/orchestrator/agent.cordis.yml` 里对应 `delegation-search-internal-deep` 块的 `persona` 与 `toolFilter.allow`,然后重跑 `./install.sh --auto`。安装器只重写三角色与主 agent persona 的有限区间,静态源里其余内容(包括你这个改动)原样保留到生成文件。
173
+ - 想调整它的 persona / 工具面:直接编辑 `presets/orchestrator/agent.cordis.yml` 里对应 `delegation-search-internal-deep` 块的 `persona` 与 `toolFilter.allow`,然后在「庖丁配置」点「保存并应用」重新生成(开发者也可用兜底 CLI `node tools/install.mjs --auto`)。生成器只重写三角色与主 agent persona 的有限区间,静态源里其余内容(包括你这个改动)原样保留到生成文件。
172
174
 
173
175
  ### 2.3 删除内置角色:roles_remove
174
176
 
175
- 顶层可选键 `roles_remove`(string[],缺省 = `[]`)把内置委派角色从部署中**整条删除**,值为被删角色的 toolName。可删范围只有 `search_external` / `design` / `implement`——正好是 `roles` 键能覆盖的三个默认角色(配置 UI 里带「内置」徽标的三张卡)。范围之外的名字会被**忽略并告警**;`search_internal_deep` 删不掉(静态角色,见 2.2)。
177
+ 顶层可选键 `roles_remove`(string[],缺省 = `[]`)把内置委派角色从部署中**整条删除**,值为被删角色的 toolName。可删范围只有 `search_external` / `design` / `implement`——正好是 `roles` 键能覆盖的三个默认角色(面板里带「内置」徽标的三张卡)。范围之外的名字会被**忽略并告警**;`search_internal_deep` 删不掉(静态角色,见 2.2)。
176
178
 
177
179
  删除即整条移除,被删角色在生成结果里整体不再出现:
178
180
 
@@ -189,12 +191,12 @@ roles_remove:
189
191
  - design # 不再生成 delegation-design 块;主 agent persona 里的 design 委派指引一并移除
190
192
  ```
191
193
 
192
- 与 `roles` 键的关系:`roles` 里仍保留**未被删**的内置角色条目(想覆盖其 persona / tools 照旧写)。「删除」的完整状态 = `roles_remove` 含该名 **且** `roles` 无该 key —— UI / CLI 会保证这一致性,手编配置请自行保持一致;两者冲突时,生成以 `roles_remove` 为准。
194
+ 与 `roles` 键的关系:`roles` 里仍保留**未被删**的内置角色条目(想覆盖其 persona / tools 照旧写)。「删除」的完整状态 = `roles_remove` 含该名 **且** `roles` 无该 key —— 面板(与兜底 CLI)会保证这一致性,手编配置请自行保持一致;两者冲突时,生成以 `roles_remove` 为准。
193
195
 
194
196
  恢复:
195
197
 
196
- - **手编**:把名字从 `roles_remove` 移除(想恢复自定义 persona / tools,同时在 `roles` 键写回该项),重跑 `./install.sh --auto`——角色按 SRC 默认 persona 与工具面重新生成。
197
- - **配置 UI**:角色列表末尾「已删除的内置角色」区一键恢复(恢复为 SRC 默认工具面)。
198
+ - **手编**:把名字从 `roles_remove` 移除(想恢复自定义 persona / tools,同时在 `roles` 键写回该项),在「庖丁配置」点「保存并应用」——角色按 SRC 默认 persona 与工具面重新生成。
199
+ - **面板**:角色列表末尾「已删除的内置角色」区一键恢复(恢复为 SRC 默认工具面)。
198
200
 
199
201
  ### 2.4 内置角色显示名:roles.\<toolName>.name
200
202
 
@@ -217,10 +219,10 @@ roles:
217
219
  - **被删除的角色不涉及**:`roles_remove` 整条删除的角色没有 persona 可改(见 2.3)。
218
220
  - **静态角色不在列**:`search_internal_deep` 不在安装器管理的三角色内,无此子键(见 2.2)。
219
221
 
220
- 生效方式与主 agent 改名同构(见 5.1):
222
+ 生效方式与主 agent 显示名同款(见 5.1):
221
223
 
222
- - **手编**:写子键后重跑 `./install.sh --auto`,再重启 DSH / 新会话生效。
223
- - **配置 UI**:设置 → 庖丁配置 → 内置角色卡(徽标「内置」)顶部「角色显示名」输入框,空 = 默认;点「保存并应用」后**重启 GUI / 新会话**生效。
224
+ - **手编**:写子键后在「庖丁配置」点「保存并应用」,再重启 DSH / 新会话生效。
225
+ - **面板**:左侧栏「庖丁配置」→ 内置角色卡(徽标「内置」)顶部「角色显示名」输入框,空 = 默认;点「保存并应用」后**重启 GUI / 新会话**生效。
224
226
 
225
227
  ### 2.5 角色专用模型:roles.\<toolName>.model / .provider
226
228
 
@@ -244,19 +246,46 @@ roles:
244
246
  - **被删除的角色不涉及**:`roles_remove` 整条删除的角色,条目里残留的 `model` / `provider` 被忽略并告警(见 2.3)。
245
247
  - **静态角色不在列**:`search_internal_deep` 无这两个子键(见 2.2)。
246
248
 
247
- 配置 UI(设置 → 庖丁配置 → 角色卡「专用模型」)中这一项是下拉选择,选项直接来自 DSH 已注册的模型路由;目录外的值(如手编配置)会以「当前配置」选项保真显示,不会被静默丢弃。
249
+ 配置页(左侧栏「庖丁配置」→ 角色卡「专用模型」)中这一项是下拉选择,选项直接来自 DSH 已注册的模型路由;目录外的值(如手编配置)会以「当前配置」选项保真显示,不会被静默丢弃。
248
250
 
249
- 生效方式与其他配置键相同:改完重新应用(`./install.sh --auto`,或配置 UI「保存并应用」),再重启 DSH / 新会话。
251
+ 生效方式与其他配置键相同:改完在「庖丁配置」点「保存并应用」,再重启 DSH / 新会话。
250
252
 
251
253
  这两个子键是 8.1 静态源 `agentOptions` 写法的配置层等价物(免改源码,推荐优先);需要连 `maxTokens` 一起控制时才落静态源(见 8.1)。
252
254
 
255
+ ### 2.6 角色会话模式:roles.\<toolName>.background_mode
256
+
257
+ 角色条目的可选子键 `background_mode`,决定该角色派出的子 agent 会话怎么收场:`'one-shot'`(一次性,用完即弃)或 `'continuable'`(可续,子会话跨轮保留)。缺省 `one-shot`;内置角色与自定义角色条目同语义,没有角色差异。
258
+
259
+ ```yaml
260
+ roles:
261
+ implement:
262
+ background_mode: continuable # 该角色的委派转后台、跨轮保留;主 agent 用 send_message 就地续修
263
+ ```
264
+
265
+ 生成语义:基础模板在四个内置角色的委派块里各预置一行 `backgroundMode: one-shot`(纯为可见性——打开生成文件不用猜默认值);配成 `continuable` 的角色,生成器把该行**原位改写**为 `backgroundMode: continuable`(块内无此行时才兜底注入,不会出现两行),`one-shot` / 缺省原样保留。自定义角色块同样恒写此行。两种模式的编排取舍、失败恢复分支见[编排](orchestration.md)「one-shot 与多轮迭代」。
266
+
267
+ continuable 的前置与代价(如实说明):
268
+
269
+ - **前置:host 层挂 `sessionPersistence` 后端。** 在 `~/.dsh/cordis.patch.yml` 挂 `@deepseek-ai/dsh-session-persistence-jsonl`(`config.root` 必填)。未挂载时 continuable 创建/续跑直接报错(错误码 `PERSISTENCE_UNAVAILABLE`)。这是机器级全局改动,卸载 preset 不撤销。
270
+ - **代价:无 TTL 落盘累积、每轮携带累积上下文。** 持久化会话没有 TTL,会持续写盘;continuable 子 agent 每轮带着自己攒下的上下文,长期挂只增不减。只给多轮打磨类委派用,用完 `interrupt_agent` 停掉、顺手清理落盘。
271
+
272
+ 面板操作路径:左侧栏「庖丁配置」→ 角色卡「会话模式」单选(「一次性(one-shot)」/「可续(continuable)」)。未探测到 `sessionPersistence` 时面板会就地警告但不拦截——警告只是提醒先把 persistence 后端挂上,保存照常可执行。
273
+
274
+ 边界:
275
+
276
+ - **静态角色不在列**:`search_internal_deep` 不经 `roles` 键(见 2.2)。它的委派块在基础模板里同样显式标了 `backgroundMode: one-shot`;要把它改成可续,直接改静态源那一行再「保存并应用」重新生成(生成器不重写该行,原样保留)。
277
+ - **被删除的角色不涉及**:`roles_remove` 整条删除的角色,条目里残留的 `background_mode` 被忽略并告警(见 2.3)。
278
+ - **主 persona 已有对应分支**:可续角色失败或产出不满时,主 agent 的委派失败 SOP 先 `send_message` 同会话续修,重委派退为续修无效后的退路(见[编排](orchestration.md))。
279
+
280
+ 生效方式与其他配置键相同:改完在「庖丁配置」点「保存并应用」,再重启 DSH / 新会话。
281
+
253
282
  ## 3. 主 agent 工具面
254
283
 
255
284
  ### 3.1 机制与 21 项白名单基线
256
285
 
257
286
  主 agent 的工具面由 `presets/orchestrator/restrict.mjs`(`orchestrator-restrict`)在 `system-prompt/assemble` 瀑布上按白名单过滤。过滤是**失败自动放行全量**的(过滤器自身出错不会锁死会话);名字按已解析的工具逐个匹配,**未挂载的名字只是缺席、永远不是错误**。
258
287
 
259
- `restrict.mjs` 里的常量 `MAIN_AGENT_ALLOW` 是生成 `config.allow` 的 **base**(21 项):`config.allow` 未注入时运行时直接回落该常量。要改主 agent 工具面,**不要改 `restrict.mjs` 源码**——一律用配置文件(`main_agent_extra` / `main_agent_remove`),或交互向导里的移除/恢复步骤。
288
+ `restrict.mjs` 里的常量 `MAIN_AGENT_ALLOW` 是生成 `config.allow` 的 **base**(21 项):`config.allow` 未注入时运行时直接回落该常量。要改主 agent 工具面,**不要改 `restrict.mjs` 源码**——一律用配置文件(`main_agent_extra` / `main_agent_remove`),或在面板「主 agent」卡片里勾选/取消。
260
289
 
261
290
  | 分组 | 工具(21 项) |
262
291
  |---|---|
@@ -280,9 +309,9 @@ main_agent_extra:
280
309
 
281
310
  要点:
282
311
 
283
- - 追加项会进入生成的 `orchestrator-restrict config.allow`。`mcp__*` 与插件工具属 **host 依赖**:安装器只把**实际检测到**的注入 allow;没检测到(MCP 未启用、拼写错误)就静默不注入、不报错。
284
- - 向导 / 配置 UI 的「主 agent」卡片里可勾选的具体 host 工具,以检测面板(工具池)为准。
285
- - `main_agent_extra` 缺省/为空时,安装器回落到智能默认(检测到的 codegraph、`memory_search` 建议归主 agent)。
312
+ - 追加项会进入生成的 `orchestrator-restrict config.allow`。注入同样走白名单对账:名字必须落在 **preset 自带工具面**(`restrict.mjs` 主 agent 白名单 ∪ 源 preset 各角色静态 allow)或**检测库存**里,host 工具(`mcp__*`、`mnemon_*` 等插件工具)以实际检测结果为准——没检测到(MCP/插件未启用、拼写错误)就不注入、不报错。注意「预览生成」的 removed 列表只覆盖**角色 allow** 的对账结果;`main_agent_extra` 被丢弃的名字只在兜底 CLI 输出里汇总数量、不列明细,需要明细可直接看预览的主 agent allow 终值。
313
+ - 面板的「主 agent」卡片里可勾选的具体 MCP / 插件工具,以检测结果(工具池)为准。
314
+ - `main_agent_extra` **键缺失**时,生成器回落到智能默认(检测到的 codegraph、`memory_search` 建议归主 agent);显式 `main_agent_extra: []` = 明确不要 host 工具、不再回落(fresh 首装落盘的基础模板即此形态)。
286
315
 
287
316
  ### 3.3 移除基础工具:main_agent_remove
288
317
 
@@ -362,28 +391,35 @@ main_agent_skills_inline:
362
391
  | 找不到对应 SKILL.md | **警告并跳过**(不中断安装);对两条键各警告一次、去重 |
363
392
  | SKILL.md 存在但正文为空 | 视为找不到,跳过 |
364
393
  | `description` 解析 | 支持单行、引号(单/双)、折叠块(`>`)与字面块(`\|`,含标记独立成行);空白折叠、去外层引号、截断至 200 字符;缺省为空串 |
365
- | SKILL.md 扫描范围 | `$DSH_HOME/skills`(默认 `~/.dsh/skills`)、`$DSH_AGENTS_HOME/skills`(默认 `~/.agents/skills`)、`<cwd>/.dsh/skills`、`<cwd>/.agents/skills`;同根内 `<root>/<name>/SKILL.md` 优先于裸 `<root>/<name>.md` |
394
+ | SKILL.md 扫描范围 | 全局(兜底 CLI 安装 / 面板「全局默认」)只扫用户级两根:`$DSH_HOME/skills`(默认 `~/.dsh/skills`)、`$DSH_AGENTS_HOME/skills`(默认 `~/.agents/skills`);按工作区生成时另加该工作区目录的 `.dsh/skills` 与 `.agents/skills`(见第 9 节)。同根内 `<root>/<name>/SKILL.md` 优先于裸 `<root>/<name>.md` |
366
395
 
367
- 技能名来自安装时的技能检测(同上四个根);向导 / 配置 UI 只会列出检测到的技能。
396
+ 技能名来自应用时的技能检测(同上四个根);面板只会列出检测到的技能。
368
397
 
369
398
  ## 5. 主 agent 人设
370
399
 
371
- ### 5.1 主 agent 名称:main_agent_name
400
+ ### 5.1 只改显示名:main_agent_display_name
401
+
402
+ `main_agent_display_name`(顶层可选键,string | null)只改**部署 preset 显示名**——GUI 预设选择器里看到的那个名字;persona 身份行 `You are the orchestrator agent powered by the {{model}} model.` 完全不动。编排主 agent 的身份是编排预设提示词语义的一部分,**不支持改名**(旧版「主 agent 名称」键已下线;老配置里的残留行下次「保存并应用」时自动清除,安装器会提示该键已忽略)。
403
+
404
+ 约束:trim 后 1–60 字符、不可含换行,违规直接报错;空 / 缺省 = 默认「编排模式 (Orchestrator)」(工作区预设用派生名)。
372
405
 
373
- 顶层可选键 `main_agent_name`(string | null)改主 agent 的名字,**一改两处**:
406
+ 生成 `preset.yml` 时显示名按下面的顺序取值:
374
407
 
375
- - **部署 preset 显示名**:`preset.yml` 的显示名——GUI 预设选择器里看到的那个名字,默认「编排模式 (Orchestrator)」;
376
- - **persona 身份行**:主 agent persona 的 `You are the <name> agent powered by the {{model}} model.`,`<name>` = 本键值。
408
+ 1. `main_agent_display_name`(本键非空时最优先);
409
+ 2. 「SRC 名·目录名」派生名(仅工作区预设,见 9.2);
410
+ 3. SRC 原名。
377
411
 
378
- 约束:trim 后 1–60 字符、不可含换行;空字符串 / 缺省 = 保持默认(不写此键时,显示名与身份行都是 SRC 原文,安装器不做任何替换)。
412
+ 不写本键时一切行为与从前逐字节一致(向后兼容,老配置零感升级)。
379
413
 
380
414
  ```yaml
381
- main_agent_name: orchestration-lead # 缺省 = 默认编排名(preset 显示名「编排模式 (Orchestrator)」)
415
+ main_agent_display_name: 庖丁 # 仅 preset 显示名换成「庖丁」,persona 身份行不动
382
416
  ```
383
417
 
384
- - **手编**:写键后重跑 `./install.sh --auto`,再重启 DSH / 新会话生效。
385
- - **配置 UI**:设置 → 庖丁配置 → 主 agent 卡顶部「主 agent 名称」输入框(带「恢复默认」按钮);点「保存并应用」后**重启 GUI / 新会话**生效。
386
- - **对照**:本键只改**主 agent**。内置角色的显示名是角色级子键 `roles.<toolName>.name`——只替换该角色默认 persona 首行身份句的主语、不改工具调用名(见 2.4),两条改名线互不牵连、可各自独立配置。
418
+ 生效方式:
419
+
420
+ - **手编**:写键后在「庖丁配置」点「保存并应用」,再重启 GUI / 新会话生效。
421
+ - **面板**:左侧栏「庖丁配置」→ 主 agent 卡「主 agent 显示名(仅 preset 显示名)」输入框(带「恢复默认」按钮),点「保存并应用」后**重启 GUI / 新会话**生效。
422
+ - **对照**:显示名线共两条、互不牵连:`main_agent_display_name`(仅主 agent 的 preset 显示名,见 5.1)、`roles.<toolName>.name`(内置角色默认 persona 首行身份句的主语,不改工具调用名,见 2.4),可各自独立配置。
387
423
 
388
424
  ### 5.2 追加三态语义:main_agent_persona_extra
389
425
 
@@ -395,11 +431,11 @@ main_agent_name: orchestration-lead # 缺省 = 默认编排名(preset 显示
395
431
  | 显式 `''` | **不追加任何内容**(连默认规则也不加) |
396
432
  | 其它文本 | **覆盖**默认,追加你的文本 |
397
433
 
398
- 写入格式:`''` 会以 `main_agent_persona_extra: ''` 写出(区别于缺省);多行文本以 `|-` 块标量写出。`tools/install.mjs` 的 `normalizeConfig` 只接受 string(非 string / 缺省 → `null`)。
434
+ 写入格式:`''` 会以 `main_agent_persona_extra: ''` 写出(区别于缺省);多行文本以 `|-` 块标量写出。`tools/lib/config.mjs` 的 `normalizeConfig` 只接受 string(非 string / 缺省 → `null`)。
399
435
 
400
436
  ### 5.3 默认常量原文
401
437
 
402
- 单点事实源是 `tools/install.mjs` 里的 `DEFAULT_MAIN_AGENT_PERSONA_EXTRA`(`presets/orchestrator/agent.cordis.yml` **不再内置**该行)。默认值原文(英文):
438
+ 单点事实源是 `tools/lib/util.mjs` 里的 `DEFAULT_MAIN_AGENT_PERSONA_EXTRA`(`tools/install.mjs` 仅 re-export 转出口,不定义;`presets/orchestrator/agent.cordis.yml` **不再内置**该行)。默认值原文(英文):
403
439
 
404
440
  > Codegraph MCP default project may be a DIFFERENT repository than {{cwd}}. Never call codegraph_* tools without passing projectPath = {{cwd}} (the absolute path of your working directory). If {{cwd}} has no .codegraph index, fall back to glob/grep/read directly and do not loop or comment on project mismatches.
405
441
 
@@ -407,9 +443,8 @@ main_agent_name: orchestration-lead # 缺省 = 默认编排名(preset 显示
407
443
 
408
444
  ### 5.4 编辑途径
409
445
 
410
- - **手编**:直接编辑配置文件的 `main_agent_persona_extra` 键,重跑 `./install.sh --auto`。
411
- - **配置 UI**:设置 → 庖丁配置 → 主 agent 卡片「人设追加」(编辑器带「恢复默认」按钮),可编辑 / 清空 / 恢复默认;点「保存并应用」后**重启 GUI / 新会话**生效。
412
- - 交互向导没有独立的人设追加步骤(从既有配置原样继承)——CLI 下改它请手编或走 UI。
446
+ - **手编**:直接编辑配置文件的 `main_agent_persona_extra` 键,然后在「庖丁配置」点「保存并应用」。
447
+ - **面板**:左侧栏「庖丁配置」→ 主 agent 卡片「人设追加」(编辑器带「恢复默认」按钮),可编辑 / 清空 / 恢复默认;点「保存并应用」后**重启 GUI / 新会话**生效。
413
448
 
414
449
  ## 6. 自定义角色
415
450
 
@@ -419,25 +454,32 @@ main_agent_name: orchestration-lead # 缺省 = 默认编排名(preset 显示
419
454
  与 `read` / `write` / `edit` / `bash` 等、persona 说明调用 `html-ppt` 技能产出 HTML 幻灯片,再把
420
455
  `html-ppt` 技能分给它(第 7 节)。装好后主 agent 说「把这份大纲做成 PPT」即委派给会做幻灯片的子 agent,
421
456
  通用角色不用什么都碰。任意已装技能都能这样变成专属角色(前端稿、图表、文档排版……)。下分三小节:
422
- 向导/UI 路径(6.1)、手写静态源路径(6.2)与配置示例(6.3,含技能型 PPT agent)。
457
+ 面板路径(6.1)、手写静态源路径(6.2)与配置示例(6.3,含技能型 PPT agent)。
423
458
 
424
459
  先说两个生成期行为:其一,**零工具的自定义角色装不上**——`tools` 缺省或写成空列表会得到一张空白
425
460
  名单(`toolFilter.allow:` 落成 null),子 agent 创建后一个工具都没有;生成器对此与内置角色一视同仁,
426
- 应用时直接报错拒绝安装,给角色配上至少一个工具再应用即可(向导里选不出工具也会一直重问)。其二,
461
+ 应用时直接报错拒绝安装,给角色配上至少一个工具再应用即可。其二,
427
462
  生成器会把角色 persona 的**首行职责句自动追加为主 agent persona 的委派行**(`- <职责>: delegate to
428
463
  <toolName>.`,紧跟既有委派行之后)——主 agent 全靠这行知道什么活该派给谁,因此建议把 persona 首行
429
464
  写成一句简短职责(例如「你的职责就是查找符合用户要求的技能」)。
430
465
 
431
- ### 6.1 路径一:交互向导 / 配置 UI(推荐)
466
+ ### 6.1 路径一:庖丁配置面板(推荐)
467
+
468
+ 面板流程(左侧栏「庖丁配置」→「Agent 工具分配」→ 底部「新建自定义 agent 角色」):
432
469
 
433
- 向导流程(`./install.sh` 交互模式,或配置 UI 的「Agent 工具分配」):
470
+ 1. 新建角色:输入 `toolName`,须匹配 `/^[a-z][a-z0-9_-]{1,31}$/`(2–32 位:首字符小写字母,其余为小写字母 / 数字 / 下划线 / 连字符;安装器侧另拒保留名、`mcp__` 前缀与 YAML 字面量);
471
+ 2. 从工具池多选工具(工具池 = 三角色静态 allow ∪ 检测到的 MCP / 插件工具);
472
+ 3. 写 persona(可给完整 persona,首行写成一句简短职责);
473
+ 4. 点「保存并应用」——生成器自动把新 `toolName` 注入主 agent 的 `orchestrator-restrict config.allow` —— **`restrict.mjs` 文件本身不用改**;并把分配持久化到配置文件(`roles` 键下多一项)。
434
474
 
435
- 1. 新建角色:输入 `toolName`,须匹配 `/^[a-z][a-z0-9_]*$/`;
436
- 2. 从工具池多选工具(工具池 = 三角色静态 allow ∪ 检测到的 host 工具);
437
- 3. 写一句 persona(向导自动展开为 `You are the <name> agent. <你的描述>`;配置 UI 可给完整 persona);
438
- 4. 向导自动把新 `toolName` 注入主 agent 的 `orchestrator-restrict config.allow` —— **`restrict.mjs` 文件本身不用改**;并把分配持久化到配置文件(`roles` 键下多一项)。
475
+ 角色卡上工具清单的口径:候选 = 源码 preset 的静态 allow 面(内置角色自带;本身含核心工具)∪ 主 agent 核心
476
+ allow(`restrictBase`,供自定义角色回落)∪ 检测库存,按三组呈现——「**基础工具**」= 非 `mcp__` 且不在检测
477
+ 库存的核心面(`read` / `glob` / `grep` / `bash` / `todo_write` 等,委派名 `search_external` / `design` /
478
+ `implement` / `search_internal_deep` 不进网格);「**MCP 工具**」= `mcp__` 前缀(含源码 preset 自带的
479
+ tavily 等行);「**插件工具**」= 检测库存中无 `mcp__` 前缀的插件直注册工具(`mnemon_*` 等)。新建角色的出厂
480
+ `tools` 即核心面加检测库存,默认全选,应用前可逐项增删。
439
481
 
440
- 之后对话里直接调该 toolName 即可委派。删除角色 = 从配置文件移除该项再重跑 `--auto`(目标文件每次重新生成,不留残留块)。**内置角色**的整条删除不同——那是 `roles_remove`(见 2.3),`roles` 键下不写即可不覆盖。
482
+ 之后对话里直接调该 toolName 即可委派。删除角色 = 面板里删卡(或从配置文件移除该项)后再点「保存并应用」(目标文件每次重新生成,不留残留块)。**内置角色**的整条删除不同——那是 `roles_remove`(见 2.3),`roles` 键下不写即可不覆盖。
441
483
 
442
484
  ### 6.2 路径二:手写静态源
443
485
 
@@ -446,7 +488,7 @@ main_agent_name: orchestration-lead # 缺省 = 默认编排名(preset 显示
446
488
  1. 复制 `presets/orchestrator/agent.cordis.yml` 里一个 `delegation-*` 块(delegation 组内);
447
489
  2. 改 `toolName` / `persona` / `toolFilter.allow`;
448
490
  3. 把新 `toolName` 加进 `presets/orchestrator/restrict.mjs` 的 `MAIN_AGENT_ALLOW`(这是生成 `config.allow` 的 base,主 agent 白名单不出现该名字就无法调用委派工具);
449
- 4. 重跑 `./install.sh --auto`(安装器只重写三角色与主 agent persona 的有限区间,你新增的块原样保留)。
491
+ 4. 重新应用(「庖丁配置」点「保存并应用」;开发者也可 `node tools/install.mjs --auto`)——生成器只重写三角色与主 agent persona 的有限区间,你新增的块原样保留。
450
492
 
451
493
  两条路径生成同一结构(`delegation-<toolName>` + 白名单含 toolName);路径一免改源码、可经 UI 管理,推荐优先。
452
494
 
@@ -470,7 +512,7 @@ roles:
470
512
  - todo_write
471
513
  ```
472
514
 
473
- 重跑 `./install.sh --auto` 后:生成 `delegation-code-reviewer` 块(persona 原样、tools 原样进 allow),主 agent `config.allow` 注入 `code-reviewer`。注意:自定义角色的 `tools` **原样写入** allow,不做 host 检测求交(向导/UI 的工具池已保证可选项都在注册面内)——手编时只列实际挂载的工具,否则子 agent 创建时 `tools.restrict()` 会以 unknown tools 拒绝。
515
+ 在「庖丁配置」点「保存并应用」后:生成 `delegation-code-reviewer` 块(persona 原样、tools 原样进 allow),主 agent `config.allow` 注入 `code-reviewer`。注意:自定义角色的 `tools` **原样写入** allow,不做 host 检测求交(面板的工具池已保证可选项都在注册面内)——手编时只列实际挂载的工具,否则子 agent 创建时 `tools.restrict()` 会以 unknown tools 拒绝。
474
516
 
475
517
  **技能型示例:`ppt` agent(做 PPT 的专属子 agent)**——工具面含 `skill` 与读写编辑,persona 引导加载
476
518
  `html-ppt` 技能,`skills` 键把技能分给该角色(persona 尾部生成 Available skills 引导行):
@@ -499,14 +541,14 @@ skills:
499
541
 
500
542
  效果与 `code-reviewer` 相同(生成 `delegation-ppt` 块、白名单注入 `ppt`);区别在多一步 `skills` 映射。
501
543
  子 agent 创建后 skill 目录对角色全量可见(DSH 机制),persona 的引导行只是**软约束**——真正干活靠子 agent
502
- 按需用 `skill` 工具读正文,装配别的技能(如做简历、出图表)同理。向导 / 配置 UI 里也能搭出同款:工具池勾
544
+ 按需用 `skill` 工具读正文,装配别的技能(如做简历、出图表)同理。庖丁配置面板里也能搭出同款:工具池勾
503
545
  `skill` + 读写编辑、写一句 persona、在技能分配面板把 `html-ppt` 分给 `ppt`。
504
546
 
505
547
  ## 7. skill 分配
506
548
 
507
549
  ### 7.1 写法与效果
508
550
 
509
- 顶层 `skills` 键把技能分给角色(值 = 角色 toolName 列表,与向导「技能分配」步骤、配置 UI「技能分配」面板同一映射):
551
+ 顶层 `skills` 键把技能分给角色(值 = 角色 toolName 列表,与面板「技能分配」网格同一映射):
510
552
 
511
553
  ```yaml
512
554
  skills:
@@ -520,6 +562,8 @@ skills:
520
562
 
521
563
  这是一条**软约束**而非硬隔离:目录可见性是 DSH 机制(按 cwd 收集、对角色全量可见),persona 引导句只是提示。硬隔离靠工具面(allow 里有没有 `skill`)实现。主 agent 例外:其注册层 deny 了 `skill`(见 3.1),所以技能对其不可见——需要时走 `main_agent_skills` / `main_agent_skills_inline`(第 4 节),而不是 `skills` 键。
522
564
 
565
+ 技能候选的扫描范围随配置对象走:全局视角只含用户级技能;工作区视角另含该工作区目录下的项目级技能(面板里带「项目」角标),见 9.5。
566
+
523
567
  ## 8. 子 agent 模型与平台细节
524
568
 
525
569
  ### 8.1 按角色分模型
@@ -548,4 +592,54 @@ skills:
548
592
 
549
593
  ### 8.3 停用 MCP / 插件后的同步
550
594
 
551
- 停用 tavily / codegraph / magic-memory(在 `~/.dsh/cordis.patch.yml` 或 profile patch 注释相应条目)后**不需要手动改 allow**:重跑 `./install.sh --auto`,安装器检测到停用后自动把对应 `mcp__tavily__*` / `memory_search` 从三角色 allow 剔除(`--dry-run` 可先预览剔除项)。检测不到或握手失败的 MCP 会被跳过:对应角色只是缺这些工具,安装不报错。检测与 patch 层的细节链见 [安装](installation.md)。
595
+ 停用 tavily / codegraph / magic-memory(在 `~/.dsh/cordis.patch.yml` 或 profile patch 注释相应条目)后**不需要手动改 allow**:在「庖丁配置」点一次「保存并应用」,生成器检测到停用后自动把对应 `mcp__tavily__*` / `memory_search` 从三角色 allow 剔除(「预览生成」可先看剔除项)。检测不到或握手失败的 MCP 会被跳过:对应角色只是缺这些工具,应用不报错。检测与 patch 层的细节链见 [安装](installation.md)。
596
+
597
+ ## 9. 按工作区配置
598
+
599
+ ### 9.1 一份全局,各自成套
600
+
601
+ DSH 用工作区(workspace,即项目目录)组织会话。顶层 `workspaces` 键让每个工作区有自己的主/子 agent 配置:全局条目照旧生成共享的 `orchestrator` 预设;工作区条目各自生成 `orchestrator-<slug>` 专属预设,预设列表里并存、互不覆盖。
602
+
603
+ 每个工作区条目是**完整一套配置**,不是增量差异:字段与顶层同构(`profile` 除外,检测层全局共享)。角色子键照搬——`background_mode`(见 2.6)同样按工作区生效:某个项目想让 implement 可续、别的项目保持一次性,各配各的。在面板里第一次配置某个工作区时,以当前全局配置为起点,改完点「保存并应用」即生成该工作区的预设。
604
+
605
+ ```yaml
606
+ workspaces:
607
+ '/Users/me/code/shop-api': # 键 = 工作区目录绝对路径(写入时归一,恒带引号)
608
+ main_agent_display_name: 店铺后端主控 # 仅该工作区预设的显示名
609
+ roles:
610
+ implement:
611
+ model: deepseek-reasoner # 这个项目写代码用推理档
612
+ '/Users/me/code/blog':
613
+ roles_remove: [design] # 写博客的项目不需要设计帮手
614
+ ```
615
+
616
+ ### 9.2 预设命名规则
617
+
618
+ - **slug** 取工作区目录名:小写、非法字符归并为 `-`;归并后为空、或恰好叫 `orchestrator`(与全局预设撞名)时改用 `ws`。
619
+ - 多个工作区目录同名时,自动追加路径哈希(sha1 前 6 位)后缀,如同为 `Shop` 的两个项目得到 `orchestrator-shop-acd95b` 与 `orchestrator-shop-34b6aa`——改名或挪动目录后重新应用即可。旧路径条目仍留在配置 `workspaces` 段时,旧预设目录暂被保留;条目移除后,下一次任何成功应用会自动回收该孤儿预设(rmSync + 告警可见),无需手动删。
620
+ - 预设显示名:条目配了 `main_agent_display_name` 就用它;没配则在默认名后缀「·目录名」(如 `编排模式 (Orchestrator)·Shop`),预设列表里一眼可辨。
621
+
622
+ ### 9.3 面板用法
623
+
624
+ 「庖丁配置」页面顶部是**配置对象**标签页:
625
+
626
+ - **全局默认**:编辑并写入共享的 `orchestrator` 预设,行为与从前完全一致;
627
+ - **工作区标签页**:列表来自宿主工作区注册表(开过会话的目录才会登记),带绿点的表示预设已生成,悬停可见路径、会话数与预设 id;
628
+ - **添加工作区**:输入目录绝对路径即注册(幂等),注册表拉不到时降级为只显示配置文件里已有的工作区,面板其余功能不受影响。
629
+
630
+ 选定某个工作区后,预览 / 应用都只作用于它;应用成功的提示里会给出预设 id。
631
+
632
+ ### 9.4 生效方式与边界
633
+
634
+ - **预设选择发生在新建会话时**:新建会话界面选好工作区后,在预设选择器里选对应的 `orchestrator-<slug>`。全局默认预设不受任何影响。预设生效需要新会话(或 DSH 重启后可见)。
635
+ - 预设目录落在 `$DSH_HOME/.agent-presets/` 下,全机共享:同一台机器上不同项目各起的 DSH 实例,因 slug 不同互不覆盖。
636
+ - 兜底 CLI 本次仍只作用于全局条目;`workspaces` 段在 CLI 应用后原样保留,不会被冲掉。
637
+ - 运行中的会话不会换预设——子 agent 的角色与工具面在会话创建时随预设组装定型,会话内不可变;要换套班底,开新会话选新预设。
638
+
639
+ ### 9.5 技能扫描范围随配置对象走
640
+
641
+ 技能候选不跟随 GUI 的启动目录:**全局默认**视角只扫用户级两根(`~/.dsh/skills`、`~/.agents/skills`),**工作区**视角另加该工作区目录下的 `.dsh/skills` 与 `.agents/skills`。于是:
642
+
643
+ - 只装在某个项目里的技能(比如知识库项目里的 `bento-slides`),在全局配置里不可见、配不上;选中那个工作区后出现在技能网格里,带「项目」角标,可分配给该工作区预设的主 agent 或角色。
644
+ - 生成时技能解析同口径:工作区预设能写出项目级技能的 SKILL.md 绝对路径(主 agent 用 `read` 按需读,路径在盘上就能读);全局预设只解析用户级,配了项目级技能名会告警跳过——全局预设要在所有项目通用,引用单一项目的技能本就不该写进去。
645
+ - 兜底 CLI 没有工作区概念,只扫用户级两根(与全局默认一致)。