dsh-plugin-subagent-director 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,37 @@
2
2
 
3
3
  本项目的所有显著变更都会记录在此文件中。格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。
4
4
 
5
+ ## [0.4.0] - 2026-08-31
6
+
7
+ ### 新增
8
+
9
+ - **纯编排模式(`/orchestrate`)**(PR #3,@WinterSold1er):`/orchestrate on|off` 命令(无参数默认 on),开启后注入「纯编排者」系统提示——主代理只允许通过 `subagent_role` 委派、禁止亲自读/写/执行,角色清单从 `subagent-director.roles` 动态渲染(无硬编码 role id),未配置角色时提示先配置;`sessionProjections` 服务缺失时命令返回明确错误而非假装成功;
10
+ - **纯编排模式改为按轮自动检测(类似 `/using aegis`)**:不再需要规定 on/off——消息开头声明 `/orchestrate`(无参数),或用自然语言写「使用orchestrate模式」(含「请使用 orchestrate 模式」「use orchestrate mode」等变体),该轮会话即自动进入纯编排模式;未声明时保持普通模式。系统提示段按轮判定:先扫描当前轮首条用户消息(`user/message` 事件)与最近一次 `orchestrate` 命令的 `command/run` 事件(以 `turn/start` 为轮次边界),投影仅作向后兼容兜底;
11
+ - **`/orchestrate <任务>` 直接编排该任务**:声明与任务同一条消息即可生效——任意任务文本(如 `/orchestrate 分析上周A股走势`)会被 handler 视为「编排该任务」,经 `agent.followup(createUserMessage(...))` 排入下一轮并唤醒模型。
12
+
13
+ ### 修复
14
+
15
+ - **真实 cordis 探针发现的隐性 bug**(issue #5):cordis 的 `ctx.effect(fn)` 契约是「立即执行 fn、以返回值为 disposer」,原先包在 effect 里的 `fiber.dispose()` 清理块会把 `/orchestrate` 命令与 projection 的 `ctx.inject` 子 fiber **在创建瞬间卸载**——真实宿主上命令从未注册成功过(既有测试全基于 fake,未覆盖该契约);子 fiber 本就随父 fiber 生命周期自动卸载,清理块已移除,并由新增的真实 cordis 探针测试永久钉住;
16
+ - **开发/测试环境对齐真实宿主 0.1.1 线**(issue #5):devDeps 与 peer ranges 由 `0.1.0-rc.6/rc.8` 升至 `^0.1.1-rc.2`(新增 `dsh-session-projection` peer);projection 注册改用真实类型契约(`SessionEventMap` / `SessionProjectionStateMap` / `SessionProjectionMap` 声明合并 + 类型化 `register`),契约形状漂移现在在 typecheck 期暴露,而不是运行期被 `snapshot()` 静默跳过;
17
+ - 顶层 `inject` 移除 `'commands'`(非 dsh-base 装配上主条目会永久 PENDING、核心委派功能全失效);命令 handler 增加 `invocation.agent.session` 可选链守卫;
18
+ - 移除未使用的 `@deepseek-ai/dsh-client-schema-form` 依赖(源码零引用,且其 0.1.0 线 peer 链与 0.1.1 线冲突);
19
+ - **「对话什么都不返回」**:`/orchestrate on` 后模型被「纯编排者」提示束缚,但 `subagent-director.roles` 未配置任何角色 → 无法委派、禁止亲自动手 → 对话无输出。现在未配置角色时不再注入束缚性的纯编排框架,而是注入一段简短「不可用提示」,指示模型明确告知用户需要先配置角色、并继续以普通模式处理请求——模型必然给出有意义的回复;
20
+ - **「不清楚是否已开启」**:`/orchestrate`(无参数)从「粘性 on」改为「本轮 on」(不写粘性事件,由 `command/run` 扫描按轮生效),命令反馈明确说明按轮/持久语义;`/orchestrate on` 保留为显式持久模式(向后兼容),`/orchestrate off` 退出持久模式;
21
+ - **`/orchestrate <任务>` 无响应**:commands 服务会整体消费斜杠命令行,任务文本到不了模型、命令返回错误 → 对话无输出。现在任意任务文本会被 handler 视为「编排该任务」:经 `agent.followup(createUserMessage(...))` 排入下一轮并唤醒模型,`command/run` 扫描(任务参数 → on)使该轮注入编排提示;
22
+ - **按轮检测被上下文注入事件击穿**(实测「分析上周A股走势」会话未编排):宿主会在用户消息之后把 runtime context / system-reminder / memos_context 作为**独立的 `user/message` 事件**追加进日志,导致「最新用户消息」「命令位于上一条与当前用户消息之间」的判定全部失效(命令被视为过期、声明消息被注入事件掩盖)。修复:检测改用 **`turn/start` 轮次边界**——消息检测取当前轮**首条**用户消息(忽略注入事件),命令扫描要求命令位于「上一轮最后一条用户消息之后、本轮 `turn/start` 之前」;无 turn 事件时回退旧逻辑。
23
+
24
+ ### 兼容性
25
+
26
+ - `orchestrate/change` 事件类型注册与投影注册保留(旧会话日志加载兼容 + 客户端 wire 视图);`renderOrchestratorPrompt` / `renderOrchestratorRoles` / `buildOrchestratorFrame` 公共 API 不变;新增导出 `detectOrchestrateRequest`、`renderOrchestratorUnavailableNotice`。
27
+
28
+ ### 测试
29
+
30
+ - 单元/集成测试由 197 增至 253:`detectOrchestrateRequest` 检测单测(斜杠/任务文本/自然语言/反例)、按轮段判定接线测试(用户消息声明、`command/run` 区间扫描、任务参数扫描、无角色不可用提示、投影兜底)、命令语义测试(无参数按轮不写事件、任务文本 followup 排队、on 持久、off 退出),以及真实 cordis `Context` + 真实 `SessionProjectionRegistry` 集成探针(无 commands 服务时主条目正常激活、核心服务缺失时保持 PENDING、commands 后到时命令经真实 `ctx.inject` 子 fiber 响应式注册、projection 经真实 `snapshot()` 驱动 on→off 折叠、按轮与任务文本探针)。
31
+
32
+ ### 已知取舍
33
+
34
+ - 用过 `/orchestrate` 的会话在未挂载本插件的 boot(卸载后、其他 profile)中无法加载:上游暂无第三方事件注册 / `ignorable` 写入 API,已在 README FAQ 与 issue #6 记录。
35
+
5
36
  ## [0.3.0] - 2026-08-29
6
37
 
7
38
  ### 新增
package/README.md CHANGED
@@ -55,7 +55,7 @@ dsh plugin --profile <name> add dsh-plugin-subagent-director
55
55
  name: dsh-plugin-subagent-director
56
56
  config:
57
57
  subagentProvider: spawn # 传输:spawn(无父上下文)/ fork(继承父历史)
58
- toolName: subagent_role # 模型可见工具名
58
+ toolName: subagent_role # 本插件注册的模型可见工具名(不是内置 subagent)
59
59
  enableRunInBackground: true
60
60
  backgroundMode: one-shot # one-shot 或 continuable
61
61
  maxDepth: 3
@@ -124,6 +124,35 @@ subagent_role({ role: "code-reviewer", model: "deepseek-chat", prompt: "..." })
124
124
  `role` 参数支持用角色 id 或显示名引用:未命中 id 时会按 `displayName` 精确匹配
125
125
  (多个同名角色取定义顺序第一个并提示);建议始终用 id,见系统提示中的 Delegate 行。
126
126
 
127
+ > **`subagent_role` 与内置 `subagent` 是两个不同的工具。** 本插件注册的是
128
+ > `subagent_role`(工具名由 `toolName` 配置,默认 `subagent_role`);DSH 基础
129
+ > bundle 另有内置的 `subagent` / `subagent_fork`,两者在同一次请求的工具清单里
130
+ > **并存**。只有走 `subagent_role` 才会应用角色 persona 与 `toolFilter`;模型改用
131
+ > 内置 `subagent` 时这两项不生效(`applyDefaultRoute` 开启时默认模型仍会生效)。
132
+ > 因此需要角色语义时,请在提示里明确要求调用 `subagent_role`。
133
+
134
+ ### 纯编排模式(`/orchestrate`)
135
+
136
+ ```text
137
+ /orchestrate 分析上周A股走势 # 本轮开启并直接编排该任务(推荐用法)
138
+ /orchestrate # 本轮开启(按轮生效,无需 on/off)
139
+ /orchestrate on # 持久开启(直到 /orchestrate off)
140
+ /orchestrate off # 退出持久模式
141
+ ```
142
+
143
+ 在消息开头声明 `/orchestrate`(可后接任务文本,如 `/orchestrate 分析上周A股走势`),
144
+ 或用自然语言写「使用orchestrate模式」(含「请使用 orchestrate 模式」「use
145
+ orchestrate mode」等变体),该轮会话即自动进入纯编排模式——类似 `/using aegis`
146
+ 的按轮声明式用法,无需记忆开关状态;未声明时保持普通模式。`/orchestrate <任务>`
147
+ 会把任务文本排入下一轮并唤醒模型,该轮以纯编排模式处理任务。开启后注入一段
148
+ 「纯编排者」系统提示:主代理只允许通过委派工具派活,角色清单从当前
149
+ `subagent-director.roles` 动态渲染(无硬编码 role id)。**未配置角色时**不会注入
150
+ 束缚性的纯编排框架,而是注入一段简短提示,让模型明确告知需要先配置角色并继续
151
+ 以普通模式处理请求(避免「对话无输出」)。该模式依赖宿主的 `commands` 与
152
+ `sessionProjections` 服务:标准 profile(dsh-base)都会提供二者;
153
+ `sessionProjections` 缺失时命令返回明确错误而不是假装成功,`commands` 缺失时
154
+ 命令不注册,插件其余功能不受影响。
155
+
127
156
  ## 术语
128
157
 
129
158
  - **subagentProvider(传输)**:`spawn` / `fork` / `acp`——子代理跑在哪条传输链路上;
@@ -135,7 +164,7 @@ subagent_role({ role: "code-reviewer", model: "deepseek-chat", prompt: "..." })
135
164
 
136
165
  ```bash
137
166
  npm install
138
- npm test # vitest(129 用例)
167
+ npm test # vitest(253 用例)
139
168
  npm run typecheck
140
169
  npm run build # host(tsc) + client(rolldown bundle)
141
170
  ```
@@ -150,6 +179,14 @@ DSH 的 Web API 只向白名单内的 settings 命名空间开放读写。本插
150
179
  `defaultProvider`/`defaultModel` 且未关闭 `applyDefaultRoute` 时,所有未显式
151
180
  指定模型的子代理(含内置工具发起的)都会使用该默认模型。
152
181
 
182
+ **用过 `/orchestrate` 的会话,卸载插件后还能打开吗?**
183
+ 不能。`/orchestrate` 会在会话日志写入 `orchestrate/change` 事件,而宿主的持久化
184
+ 加载校验遇到「未知且未标记 ignorable」的事件类型时会拒绝加载整个日志(避免误解
185
+ 日志语义)。插件挂载时会动态注册该事件类型,正常使用不受影响;但在未挂载本插件
186
+ 的环境(卸载后、其他 profile)中,这些会话将无法打开。上游暂未提供第三方事件
187
+ 类型的官方注册或 `ignorable` 写入 API,此为已知取舍,详见
188
+ [issue #6](https://github.com/SeverusZh/dsh-plugin-subagent-director/issues/6)。
189
+
153
190
  **新供应商/API 会自动出现吗?**
154
191
  会。设置页订阅了供应商与设置变更事件,在 Models 页新增供应商/API key 后,下拉列表自动刷新,无需重启。
155
192
 
package/lib/config.d.ts CHANGED
@@ -27,7 +27,17 @@ export interface DirectorConfig {
27
27
  * Default 'spawn'.
28
28
  */
29
29
  subagentProvider?: string;
30
- /** Model-facing tool name, default 'subagent_role'. Each loaded instance must use a distinct name. */
30
+ /**
31
+ * Model-facing tool name for THIS plugin's delegation tool, default
32
+ * 'subagent_role'. Each loaded instance must use a distinct name.
33
+ *
34
+ * Not the same tool as DSH's built-in `subagent` / `subagent_fork`: those are
35
+ * registered by the base bundle and coexist with this one in the same request
36
+ * tool catalog. Only calls that go through this name apply role persona and
37
+ * role `toolFilter`; a model that picks the built-in `subagent` instead gets
38
+ * neither (the default model route still applies when `applyDefaultRoute` is
39
+ * on — see below).
40
+ */
31
41
  toolName?: string;
32
42
  /** Expose `run_in_background` (default true). Disabled instances omit the argument. */
33
43
  enableRunInBackground?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,CAAC,MAAM,0BAA0B,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,sGAAsG;IACtG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,uFAAuF;IACvF,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC;IAE5C;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAAC;IAEvC;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,qDAAqD;AACrD,eAAO,MAAM,MAAM;;;;;;;;;;;;;;GAQjB,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,CAAC,MAAM,0BAA0B,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,uFAAuF;IACvF,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,UAAU,GAAG,aAAa,CAAC;IAE5C;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAAC;IAEvC;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,qDAAqD;AACrD,eAAO,MAAM,MAAM;;;;;;;;;;;;;;GAQjB,CAAC"}
package/lib/config.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,CAAC,MAAM,0BAA0B,CAAC;AAiDzC,qDAAqD;AACrD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IAC7C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC;IAC7C,qBAAqB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAChD,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IACxE,QAAQ,EAAE,CAAC;SACR,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACjF,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAC7C,CAAC,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,CAAC,MAAM,0BAA0B,CAAC;AA2DzC,qDAAqD;AACrD,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IAC7C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC;IAC7C,qBAAqB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAChD,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IACxE,QAAQ,EAAE,CAAC;SACR,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACjF,iBAAiB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CAC7C,CAAC,CAAC"}
package/lib/index.d.ts CHANGED
@@ -8,7 +8,10 @@
8
8
  * Dependency posture: tools/subagents/llm/settings are required through inject
9
9
  * (both web and headless bundles mount the settings service); systemPrompt
10
10
  * remains optional and is acquired lazily so its absence does not block the
11
- * rest. The webServer-dependent HTTP bridge lives in the separate
11
+ * rest. The /orchestrate command's `commands` dependency likewise stays
12
+ * optional — acquired reactively (ctx.inject child fiber) in orchestrate.ts,
13
+ * so hosts without a command registry lose only that command. The
14
+ * webServer-dependent HTTP bridge lives in the separate
12
15
  * \`subagent-director-bridge\` entry (src/bridge-entry.ts).
13
16
  *
14
17
  * Background modes: 'one-shot' defaults calls to foreground and runs background
@@ -22,6 +25,7 @@ export { Config } from './config.js';
22
25
  export type { DirectorConfig } from './config.js';
23
26
  export { assertDelegationCapabilities, buildSubagentRequest, createDelegationParameters, createDelegationOutputSchema, createDelegationTool, DELEGATION_TOOL_PREFIX, resolveDelegationMode, renderDelegationResult, type DelegationToolArgs, type DelegationResult, type DelegationRoute, type DelegationModeDecision, type SubagentRequestParts, } from './delegation-tool.js';
24
27
  export { applyGuidance, renderRolesGuidance, GUIDANCE_SECTION_ORDER, GUIDANCE_SECTION_NAME } from './guidance.js';
28
+ export { applyOrchestrate, renderOrchestratorPrompt, renderOrchestratorRoles, renderOrchestratorUnavailableNotice, buildOrchestratorFrame, detectOrchestrateRequest, ORCHESTRATE_SECTION_NAME, ORCHESTRATE_SECTION_ORDER, ORCHESTRATE_PROJECTION_KEY, ORCHESTRATE_EVENT_TYPE, ORCHESTRATE_VALID_MODES, type OrchestrateMode, type OrchestrateRequest, } from './orchestrate.js';
25
29
  export { CLOSE_SUBAGENT_TOOL_NAME, createCloseSubagentTool } from './close-tool.js';
26
30
  export { SUBAGENT_DIRECTOR_SETTINGS_NAMESPACE, SettingsSchema, validateDirectorSettings, installDirectorSettings, type RoleTemplate, type SubagentDirectorSettings, } from './settings.js';
27
31
  export declare const name = "subagent-director";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAUnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,0BAA0B,EAC1B,4BAA4B,EAC5B,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAClH,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EACL,oCAAoC,EACpC,cAAc,EACd,wBAAwB,EACxB,uBAAuB,EACvB,KAAK,YAAY,EACjB,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC;AAEvB,eAAO,MAAM,IAAI,sBAAsB,CAAC;AAExC,eAAO,MAAM,MAAM,UAA4C,CAAC;AAEhE,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,aAAa,EAAE,cAAc,QAgE/E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAWnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EACL,4BAA4B,EAC5B,oBAAoB,EACpB,0BAA0B,EAC1B,4BAA4B,EAC5B,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,sBAAsB,EACtB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAClH,OAAO,EACL,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,mCAAmC,EACnC,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,yBAAyB,EACzB,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACxB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AACpF,OAAO,EACL,oCAAoC,EACpC,cAAc,EACd,wBAAwB,EACxB,uBAAuB,EACvB,KAAK,YAAY,EACjB,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC;AAEvB,eAAO,MAAM,IAAI,sBAAsB,CAAC;AAExC,eAAO,MAAM,MAAM,UAA4C,CAAC;AAEhE,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,aAAa,EAAE,cAAc,QAmE/E"}
package/lib/index.js CHANGED
@@ -3,10 +3,12 @@ import { createDelegationTool } from './delegation-tool.js';
3
3
  import { CLOSE_SUBAGENT_TOOL_NAME, createCloseSubagentTool } from './close-tool.js';
4
4
  import { applyDefaultRouteSeam } from './default-route.js';
5
5
  import { applyGuidance } from './guidance.js';
6
+ import { applyOrchestrate } from './orchestrate.js';
6
7
  import { createSettingsSnapshot, installDirectorSettings } from './settings.js';
7
8
  export { Config } from './config.js';
8
9
  export { assertDelegationCapabilities, buildSubagentRequest, createDelegationParameters, createDelegationOutputSchema, createDelegationTool, DELEGATION_TOOL_PREFIX, resolveDelegationMode, renderDelegationResult, } from './delegation-tool.js';
9
10
  export { applyGuidance, renderRolesGuidance, GUIDANCE_SECTION_ORDER, GUIDANCE_SECTION_NAME } from './guidance.js';
11
+ export { applyOrchestrate, renderOrchestratorPrompt, renderOrchestratorRoles, renderOrchestratorUnavailableNotice, buildOrchestratorFrame, detectOrchestrateRequest, ORCHESTRATE_SECTION_NAME, ORCHESTRATE_SECTION_ORDER, ORCHESTRATE_PROJECTION_KEY, ORCHESTRATE_EVENT_TYPE, ORCHESTRATE_VALID_MODES, } from './orchestrate.js';
10
12
  export { CLOSE_SUBAGENT_TOOL_NAME, createCloseSubagentTool } from './close-tool.js';
11
13
  export { SUBAGENT_DIRECTOR_SETTINGS_NAMESPACE, SettingsSchema, validateDirectorSettings, installDirectorSettings, } from './settings.js';
12
14
  export const name = 'subagent-director';
@@ -35,6 +37,8 @@ export function apply(ctx, config) {
35
37
  }
36
38
  // ---- role guidance ----------------------------------------------------
37
39
  applyGuidance(ctx, getSettings, toolName);
40
+ // ---- orchestrate command + projection + prompt section ----------------
41
+ applyOrchestrate(ctx, getSettings, toolName);
38
42
  // ---- close_subagent tool ----------------------------------------------
39
43
  // Provider-independent (drain is a global subagents operation), so it
40
44
  // registers at mount time like the control tools; on a deployment without
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Orchestrate command for Subagent Director (merged from the standalone
3
+ * `orchestrate` plugin).
4
+ *
5
+ * Adds a `/orchestrate on|off` slash command that flips a per-session
6
+ * projection and, when on, injects a pure-orchestrator system-prompt section.
7
+ * The orchestrator delegates exclusively through the subagent-director
8
+ * delegation tool, whose model-facing name is `config.toolName` (default
9
+ * `subagent_role`) and is threaded in here as `toolName`.
10
+ *
11
+ * Naming caveat (observed on a live 0.1.1-rc.x web host): the assembled tool catalog
12
+ * contains BOTH this plugin's `subagent_role` and the base bundle's built-in
13
+ * `subagent` / `subagent_fork`. They are distinct tools, not two names for one
14
+ * wire entry. The prompt below names `toolName` explicitly precisely because a
15
+ * model that reaches for the built-in `subagent` bypasses role persona and role
16
+ * toolFilter.
17
+ *
18
+ * The role list rendered into the prompt is derived dynamically from the live
19
+ * plugin settings (`subagent-director.roles`) — the same source `guidance.ts`
20
+ * reads — so it never hard-codes role ids and stays correct when the operator
21
+ * reconfigures roles. When no roles are configured the prompt tells the user
22
+ * to configure them rather than silently emitting an empty section.
23
+ *
24
+ * Service posture mirrors `guidance.ts`: `commands` and `sessionProjections` are
25
+ * acquired reactively through `ctx.inject` (so the `/orchestrate` command and the
26
+ * projection register as soon as the host service is ready, even if it mounts
27
+ * slightly after `apply`), while `systemPrompt` is still read lazily via
28
+ * `ctx.get`. A host that never provides `sessionProjections` degrades to an
29
+ * honest error from the command handler rather than a silent no-op.
30
+ */
31
+ import type { Context } from '@deepseek-ai/cordis';
32
+ import type { SubagentDirectorSettings } from './settings.js';
33
+ /** Stable system-prompt section name. */
34
+ export declare const ORCHESTRATE_SECTION_NAME = "orchestrate-mode";
35
+ /** Prompt order: sits low (55) so the orchestrator contract is near the top. */
36
+ export declare const ORCHESTRATE_SECTION_ORDER = 55;
37
+ /** Per-session projection key holding the orchestrator on/off state. */
38
+ export declare const ORCHESTRATE_PROJECTION_KEY = "orchestrate";
39
+ /** Session event type emitted when the mode changes. */
40
+ export declare const ORCHESTRATE_EVENT_TYPE = "orchestrate/change";
41
+ /** Accepted mode values. */
42
+ export declare const ORCHESTRATE_VALID_MODES: readonly ['on', 'off'];
43
+ export type OrchestrateMode = (typeof ORCHESTRATE_VALID_MODES)[number];
44
+ /** Per-turn orchestrate request parsed from one user message. */
45
+ export type OrchestrateRequest = 'on' | 'off' | undefined;
46
+ /**
47
+ * Detect whether a user message requests pure-orchestrator mode for this turn.
48
+ * Slash form: `/orchestrate` — `off` → off; no args, `on`, or any task text
49
+ * (e.g. `/orchestrate 分析上周A股走势`) → on.
50
+ * Natural-language form (case-insensitive, anchored at the start with an
51
+ * optional politeness prefix so questions like 什么是orchestrate模式 do not
52
+ * false-positive): 使用orchestrate模式 / 使用 orchestrate mode / use orchestrate mode.
53
+ */
54
+ export declare function detectOrchestrateRequest(text: string): OrchestrateRequest;
55
+ /**
56
+ * Short notice injected instead of the pure-orchestrator frame when the mode
57
+ * is on but no roles are configured: the model must inform the user and
58
+ * continue in normal mode — never sit paralyzed (the "returns nothing" bug).
59
+ */
60
+ export declare function renderOrchestratorUnavailableNotice(toolName: string): string;
61
+ interface OrchestrateState {
62
+ mode: OrchestrateMode;
63
+ }
64
+ declare module '@deepseek-ai/dsh-session/types' {
65
+ interface SessionEventMap {
66
+ 'orchestrate/change': {
67
+ mode: OrchestrateMode;
68
+ };
69
+ }
70
+ }
71
+ declare module '@deepseek-ai/dsh-session-projection/types' {
72
+ interface SessionProjectionStateMap {
73
+ /** /orchestrate mode state, folded from `orchestrate/change` events. */
74
+ orchestrate: OrchestrateState;
75
+ }
76
+ interface SessionProjectionMap {
77
+ /** Client-visible wire payload of the orchestrate projection unit. */
78
+ orchestrate: {
79
+ mode: OrchestrateMode;
80
+ };
81
+ }
82
+ }
83
+ /**
84
+ * Build the data-independent framing of the orchestrator prompt for a given
85
+ * delegation tool name. The role list is appended separately by
86
+ * {@link renderOrchestratorRoles}.
87
+ * @param toolName - the configured model-facing delegation tool name.
88
+ */
89
+ export declare function buildOrchestratorFrame(toolName: string): string;
90
+ /**
91
+ * Render the role list portion of the orchestrator prompt from the live
92
+ * settings. Returns a "configure roles first" notice when no roles exist so
93
+ * the operator is told what to do instead of receiving a blank contract.
94
+ * @param settings - current resolved settings snapshot.
95
+ * @param toolName - the configured model-facing delegation tool name.
96
+ */
97
+ export declare function renderOrchestratorRoles(settings: SubagentDirectorSettings, toolName: string): string;
98
+ /**
99
+ * Assemble the full orchestrator prompt (framing + dynamic role list).
100
+ * @param settings - current resolved settings snapshot.
101
+ * @param toolName - the configured model-facing delegation tool name.
102
+ */
103
+ export declare function renderOrchestratorPrompt(settings: SubagentDirectorSettings, toolName: string): string;
104
+ /**
105
+ * Wire the `/orchestrate` command, its session projection, and the
106
+ * orchestrator prompt section into the host. Each host-plane service is
107
+ * acquired lazily and guarded, so a missing service degrades to a no-op.
108
+ * @param ctx - plugin context.
109
+ * @param getSettings - returns the current settings snapshot.
110
+ * @param toolName - the configured model-facing delegation tool name.
111
+ */
112
+ export declare function applyOrchestrate(ctx: Context, getSettings: () => SubagentDirectorSettings, toolName: string): void;
113
+ export {};
114
+ //# sourceMappingURL=orchestrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrate.d.ts","sourceRoot":"","sources":["../src/orchestrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAMnD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAE9D,yCAAyC;AACzC,eAAO,MAAM,wBAAwB,qBAAqB,CAAC;AAE3D,gFAAgF;AAChF,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAE5C,wEAAwE;AACxE,eAAO,MAAM,0BAA0B,gBAAgB,CAAC;AAExD,wDAAwD;AACxD,eAAO,MAAM,sBAAsB,uBAAuB,CAAC;AAE3D,4BAA4B;AAC5B,eAAO,MAAM,uBAAuB,YAAI,IAAI,EAAE,KAAK,CAAU,CAAC;AAC9D,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE,iEAAiE;AACjE,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,KAAK,GAAG,SAAS,CAAC;AAE1D;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAWzE;AAED;;;;GAIG;AACH,wBAAgB,mCAAmC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK5E;AAED,UAAU,gBAAgB;IACxB,IAAI,EAAE,eAAe,CAAC;CACvB;AAYD,OAAO,QAAQ,gCAAgC,CAAC;IAC9C,UAAU,eAAe;QACvB,oBAAoB,EAAE;YAAE,IAAI,EAAE,eAAe,CAAA;SAAE,CAAC;KACjD;CACF;AAED,OAAO,QAAQ,2CAA2C,CAAC;IACzD,UAAU,yBAAyB;QACjC,wEAAwE;QACxE,WAAW,EAAE,gBAAgB,CAAC;KAC/B;IACD,UAAU,oBAAoB;QAC5B,sEAAsE;QACtE,WAAW,EAAE;YAAE,IAAI,EAAE,eAAe,CAAA;SAAE,CAAC;KACxC;CACF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM/D;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAepG;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUrG;AA4GD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,OAAO,EACZ,WAAW,EAAE,MAAM,wBAAwB,EAC3C,QAAQ,EAAE,MAAM,GACf,IAAI,CA8QN"}
@@ -0,0 +1,483 @@
1
+ import { z } from 'zod';
2
+ import { createUserMessage } from '@deepseek-ai/dsh-llm';
3
+ import { KNOWN_SESSION_EVENT_TYPES } from '@deepseek-ai/dsh-session';
4
+ /** Stable system-prompt section name. */
5
+ export const ORCHESTRATE_SECTION_NAME = 'orchestrate-mode';
6
+ /** Prompt order: sits low (55) so the orchestrator contract is near the top. */
7
+ export const ORCHESTRATE_SECTION_ORDER = 55;
8
+ /** Per-session projection key holding the orchestrator on/off state. */
9
+ export const ORCHESTRATE_PROJECTION_KEY = 'orchestrate';
10
+ /** Session event type emitted when the mode changes. */
11
+ export const ORCHESTRATE_EVENT_TYPE = 'orchestrate/change';
12
+ /** Accepted mode values. */
13
+ export const ORCHESTRATE_VALID_MODES = ['on', 'off'];
14
+ /**
15
+ * Detect whether a user message requests pure-orchestrator mode for this turn.
16
+ * Slash form: `/orchestrate` — `off` → off; no args, `on`, or any task text
17
+ * (e.g. `/orchestrate 分析上周A股走势`) → on.
18
+ * Natural-language form (case-insensitive, anchored at the start with an
19
+ * optional politeness prefix so questions like 什么是orchestrate模式 do not
20
+ * false-positive): 使用orchestrate模式 / 使用 orchestrate mode / use orchestrate mode.
21
+ */
22
+ export function detectOrchestrateRequest(text) {
23
+ const trimmed = text.trimStart();
24
+ const slash = trimmed.match(/^\/orchestrate(?:\s+(\S+))?/i);
25
+ if (slash) {
26
+ const arg = (slash[1] ?? '').trim().toLowerCase();
27
+ if (arg === 'off')
28
+ return 'off';
29
+ return 'on';
30
+ }
31
+ if (/^(请|麻烦|麻烦你|帮我|请帮我|我想|我要)?\s*使用\s*orchestrate\s*(模式|mode)/i.test(trimmed))
32
+ return 'on';
33
+ if (/^use\s+orchestrate\s+mode/i.test(trimmed))
34
+ return 'on';
35
+ return undefined;
36
+ }
37
+ /**
38
+ * Short notice injected instead of the pure-orchestrator frame when the mode
39
+ * is on but no roles are configured: the model must inform the user and
40
+ * continue in normal mode — never sit paralyzed (the "returns nothing" bug).
41
+ */
42
+ export function renderOrchestratorUnavailableNotice(toolName) {
43
+ return (`Orchestrator mode is active, but no subagent-director roles are configured (subagent-director.roles is empty), so you cannot delegate work via \`${toolName}\`. ` +
44
+ `Inform the user that orchestrator mode requires roles to be configured first, then handle their request in normal mode.`);
45
+ }
46
+ /**
47
+ * Build the data-independent framing of the orchestrator prompt for a given
48
+ * delegation tool name. The role list is appended separately by
49
+ * {@link renderOrchestratorRoles}.
50
+ * @param toolName - the configured model-facing delegation tool name.
51
+ */
52
+ export function buildOrchestratorFrame(toolName) {
53
+ return `You are a PURE ORCHESTRATOR. Your only action is to call the \`${toolName}\` tool (provided by the subagent-director plugin) to delegate work. You must NEVER read, write, edit, grep, find, or execute anything yourself.
54
+
55
+ The subagent-director plugin supplies its role templates from settings (subagent-director.roles) and the guidance section 'subagent-director:roles'. Delegate exactly one task per call:
56
+
57
+ ${toolName}({ role: '<role-id>', prompt: '<self-contained task>', description: '<what this delegation produces>' })`;
58
+ }
59
+ /**
60
+ * Render the role list portion of the orchestrator prompt from the live
61
+ * settings. Returns a "configure roles first" notice when no roles exist so
62
+ * the operator is told what to do instead of receiving a blank contract.
63
+ * @param settings - current resolved settings snapshot.
64
+ * @param toolName - the configured model-facing delegation tool name.
65
+ */
66
+ export function renderOrchestratorRoles(settings, toolName) {
67
+ const roles = settings.roles ?? {};
68
+ const entries = Object.entries(roles).filter(([, role]) => role !== undefined);
69
+ if (entries.length === 0) {
70
+ return 'No Subagent Director roles are configured yet. Configure `subagent-director.roles` (settings.yaml or the settings panel) before entering orchestrator mode — the orchestrator can only delegate to defined roles.';
71
+ }
72
+ const lines = [
73
+ `Delegate work by calling the \`${toolName}\` tool with a role id from the list below. Reference roles by their id (shown), never by display name, and never invent a role id that is not listed:`,
74
+ ];
75
+ for (const [id, role] of entries) {
76
+ lines.push(`- ${role.displayName || id}: ${role.description}`);
77
+ lines.push(` ${toolName}({ role: "${id}", prompt: "..." })`);
78
+ }
79
+ return lines.join('\n');
80
+ }
81
+ /**
82
+ * Assemble the full orchestrator prompt (framing + dynamic role list).
83
+ * @param settings - current resolved settings snapshot.
84
+ * @param toolName - the configured model-facing delegation tool name.
85
+ */
86
+ export function renderOrchestratorPrompt(settings, toolName) {
87
+ return `${buildOrchestratorFrame(toolName)}\n\n${renderOrchestratorRoles(settings, toolName)}\n\nOrchestration rules:
88
+ 1. Only dispatch. Forbid doing the work yourself.
89
+ 2. Independent tasks -> dispatch them in parallel (multiple ${toolName} calls in one turn).
90
+ 3. Dependent / relay tasks -> wait for the prior subagent to finish, then dispatch the next stage.
91
+ 4. Every subagent prompt must be self-contained: goal, constraints, output format, acceptance criteria. Subagents receive NO parent context.
92
+ 5. If the user's request names a specific role, dispatch to that role id. If a display name is given, map it to its id. If no role is named, dispatch to the role whose display name indicates coordination (e.g. contains 协调 / Orchestrator / Coordinator); when no such role exists, dispatch to the first configured role and let it decompose and coordinate.
93
+ 6. Unclear dependencies or missing information -> ask the USER, never guess.
94
+ 7. For independent fan-out you may set run_in_background: true and collect results later; for relay steps set run_in_background: false so you wait for the result before dispatching the next stage.
95
+ 8. Finish only when every subagent has completed. Then output a summary report: who produced what, and remaining todos.`;
96
+ }
97
+ /**
98
+ * Full orchestrator prompt when roles are configured, else the short
99
+ * unavailable notice. The notice (not the paralyzing pure-orchestrator frame)
100
+ * is what prevents the "conversation returns nothing" failure: a model that
101
+ * cannot delegate must be told to inform the user and continue normally.
102
+ * @param settings - current resolved settings snapshot.
103
+ * @param toolName - the configured model-facing delegation tool name.
104
+ */
105
+ function renderOrchestratorSection(settings, toolName) {
106
+ const roles = settings.roles ?? {};
107
+ const hasRoles = Object.values(roles).some((role) => role !== undefined);
108
+ if (!hasRoles)
109
+ return renderOrchestratorUnavailableNotice(toolName);
110
+ return renderOrchestratorPrompt(settings, toolName);
111
+ }
112
+ /**
113
+ * Text of the user message that started the CURRENT turn, or undefined when
114
+ * the log has no user message in the current turn.
115
+ *
116
+ * The harness appends runtime-context injections (runtime snapshot,
117
+ * system-reminder, memos_context) as SEPARATE `user/message` events AFTER the
118
+ * real user message, so the FIRST user/message at or after the latest
119
+ * `turn/start` — not the latest event — carries the user's actual prompt.
120
+ * Without a `turn/start` (degenerate seed), falls back to the latest
121
+ * user/message. Text blocks are concatenated in order; non-text blocks skipped.
122
+ * @param session - a live Session (or a faithful fake with `.events`).
123
+ */
124
+ function currentTurnUserMessageText(session) {
125
+ const events = session?.events;
126
+ if (!Array.isArray(events))
127
+ return undefined;
128
+ let turnStart = -1;
129
+ for (const ev of events) {
130
+ if (ev && ev.type === 'turn/start' && typeof ev.seq === 'number')
131
+ turnStart = ev.seq;
132
+ }
133
+ for (const ev of events) {
134
+ if (!ev || ev.type !== 'user/message')
135
+ continue;
136
+ if (turnStart >= 0 && typeof ev.seq === 'number' && ev.seq < turnStart)
137
+ continue;
138
+ const blocks = ev.data?.content;
139
+ if (!Array.isArray(blocks))
140
+ return '';
141
+ let text = '';
142
+ for (const b of blocks) {
143
+ if (b && b.type === 'text' && typeof b.text === 'string')
144
+ text += b.text;
145
+ }
146
+ return text;
147
+ }
148
+ return undefined;
149
+ }
150
+ /**
151
+ * Per-turn slash path: an `orchestrate` command/run that happened since the
152
+ * previous turn marks the current turn (the command itself is consumed by the
153
+ * commands service and never appears in a user/message event). The command is
154
+ * "recent" when it sits strictly AFTER the last user message of the previous
155
+ * turn and BEFORE the current turn's `turn/start` — context-injection
156
+ * user/message events inside the current turn do not count as "previous".
157
+ * Without any `turn/start` (degenerate seed) falls back to the strictly
158
+ * between previous/current user-message check. Returns 'on' | 'off' | undefined.
159
+ * @param session - a live Session (or a faithful fake with `.events`).
160
+ */
161
+ function recentOrchestrateCommandRun(session) {
162
+ const events = session?.events;
163
+ if (!Array.isArray(events))
164
+ return undefined;
165
+ let turnStart = -1;
166
+ let cmdSeq = -1;
167
+ let cmdArgs;
168
+ for (const ev of events) {
169
+ if (!ev || typeof ev.seq !== 'number')
170
+ continue;
171
+ if (ev.type === 'turn/start')
172
+ turnStart = ev.seq;
173
+ if (ev.type === 'command/run' && ev.data?.name === 'orchestrate') {
174
+ cmdSeq = ev.seq;
175
+ cmdArgs = ev.data.args;
176
+ }
177
+ }
178
+ if (cmdSeq < 0)
179
+ return undefined;
180
+ if (turnStart >= 0) {
181
+ // The command must have happened after the last user message of the
182
+ // previous turn(s) AND before the current turn started.
183
+ let lastUserBeforeTurn = -1;
184
+ for (const ev of events) {
185
+ if (!ev || ev.type !== 'user/message')
186
+ continue;
187
+ const s = typeof ev.seq === 'number' ? ev.seq : -1;
188
+ if (s >= 0 && s < turnStart && s > lastUserBeforeTurn)
189
+ lastUserBeforeTurn = s;
190
+ }
191
+ if (cmdSeq <= lastUserBeforeTurn || cmdSeq >= turnStart)
192
+ return undefined;
193
+ }
194
+ else {
195
+ // Fallback: strictly between the previous and the current user message.
196
+ let prevUserSeq = -1;
197
+ let currentUserSeq = -1;
198
+ for (const ev of events) {
199
+ if (!ev || ev.type !== 'user/message')
200
+ continue;
201
+ const s = typeof ev.seq === 'number' ? ev.seq : -1;
202
+ if (s < 0)
203
+ continue;
204
+ prevUserSeq = currentUserSeq;
205
+ currentUserSeq = s;
206
+ }
207
+ if (cmdSeq <= prevUserSeq || cmdSeq >= currentUserSeq)
208
+ return undefined;
209
+ }
210
+ const arg = (cmdArgs ?? '').trim().toLowerCase();
211
+ if (arg === 'off')
212
+ return 'off';
213
+ // '' (bare), 'on', or task text (e.g. 分析上周A股走势 — the handler queued
214
+ // it as a follow-up turn) all mark this turn orchestrated.
215
+ return 'on';
216
+ }
217
+ /**
218
+ * Wire the `/orchestrate` command, its session projection, and the
219
+ * orchestrator prompt section into the host. Each host-plane service is
220
+ * acquired lazily and guarded, so a missing service degrades to a no-op.
221
+ * @param ctx - plugin context.
222
+ * @param getSettings - returns the current settings snapshot.
223
+ * @param toolName - the configured model-facing delegation tool name.
224
+ */
225
+ export function applyOrchestrate(ctx, getSettings, toolName) {
226
+ // Register our event type on the shared KNOWN set so session logs carrying
227
+ // `orchestrate/change` load in any boot that mounts this plugin.
228
+ // The shared set is a mutable Set at runtime; its exported type is
229
+ // ReadonlySet, so we widen to Set<string> for the add call.
230
+ try {
231
+ KNOWN_SESSION_EVENT_TYPES.add(ORCHESTRATE_EVENT_TYPE);
232
+ }
233
+ catch (err) {
234
+ ctx.logger.warn('[orchestrate] could not register event type:', err?.message);
235
+ }
236
+ // Resolve sessionProjections *reactively*. At plugin apply time the host
237
+ // may not have mounted the sessionProjections service yet — that is the P0
238
+ // timing root cause: a one-shot `ctx.get` here returned undefined and
239
+ // silently no-op'd the projection registration, so /orchestrate never
240
+ // injected. Instead we register the projection the moment the service becomes
241
+ // available via ctx.inject, and keep `projections` in a closure so the
242
+ // command handler and prompt section observe it once it resolves. If the
243
+ // service is genuinely absent the handler (and the apply-time fallback)
244
+ // surface an honest error instead of a silent no-op.
245
+ let projections = undefined;
246
+ const missing = () => ctx.logger.warn('[orchestrate] sessionProjections service is missing on this host — the /orchestrate command will NOT take effect (no projection registered, orchestrator prompt will not inject). Provide the dsh-session-projection sessionProjections service to enable orchestrator mode.');
247
+ const registerProjection = (sp) => {
248
+ if (projections !== undefined)
249
+ return; // idempotent: inject may re-fire
250
+ projections = sp;
251
+ sp.register({
252
+ key: ORCHESTRATE_PROJECTION_KEY,
253
+ stateVersion: 1,
254
+ // Real @deepseek-ai/dsh-session-projection contract (SessionProjectionRegistry):
255
+ // `stateSchema` validates host state (persisted-cache restore path); a
256
+ // client-visible unit MUST declare `wire: { viewSchema, view }` or
257
+ // `snapshot()` SKIPS it entirely (`if (def.wire === undefined) continue`),
258
+ // so `snapshot().values['orchestrate']` is never populated and the prompt
259
+ // section always reads undefined → no injection. The prior `schema` + bare
260
+ // `view` made this a host-only unit — the actual root cause of the
261
+ // on==off byte-identical system prompts. Fix: declare both correctly.
262
+ stateSchema: z.object({ mode: z.enum(ORCHESTRATE_VALID_MODES) }),
263
+ init: () => ({ mode: 'off' }),
264
+ apply: (state, event) => {
265
+ if (!event || event.type !== ORCHESTRATE_EVENT_TYPE)
266
+ return state;
267
+ const mode = event.data.mode;
268
+ if (!ORCHESTRATE_VALID_MODES.includes(mode) || state.mode === mode)
269
+ return state;
270
+ return { mode };
271
+ },
272
+ wire: {
273
+ viewSchema: z.object({ mode: z.enum(ORCHESTRATE_VALID_MODES) }),
274
+ view: (state) => ({ mode: state.mode }),
275
+ },
276
+ });
277
+ ctx.logger.info('[orchestrate] host active (command + projection + prompt section)');
278
+ };
279
+ const spNow = ctx.get('sessionProjections');
280
+ if (spNow !== undefined) {
281
+ registerProjection(spNow);
282
+ }
283
+ else {
284
+ // Reactive path: register once the host mounts sessionProjections. The
285
+ // child fiber's callback only runs when the dependency is present, so
286
+ // this also covers the "ready slightly later" case that the one-shot get
287
+ // missed. If the service never appears, the handler below returns an
288
+ // honest error — no silent no-op.
289
+ //
290
+ // The child fiber is owned by this plugin's fiber lifecycle (its
291
+ // registration effect lives on the parent fiber), so it unloads
292
+ // automatically with the plugin. Do NOT wrap it in ctx.effect: cordis
293
+ // effects run their callback immediately and treat the return value as
294
+ // the disposer, so `ctx.effect(() => fiber.dispose())` would unload the
295
+ // child at birth — pinned by the real-cordis probe in
296
+ // test/orchestrate-cordis.test.ts.
297
+ ctx.inject(['sessionProjections'], (injectedCtx) => {
298
+ registerProjection(injectedCtx.get('sessionProjections'));
299
+ });
300
+ }
301
+ // Register the `/orchestrate` slash command *reactively* through a
302
+ // `ctx.inject` child fiber (the dsh-plan-mode precedent). `commands` is NOT a
303
+ // required entry-inject: standard profiles mount it via dsh-base (so the
304
+ // child fiber activates immediately there), but non-dsh-base assemblies (ACP
305
+ // hosts, UI-less demo spines, custom harnesses) may never provide it, and a
306
+ // required inject would leave the whole main entry PENDING on those hosts —
307
+ // the core delegation features would never load. The child-fiber shape also
308
+ // recovers from a host that mounts `commands` slightly after `apply`. The
309
+ // handler reads `projections` from the closure, so command availability and
310
+ // projection availability are decoupled: the handler still refuses honestly
311
+ // (with a warning) if the projection service never came up.
312
+ // The child fiber is owned by this plugin's fiber lifecycle and unloads
313
+ // with the plugin — never wrap it in ctx.effect (cordis effects run their
314
+ // callback immediately and treat the return value as the disposer, so
315
+ // `ctx.effect(() => fiber.dispose())` would unload the child at birth;
316
+ // pinned by the real-cordis probe in test/orchestrate-cordis.test.ts).
317
+ ctx.inject(['commands'], (injectedCtx) => {
318
+ const commands = injectedCtx.get('commands');
319
+ commands.register({
320
+ name: 'orchestrate',
321
+ description: 'Enter pure-orchestrator mode for this turn — /orchestrate <task> (e.g. /orchestrate 分析上周A股走势) or say 使用orchestrate模式. No args = this turn; on = persistent until off.',
322
+ input: { hint: '<task> | on | off (no args = this turn)' },
323
+ handler: (invocation) => {
324
+ const raw = (invocation.rawInput || '').trim();
325
+ const lower = raw.toLowerCase();
326
+ const mode = lower || 'on';
327
+ // Without sessionProjections the projection is never registered, so
328
+ // /orchestrate cannot take effect. Refuse with an honest message
329
+ // instead of falsely reporting success (P0 silent-degradation fix).
330
+ if (projections === undefined) {
331
+ // Service never became available (truly absent host): refuse with an
332
+ // honest message and warn, instead of falsely reporting success (P0
333
+ // silent-degradation fix).
334
+ missing();
335
+ return {
336
+ kind: 'error',
337
+ text: `Orchestrator mode "${mode}" was NOT applied: the sessionProjections service is missing on this host, so /orchestrate has no effect and the orchestrator prompt will not inject. ` +
338
+ `Provide the dsh-session-projection sessionProjections service to enable orchestrator mode.`,
339
+ };
340
+ }
341
+ const agent = invocation?.agent;
342
+ const session = agent?.session;
343
+ if (session === undefined || typeof session.append !== 'function') {
344
+ return {
345
+ kind: 'error',
346
+ text: `Orchestrator mode "${mode}" was NOT applied: this command invocation carries no agent session to append the mode change to.`,
347
+ };
348
+ }
349
+ if (!ORCHESTRATE_VALID_MODES.includes(mode)) {
350
+ // Task text: orchestrate THIS task. The commands service consumes the
351
+ // whole line, so queue the task as a follow-up turn (wakes the agent);
352
+ // the per-turn command/run scan marks that turn orchestrated.
353
+ if (typeof agent?.followup !== 'function') {
354
+ return {
355
+ kind: 'error',
356
+ text: `Orchestrator mode was NOT applied: this agent cannot queue a follow-up turn (no followup method).`,
357
+ };
358
+ }
359
+ agent.followup(createUserMessage({
360
+ content: [{ type: 'text', text: raw }],
361
+ source: { kind: 'user' },
362
+ }));
363
+ const preview = raw.length > 60 ? `${raw.slice(0, 60)}…` : raw;
364
+ return {
365
+ kind: 'success',
366
+ text: `Orchestrator mode: on for this turn — task queued: "${preview}"`,
367
+ };
368
+ }
369
+ if (mode === 'on' && raw === '') {
370
+ // Per-turn: no sticky event. The section detects this command/run
371
+ // and orchestrates the NEXT user-message turn only.
372
+ return {
373
+ kind: 'success',
374
+ text: 'Orchestrator mode: on for this turn. Declare /orchestrate at the start of your message (or say 使用orchestrate模式) to enable it per turn; use /orchestrate on to keep it on until /orchestrate off.',
375
+ };
376
+ }
377
+ session.append(ORCHESTRATE_EVENT_TYPE, { mode });
378
+ return {
379
+ kind: 'success',
380
+ text: mode === 'off' ? 'Orchestrator mode: off' : 'Orchestrator mode: on (persistent until /orchestrate off)',
381
+ };
382
+ },
383
+ });
384
+ });
385
+ const systemPrompt = ctx.get('systemPrompt');
386
+ if (systemPrompt !== undefined) {
387
+ systemPrompt.section({
388
+ name: ORCHESTRATE_SECTION_NAME,
389
+ order: ORCHESTRATE_SECTION_ORDER,
390
+ text: (context) => {
391
+ // Root-cause note (P0 render-time silent no-op, sibling of C1):
392
+ // @deepseek-ai/dsh-session-projection's read face keys its per-session
393
+ // watermark cache by the SESSION OBJECT via a WeakMap and folds
394
+ // `session.events` (see cellFor/buildCell in the package's lib/index.js).
395
+ // A snapshot therefore reads the mode ONLY from the live Session object
396
+ // whose `.events` log carries the `orchestrate/change` event that the
397
+ // /orchestrate command appended. If the assembly context hands a
398
+ // DIFFERENT session reference (e.g. a request wrapper instead of the
399
+ // agent's own session), the cell is rebuilt from an empty log and
400
+ // silently returns 'off', dropping the section. We must hand the
401
+ // canonical session object — and try every session reference the
402
+ // context exposes so a stray wrapper reference cannot downgrade us.
403
+ const sessionCandidates = [];
404
+ if (context?.agent?.session)
405
+ sessionCandidates.push(context.agent.session);
406
+ if (context?.session && context.session !== context?.agent?.session) {
407
+ sessionCandidates.push(context.session);
408
+ }
409
+ if (sessionCandidates.length === 0) {
410
+ // No resolvable session — cannot read the projection. Warn instead of
411
+ // silently dropping (P0 honest-degradation; do not return '' silently).
412
+ ctx.logger.warn('[orchestrate] system-prompt section invoked without a resolvable session (both context.agent.session and context.session are absent) — orchestrator-mode section skipped. Possible cause: the assembly context shape differs from the dsh-agent AssembleContext contract.');
413
+ return '';
414
+ }
415
+ // P0 missing-service path: the service never mounted. The apply-time
416
+ // missing() already emitted the loud warning, so only the section is
417
+ // skipped here (no per-assembly re-warning).
418
+ if (projections === undefined)
419
+ return '';
420
+ // Per-turn detection (the /using-aegis-like usage): the user message
421
+ // that started THIS turn, or a just-run /orchestrate command, decides
422
+ // this turn. The sticky projection below is only the backward-compat
423
+ // fallback. (Context-injection user/message events after the real
424
+ // message are ignored: currentTurnUserMessageText reads the FIRST
425
+ // message of the turn, and recentOrchestrateCommandRun bounds the
426
+ // command by turn/start, not by those injection events.)
427
+ for (const candidate of sessionCandidates) {
428
+ const msgText = currentTurnUserMessageText(candidate);
429
+ if (msgText !== undefined) {
430
+ const req = detectOrchestrateRequest(msgText);
431
+ if (req === 'on')
432
+ return renderOrchestratorSection(getSettings(), toolName);
433
+ if (req === 'off')
434
+ return '';
435
+ }
436
+ const cmdReq = recentOrchestrateCommandRun(candidate);
437
+ if (cmdReq === 'on')
438
+ return renderOrchestratorSection(getSettings(), toolName);
439
+ if (cmdReq === 'off')
440
+ return '';
441
+ }
442
+ let resolvedMode;
443
+ let sawError = false;
444
+ for (const candidate of sessionCandidates) {
445
+ try {
446
+ const snap = projections.snapshot(candidate);
447
+ const value = snap?.values?.[ORCHESTRATE_PROJECTION_KEY];
448
+ if (value && typeof value.mode === 'string') {
449
+ const m = value.mode;
450
+ // 'on' wins immediately; otherwise remember the first known value.
451
+ if (m === 'on') {
452
+ resolvedMode = 'on';
453
+ break;
454
+ }
455
+ if (resolvedMode === undefined)
456
+ resolvedMode = m;
457
+ }
458
+ }
459
+ catch (err) {
460
+ // Surface instead of silently dropping (D1). The most likely cause
461
+ // is a session-identity mismatch: this candidate is not the object
462
+ // the /orchestrate command wrote the orchestrate/change event to.
463
+ sawError = true;
464
+ ctx.logger.warn('[orchestrate] could not read orchestrator mode from projection for a candidate session (session identity may not match the session /orchestrate on wrote to):', err?.message);
465
+ }
466
+ }
467
+ if (resolvedMode === undefined) {
468
+ // Could not resolve any mode from any candidate session. Warn with the
469
+ // likely cause; do NOT silently pretend 'off'.
470
+ if (!sawError) {
471
+ ctx.logger.warn('[orchestrate] orchestrator mode could not be resolved from any candidate session — orchestrator-mode section skipped. Possible cause: the assembly context session identity does not match the session the /orchestrate command wrote the orchestrate/change event to (the projection cache is keyed by the live Session object, per @deepseek-ai/dsh-session-projection).');
472
+ }
473
+ return '';
474
+ }
475
+ // Legitimate off: no section, no warning (intended behavior).
476
+ if (resolvedMode === 'off')
477
+ return '';
478
+ return renderOrchestratorSection(getSettings(), toolName);
479
+ },
480
+ });
481
+ }
482
+ }
483
+ //# sourceMappingURL=orchestrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrate.js","sourceRoot":"","sources":["../src/orchestrate.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-subagent-director",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Subagent Director: choose an LLM provider/model for each subagent (call args > role binding > plugin default > inherit parent) and plan main-agent/subagent responsibilities with role templates, plus a settings UI.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -65,23 +65,27 @@
65
65
  "model",
66
66
  "role-template"
67
67
  ],
68
+ "dependencies": {
69
+ "zod": "^4.4.3"
70
+ },
68
71
  "license": "MIT",
69
72
  "peerDependencies": {
70
73
  "react": "^18.2.0",
71
74
  "@deepseek-ai/cordis": "^4.0.1",
72
- "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
73
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
74
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
75
- "@deepseek-ai/dsh-subagent": "^0.1.0-rc.8",
76
- "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
77
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
78
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
79
- "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6",
80
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
81
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6",
82
- "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.6",
83
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
84
- "@deepseek-ai/dsh-host-apiproxy": "^0.1.0-rc.6"
75
+ "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
76
+ "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
77
+ "@deepseek-ai/dsh-settings": "^0.1.1-rc.2",
78
+ "@deepseek-ai/dsh-subagent": "^0.1.1-rc.2",
79
+ "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.2",
80
+ "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
81
+ "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
82
+ "@deepseek-ai/dsh-client-connection": "^0.1.1-rc.2",
83
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
84
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.2",
85
+ "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
86
+ "@deepseek-ai/dsh-host-apiproxy": "^0.1.1-rc.2",
87
+ "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
88
+ "@deepseek-ai/dsh-session-projection": "^0.1.1-rc.2"
85
89
  },
86
90
  "devDependencies": {
87
91
  "react": "^18.2.0",
@@ -90,21 +94,22 @@
90
94
  "@types/react": "^18.3.1",
91
95
  "@types/react-dom": "^18.3.1",
92
96
  "@deepseek-ai/cordis": "^4.0.1",
93
- "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
94
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
95
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
96
- "@deepseek-ai/dsh-subagent": "^0.1.0-rc.8",
97
- "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
98
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
97
+ "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
98
+ "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
99
+ "@deepseek-ai/dsh-settings": "^0.1.1-rc.2",
100
+ "@deepseek-ai/dsh-subagent": "^0.1.1-rc.2",
101
+ "@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.2",
102
+ "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
99
103
  "@deepseek-ai/schemastery": "^3.18.1",
100
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
101
- "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6",
102
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
103
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6",
104
- "@deepseek-ai/dsh-client-schema-form": "^0.1.0-rc.6",
105
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
106
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
107
- "@deepseek-ai/dsh-host-apiproxy": "^0.1.0-rc.6",
104
+ "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
105
+ "@deepseek-ai/dsh-client-connection": "^0.1.1-rc.2",
106
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
107
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.1-rc.2",
108
+ "@deepseek-ai/dsh-client-locale": "^0.1.1-rc.2",
109
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.1-rc.2",
110
+ "@deepseek-ai/dsh-host-apiproxy": "^0.1.1-rc.2",
111
+ "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
112
+ "@deepseek-ai/dsh-session-projection": "^0.1.1-rc.2",
108
113
  "rolldown": "^1.2.4",
109
114
  "@types/node": "^26.2.0",
110
115
  "typescript": "^7.0.2",