@mickorz/opencode-agentic-workflow 0.4.0 → 0.5.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 (127) hide show
  1. package/README.md +306 -5
  2. package/dist/cli/config.d.ts +121 -0
  3. package/dist/cli/config.js +331 -0
  4. package/dist/cli/config.js.map +1 -0
  5. package/dist/cli/doctor.d.ts +5 -0
  6. package/dist/cli/doctor.js +141 -0
  7. package/dist/cli/doctor.js.map +1 -0
  8. package/dist/cli/index.d.ts +18 -0
  9. package/dist/cli/index.js +120 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/install.d.ts +19 -0
  12. package/dist/cli/install.js +135 -0
  13. package/dist/cli/install.js.map +1 -0
  14. package/dist/cli/uninstall.d.ts +16 -0
  15. package/dist/cli/uninstall.js +110 -0
  16. package/dist/cli/uninstall.js.map +1 -0
  17. package/dist/cli/update.d.ts +15 -0
  18. package/dist/cli/update.js +86 -0
  19. package/dist/cli/update.js.map +1 -0
  20. package/dist/core/index.d.ts +39 -0
  21. package/dist/core/index.js +38 -0
  22. package/dist/core/index.js.map +1 -0
  23. package/dist/observability/events.d.ts +43 -0
  24. package/dist/observability/events.js.map +1 -1
  25. package/dist/plugin/checkpoint-override.d.ts +7 -9
  26. package/dist/plugin/checkpoint-override.js +8 -14
  27. package/dist/plugin/checkpoint-override.js.map +1 -1
  28. package/dist/plugin/define-workflow.d.ts +33 -0
  29. package/dist/plugin/define-workflow.js +103 -0
  30. package/dist/plugin/define-workflow.js.map +1 -0
  31. package/dist/plugin/index.js +406 -26
  32. package/dist/plugin/index.js.map +1 -1
  33. package/dist/plugin/opencode-v2-executor.js +58 -46
  34. package/dist/plugin/opencode-v2-executor.js.map +1 -1
  35. package/dist/plugin/progress-board.d.ts +64 -0
  36. package/dist/plugin/progress-board.js +150 -0
  37. package/dist/plugin/progress-board.js.map +1 -0
  38. package/dist/plugin/progress-rpc.d.ts +390 -0
  39. package/dist/plugin/progress-rpc.js +318 -0
  40. package/dist/plugin/progress-rpc.js.map +1 -0
  41. package/dist/plugin/progress-view.d.ts +82 -0
  42. package/dist/plugin/progress-view.js +244 -0
  43. package/dist/plugin/progress-view.js.map +1 -0
  44. package/dist/plugin/run-sessions.d.ts +28 -0
  45. package/dist/plugin/run-sessions.js +46 -0
  46. package/dist/plugin/run-sessions.js.map +1 -0
  47. package/dist/plugin/tool-args.d.ts +15 -0
  48. package/dist/plugin/tool-args.js +28 -0
  49. package/dist/plugin/tool-args.js.map +1 -0
  50. package/dist/plugin/tui.d.ts +11 -4
  51. package/dist/plugin/tui.js +160 -5
  52. package/dist/plugin/tui.js.map +1 -1
  53. package/dist/plugin/workflow-control.d.ts +16 -0
  54. package/dist/plugin/workflow-control.js +85 -0
  55. package/dist/plugin/workflow-control.js.map +1 -0
  56. package/dist/plugin/workflow-schedule.d.ts +24 -0
  57. package/dist/plugin/workflow-schedule.js +97 -0
  58. package/dist/plugin/workflow-schedule.js.map +1 -0
  59. package/dist/quality/checkpoint.d.ts +5 -2
  60. package/dist/quality/checkpoint.js +11 -6
  61. package/dist/quality/checkpoint.js.map +1 -1
  62. package/dist/quality/verify.d.ts +21 -2
  63. package/dist/quality/verify.js +36 -14
  64. package/dist/quality/verify.js.map +1 -1
  65. package/dist/registry/definition.d.ts +12 -0
  66. package/dist/registry/definition.js.map +1 -1
  67. package/dist/registry/registry.d.ts +4 -0
  68. package/dist/registry/registry.js +20 -1
  69. package/dist/registry/registry.js.map +1 -1
  70. package/dist/registry/run-control.d.ts +27 -0
  71. package/dist/registry/run-control.js +51 -0
  72. package/dist/registry/run-control.js.map +1 -0
  73. package/dist/registry/runner.d.ts +29 -6
  74. package/dist/registry/runner.js +153 -35
  75. package/dist/registry/runner.js.map +1 -1
  76. package/dist/runtime/errors.d.ts +26 -0
  77. package/dist/runtime/errors.js +30 -0
  78. package/dist/runtime/errors.js.map +1 -1
  79. package/dist/runtime/executor.d.ts +22 -0
  80. package/dist/runtime/executor.js.map +1 -1
  81. package/dist/runtime/run-context.d.ts +44 -0
  82. package/dist/runtime/run-context.js +32 -0
  83. package/dist/runtime/run-context.js.map +1 -0
  84. package/dist/scheduler/cron.d.ts +29 -0
  85. package/dist/scheduler/cron.js +171 -0
  86. package/dist/scheduler/cron.js.map +1 -0
  87. package/dist/scheduler/service.d.ts +78 -0
  88. package/dist/scheduler/service.js +215 -0
  89. package/dist/scheduler/service.js.map +1 -0
  90. package/dist/scheduler/store.d.ts +26 -0
  91. package/dist/scheduler/store.js +94 -0
  92. package/dist/scheduler/store.js.map +1 -0
  93. package/dist/scheduler/types.d.ts +53 -0
  94. package/dist/scheduler/types.js +12 -0
  95. package/dist/scheduler/types.js.map +1 -0
  96. package/dist/state/journal.d.ts +23 -0
  97. package/dist/state/journal.js +2 -0
  98. package/dist/state/journal.js.map +1 -1
  99. package/dist/state/recorder.d.ts +67 -0
  100. package/dist/state/recorder.js +148 -2
  101. package/dist/state/recorder.js.map +1 -1
  102. package/dist/workflow/agent.d.ts +42 -1
  103. package/dist/workflow/agent.js +116 -6
  104. package/dist/workflow/agent.js.map +1 -1
  105. package/dist/workflow/judge-panel.d.ts +37 -0
  106. package/dist/workflow/judge-panel.js +66 -0
  107. package/dist/workflow/judge-panel.js.map +1 -0
  108. package/dist/workflow/pipeline.d.ts +21 -0
  109. package/dist/workflow/pipeline.js +71 -0
  110. package/dist/workflow/pipeline.js.map +1 -0
  111. package/dist/workflow/race.d.ts +16 -0
  112. package/dist/workflow/race.js +46 -0
  113. package/dist/workflow/race.js.map +1 -0
  114. package/dist/workflow/sequence.js +6 -0
  115. package/dist/workflow/sequence.js.map +1 -1
  116. package/dist/workflows/loader.d.ts +124 -0
  117. package/dist/workflows/loader.js +500 -0
  118. package/dist/workflows/loader.js.map +1 -0
  119. package/dist/workspace/ambient.d.ts +6 -4
  120. package/dist/workspace/ambient.js +10 -4
  121. package/dist/workspace/ambient.js.map +1 -1
  122. package/package.json +21 -6
  123. package/skills/workflow-authoring/SKILL.md +111 -0
  124. package/skills/workflow-optimize/SKILL.md +70 -0
  125. package/dist/workflows/index.d.ts +0 -19
  126. package/dist/workflows/index.js +0 -40
  127. package/dist/workflows/index.js.map +0 -1
