dsh-paoding 0.3.0 → 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.
@@ -22,19 +22,19 @@ The main agent's model-facing surface is narrowed by `restrict.mjs` on the `syst
22
22
  | Child management | `send_message` / `list_agents` / `interrupt_agent` |
23
23
  | Internal search (hot path) | `glob` / `grep` / `read` / `read_image` / `bash` |
24
24
  | Coordination | `todo_write` / `ask_user_question` / `get_goal` / `create_goal` / `update_goal` / `exit_plan_mode` / `job_output` / `job_list` / `job_kill` |
25
- | Deliberately hidden from the main agent | `web_search`, `mcp__tavily__*`, `write` / `edit`, `skill`, `workflow`, `ralph`, bare `subagent` / `subagent_fork` |
25
+ | Deliberately hidden from the main agent (excerpt; full list in the `restrict.mjs` header comment) | `web_search`, `mcp__tavily__*`, `write` / `edit` / `str_replace_editor`, `skill`, `workflow`, `ralph`, `ssh_*`, `mcp__tablepro__*`, `describe_image`, bare `subagent` / `subagent_fork` |
26
26
 
27
27
  Per-request tool tax (estimates; they float with the registered surface): full monolithic main agent ~16.2k tokens → ~5.5k after the allow list; `search_external` ~3.0k / `design` ~3.3k / `implement` ~3.8k, incurred only when actually delegated (figures from the header comment of `agent.cordis.yml`).
28
28
 
29
29
  ### Main-agent persona (excerpt, verbatim)
30
30
 
31
- Taken from the `- id: persona` row of `presets/orchestrator/agent.cordis.yml` (a YAML `text: |-` block scalar whose content lines are indented 6 spaces). The overall orchestration-and-delegation guidance:
31
+ Taken from the `- id: persona` row of `presets/orchestrator/agent.cordis.yml` (a YAML `prefix: |-` block scalar whose content lines are indented 6 spaces; as of v0.3.0 the persona config key is `prefix`, with `text` kept as a legacy alias the generator still accepts). The overall orchestration-and-delegation guidance:
32
32
 
