@zhushanwen/pi-subagent-workflow 8.8.0 → 8.8.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 (35) hide show
  1. package/package.json +8 -8
  2. package/src/host/pi-host.ts +5 -4
  3. package/src/index.ts +145 -464
  4. package/src/injectors/__tests__/engine-awareness.test.ts +4 -2
  5. package/src/injectors/__tests__/engine-section-stability.test.ts +42 -29
  6. package/src/injectors/engine-awareness.ts +80 -4
  7. package/src/injectors/resource-list-injector.ts +209 -0
  8. package/src/injectors/subagent-list-injector.ts +30 -143
  9. package/src/injectors/workflow-list-injector.ts +23 -150
  10. package/src/interface/__tests__/detectors.test.ts +1 -1
  11. package/src/interface/__tests__/subagent-tool-path-guard.test.ts +42 -26
  12. package/src/interface/__tests__/subagent-tool-prompt.test.ts +10 -2
  13. package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +1 -1
  14. package/src/interface/bg-notify-render.ts +4 -4
  15. package/src/interface/commands.ts +115 -75
  16. package/src/interface/format.ts +339 -241
  17. package/src/interface/helpers.ts +2 -2
  18. package/src/interface/list-component.ts +163 -116
  19. package/src/interface/list-shared.ts +2 -2
  20. package/src/interface/list-view.ts +129 -72
  21. package/src/interface/subagent-actions.ts +5 -5
  22. package/src/interface/subagent-tool-schema.ts +6 -5
  23. package/src/interface/subagent-tool.ts +4 -3
  24. package/src/interface/subagents.ts +8 -7
  25. package/src/interface/tool-render.ts +2 -2
  26. package/src/interface/tool-workflow-script.ts +15 -14
  27. package/src/interface/tool-workflow.ts +14 -11
  28. package/src/interface/tui-kit.ts +305 -0
  29. package/src/interface/views/WorkflowsView.ts +267 -196
  30. package/src/interface/views/__tests__/WorkflowsView-signature.test.ts +3 -3
  31. package/src/interface/views/__tests__/detail-content-session-file.test.ts +7 -4
  32. package/src/interface/views/detail-content.ts +16 -14
  33. package/src/interface/views/view-constants.ts +19 -0
  34. package/src/jsonl-run-store.ts +11 -7
  35. package/src/interface/views/format.ts +0 -281
@@ -35,8 +35,8 @@
35
35
  import { matchesKey } from "@earendil-works/pi-tui";
36
36
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
37
37
 
38
- import type { SubagentService } from "@zhushanwen/subagent-core/execution/subagent-service.ts";
39
- import type { SubagentRecord } from "@zhushanwen/subagent-core/execution/types.ts";
38
+ import type { SubagentService } from "@zhushanwen/subagent-core";
39
+ import type { SubagentRecord } from "@zhushanwen/subagent-core";
40
40
  import { type ThemeLike } from "./format.ts";
41
41
  import { SubagentsListComponent } from "./list-component.ts";