@@ -12,6 +12,7 @@
12
12
  *
13
13
  * 架构约束:本文件与 plugin/index.ts 是仅有的允许触碰 OpenCode API 的位置。
14
14
  */
15
+ import { trackRunSession, untrackRunSession } from "./run-sessions.js";
15
16
  export class OpenCodeV2Executor {
16
17
  session;
17
18
  parentSessionId;
@@ -33,60 +34,71 @@ export class OpenCodeV2Executor {
33
34
  const created = await this.session.create({
34
35
  parentID: this.parentSessionId,
35
36
  title: `${this.titlePrefix}#${this.counter}`,
36
- model: this.model,
37
+ // P1-4 调用级覆盖:task.model 优先于构造期默认(agent() 注入)
38
+ model: task.model ?? this.model,
37
39
  agent: this.agent,
38
40
  // P2.7 隔离:子会话 cwd 绑定到 workflow workspace(worktree 根)
39
41
  ...(task.cwd ? { location: { directory: task.cwd } } : {}),
40
42
  });
41
43
  const sessionID = created.id;
42
- await this.session.prompt({
43
- sessionID,
44
- text: task.prompt,
45
- });
46
- // V2 的 prompt 是 inbox 投递:等待会话处理完成后再读结果
47
- await this.session.wait({ sessionID });
48
- const messages = await this.session.context({ sessionID });
49
- // 从后往前找最后一条 assistant 消息
50
- for (let i = messages.length - 1; i >= 0; i--) {
51
- const message = messages[i];
52
- if (message && message.type === "assistant") {
53
- const output = message.content
54
- .filter((part) => part.type === "text")
55
- .map((part) => part.text)
56
- .join("\n")
57
- .trim();
58
- if (output.length > 0) {
59
- // token 用量 / 成本 / 模型(V2 assistant 消息自带;P2.6 metrics 消费)
60
- const usage = message.tokens && {
61
- input: message.tokens.input,
62
- output: message.tokens.output,
63
- reasoning: message.tokens.reasoning,
64
- cache: {
65
- read: message.tokens.cache.read,
66
- write: message.tokens.cache.write,
67
- },
68
- };
69
- const model = message.model && `${message.model.providerID}/${message.model.id}`;
70
- return {
71
- output,
72
- usage,
73
- // 成本优先级:宿主正值(精确)> 价目表估算(宿主 0/缺失时兜底——
74
- // 实测部分 provider 宿主记账为 0 但 models.dev 有实价)> 宿主原值
75
- costUSD: message.cost && message.cost > 0
76
- ? message.cost
77
- : (usage && model ? this.estimateCost?.(model, usage) : undefined) ??
78
- message.cost,
79
- model,
80
- };
44
+ // 并发 run 递归防护:任务执行期内登记本会话(workflow 工具据此拒绝
45
+ // 来自 run 内部的嵌套调用);结束注销——空闲会话不会再发起工具调用
46
+ trackRunSession(sessionID);
47
+ try {
48
+ await this.session.prompt({
49
+ sessionID,
50
+ text: task.prompt,
51
+ });
52
+ // V2 的 prompt 是 inbox 投递:等待会话处理完成后再读结果
53
+ await this.session.wait({ sessionID });
54
+ const messages = await this.session.context({ sessionID });
55
+ // 从后往前找最后一条 assistant 消息
56
+ for (let i = messages.length - 1; i >= 0; i--) {
57
+ const message = messages[i];
58
+ if (message && message.type === "assistant") {
59
+ const output = message.content
60
+ .filter((part) => part.type === "text")
61
+ .map((part) => part.text)
62
+ .join("\n")
63
+ .trim();
64
+ if (output.length > 0) {
65
+ // token 用量 / 成本 / 模型(V2 assistant 消息自带;P2.6 metrics 消费)
66
+ const usage = message.tokens && {
67
+ input: message.tokens.input,
68
+ output: message.tokens.output,
69
+ reasoning: message.tokens.reasoning,
70
+ cache: {
71
+ read: message.tokens.cache.read,
72
+ write: message.tokens.cache.write,
73
+ },
74
+ };
75
+ const model = message.model && `${message.model.providerID}/${message.model.id}`;
76
+ return {
77
+ output,
78
+ usage,
79
+ // 成本优先级:宿主正值(精确)> 价目表估算(宿主 0/缺失时兜底——
80
+ // 实测部分 provider 宿主记账为 0 但 models.dev 有实价)> 宿主原值
81
+ costUSD: message.cost && message.cost > 0
82
+ ? message.cost
83
+ : (usage && model ? this.estimateCost?.(model, usage) : undefined) ??
84
+ message.cost,
85
+ model,
86
+ // Open Session 回放:journal 按步骤聚合,详情/回放按它拉取完整对话
87
+ sessionID,
88
+ };
89
+ }
90
+ // assistant 存在但无文本:带出底层错误信息(如 provider 限流),便于排查
91
+ const detail = message.error
92
+ ? `${message.error.type ?? "error"}: ${message.error.message ?? "unknown"}`
93
+ : "assistant message has no text parts";
94
+ throw new Error(`[agentic-workflow] session ${sessionID} failed: ${detail}`);
81
95
  }
82
- // assistant 存在但无文本:带出底层错误信息(如 provider 限流),便于排查
83
- const detail = message.error
84
- ? `${message.error.type ?? "error"}: ${message.error.message ?? "unknown"}`
85
- : "assistant message has no text parts";
86
- throw new Error(`[agentic-workflow] session ${sessionID} failed: ${detail}`);
87
96
  }
97
+ throw new Error(`[agentic-workflow] session ${sessionID} finished without assistant message`);
98
+ }
99
+ finally {
100
+ untrackRunSession(sessionID);
88
101
  }
89
- throw new Error(`[agentic-workflow] session ${sessionID} finished without assistant message`);
90
102
  }
91
103
  }
92
104
  //# sourceMappingURL=opencode-v2-executor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"opencode-v2-executor.js","sourceRoot":"","sources":["../../src/plugin/opencode-v2-executor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"opencode-v2-executor.js","sourceRoot":"","sources":["../../src/plugin/opencode-v2-executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAiCtE,MAAM,OAAO,kBAAkB;IACZ,OAAO,CAAe;IACtB,eAAe,CAAS;IACxB,WAAW,CAAQ;IACnB,KAAK,CAAmB;IACxB,KAAK,CAAS;IACd,YAAY,CAA2D;IAChF,OAAO,GAAG,CAAC,CAAA;IAEnB,YAAY,OAAkC;QAC5C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAA;QAC9B,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,CAAA;QAC9C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,UAAU,CAAA;QACpD,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;QAC1B,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAA;QAC1B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAA;IAC1C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAe;QAC3B,IAAI,CAAC,OAAO,IAAI,CAAC,CAAA;QAEjB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YACxC,QAAQ,EAAE,IAAI,CAAC,eAAe;YAC9B,KAAK,EAAE,GAAG,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,OAAO,EAAE;YAC5C,6CAA6C;YAC7C,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,qDAAqD;YACrD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC3D,CAAC,CAAA;QAEF,MAAM,SAAS,GAAG,OAAO,CAAC,EAAE,CAAA;QAC5B,0CAA0C;QAC1C,sCAAsC;QACtC,eAAe,CAAC,SAAS,CAAC,CAAA;QAC1B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;gBACxB,SAAS;gBACT,IAAI,EAAE,IAAI,CAAC,MAAM;aAClB,CAAC,CAAA;YAEF,uCAAuC;YACvC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;YAEtC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC,CAAA;YAE1D,yBAAyB;YACzB,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAA;gBAC3B,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;oBAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO;yBAC3B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC;yBACtC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;yBACxB,IAAI,CAAC,IAAI,CAAC;yBACV,IAAI,EAAE,CAAA;oBACT,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wBACtB,wDAAwD;wBACxD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,IAAI;4BAC9B,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK;4BAC3B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM;4BAC7B,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS;4BACnC,KAAK,EAAE;gCACL,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI;gCAC/B,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK;6BAClC;yBACF,CAAA;wBACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,EAAE,CAAA;wBAChF,OAAO;4BACL,MAAM;4BACN,KAAK;4BACL,qCAAqC;4BACrC,gDAAgD;4BAChD,OAAO,EACL,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC;gCAC9B,CAAC,CAAC,OAAO,CAAC,IAAI;gCACd,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;oCAChE,OAAO,CAAC,IAAI;4BAClB,KAAK;4BACL,8CAA8C;4BAC9C,SAAS;yBACV,CAAA;oBACH,CAAC;oBACD,gDAAgD;oBAChD,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK;wBAC1B,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,IAAI,OAAO,KAAK,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI,SAAS,EAAE;wBAC3E,CAAC,CAAC,qCAAqC,CAAA;oBACzC,MAAM,IAAI,KAAK,CACb,8BAA8B,SAAS,YAAY,MAAM,EAAE,CAC5D,CAAA;gBACH,CAAC;YACH,CAAC;YAED,MAAM,IAAI,KAAK,CACb,8BAA8B,SAAS,qCAAqC,CAC7E,CAAA;QACH,CAAC;gBAAS,CAAC;YACT,iBAAiB,CAAC,SAAS,CAAC,CAAA;QAC9B,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * ProgressBoard —— server 侧运行看板(P2-8 TUI 进度树数据面)
3
+ *
4
+ * 职责:
5
+ * - 订阅核心事件总线的 run.progress(RunJournal 每次状态转换的全量快照)
6
+ * - 维护近期 run 快照(runId 去重、newest first、容量上限)
7
+ * - 每次更新转发为 RPC 事件(TUI 面板实时消费);无 TUI 监听时成本可忽略
8
+ * - snapshot 方法返回当前板(面板打开时初始同步)
9
+ *
10
+ * 快照即真相:不做增量对账——单飞语义下(每进程同时至多一个 run),
11
+ * 全量快照流天然有序;历史 run 以 store 种子补齐。
12
+ *
13
+ * 依赖全部注入(subscribe/emit/store),单测用 fake 即可覆盖。
14
+ */
15
+ import type { Plugin } from "@opencode/plugin";
16
+ import { type EventBus, type RunProgressSnapshot, type WorkflowEvent } from "../observability/events.js";
17
+ import type { ExecutionStore } from "../state/store.js";
18
+ import { type SessionReplayMessage } from "./progress-rpc.js";
19
+ type RpcDomain = Plugin.Context["rpc"];
20
+ export interface ProgressBoardOptions {
21
+ /** 近期 run 保留上限(默认 20) */
22
+ capacity?: number;
23
+ /** 事件总线(默认全局 bus;测试注入) */
24
+ bus?: EventBus;
25
+ /** 初始种子(bind 时由 store 读出) */
26
+ seed?: readonly RunProgressSnapshot[];
27
+ }
28
+ export declare class ProgressBoard {
29
+ private readonly emit;
30
+ private readonly runs;
31
+ private readonly order;
32
+ private readonly capacity;
33
+ private unsubscribe;
34
+ constructor(emit: (run: RunProgressSnapshot) => void, options?: ProgressBoardOptions);
35
+ /** 核心事件入口(仅消费 run.progress) */
36
+ onEvent(event: WorkflowEvent): void;
37
+ /**
38
+ * 应用一个快照:runId 去重、维持 newest-first、容量淘汰。
39
+ * forward=false 用于种子(不回发 RPC——面板尚未订阅,快照方法自会读到)。
40
+ */
41
+ apply(run: RunProgressSnapshot, options?: {
42
+ forward?: boolean;
43
+ }): void;
44
+ /** 当前板(newest first;snapshot 方法与测试用) */
45
+ list(): readonly RunProgressSnapshot[];
46
+ dispose(): void;
47
+ }
48
+ /**
49
+ * 插件装配:注册 ProgressRpc(snapshot/detail/session 方法)+ 订阅事件总线
50
+ * + store 种子。返回 board(持有者可 dispose;插件生命周期内常驻)。
51
+ */
52
+ export declare function bindProgressBoard(deps: {
53
+ rpc: RpcDomain;
54
+ store?: ExecutionStore;
55
+ /**
56
+ * Open Session 回放数据源:宿主会话消息拉取(ctx.session.context 映射)。
57
+ * 缺席时 session 方法统一回 null(旧 server 行为,面板静默降级)。
58
+ */
59
+ fetchSessionMessages?: (sessionID: string) => Promise<SessionReplayMessage[]>;
60
+ options?: ProgressBoardOptions;
61
+ }): Promise<ProgressBoard>;
62
+ /** store 里的近期 run -> 快照种子(newest first,容量截断) */
63
+ export declare function seedFromStore(store: ExecutionStore, capacity?: number): Promise<RunProgressSnapshot[]>;
64
+ export {};
@@ -0,0 +1,150 @@
1
+ /**
2
+ * ProgressBoard —— server 侧运行看板(P2-8 TUI 进度树数据面)
3
+ *
4
+ * 职责:
5
+ * - 订阅核心事件总线的 run.progress(RunJournal 每次状态转换的全量快照)
6
+ * - 维护近期 run 快照(runId 去重、newest first、容量上限)
7
+ * - 每次更新转发为 RPC 事件(TUI 面板实时消费);无 TUI 监听时成本可忽略
8
+ * - snapshot 方法返回当前板(面板打开时初始同步)
9
+ *
10
+ * 快照即真相:不做增量对账——单飞语义下(每进程同时至多一个 run),
11
+ * 全量快照流天然有序;历史 run 以 store 种子补齐。
12
+ *
13
+ * 依赖全部注入(subscribe/emit/store),单测用 fake 即可覆盖。
14
+ */
15
+ import { getEventBus, } from "../observability/events.js";
16
+ import { toProgressSnapshot, toRunDetail } from "../state/recorder.js";
17
+ import { ProgressRpc, parseRunDetailRequest, parseSessionReplayRequest, } from "./progress-rpc.js";
18
+ /** 回放消息的展示上限(防大对话刷爆面板/RPC 载荷) */
19
+ const REPLAY_MESSAGE_LIMIT = 50;
20
+ /** 单条消息文本预览上限 */
21
+ const REPLAY_TEXT_LIMIT = 800;
22
+ export class ProgressBoard {
23
+ emit;
24
+ runs = new Map();
25
+ order = [];
26
+ capacity;
27
+ unsubscribe;
28
+ constructor(emit, options) {
29
+ this.emit = emit;
30
+ this.capacity = options?.capacity ?? 20;
31
+ for (const run of options?.seed ?? []) {
32
+ this.apply(run, { forward: false });
33
+ }
34
+ this.unsubscribe = (options?.bus ?? getEventBus()).subscribe((event) => {
35
+ this.onEvent(event);
36
+ });
37
+ }
38
+ /** 核心事件入口(仅消费 run.progress) */
39
+ onEvent(event) {
40
+ if (event.type !== "run.progress")
41
+ return;
42
+ this.apply(event.run, { forward: true });
43
+ }
44
+ /**
45
+ * 应用一个快照:runId 去重、维持 newest-first、容量淘汰。
46
+ * forward=false 用于种子(不回发 RPC——面板尚未订阅,快照方法自会读到)。
47
+ */
48
+ apply(run, options) {
49
+ const forward = options?.forward ?? true;
50
+ if (!this.runs.has(run.runId)) {
51
+ this.order.unshift(run.runId);
52
+ }
53
+ this.runs.set(run.runId, run);
54
+ // 重新按开始时间排序(runId 重复应用时保持位置稳定即可)
55
+ this.order.sort((a, b) => {
56
+ const ra = this.runs.get(a);
57
+ const rb = this.runs.get(b);
58
+ const sa = ra?.startedAt ?? 0;
59
+ const sb = rb?.startedAt ?? 0;
60
+ return sb - sa;
61
+ });
62
+ while (this.order.length > this.capacity) {
63
+ const evicted = this.order.pop();
64
+ if (evicted !== undefined)
65
+ this.runs.delete(evicted);
66
+ }
67
+ if (forward) {
68
+ this.emit(run);
69
+ }
70
+ }
71
+ /** 当前板(newest first;snapshot 方法与测试用) */
72
+ list() {
73
+ const out = [];
74
+ for (const runId of this.order) {
75
+ const run = this.runs.get(runId);
76
+ if (run)
77
+ out.push(run);
78
+ }
79
+ return out;
80
+ }
81
+ dispose() {
82
+ this.unsubscribe?.();
83
+ this.unsubscribe = undefined;
84
+ }
85
+ }
86
+ /**
87
+ * 插件装配:注册 ProgressRpc(snapshot/detail/session 方法)+ 订阅事件总线
88
+ * + store 种子。返回 board(持有者可 dispose;插件生命周期内常驻)。
89
+ */
90
+ export async function bindProgressBoard(deps) {
91
+ let board;
92
+ const registration = await deps.rpc.register(ProgressRpc, {
93
+ snapshot: async () => ({ runs: board ? board.list().slice() : [] }),
94
+ // journal 单读(无 journalDir 配置 -> store 缺席 -> null;面板不渲染详情区)
95
+ detail: async (input) => {
96
+ const runId = parseRunDetailRequest(input);
97
+ if (!deps.store || runId === undefined)
98
+ return { run: null };
99
+ const run = await deps.store.getRun(runId);
100
+ return { run: run ? toRunDetail(run) : null };
101
+ },
102
+ // Open Session 回放:journal 定位步骤会话 -> 宿主拉取 -> 预览截断
103
+ session: async (input) => {
104
+ const request = parseSessionReplayRequest(input);
105
+ if (!deps.store || !deps.fetchSessionMessages || request === undefined) {
106
+ return { session: null };
107
+ }
108
+ const run = await deps.store.getRun(request.runId);
109
+ const step = run?.steps.find((s) => s.name === request.step && s.sessionIDs !== undefined && s.sessionIDs.length > 0);
110
+ const sessionIDs = step?.sessionIDs;
111
+ if (!sessionIDs)
112
+ return { session: null };
113
+ const sessionID = request.index !== undefined
114
+ ? (sessionIDs[request.index] ?? sessionIDs[sessionIDs.length - 1])
115
+ : sessionIDs[sessionIDs.length - 1];
116
+ const messages = await deps.fetchSessionMessages(sessionID);
117
+ return {
118
+ session: {
119
+ sessionID,
120
+ step: request.step,
121
+ messages: messages
122
+ .slice(0, REPLAY_MESSAGE_LIMIT)
123
+ .map((message) => ({ ...message, text: message.text.slice(0, REPLAY_TEXT_LIMIT) })),
124
+ },
125
+ };
126
+ },
127
+ });
128
+ // store 种子:面板打开时能立即看到近期历史 run(不只是本次会话的)
129
+ let seed;
130
+ if (deps.store) {
131
+ seed = await seedFromStore(deps.store, deps.options?.capacity ?? 20);
132
+ }
133
+ board = new ProgressBoard((run) => {
134
+ void registration.events.emit("progress", run).catch((error) => {
135
+ // 转发失败绝不影响 workflow(事件总线隔离原则的同款纪律)
136
+ console.log(`[agentic-workflow] progress emit failed (runId=${run.runId}): ` +
137
+ `${error instanceof Error ? error.message : String(error)}`);
138
+ });
139
+ }, { ...deps.options, ...(seed ? { seed } : {}) });
140
+ return board;
141
+ }
142
+ /** store 里的近期 run -> 快照种子(newest first,容量截断) */
143
+ export async function seedFromStore(store, capacity = 20) {
144
+ const runs = await store.listRuns();
145
+ return runs
146
+ .sort((a, b) => b.startedAt - a.startedAt)
147
+ .slice(0, capacity)
148
+ .map(toProgressSnapshot);
149
+ }
150
+ //# sourceMappingURL=progress-board.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-board.js","sourceRoot":"","sources":["../../src/plugin/progress-board.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EACL,WAAW,GAIZ,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACtE,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,yBAAyB,GAE1B,MAAM,mBAAmB,CAAA;AAI1B,iCAAiC;AACjC,MAAM,oBAAoB,GAAG,EAAE,CAAA;AAC/B,iBAAiB;AACjB,MAAM,iBAAiB,GAAG,GAAG,CAAA;AAkB7B,MAAM,OAAO,aAAa;IAOL,IAAI;IANN,IAAI,GAAG,IAAI,GAAG,EAA+B,CAAA;IAC7C,KAAK,GAAa,EAAE,CAAA;IACpB,QAAQ,CAAQ;IACzB,WAAW,CAA0B;IAE7C,YACmB,IAAwC,EACzD,OAA8B;oBADb,IAAI;QAGrB,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAA;QACvC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;YACtC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;QACrC,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE;YACrE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QACrB,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,+BAA+B;IAC/B,OAAO,CAAC,KAAoB;QAC1B,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc;YAAE,OAAM;QACzC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,GAAwB,EAAE,OAA+B;QAC7D,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,IAAI,CAAA;QACxC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAC/B,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAC7B,iCAAiC;QACjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACvB,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YAC3B,MAAM,EAAE,GAAG,EAAE,EAAE,SAAS,IAAI,CAAC,CAAA;YAC7B,MAAM,EAAE,GAAG,EAAE,EAAE,SAAS,IAAI,CAAC,CAAA;YAC7B,OAAO,EAAE,GAAG,EAAE,CAAA;QAChB,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAA;YAChC,IAAI,OAAO,KAAK,SAAS;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACtD,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAChB,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,IAAI;QACF,MAAM,GAAG,GAA0B,EAAE,CAAA;QACrC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAChC,IAAI,GAAG;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACxB,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,OAAO;QACL,IAAI,CAAC,WAAW,EAAE,EAAE,CAAA;QACpB,IAAI,CAAC,WAAW,GAAG,SAAS,CAAA;IAC9B,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IASvC;IACC,IAAI,KAAgC,CAAA;IACpC,MAAM,YAAY,GAAyB,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE;QAC9E,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACnE,2DAA2D;QAC3D,MAAM,EAAE,KAAK,EAAE,KAAc,EAAE,EAAE;YAC/B,MAAM,KAAK,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAA;YAC1C,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAA;YAC5D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;YAC1C,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;QAC/C,CAAC;QACD,iDAAiD;QACjD,OAAO,EAAE,KAAK,EAAE,KAAc,EAAE,EAAE;YAChC,MAAM,OAAO,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAA;YAChD,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,oBAAoB,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBACvE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;YAC1B,CAAC;YACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YAClD,MAAM,IAAI,GAAG,GAAG,EAAE,KAAK,CAAC,IAAI,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CACxF,CAAA;YACD,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,CAAA;YACnC,IAAI,CAAC,UAAU;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;YACzC,MAAM,SAAS,GACb,OAAO,CAAC,KAAK,KAAK,SAAS;gBACzB,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;gBACnE,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAE,CAAA;YACxC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAA;YAC3D,OAAO;gBACL,OAAO,EAAE;oBACP,SAAS;oBACT,IAAI,EAAE,OAAO,CAAC,IAAI;oBAClB,QAAQ,EAAE,QAAQ;yBACf,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC;yBAC9B,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC;iBACtF;aACF,CAAA;QACH,CAAC;KACF,CAAC,CAAA;IACF,wCAAwC;IACxC,IAAI,IAAuC,CAAA;IAC3C,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,IAAI,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAA;IACtE,CAAC;IACD,KAAK,GAAG,IAAI,aAAa,CACvB,CAAC,GAAG,EAAE,EAAE;QACN,KAAK,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,GAAyC,CAAC,CAAC,KAAK,CACxF,CAAC,KAAK,EAAE,EAAE;YACR,mCAAmC;YACnC,OAAO,CAAC,GAAG,CACT,kDAAkD,GAAG,CAAC,KAAK,KAAK;gBAC9D,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC9D,CAAA;QACH,CAAC,CACF,CAAA;IACH,CAAC,EACD,EAAE,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAC/C,CAAA;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,gDAAgD;AAChD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAqB,EACrB,QAAQ,GAAG,EAAE;IAEb,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAA;IACnC,OAAO,IAAI;SACR,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC;SACzC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC;SAClB,GAAG,CAAC,kBAAkB,CAAC,CAAA;AAC5B,CAAC"}