33
33
  ```text
34
34
  You are the orchestrator agent powered by the {{model}} model. Your working directory is {{cwd}}.
35
35
 
36
36
  Decompose the task, delegate to role agents, integrate results.
37
- - Internal file questions (finding code, references, reading files): solve yourself with glob/grep/read/codegraph — never delegate them.
37
+ - Internal file questions (finding code, references, reading files): solve yourself with glob/grep/read (and codegraph if enabled) — never delegate them.
38
38
  - External research: delegate to search_external.
39
39
  - UI/design work: delegate to design.
40
40
  - Code implementation: delegate to implement.
@@ -44,7 +44,7 @@ Keep your own context lean; integrate only summaries. Use todo_write to plan, an
44
44
  Reading notes:
45
45
 
46
46
  - The main agent is an orchestrator running the **decompose → delegate → integrate** loop rather than doing everything itself.
47
- - "Internal file questions (finding code, references, reading files): solve yourself with glob/grep/read/codegraph — **never delegate them**": internal search is the hot path — delegation costs round-trips and cold starts, and the main agent already carries a full read-only set, so it goes direct. (Note: `codegraph` is a host MCP tool and is only usable once injected into the allow list at runtime, see above.)
47
+ - "Internal file questions (finding code, references, reading files): solve yourself with glob/grep/read (and codegraph if enabled) — **never delegate them**": internal search is the hot path — delegation costs round-trips and cold starts, and the main agent already carries a full read-only set, so it goes direct. (Note: `codegraph` is a host MCP tool and only becomes usable when install-time detection finds it and it is explicitly injected via `main_agent_extra`, see above.)
48
48
  - Task texture decides the destination: networked research → `search_external`; UI/design → `design`; code → `implement` (whole-repo exploration → `search_internal_deep`).
49
49
  - **Keep your own context lean**: integrate only summaries; plan with `todo_write`; use `ask_user_question` only for user-owned choices — questions that inspection can answer must not bother the user.
50
50
  - The failure-handling SOP lives inline in the persona, so it is active in every session with zero extra configuration — see the next section.
@@ -61,9 +61,9 @@ A delegated run reports failure in two runtime shapes (verbatim from the persona
61
61
 
62
62
  At child creation, DSH validates `toolFilter.allow` through `tools.restrict()`: every allow name must exist in the child's visible registry (= this composition's full registration plus host-layer MCP/plugin tools), otherwise creation is rejected (`tools.restrict() ... unknown tools`).
63
63
 
64
- The preset eliminates this class of failure at generation time: the generator (the same pipeline behind the panel's Save & Apply and the fallback CLI) reads the host patch layers (home / profile / `--patch`), detects which MCP servers and local tool plugins are actually enabled, resolves exact tool names (a static known-tools table first, then a live JSON-RPC handshake for unknown servers), and rewrites each role's allow list as "static intent ∩ actually detected tools" — composition-guaranteed base tools stay untouched, host tools that are disabled or unresolvable are removed. MCPs that fail the handshake or use an unsupported transport are skipped: the role simply lacks those tools and applying does not error. After enabling/disabling MCPs or plugins on the host, hit Save & Apply once in 庖丁配置 to sync the allow lists (Preview shows the list first). Details in [Installation](installation_en.md).
64
+ The preset eliminates this class of failure at generation time: the generator (the same pipeline behind the panel's Save & Apply and the fallback CLI) reads the host patch layers (home / profile / `--patch`), detects which MCP servers and local tool plugins are actually enabled, resolves exact tool names (a live JSON-RPC handshake first for every server; known servers fall back to the static known-tools table only when the handshake fails), and rewrites the allow lists of the three configurable roles (search_external / design / implement) as "static intent ∩ actually detected tools" — composition-guaranteed base tools stay untouched, host tools that are disabled or unresolvable are removed. Only unknown servers that fail the handshake or use an unsupported transport are skipped entirely (known servers keep their table tools on handshake failure): the role simply lacks those tools and applying does not error. After enabling/disabling MCPs or plugins on the host, hit Save & Apply once in 庖丁配置 to sync the allow lists (Preview shows the list first). Details in [Installation](installation_en.md).
65
65
 
66
- Note that the generator's allow rewriting covers only the three built-in roles (`search_external` / `design` / `implement` — the `ROLES` constant in tools/install.mjs). Hand-written extra `delegation-*` blocks (e.g. the hand-written `implement_cont` in section 4) ship **as-is and are never auto-cleaned**: host-dependent names inside them must be kept in sync with the plugins actually enabled on the host, or child creation is rejected. That is exactly why role allow lists dropped `memory_search` / `mcp__codegraph__codegraph_explore` as of 2026-09-02 (those names are not in the registry while the plugins are off; add them back when you re-enable the plugin — see the comment on `delegation-search-internal-deep` in `agent.cordis.yml`).
66
+ Note that the generator's allow rewriting covers only the three built-in roles (`search_external` / `design` / `implement` — the `ROLES` constant in `tools/lib/util.mjs`, re-exported by `tools/install.mjs`). Hand-written extra `delegation-*` blocks (e.g. the hand-written `implement_cont` in section 4) ship **as-is and are never auto-cleaned**: host-dependent names inside them must be kept in sync with the plugins actually enabled on the host, or child creation is rejected. That is exactly why role allow lists dropped `memory_search` / `mcp__codegraph__codegraph_explore` as of 2026-09-02 (those names are not in the registry while the plugins are off; add them back when you re-enable the plugin — see the comment on `delegation-search-internal-deep` in `agent.cordis.yml`).
67
67
 
68
68
  ### Layer 2: detection
69
69
 
@@ -94,6 +94,11 @@ Delegation failure handling (SOP):
94
94
  · aborted → only re-delegate when the cancellation was accidental.
95
95
  · completed but poor output → re-delegate with concrete missing points, or send_message
96
96
  to ask a continuable child to finish the gaps.
97
+ - Continuable roles (background_mode: continuable): when a delegated run fails or
98
+ the output falls short, first send_message in the SAME child session to continue
99
+ and fix in place — resuming keeps the child's accumulated context, while
100
+ re-delegating starts a cold task and repeats finished work. Only re-delegate
101
+ when the child session is gone or the task needs a different role.
97
102
  - If the same task fails twice, stop retrying: report to the user what failed, why,
98
103
  and what you already tried. Never loop a failing delegation.
99
104
  - When re-delegating (fresh task or continuation), always include your integration
@@ -113,9 +118,9 @@ Behavior by stop reason (complete coverage, one-to-one with the persona):
113
118
  | Same task fails **twice** | Stop retrying; report to the user what failed, why, and what you already tried; never loop a failing delegation |
114
119
  | Any re-delegation | **Always carry the previous integration summary** — what was done, what failed, what to pick up from — so the child never re-derives it from a cold context |
115
120
 
116
- The continuable branch (new in the SOP): when a run fails or the output disappoints **and the role is configured continuable**, first resume the same child conversation with `send_message` — the child remembers where it left off and finishes in place; only if that does not help fall back to the table above and re-delegate (re-delegation drops from first choice to fallback).
121
+ The continuable branch: when a run fails or the output disappoints **and the role is configured continuable**, first resume the same child conversation with `send_message` — the child remembers where it left off and finishes in place; re-delegate only when the child session is gone or the task needs a different role (the same wording as the Continuable roles entry in the persona SOP); otherwise fall back to the table above (re-delegation drops from first choice to fallback).
117
122
 
118
- Design note: the SOP is persona text, not code, so it is tunable: edit the persona block in `presets/orchestrator/agent.cordis.yml` (YAML block scalar; content lines are indented 10 spaces — keep the indentation), then hit Save & Apply in 庖丁配置 to regenerate. For example, you can make failures bounce back to the main agent more often, or give a specific role a different retry ceiling.
123
+ Design note: the SOP is persona text, not code, so it is tunable: edit the persona block in `presets/orchestrator/agent.cordis.yml` (YAML block scalar; content lines are indented 6 spaces — keep the indentation), then hit Save & Apply in 庖丁配置 to regenerate. For example, you can make failures bounce back to the main agent more often, or give a specific role a different retry ceiling.
119
124
 
120
125
  ## One-shot vs continuable
121
126
 
@@ -153,7 +158,7 @@ Quick comparison:
153
158
 
154
159
  ## Advanced: hand-editing implement_cont (no panel)
155
160
 
156
- The main path for Path B is the panel or the config key — one toggle on the role card's「会话模式」("session mode") control (see [Configuration](configuration_en.md) 2.6). This section is the equivalent panel-free route, in 5 steps — read it when you want to see exactly what the generation layer writes, or when working without the panel. The default preset does **not** ship `implement_cont`; enable it when you need it and remove it entirely when you no longer do. All YAML below is verbatim configuration (adapted from the example in [README.md](../README_en.md) and checked against the source).
161
+ The main path for Path B is the panel or the config key — one toggle on the role card's「会话模式」("session mode") control (see [Configuration](configuration_en.md) 2.6). This section is the equivalent panel-free route, in 5 steps — read it when you want to see exactly what the generation layer writes, or when working without the panel. The default preset does **not** ship `implement_cont`; enable it when you need it and remove it entirely when you no longer do. All YAML below is verbatim configuration (structured like the preset's delegation blocks and checked against the source).
157
162
 
158
163
  ### Step 1 — mount the persistence backend at the host layer (machine-level, global)
159
164
 
@@ -215,28 +220,19 @@ Two caveats:
215
220
  - `memory_search` depends on the host magic-memory plugin: **if the plugin is not enabled, remove that line from the allow list** or child creation is rejected by `tools.restrict()` with unknown tools. This is consistent with the 2026-09-02 decision to strip `memory_search` / `mcp__codegraph__codegraph_explore` from role allow lists (see the in-file comment in `agent.cordis.yml`); and since the installer's allow rewriting covers only the three built-in roles, the hand-written `implement_cont` block is **never auto-cleaned** — keep its allow list in sync with the plugins actually enabled on the host by hand.
216
221
  - The persona in the block above is a YAML `|-` block scalar whose content lines are indented 10 spaces; preserve the indentation when editing the text.
217
222
 
218
- ### Step 3 — let the main agent call `implement_cont` (pick one of two)
223
+ ### Step 3 — let the main agent call `implement_cont` (edit the restrict constant)
219
224
 
220
- The main agent can only call tools on its allow list; you have two ways to add `implement_cont`.
225
+ The main agent can only call tools on its allow list. The preferred way is to edit the `MAIN_AGENT_ALLOW` constant directly — add a line `'implement_cont'` to `MAIN_AGENT_ALLOW` (the 21-entry allow constant, `new Set([...])`) in `presets/orchestrator/restrict.mjs` (this edits the SRC, so you must re-apply afterwards, see step 4).
221
226
 
222
- **Recommended: config-file injection (no source edit).** Add `main_agent_extra` at the top level of `~/.dsh/dsh-paoding.config.yml`:
227
+ Why the config file is not an option here: `main_agent_extra` injections go through the whitelist reconciliation — a name is kept only if it belongs to the **presetUniverse** (the `restrict.mjs` main-agent allow ∪ the source preset's role allows) or to the **detection inventory**; names in neither are always dropped. A custom delegation name like `implement_cont` falls in neither bucket: written under `main_agent_extra` it is silently dropped by the generator (the fallback CLI output only totals the count, with no per-name detail), and the panel's main-agent card cannot tick it either. For the config-layer path to work, a hand-written name must first exist in the presetUniverse / inventory.
223
228
 
224
- ```yaml
225
- main_agent_extra:
226
- - implement_cont
227
- ```
228
-
229
- At apply time `implement_cont` — not a host-dependent name — is merged into the generated `config.allow`. You can equally tick it in the panel (Settings → 庖丁配置 → the main-agent card); see [Configuration](configuration_en.md).
230
-
231
- **Alternative: edit the `restrict.mjs` constant.** Add a line `'implement_cont'` to `MAIN_AGENT_ALLOW` (the 21-entry allow constant, `new Set([...])`) in `presets/orchestrator/restrict.mjs`. Mind the **override semantics**: at runtime `allow = config.allow ?? MAIN_AGENT_ALLOW` (an empty allow refuses to load). The generator re-extracts this constant from `restrict.mjs` source as its base and generates `config.allow = base + main_agent_extra (only detected host names kept) − main_agent_remove`, injecting the `config.allow` row **only when the result differs from the base**. So after editing the constant you must re-apply (the base is re-extracted and the installed copy refreshed); and when the running `agent.cordis.yml` already has an injected `config.allow`, that generated list wins at runtime and the constant only serves as fallback.
232
-
233
- Either way, re-apply to take effect (next step).
229
+ Mind the **override semantics**: at runtime `allow = config.allow ?? MAIN_AGENT_ALLOW` (an empty allow refuses to load). The generator re-extracts this constant from `restrict.mjs` source as its base and generates `config.allow = (base + main_agent_extra − main_agent_remove) ∩ (presetUniverse ∪ inventory)`, injecting the `config.allow` row **only when the result differs from the base**. So after editing the constant you must re-apply (the base is re-extracted and the installed copy refreshed); and when the running `agent.cordis.yml` already has an injected `config.allow`, that generated list wins at runtime and the constant only serves as fallback.
234
230
 
235
231
  ### Step 4 — apply
236
232
 
237
- Open Settings → **庖丁配置** and hit「**保存并应用**」(Save & Apply) — the preset regenerates (new delegation block + allow-list changes), and your hand edits go live with it.
233
+ Open the「**庖丁配置**」entry in the action bar at the bottom of the left sidebar (just above the Settings row) and hit「**保存并应用**」(Save & Apply) — the preset regenerates (new delegation block + allow-list changes), and your hand edits go live with it.
238
234
 
239
- Then **restart the host or open a new session** for it to take effect. If step 3 used the config-file path, the choice is persisted in `~/.dsh/dsh-paoding.config.yml`; change it later and hit Save & Apply in the panel again for an idempotent re-apply (developers who cloned the repo can also use the fallback CLI, `node tools/install.mjs --auto`).
235
+ Then **restart the host or open a new session** for it to take effect. Later config changes re-apply idempotently the same way — hit Save & Apply again (developers who cloned the repo can also use the fallback CLI, `node tools/install.mjs --auto`).
240
236
 
241
237
  ### Step 5 — clean up after use
242
238
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-paoding",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "庖丁 — DSH (DeepSeek Harness) 编排模式安装器:host 感知的角色工具过滤 + Web 设置页可视化配置器",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -10,8 +10,9 @@
10
10
  * 兜底);upgrade 经 tools/lib/upgrade.mjs spawn `dsh plugin update` 完成
11
11
  * 一键升级。首装 / 升级后 preset 自动重生成(ensurePresetInstalled,等价
12
12
  * install --auto 语义)在路由注册完成后异步触发,不阻塞启动。
13
- * - Client 侧:lib/client.js 在左侧栏「新会话」下方注入「庖丁配置」入口,
14
- * 点击后在会话中栏打开全页配置 overlay(data-dsh-paoding-active)。
13
+ * - Client 侧:lib/client.js 经宿主 sidebar.footer.action 键控槽在左侧栏
14
+ * 底部(设置行上方)注册「庖丁配置」入口,点击后在会话中栏打开全页配置
15
+ * overlay(data-dsh-paoding-active)。
15
16
  *
16
17
  * 挂载(~/.dsh/cordis.patch.yml):
17
18
  * - id: paoding-config-ui
@@ -177,7 +178,7 @@ function triggerPresetEnsure(ctx, isDisposed) {
177
178
  } else if (r.error) {
178
179
  // 失败复位防抖闩:下次 activate(热重载 / 重注册)可重试
179
180
  presetEnsureStarted = false
180
- ctx.logger?.warn?.(`paoding-config-ui: preset 自动生成失败(可在 设置 → 庖丁配置 手动应用): ${r.error}`)
181
+ ctx.logger?.warn?.(`paoding-config-ui: preset 自动生成失败(可在侧栏底部「庖丁配置」入口手动应用): ${r.error}`)
181
182
  }
182
183
  // 版本一致的常规跳过不打日志:每次启动都刷一行纯噪音。
183
184
  })
@@ -2526,7 +2526,7 @@ window.__ModuleLoader__.load({
2526
2526
  }
2527
2527
 
2528
2528
  // ── 侧栏底部入口(sidebar.footer.action 键控槽)────────────────────────
2529
- // 入口从「新会话下方侧栏卡片」迁到左下角底部:注册 sidebar.footer.action
2529
+ // 入口挂在左下角底部动作条:注册 sidebar.footer.action
2530
2530
  // 列表槽(与插件广场 cordis 徽章同一槽位,渲染在设置行上方的动作条里)。
2531
2531
  // 观感复刻 cordis 徽章 / 设置触发钮:宽栏 = 42px 圆角行(图标 + 文案),
2532
2532
  // 窄栏(56px rail)= 36px 圆形图标钮。点击开 / 关全页 overlay(mountPanel
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "paoding-config-ui",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "main": "index.mjs",
@@ -74,8 +74,8 @@ export function keywords(names, pattern) {
74
74
  /**
75
75
  * 基础模板 assignments(fresh 非交互安装的默认起点):每个内置角色保留静态
76
76
  * preset 的 dsh 基础工具,host/MCP 工具一概不纳入 —— 首装(插件通道启动自愈
77
- * 或 --auto)先装完可用基础版,host 工具留给用户在 设置 → 庖丁配置 里显式
78
- * 开启,避免智能默认把检测到的 host 工具静默塞进委派链。形状与 smartDefaults
77
+ * 或 --auto)先装完可用基础版,host 工具留给用户在侧栏底部「庖丁配置」入口
78
+ * 里显式开启,避免智能默认把检测到的 host 工具静默塞进委派链。形状与 smartDefaults
79
79
  * 返回值完全一致,生成层 / 序列化层无需区分来源;staticBase 复制而非别名,
80
80
  * 防调用方原地改写。每个内置角色条目显式带 background_mode: 'one-shot',随
81
81
  * serializeConfig 恒写出 —— fresh 落盘的配置文件里旋钮可见。
package/tools/lib/cli.mjs CHANGED
@@ -5,7 +5,7 @@
5
5
  * 官方安装通道是 DSH 插件通道(dsh plugin --profile web add dsh-paoding),
6
6
  * npm 包不再携带 CLI 入口;本 CLI 仅作仓库内不宣传的开发兜底(--auto /
7
7
  * --dry-run / --config / --help)。交互模式已整块移除:可视化配置走插件通道
8
- * 自带的 Web 配置器(设置 → 庖丁配置)。
8
+ * 自带的 Web 配置器(侧栏底部「庖丁配置」入口)。
9
9
  *
10
10
  * 依赖 util(ROLES / SRC_DIR / PROFILE_NAME_RE)、config(normalizeRoleName)、
11
11
  * host(removedReason)、state(collectState /
@@ -31,7 +31,7 @@ export function printHelp() {
31
31
 
32
32
  dsh plugin --profile web add dsh-paoding
33
33
 
34
- 可视化配置随插件通道自带:DSH Web 设置 → 庖丁配置。
34
+ 可视化配置随插件通道自带:DSH Web 侧栏底部「庖丁配置」入口。
35
35
 
36
36
  Usage:
37
37
  node tools/install.mjs [options]
@@ -58,9 +58,10 @@ Environment:
58
58
  DSH_HOME Directory holding cordis.patch.yml etc. (default: $HOME/.dsh)
59
59
 
60
60
  With --auto and no config file, a base template is written: only the dsh
61
- built-in tools stay enabled — add host/MCP tools afterwards in 设置 → 庖丁配置
62
- (visual config UI from the plugin channel). Pass --suggest to fall back to
63
- the smart defaults that fold detected host tools in automatically.`)
61
+ built-in tools stay enabled — add host/MCP tools afterwards via the 庖丁配置
62
+ entry at the sidebar bottom (visual config UI from the plugin channel).
63
+ Pass --suggest to fall back to the smart defaults that fold detected host
64
+ tools in automatically.`)
64
65
  }
65
66
 
66
67
  // --profile 值白名单:与 bin/dsh-paoding.mjs 共用同一份 PROFILE_NAME_RE(抽在
@@ -311,7 +312,7 @@ export async function main({ argv = process.argv.slice(2) } = {}) {
311
312
  // fresh 非交互安装:提示基础模板已落盘、host/MCP 工具去哪补(--suggest 可
312
313
  // 恢复智能默认自动纳入)。
313
314
  console.log(
314
- `\n基础模板已写入 ${configFile}:默认仅 dsh 基础工具,重启后在 设置 → 庖丁配置` +
315
+ `\n基础模板已写入 ${configFile}:默认仅 dsh 基础工具,重启后在侧栏底部「庖丁配置」入口` +
315
316
  `里自定义 host/MCP 工具。`,
316
317
  )
317
318
  }
@@ -457,7 +457,7 @@ function writeWorkspaces(lines, workspaces) {
457
457
 
458
458
  /** Serialize the config back to YAML (fixed structure, hand-rolled writer). */
459
459
  export function serializeConfig(config) {
460
- const lines = ['# dsh-paoding(庖丁)安装配置 —— 可手编;改后在 设置 → 庖丁配置 应用,或重跑 node tools/install.mjs --auto']
460
+ const lines = ['# dsh-paoding(庖丁)安装配置 —— 可手编;改后在侧栏底部「庖丁配置」入口应用,或重跑 node tools/install.mjs --auto']
461
461
  lines.push(`profile: ${config.profile ?? 'web'}`)
462
462
  writeTargetFields(lines, '', config)
463
463
  // workspaces 段可选:键缺失 / 空对象整段省略(不含 workspaces 的配置输出与
package/docs/images/2.png DELETED
Binary file
package/docs/images/3.png DELETED
Binary file
package/docs/images/4.png DELETED
Binary file
package/docs/images/5.png DELETED
Binary file
package/docs/images/6.png DELETED
Binary file