42
42
  import {
@@ -48,21 +48,21 @@ import {
48
48
  type TuiLike,
49
49
  type ViewState,
50
50
  } from "./list-shared.ts";
51
+ import { PAGE_SCROLL_DEFAULT } from "./tui-kit.ts";
51
52
 
52
53
  // ============================================================
53
54
  // 常量
54
55
  // ============================================================
55
56
 
56
57
  // 布局/边框常量(LEFT_COL_RATIO、COL_*、BORDER_WIDTH、PAD_*、MIN_*、TITLE_*、
57
- // SPLIT_FIXED_LINES、TERM_ROWS_FALLBACK、DETAIL_LEN_PROBE_WIDTH、VERT_CENTER_DIVISOR、
58
- // SPINNER_FRAME_MS、PREVIEW_RECENT_LINES)已随 SubagentsListComponent 移至 list-component.ts。
58
+ // SPLIT_FIXED_LINES、DETAIL_LEN_PROBE_WIDTH、VERT_CENTER_DIVISOR、
59
+ // SPINNER_FRAME_MS、PREVIEW_RECENT_LINES)已随 SubagentsListComponent 移至 list-component.ts;
60
+ // 终端兜底零件(终端行数兜底/termRows/边框家族)单定义在 ./tui-kit.ts(C4)。
59
61
  // 共享类型/常量/纯函数(LIST_LIMIT/ViewState/DetailKeyContext/TuiLike/NotifyFn/applyFilter/
60
62
  // KeyResult/KeyHandler)已移至 list-shared.ts(消除 list-view ↔ list-component 循环依赖)。
61
63
 
62
64
  /** 详情区 eventLog 翻屏步长(方向键单步)。 */
63
65
  const DETAIL_SCROLL_STEP = 1;
64
- /** 详情区 PgUp/PgDn 默认步长(无 viewport 信息时)。 */
65
- const PAGE_SCROLL_DEFAULT = 10;
66
66
 
67
67
  /** overlay 动画刷新间隔(spinner 换帧 + elapsed 跳动)。同 tool-render.ts SPINNER_INTERVAL_MS。 */
68
68
  const OVERLAY_REFRESH_MS = 250;
@@ -88,7 +88,7 @@ let activeView: { close: () => void } | null = null;
88
88
  * ╔══════════════════════════════════════════════════════════════════╗
89
89
  * ║ 1. G-017 防叠加:activeView?.close() ║
90
90
  * ║ 2. ctx.ui.custom((tui, theme, kb, done) => { ║
91
- * ║ unsubscribe = service.onChange(() => tui.requestRender()) ║
91
+ * ║ unsubscribe = service.queries.onChange(() => tui.requestRender()) ║
92
92
  * ║ activeView = { close: wrappedDone } ║
93
93
  * ║ return new SubagentsListComponent(...) ║
94
94
  * ║ }, { overlay:true, overlayOptions:{margin:0, width:"100%"}}) ║
@@ -112,7 +112,7 @@ export async function createSubagentsView(
112
112
 
113
113
  // directId 提示
114
114
  if (directId) {
115
- const all = service.collectRecords(LIST_LIMIT);
115
+ const all = service.queries.collectRecords(LIST_LIMIT);
116
116
  if (!all.some((r) => r.id === directId)) {
117
117
  notify(`No record found for id "${directId}", showing all`, "warning");
118
118
  }
@@ -143,7 +143,7 @@ export async function createSubagentsView(
143
143
  // 易产生 cell 残留(视觉重影)。节流到 ONCHANGE_DEBOUNCE_MS,animTimer(250ms)
144
144
  // 兜底刷新。终态变化(record 完成)延迟可接受。
145
145
  let renderDebounce: ReturnType<typeof setTimeout> | undefined;
146
- const unsubscribe = service.onChange(() => {
146
+ const unsubscribe = service.queries.onChange(() => {
147
147
  if (state.disposed) return;
148
148
  if (renderDebounce) clearTimeout(renderDebounce);
149
149
  renderDebounce = setTimeout(() => {
@@ -156,7 +156,7 @@ export async function createSubagentsView(
156
156
 
157
157
  // directId 命中 → 进详情模式(右侧就地展开,底部对齐)
158
158
  if (directId) {
159
- const records = service.collectRecords(LIST_LIMIT);
159
+ const records = service.queries.collectRecords(LIST_LIMIT);
160
160
  const idx = records.findIndex((r) => r.id === directId);
161
161
  if (idx >= 0) {
162
162
  state.selectedIdx = idx;
@@ -218,27 +218,28 @@ export async function createSubagentsView(
218
218
  }
219
219
 
220
220
  // ============================================================
221
- // 按键处理(纯函数,可单测)
221
+ // 按键处理(纯函数,可单测)——阶段化提取(形态 1)
222
222
  // ============================================================
223
223
 
224
224
  /**
225
- * 按键处理。两阶段焦点(detailMode 控制):
225
+ * 按键处理入口。两阶段焦点(detailMode 控制),主函数只留阶段编排:
226
226
  *
227
227
  * ╔══════════════════════════════════════════════════════════════════╗
228
- // ║ 阶段 1(list 焦点,detailMode=false): ║
229
- // ║ Esc 退出(有 filter 先清)/ ↑↓ 导航左列 / Enter 进阶段 2 ║
230
- // ║ Backspace 删 filter / 可打印字符直接 filter ║
231
- // ║ ║
232
- // ║ 阶段 2(detail 焦点,detailMode=true):左侧锚定,滚右侧详情 ║
233
- // ║ Esc 返回阶段 1 / ↑↓ PgUp/PgDn Home End 滚右侧 eventLog ║
234
- // ║ x 停止:background → service.cancel(id)(真正 abort) ║
235
- // ╚══════════════════════════════════════════════════════════════════╝
228
+ * ║ 阶段 1(list 焦点,detailMode=false): ║
229
+ * ║ Esc 退出(有 filter 先清)/ ↑↓ 导航左列 / Enter 进阶段 2 ║
230
+ * ║ Backspace 删 filter / 可打印字符直接 filter ║
231
+ * ║ ║
232
+ * ║ 阶段 2(detail 焦点,detailMode=true):左侧锚定,滚右侧详情 ║
233
+ * ║ Esc 返回阶段 1 / ↑↓ PgUp/PgDn Home End 滚右侧 eventLog ║
234
+ * ║ x 停止:background → service.cancel(id)(真正 abort) ║
235
+ * ╚══════════════════════════════════════════════════════════════════╝
236
236
  *
237
237
  * 返回 KeyResult:changed 表示状态变更需重绘;exit 表示调用方应关闭 overlay。
238
238
  * 二者正交——Esc 在阶段 1 无 filter 时 changed=false + exit=true。
239
239
  *
240
240
  * 注:KeyResult/KeyHandler 类型定义在 list-shared.ts(list-component 也用 KeyHandler 做构造
241
241
  * 参数类型,避免组件 import list-view)。本函数由 list-view factory 注入组件(依赖注入)。
242
+ * 各阶段子函数按原 if 链顺序匹配,命中短路返回(与原单函数版时序逐一对齐)。
242
243
  */
243
244
  export const processKey: KeyHandler = (
244
245
  data,
@@ -249,50 +250,118 @@ export const processKey: KeyHandler = (
249
250
  detailCtx,
250
251
  notify,
251
252
  ): KeyResult => {
252
- // ── 阶段 2(detail 焦点,detailMode=true):左侧锚定,滚右侧详情 ──
253
253
  if (state.detailMode) {
254
- if (matchesKey(data, "escape")) {
255
- state.detailMode = false;
256
- state.scrollOffset = 0;
257
- return { changed: true, exit: false };
258
- }
259
- if (matchesKey(data, "up")) {
260
- state.scrollOffset = Math.max(0, state.scrollOffset - DETAIL_SCROLL_STEP);
261
- return { changed: true, exit: false };
262
- }
263
- if (matchesKey(data, "down")) {
264
- const max = detailScrollMax(detailCtx);
265
- state.scrollOffset = Math.min(max, state.scrollOffset + DETAIL_SCROLL_STEP);
266
- return { changed: true, exit: false };
267
- }
268
- if (matchesKey(data, "pageUp")) {
269
- const step = detailCtx?.viewportHeight ?? PAGE_SCROLL_DEFAULT;
270
- state.scrollOffset = Math.max(0, state.scrollOffset - step);
271
- return { changed: true, exit: false };
272
- }
273
- if (matchesKey(data, "pageDown")) {
274
- const step = detailCtx?.viewportHeight ?? PAGE_SCROLL_DEFAULT;
275
- const max = detailScrollMax(detailCtx);
276
- state.scrollOffset = Math.min(max, state.scrollOffset + step);
277
- return { changed: true, exit: false };
278
- }
279
- if (matchesKey(data, "home")) {
280
- state.scrollOffset = 0;
281
- return { changed: true, exit: false };
282
- }
283
- if (matchesKey(data, "end")) {
284
- state.scrollOffset = detailScrollMax(detailCtx);
254
+ return processDetailModeKey(data, state, selected, service, detailCtx, notify);
255
+ }
256
+ return processListModeKey(data, records, state, selected);
257
+ };
258
+
259
+ // ============================================================
260
+ // 阶段 2(detail 焦点,detailMode=true):左侧锚定,滚右侧详情
261
+ // ============================================================
262
+
263
+ /** 阶段 2 滚动/返回键(Esc/↑/↓/PgUp/PgDn/Home/End,匹配顺序同原 if 链)。未命中返回 undefined。 */
264
+ function detailScrollKey(
265
+ data: string,
266
+ state: ViewState,
267
+ detailCtx: DetailKeyContext | undefined,
268
+ ): KeyResult | undefined {
269
+ if (matchesKey(data, "escape")) {
270
+ state.detailMode = false;
271
+ state.scrollOffset = 0;
272
+ return { changed: true, exit: false };
273
+ }
274
+ if (matchesKey(data, "up")) {
275
+ state.scrollOffset = Math.max(0, state.scrollOffset - DETAIL_SCROLL_STEP);
276
+ return { changed: true, exit: false };
277
+ }
278
+ if (matchesKey(data, "down")) {
279
+ const max = detailScrollMax(detailCtx);
280
+ state.scrollOffset = Math.min(max, state.scrollOffset + DETAIL_SCROLL_STEP);
281
+ return { changed: true, exit: false };
282
+ }
283
+ if (matchesKey(data, "pageUp")) {
284
+ const step = detailCtx?.viewportHeight ?? PAGE_SCROLL_DEFAULT;
285
+ state.scrollOffset = Math.max(0, state.scrollOffset - step);
286
+ return { changed: true, exit: false };
287
+ }
288
+ if (matchesKey(data, "pageDown")) {
289
+ const step = detailCtx?.viewportHeight ?? PAGE_SCROLL_DEFAULT;
290
+ const max = detailScrollMax(detailCtx);
291
+ state.scrollOffset = Math.min(max, state.scrollOffset + step);
292
+ return { changed: true, exit: false };
293
+ }
294
+ if (matchesKey(data, "home")) {
295
+ state.scrollOffset = 0;
296
+ return { changed: true, exit: false };
297
+ }
298
+ if (matchesKey(data, "end")) {
299
+ state.scrollOffset = detailScrollMax(detailCtx);
300
+ return { changed: true, exit: false };
301
+ }
302
+ return undefined;
303
+ }
304
+
305
+ /** 阶段 2 停止键(x):background → service.cancel(id) 真正 abort。未命中返回 undefined。 */
306
+ function detailStopKey(
307
+ data: string,
308
+ selected: SubagentRecord | null,
309
+ service: SubagentService | null,
310
+ notify: NotifyFn | undefined,
311
+ ): KeyResult | undefined {
312
+ if (data === "x" && selected) {
313
+ const changed = handleCancel(selected, service, notify);
314
+ return { changed, exit: false };
315
+ }
316
+ return undefined;
317
+ }
318
+
319
+ /** 阶段 2 编排:滚动/返回 → 停止 → 落空(与原阶段 2 if 链 + 兜底 return 逐一对齐)。 */
320
+ function processDetailModeKey(
321
+ data: string,
322
+ state: ViewState,
323
+ selected: SubagentRecord | null,
324
+ service: SubagentService | null,
325
+ detailCtx: DetailKeyContext | undefined,
326
+ notify: NotifyFn | undefined,
327
+ ): KeyResult {
328
+ const scroll = detailScrollKey(data, state, detailCtx);
329
+ if (scroll) return scroll;
330
+ const stop = detailStopKey(data, selected, service, notify);
331
+ if (stop) return stop;
332
+ return { changed: false, exit: false };
333
+ }
334
+
335
+ // ============================================================
336
+ // 阶段 1(list 焦点,detailMode=false):↑↓ 导航左列 + filter 编辑
337
+ // ============================================================
338
+
339
+ /** 阶段 1 filter 编辑键(backspace 删末字符 / 可打印 ASCII 字符追加)。未命中返回 undefined。 */
340
+ function listFilterKey(data: string, state: ViewState): KeyResult | undefined {
341
+ if (matchesKey(data, "backspace")) {
342
+ if (state.filterText.length > 0) {
343
+ state.filterText = state.filterText.slice(0, -1);
344
+ state.selectedIdx = 0;
285
345
  return { changed: true, exit: false };
286
346
  }
287
- // x:停止当前 record
288
- if (data === "x" && selected) {
289
- const changed = handleCancel(selected, service, notify);
290
- return { changed, exit: false };
291
- }
292
347
  return { changed: false, exit: false };
293
348
  }
349
+ // 可打印字符 → filter(单字符 ASCII 可见区)
350
+ if (data.length === 1 && data >= " " && data <= "~") {
351
+ state.filterText += data;
352
+ state.selectedIdx = 0;
353
+ return { changed: true, exit: false };
354
+ }
355
+ return undefined;
356
+ }
294
357
 
295
- // ── 阶段 1(list 焦点,detailMode=false):↑↓ 导航左列 ──
358
+ /** 阶段 1 编排:Esc 清 filter/退出 → 导航 → 进详情 → filter 编辑 → 落空(匹配顺序同原 if 链)。 */
359
+ function processListModeKey(
360
+ data: string,
361
+ records: SubagentRecord[],
362
+ state: ViewState,
363
+ selected: SubagentRecord | null,
364
+ ): KeyResult {
296
365
  if (matchesKey(data, "escape")) {
297
366
  // 有 filter 先清(changed);无 filter → 退出 overlay(exit)
298
367
  if (state.filterText.length > 0) {
@@ -322,20 +391,8 @@ export const processKey: KeyHandler = (
322
391
  }
323
392
  return { changed: false, exit: false };
324
393
  }
325
- if (matchesKey(data, "backspace")) {
326
- if (state.filterText.length > 0) {
327
- state.filterText = state.filterText.slice(0, -1);
328
- state.selectedIdx = 0;
329
- return { changed: true, exit: false };
330
- }
331
- return { changed: false, exit: false };
332
- }
333
- // 可打印字符 → filter(单字符 ASCII 可见区)
334
- if (data.length === 1 && data >= " " && data <= "~") {
335
- state.filterText += data;
336
- state.selectedIdx = 0;
337
- return { changed: true, exit: false };
338
- }
394
+ const filter = listFilterKey(data, state);
395
+ if (filter) return filter;
339
396
  return { changed: false, exit: false };
340
397
  }
341
398
 
@@ -21,7 +21,6 @@ import {
21
21
  isGuiCapable,
22
22
  } from "@xyz-agent/extension-protocol";
23
23
 
24
- import type { SubagentToolResult } from "@zhushanwen/subagent-core/execution/types.ts";
25
24
  import type {
26
25
  CancelHandlerResult,
27
26
  CloseHandlerResult,
@@ -29,11 +28,12 @@ import type {
29
28
  ListHandlerResult,
30
29
  MessageHandlerResult,
31
30
  StartHandlerResult,
32
- } from "@zhushanwen/subagent-core/execution/subagent-actions-core.ts";
31
+ SubagentToolResult,
32
+ } from "@zhushanwen/subagent-core";
33
33
  import { mapRunIcon, mapRunStatus } from "./gui-mappers.ts";
34
34
 
35
35
  // ============================================================
36
- // core 领域内核 re-export(pi 消费面符号与收缩前一致,deep path 直连 core 源码)
36
+ // core 领域内核 re-export(pi 消费面符号与收缩前一致,经 core barrel 统一消费)
37
37
  // ============================================================
38
38
 
39
39
  export {
@@ -46,7 +46,7 @@ export {
46
46
  messageHandler,
47
47
  recordToListItem,
48
48
  startHandler,
49
- } from "@zhushanwen/subagent-core/execution/subagent-actions-core.ts";
49
+ } from "@zhushanwen/subagent-core";
50
50
 
51
51
  export type {
52
52
  CancelHandlerInput,
@@ -61,7 +61,7 @@ export type {
61
61
  MessageHandlerResult,
62
62
  StartHandlerInput,
63
63
  StartHandlerResult,
64
- } from "@zhushanwen/subagent-core/execution/subagent-actions-core.ts";
64
+ } from "@zhushanwen/subagent-core";
65
65
 
66
66
  // ============================================================
67
67
  // 渲染层常量 / 类型(pi TUI 渲染族,按设计留壳)
@@ -12,16 +12,17 @@
12
12
  // 编译本 schema 并断言 required/description/enum/pattern 存活——SW 自身测试环境
13
13
  // 把 typebox alias 到 mock(丢 options),SO 侧测试以真实构造为对照基准。
14
14
  //
15
- // 层归属:Interface(工具 schema 的家)。SLUG_MAX_LENGTH 权威定义回归 core 侧
16
- // execution/execute-options-mapper.ts(subagent-core 包抽离 u1-move:core 切面不得
17
- // 反向 import 壳侧 interface,常量随之内化)——此处 re-export 保持既有 import 路径。
15
+ // 层归属:Interface(工具 schema 的家)。SLUG_MAX_LENGTH 权威定义在 core 侧
16
+ // orchestration/models/types.ts([D6 合流迁址] 原 execution/execute-options-mapper.ts
17
+ // 已随 mapper 删除,常量迁至 AgentCallOpts.description 字段同文件;core 切面不得
18
+ // 反向 import 壳侧 interface 的约束不变)——此处 re-export 保持既有 import 路径。
18
19
 
19
20
  import { StringEnum } from "@earendil-works/pi-ai";
20
21
  import { Type } from "typebox";
21
22
 
22
- import { THINKING_ORDER } from "@zhushanwen/subagent-core/shared/model-ref.ts";
23
+ import { THINKING_ORDER } from "@zhushanwen/subagent-core";
23
24
 
24
- import { SLUG_MAX_LENGTH } from "@zhushanwen/subagent-core/execution/execute-options-mapper.ts";
25
+ import { SLUG_MAX_LENGTH } from "@zhushanwen/subagent-core";
25
26
 
26
27
  export { SLUG_MAX_LENGTH };
27
28
 
@@ -16,13 +16,14 @@ import type { AgentToolResult, ExtensionAPI, ExtensionContext, Theme } from "@ea
16
16
  import { getLogger } from "@zhushanwen/pi-extension-logger";
17
17
  import type { Static } from "typebox";
18
18
 
19
- import { getSubagentService } from "@zhushanwen/subagent-core/execution/subagent-service.ts";
20
- import type { SubagentToolResult } from "@zhushanwen/subagent-core/execution/types.ts";
19
+ import { getSubagentService } from "@zhushanwen/subagent-core";
20
+ import type { SubagentToolResult } from "@zhushanwen/subagent-core";
21
21
  import { extractAgentName } from "./format.ts";
22
22
  import { toGuiCtx } from "./gui-mappers.ts";
23
23
  import { adapter, cancelHandler, closeHandler, forkFromHandler, listHandler, messageHandler, startHandler } from "./subagent-actions.ts";
24
24
  import { SubagentParams } from "./subagent-tool-schema.ts";
25
25
  import { type RenderContext,renderSubagentCall, renderSubagentResult } from "./tool-render.ts";
26
+ import { toErrorMessage } from "@zhushanwen/pi-ext-guards";
26
27
 
27
28
  // ============================================================
28
29
  // 回调类型(抽 alias 绕 registerTool(unknown) 的 TS2307 误报)
@@ -261,7 +262,7 @@ const subagentRenderCall: SubagentRenderCallCb = (args, theme, ctx) => {
261
262
  // streaming 中间态(partial JSON)或 service 未就绪 → 降级不显示 model(renderCall 不应崩)。
262
263
  // 不阻断渲染,不污染 TUI。开发期开 XYZ_AGENT_DEBUG=1 可写文件日志排查。
263
264
  renderCallLogger.debug("renderCall model resolution failed, degrading", {
264
- reason: err instanceof Error ? err.message : String(err),
265
+ reason: toErrorMessage(err),
265
266
  });
266
267
  }
267
268
  return renderSubagentCall(args, theme, ctx, resolved);
@@ -9,14 +9,15 @@
9
9
 
10
10
  import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
11
11
 
12
- import { getSubagentService } from "@zhushanwen/subagent-core/execution/subagent-service.ts";
13
- import type { SubagentService } from "@zhushanwen/subagent-core/execution/subagent-service.ts";
14
- import { displayAgentName } from "@zhushanwen/subagent-core/shared/agent-ref.ts";
12
+ import { getSubagentService } from "@zhushanwen/subagent-core";
13
+ import type { SubagentService } from "@zhushanwen/subagent-core";
14
+ import { displayAgentName } from "@zhushanwen/subagent-core";
15
15
  import { messageHandler, startHandler } from "./subagent-actions.ts";
16
16
  import { parseSubagentRpcCommand } from "./command-actions.ts";
17
17
  import type { SubagentRpcAction } from "./command-actions.ts";
18
18
  import { LIST_LIMIT } from "./list-shared.ts";
19
19
  import { createSubagentsView } from "./list-view.ts";
20
+ import { toErrorMessage } from "@zhushanwen/pi-ext-guards";
20
21
 
21
22
  /**
22
23
  * subagent-directive custom_message 的 customType。
@@ -84,7 +85,7 @@ async function rpcCancel(
84
85
  );
85
86
  } catch (err) {
86
87
  // service.cancel 内部 assertReady 在 session_shutdown 并发 dispose 时会抛
87
- const msg = err instanceof Error ? err.message : String(err);
88
+ const msg = toErrorMessage(err);
88
89
  ctx.ui.notify(`Failed to cancel subagent ${recordId}: ${msg}`, "warning");
89
90
  }
90
91
  }
@@ -115,7 +116,7 @@ async function rpcMessage(
115
116
  );
116
117
  ctx.ui.notify(`Message delivered to subagent ${result.slug} (${result.subagentId})`, "info");
117
118
  } catch (err) {
118
- const msg = err instanceof Error ? err.message : String(err);
119
+ const msg = toErrorMessage(err);
119
120
  ctx.ui.notify(`Failed to message subagent ${recordId}: ${msg}`, "warning");
120
121
  }
121
122
  }
@@ -149,7 +150,7 @@ async function rpcStart(
149
150
  );
150
151
  ctx.ui.notify(`Started subagent ${result.slug} (${result.subagentId})`, "info");
151
152
  } catch (err) {
152
- const msg = err instanceof Error ? err.message : String(err);
153
+ const msg = toErrorMessage(err);
153
154
  ctx.ui.notify(`Failed to start subagent ${slug}: ${msg}`, "warning");
154
155
  }
155
156
  }
@@ -230,7 +231,7 @@ export function registerSubagentsCommand(pi: ExtensionAPI): void {
230
231
  if (!service) return null;
231
232
  // collectRecords 合并内存(running) + 磁盘重建 record,按 rootSessionId 过滤。
232
233
  // cancel 只对 running 有效,但全部列出便于用户辨认(终态 record 会被 service 拒绝)。
233
- const records = service.collectRecords(LIST_LIMIT);
234
+ const records = service.queries.collectRecords(LIST_LIMIT);
234
235
  if (records.length === 0) return null;
235
236
  return records.map((r) => ({
236
237
  label: r.id,
@@ -24,8 +24,8 @@ import type { AgentToolResult, Theme } from "@earendil-works/pi-coding-agent";
24
24
  import type {
25
25
  ListResponse,
26
26
  SubagentToolResult,
27
- } from "@zhushanwen/subagent-core/execution/types.ts";
28
- import { displayAgentName } from "@zhushanwen/subagent-core/shared/agent-ref.ts";
27
+ } from "@zhushanwen/subagent-core";
28
+ import { displayAgentName } from "@zhushanwen/subagent-core";
29
29
  import {
30
30
  extractAgentName,
31
31
  firstLineSanitized,
@@ -27,23 +27,24 @@ import { Text } from "@earendil-works/pi-tui";
27
27
  import { type Static, Type } from "typebox";
28
28
 
29
29
  import {
30
- guiComponent,
31
- type GuiContext,
32
- type GuiRenderResult,
33
- guiResult,
34
- isGuiCapable,
30
+ guiComponent,
31
+ type GuiContext,
32
+ type GuiRenderResult,
33
+ guiResult,
34
+ isGuiCapable,
35
35
  } from "@xyz-agent/extension-protocol";
36
36
  // C5②/C5⑦:创作闭环统一走 core barrel(generateWorkflowScript/saveWorkflow/
37
37
  // deleteWorkflow/lintScript 均为 barrel 导出面;深路径在 npm/vendored 形态不可达)
38
38
  import {
39
- deleteWorkflow,
40
- generateWorkflowScript,
41
- lintScript,
42
- saveWorkflow,
39
+ deleteWorkflow,
40
+ generateWorkflowScript,
41
+ lintScript,
42
+ saveWorkflow,
43
43
  } from "@zhushanwen/subagent-core";
44
- import type { WorkflowScriptRegistry } from "@zhushanwen/subagent-core/orchestration/models/workflow-script-registry.ts";
44
+ import type { WorkflowScriptRegistry } from "@zhushanwen/subagent-core";
45
45
  import { toGuiCtx } from "./gui-mappers.ts";
46
- import { renderTextFallback } from "./views/format.ts";
46
+ import { renderTextFallback } from "./format.ts";
47
+ import { toErrorMessage } from "@zhushanwen/pi-ext-guards";
47
48
 
48
49
  // ── Parameter schema ─────────────────────────────────────────
49
50
 
@@ -351,7 +352,7 @@ async function actionSave(params: ScriptParams): Promise<TextContent> {
351
352
  } catch (err: unknown) {
352
353
  // throw(W4):pi 只对 execute throw 置 isError:true(返回值里的 isError 被
353
354
  // agent-loop 丢弃,agent-loop.js:453-483)——文案原样进 toolResult。
354
- const msg = err instanceof Error ? err.message : String(err);
355
+ const msg = toErrorMessage(err);
355
356
  throw new Error(`Save failed: ${msg}`);
356
357
  }
357
358
  }
@@ -378,7 +379,7 @@ function actionDelete(
378
379
  };
379
380
  } catch (err: unknown) {
380
381
  // throw(W4):同 save——pi 契约只有 throw 才置 isError:true。
381
- const msg = err instanceof Error ? err.message : String(err);
382
+ const msg = toErrorMessage(err);
382
383
  throw new Error(`Delete failed: ${msg}`);
383
384
  }
384
385
  }
@@ -401,7 +402,7 @@ async function actionList(registry: WorkflowScriptRegistry): Promise<TextContent
401
402
  };
402
403
  } catch (err: unknown) {
403
404
  // throw(W4b):list 失败改 throw(原 return isError 被 pi 丢弃),文案保持
404
- const msg = err instanceof Error ? err.message : String(err);
405
+ const msg = toErrorMessage(err);
405
406
  throw new Error(`List failed: ${msg}`);
406
407
  }
407
408
  }
@@ -31,18 +31,20 @@ import {
31
31
  } from "@xyz-agent/extension-protocol";
32
32
  import { type Static, Type } from "typebox";
33
33
 
34
- import { SLUG_MAX_LENGTH } from "@zhushanwen/subagent-core/execution/execute-options-mapper.ts";
35
- import { THINKING_ORDER } from "@zhushanwen/subagent-core/execution/model-resolver.ts";
36
- import { MAX_TIMER_DELAY_MS } from "@zhushanwen/subagent-core/shared/timer-delay.ts";
34
+ import { SLUG_MAX_LENGTH } from "@zhushanwen/subagent-core";
35
+ import { THINKING_ORDER } from "@zhushanwen/subagent-core";
36
+ import type { LauncherDeps } from "@zhushanwen/subagent-core";
37
+ import { abortRun, runWorkflow } from "@zhushanwen/subagent-core";
38
+ import type { RunStore } from "@zhushanwen/subagent-core";
39
+ import type { WorkflowRun } from "@zhushanwen/subagent-core";
40
+ // D9 closure:core args-meta 消费(reservedKeys 注入见下方 ARGS_META_OPTIONS)
41
+ // MAX_TIMER_DELAY_MS:OR-1 消费(barrel 导出,深路径经 u-2c 删通配后 tsc 不可解析)
37
42
  import {
38
43
  argKeysFromMeta,
39
44
  findFlattenedArgKeys,
40
- } from "@zhushanwen/subagent-core/orchestration/args-meta.ts";
41
- import type { LauncherDeps } from "@zhushanwen/subagent-core/orchestration/launcher.ts";
42
- import { abortRun, runWorkflow } from "@zhushanwen/subagent-core/orchestration/lifecycle.ts";
43
- import type { RunStore } from "@zhushanwen/subagent-core/orchestration/models/ports.ts";
44
- import type { WorkflowRun } from "@zhushanwen/subagent-core/orchestration/models/workflow-run.ts";
45
- import { runSummary } from "@zhushanwen/subagent-core/orchestration/workflow-run-summary.ts";
45
+ MAX_TIMER_DELAY_MS,
46
+ } from "@zhushanwen/subagent-core";
47
+ import { runSummary } from "@zhushanwen/subagent-core";
46
48
  import { mapRunIcon, mapRunStatus, toGuiCtx } from "./gui-mappers.ts";
47
49
  import {
48
50
  acquireReentryGuard,
@@ -50,7 +52,8 @@ import {
50
52
  type ReentryGuardRef,
51
53
  releaseReentryGuard,
52
54
  } from "./reentry-guard.ts";
53
- import { formatElapsed, renderTextFallback } from "./views/format.ts";
55
+ import { formatElapsed, renderTextFallback } from "./format.ts";
56
+ import { toErrorMessage } from "@zhushanwen/pi-ext-guards";
54
57
 
55
58
  // ── Parameter schema ─────────────────────────────────────────
56
59
 
@@ -531,7 +534,7 @@ async function actionLifecycle(
531
534
  };
532
535
  } catch (err) {
533
536
  // throw(W4b):abortRun 失败改 throw(原 return isError 被 pi 丢弃),"Error: " 前缀保持
534
- const msg = err instanceof Error ? err.message : String(err);
537
+ const msg = toErrorMessage(err);
535
538
  throw new Error(`Error: ${msg}`);
536
539
  }
537
540
  }