@zhushanwen/pi-subagent-workflow 0.1.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.
Files changed (143) hide show
  1. package/agents/context-builder.md +17 -0
  2. package/agents/general-purpose.md +16 -0
  3. package/agents/oracle.md +17 -0
  4. package/agents/planner.md +17 -0
  5. package/agents/researcher.md +17 -0
  6. package/agents/reviewer.md +17 -0
  7. package/agents/scout.md +17 -0
  8. package/agents/worker.md +16 -0
  9. package/examples/README.md +43 -0
  10. package/examples/chain.example.js +92 -0
  11. package/examples/map-reduce.example.js +99 -0
  12. package/examples/parallel.example.js +82 -0
  13. package/examples/scatter-gather.example.js +106 -0
  14. package/index.ts +1 -0
  15. package/package.json +66 -0
  16. package/skills/workflow-script-format/SKILL.md +328 -0
  17. package/src/execution/__tests__/agent-registry.test.ts +164 -0
  18. package/src/execution/__tests__/agent-result-mapper.test.ts +128 -0
  19. package/src/execution/__tests__/alive-store.test.ts +147 -0
  20. package/src/execution/__tests__/bg-notify-render.test.ts +256 -0
  21. package/src/execution/__tests__/concurrency-pool.test.ts +217 -0
  22. package/src/execution/__tests__/config.test.ts +110 -0
  23. package/src/execution/__tests__/crash-recovery.test.ts +311 -0
  24. package/src/execution/__tests__/execute-nesting.test.ts +359 -0
  25. package/src/execution/__tests__/execute-options-mapper.test.ts +138 -0
  26. package/src/execution/__tests__/execution-record.test.ts +959 -0
  27. package/src/execution/__tests__/finalized-marker.test.ts +82 -0
  28. package/src/execution/__tests__/format-schema-instruction.test.ts +135 -0
  29. package/src/execution/__tests__/format.test.ts +320 -0
  30. package/src/execution/__tests__/helpers/mock-extension-api.ts +30 -0
  31. package/src/execution/__tests__/list-component.test.ts +347 -0
  32. package/src/execution/__tests__/model-resolver.test.ts +356 -0
  33. package/src/execution/__tests__/output-collector.test.ts +61 -0
  34. package/src/execution/__tests__/path-encoding.test.ts +75 -0
  35. package/src/execution/__tests__/pi-invocation.test.ts +73 -0
  36. package/src/execution/__tests__/record-store.test.ts +545 -0
  37. package/src/execution/__tests__/run-spawn-edges.test.ts +439 -0
  38. package/src/execution/__tests__/run-spawn-integration.test.ts +897 -0
  39. package/src/execution/__tests__/sdk-contract.test.ts +272 -0
  40. package/src/execution/__tests__/session-context-resolver.test.ts +167 -0
  41. package/src/execution/__tests__/session-file-gc.test.ts +247 -0
  42. package/src/execution/__tests__/session-reconstructor.test.ts +359 -0
  43. package/src/execution/__tests__/session-runner-schema-env.test.ts +314 -0
  44. package/src/execution/__tests__/session-start-reaper.test.ts +227 -0
  45. package/src/execution/__tests__/spawn-args.test.ts +244 -0
  46. package/src/execution/__tests__/spawn-event-adapter.test.ts +167 -0
  47. package/src/execution/__tests__/subagent-service.test.ts +678 -0
  48. package/src/execution/__tests__/subprocess-agent-runner.test.ts +389 -0
  49. package/src/execution/__tests__/temp-prompt.test.ts +53 -0
  50. package/src/execution/__tests__/timeout-integration.test.ts +381 -0
  51. package/src/execution/__tests__/tombstone-store.test.ts +73 -0
  52. package/src/execution/__tests__/tool-action.test.ts +330 -0
  53. package/src/execution/__tests__/turn-limiter.test.ts +65 -0
  54. package/src/execution/__tests__/worktree-manager.test.ts +423 -0
  55. package/src/execution/__tests__/worktree-registry.test.ts +161 -0
  56. package/src/execution/agent-registry.ts +252 -0
  57. package/src/execution/agent-result-mapper.ts +84 -0
  58. package/src/execution/alive-store.ts +92 -0
  59. package/src/execution/best-effort.ts +30 -0
  60. package/src/execution/concurrency-pool.ts +84 -0
  61. package/src/execution/config.ts +73 -0
  62. package/src/execution/execute-options-mapper.ts +86 -0
  63. package/src/execution/execution-record.ts +778 -0
  64. package/src/execution/finalized-marker.ts +51 -0
  65. package/src/execution/model-config-service.ts +225 -0
  66. package/src/execution/model-resolver.ts +247 -0
  67. package/src/execution/notifier.ts +168 -0
  68. package/src/execution/output-collector.ts +88 -0
  69. package/src/execution/path-encoding.ts +34 -0
  70. package/src/execution/pi-invocation.ts +70 -0
  71. package/src/execution/record-store.ts +350 -0
  72. package/src/execution/session-context-resolver.ts +64 -0
  73. package/src/execution/session-file-gc.ts +98 -0
  74. package/src/execution/session-reconstructor.ts +450 -0
  75. package/src/execution/session-runner.ts +725 -0
  76. package/src/execution/spawn-event-adapter.ts +150 -0
  77. package/src/execution/subagent-service.ts +973 -0
  78. package/src/execution/subprocess-agent-runner.ts +108 -0
  79. package/src/execution/temp-prompt.ts +57 -0
  80. package/src/execution/tombstone-store.ts +72 -0
  81. package/src/execution/turn-limiter.ts +88 -0
  82. package/src/execution/types.ts +634 -0
  83. package/src/execution/worktree-manager.ts +285 -0
  84. package/src/execution/worktree-registry.ts +144 -0
  85. package/src/index.ts +454 -0
  86. package/src/interface/bg-notify-render.ts +286 -0
  87. package/src/interface/commands.ts +157 -0
  88. package/src/interface/format.ts +501 -0
  89. package/src/interface/gui-adapter.ts +136 -0
  90. package/src/interface/helpers.ts +110 -0
  91. package/src/interface/list-component.ts +643 -0
  92. package/src/interface/list-shared.ts +84 -0
  93. package/src/interface/list-view.ts +373 -0
  94. package/src/interface/reentry-guard.ts +30 -0
  95. package/src/interface/subagent-actions.ts +294 -0
  96. package/src/interface/subagent-tool.ts +294 -0
  97. package/src/interface/subagents.ts +30 -0
  98. package/src/interface/tool-render.ts +333 -0
  99. package/src/interface/tool-workflow-script.ts +351 -0
  100. package/src/interface/tool-workflow.ts +485 -0
  101. package/src/interface/views/WorkflowsView.ts +944 -0
  102. package/src/interface/views/detail-content.ts +298 -0
  103. package/src/interface/views/format.ts +320 -0
  104. package/src/orchestration/__tests__/concurrency-gate.test.ts +125 -0
  105. package/src/orchestration/__tests__/config-loader.test.ts +381 -0
  106. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +332 -0
  107. package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +166 -0
  108. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +248 -0
  109. package/src/orchestration/__tests__/lifecycle.test.ts +385 -0
  110. package/src/orchestration/__tests__/script-lint.test.ts +347 -0
  111. package/src/orchestration/__tests__/worker-script-builder.test.ts +42 -0
  112. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +319 -0
  113. package/src/orchestration/agent-opts-resolver.ts +128 -0
  114. package/src/orchestration/concurrency-gate.ts +69 -0
  115. package/src/orchestration/config-loader.ts +313 -0
  116. package/src/orchestration/error-recovery.ts +578 -0
  117. package/src/orchestration/execute-agent-call.ts +174 -0
  118. package/src/orchestration/jsonl-run-store.ts +292 -0
  119. package/src/orchestration/launcher.ts +368 -0
  120. package/src/orchestration/lifecycle.ts +373 -0
  121. package/src/orchestration/models/__tests__/budget.test.ts +367 -0
  122. package/src/orchestration/models/agent-call.ts +76 -0
  123. package/src/orchestration/models/budget.ts +148 -0
  124. package/src/orchestration/models/ports.ts +165 -0
  125. package/src/orchestration/models/run-runtime.ts +91 -0
  126. package/src/orchestration/models/run-spec.ts +54 -0
  127. package/src/orchestration/models/run-state.ts +44 -0
  128. package/src/orchestration/models/trace.ts +102 -0
  129. package/src/orchestration/models/types.ts +242 -0
  130. package/src/orchestration/models/workflow-run.ts +275 -0
  131. package/src/orchestration/models/workflow-script-registry.ts +32 -0
  132. package/src/orchestration/models/workflow-script.ts +90 -0
  133. package/src/orchestration/node-ops.ts +192 -0
  134. package/src/orchestration/script-lint.ts +387 -0
  135. package/src/orchestration/skill-discovery.ts +60 -0
  136. package/src/orchestration/worker-handle.ts +115 -0
  137. package/src/orchestration/worker-host.ts +93 -0
  138. package/src/orchestration/worker-script-builder.ts +281 -0
  139. package/src/orchestration/workflow-files.ts +85 -0
  140. package/src/orchestration/workflow-script-registry-impl.ts +128 -0
  141. package/src/shared/__tests__/resource-discovery.test.ts +226 -0
  142. package/src/shared/agent-event.ts +13 -0
  143. package/src/shared/resource-discovery.ts +535 -0
@@ -0,0 +1,150 @@
1
+ // src/core/spawn-event-adapter.ts
2
+ //
3
+ // pi 子进程 stdout JSON 事件流的解析器。Core 叶子原语(仅依赖 types.ts)。
4
+ //
5
+ // spawn 改造的基座模块。pi --mode json 子进程通过 stdout 输出两种行:
6
+ // 1. header 行(首行):{ type: "session", id, timestamp, cwd, ... }
7
+ // —— session 元信息,含 session id(文件路径由 W2 runSpawn 配合 --session-dir 推导)
8
+ // 2. 事件行:{ type: "tool_execution_start" | "message_end" | ..., ... }
9
+ // —— 与 in-process session.subscribe 收到的 SdkEvent 同源同构
10
+ //
11
+ // 本模块只做「行 → 分类事件对象」的纯解析,不做累积/翻译(那是 runSpawn +
12
+ // handleSdkEvent 的职责)。刻意保持薄,便于单测。
13
+ //
14
+ // 与 session-runner.handleSdkEvent 的契约:parseSpawnLine 返回 kind:"event" 的
15
+ // event 字段即为 SdkEvent,可直接喂给 handleSdkEvent(事件 type schema 一致,
16
+ // 由 print-mode.ts:106 JSON.stringify(event) 保证同源)。
17
+
18
+ import * as fs from "node:fs";
19
+ import * as path from "node:path";
20
+
21
+ import type { SdkEvent } from "./types.ts";
22
+
23
+ /** pi stdout header 行(session 元信息)。type 固定为 "session"。 */
24
+ export interface SpawnSessionHeader {
25
+ readonly type: "session";
26
+ readonly id: string;
27
+ readonly timestamp: string;
28
+ readonly cwd: string;
29
+ readonly parentSession?: string;
30
+ readonly version?: number;
31
+ }
32
+
33
+ /** parseSpawnLine 的分类结果。 */
34
+ export type ParsedSpawnLine =
35
+ | { kind: "header"; header: SpawnSessionHeader }
36
+ | { kind: "event"; event: SdkEvent }
37
+ | { kind: "invalid"; raw: string; error: string };
38
+
39
+ /**
40
+ * 判断解析出的 JSON 是否为 header 行(type === "session")。
41
+ * 校验所有必需字段(id/timestamp/cwd),缺任一则不收窄——避免下游
42
+ * deriveSessionFilePath 访问 undefined 字段时抛 TypeError。
43
+ */
44
+ function isSessionHeader(obj: unknown): obj is SpawnSessionHeader {
45
+ if (typeof obj !== "object" || obj === null) return false;
46
+ const r = obj as Record<string, unknown>;
47
+ return (
48
+ r.type === "session" &&
49
+ typeof r.id === "string" &&
50
+ typeof r.timestamp === "string" &&
51
+ typeof r.cwd === "string"
52
+ );
53
+ }
54
+
55
+ /**
56
+ * 解析 pi stdout 的一行。
57
+ *
58
+ * @param line stdout 的一行(不含换行符;空行返回 null)
59
+ * @returns 分类结果,或 null(空行/仅空白)
60
+ *
61
+ * 分类规则:
62
+ * - 空白行 → null(pi 可能输出空行,跳过)
63
+ * - 合法 JSON + type:"session" + 有 id → header
64
+ * - 合法 JSON + 有 type 字段 → event(SdkEvent,type schema 由调用方校验)
65
+ * - 合法 JSON 但无 type → invalid
66
+ * - 非法 JSON → invalid(记录 error,不抛——单行损坏不应中断整个流)
67
+ *
68
+ * 容错原则:stdout 是流式输出,任何单行解析失败都不应中断进程。invalid 归类
69
+ * 由 runSpawn 决定是否记录/忽略,本函数不丢弃信息。
70
+ */
71
+ export function parseSpawnLine(line: string): ParsedSpawnLine | null {
72
+ const trimmed = line.trim();
73
+ if (trimmed === "") return null;
74
+
75
+ let obj: unknown;
76
+ try {
77
+ obj = JSON.parse(trimmed);
78
+ } catch (err) {
79
+ return {
80
+ kind: "invalid",
81
+ raw: trimmed,
82
+ error: err instanceof Error ? err.message : String(err),
83
+ };
84
+ }
85
+
86
+ if (isSessionHeader(obj)) {
87
+ return { kind: "header", header: obj };
88
+ }
89
+
90
+ // 事件行:必须有 type 字段(SdkEvent 契约)
91
+ if (
92
+ typeof obj === "object" &&
93
+ obj !== null &&
94
+ typeof (obj as Record<string, unknown>).type === "string"
95
+ ) {
96
+ return { kind: "event", event: obj as SdkEvent };
97
+ }
98
+
99
+ return {
100
+ kind: "invalid",
101
+ raw: trimmed,
102
+ error: "JSON missing string 'type' field",
103
+ };
104
+ }
105
+
106
+ /**
107
+ * 从已收集的 header + 事件流推导子进程的 session 文件路径。
108
+ *
109
+ * pi session 文件命名规则(session-manager.ts:846):
110
+ * `${fileTimestamp}_${sessionId}.jsonl`
111
+ * 其中 fileTimestamp = header.timestamp.replace(/[:.]/g, "-")
112
+ * (ISO 时间里的冒号和点替换为连字符,如 2026-07-03T12-34-56-789Z)。
113
+ *
114
+ * @param header spawn 解析出的 session header
115
+ * @param sessionDir 指定的 session 目录(spawn 时通过 --session-dir 传入)
116
+ * @returns 推导的 session 文件绝对路径(不保证文件存在——子进程可能仍在写入)
117
+ *
118
+ * 注意:这是基于 pi 命名规则的推导。runSpawn 会在进程结束后校验文件实际存在,
119
+ * 不存在时用 sessionId 后缀匹配兜底。
120
+ */
121
+ export function deriveSessionFilePath(
122
+ header: SpawnSessionHeader,
123
+ sessionDir: string,
124
+ ): string {
125
+ const fileTimestamp = header.timestamp.replace(/[:.]/g, "-");
126
+ return `${sessionDir}/${fileTimestamp}_${header.id}.jsonl`;
127
+ }
128
+
129
+ /**
130
+ * 在 sessionDir 中按 sessionId 后缀匹配查找实际存在的 session 文件。
131
+ *
132
+ * 兜底机制:deriveSessionFilePath 基于命名规则推导,若 pi 命名规则变化导致
133
+ * 推导路径不存在,用 sessionId 作为后缀匹配实际文件。sessionId 是 header
134
+ * 的稳定标识,文件名必含它,匹配可靠。
135
+ *
136
+ * @returns 匹配到的文件绝对路径,或 undefined(无匹配)
137
+ */
138
+ export function findSessionFileByHeaderId(
139
+ sessionDir: string,
140
+ sessionId: string,
141
+ ): string | undefined {
142
+ try {
143
+ const files = fs.readdirSync(sessionDir);
144
+ // 文件名格式:<fileTimestamp>_<sessionId>.jsonl,sessionId 是后缀(去掉 .jsonl)
145
+ const match = files.find((f) => f.endsWith(`_${sessionId}.jsonl`));
146
+ return match ? path.join(sessionDir, match) : undefined;
147
+ } catch {
148
+ return undefined;
149
+ }
150
+ }