@zhushanwen/pi-subagent-workflow 8.6.0 → 8.8.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 (364) hide show
  1. package/README.md +5 -11
  2. package/package.json +13 -20
  3. package/relay/relay.mjs +1 -1
  4. package/skills/workflow-script-format/SKILL.md +32 -13
  5. package/src/host/__tests__/pi-host.test.ts +235 -0
  6. package/src/host/pi-host.ts +163 -0
  7. package/src/index.ts +141 -138
  8. package/src/injectors/__tests__/engine-awareness.test.ts +292 -0
  9. package/src/injectors/__tests__/engine-section-stability.test.ts +343 -0
  10. package/src/injectors/__tests__/model-list-injector.test.ts +18 -21
  11. package/src/injectors/__tests__/subagent-list-injector.test.ts +59 -19
  12. package/src/injectors/__tests__/workflow-list-injector.test.ts +31 -17
  13. package/src/injectors/engine-awareness.ts +119 -0
  14. package/src/injectors/model-list-injector.ts +15 -58
  15. package/src/injectors/subagent-list-injector.ts +56 -114
  16. package/src/injectors/workflow-list-injector.ts +37 -70
  17. package/src/interface/__tests__/detectors.test.ts +48 -37
  18. package/src/interface/__tests__/subagent-tool-path-guard.test.ts +2 -2
  19. package/src/interface/__tests__/subagent-tool-prompt.test.ts +6 -3
  20. package/src/interface/__tests__/tool-workflow-run-builtin-name.test.ts +216 -0
  21. package/src/interface/__tests__/tool-workflow-script-generate.test.ts +17 -6
  22. package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +38 -2
  23. package/src/interface/bg-notify-render.ts +7 -17
  24. package/src/interface/command-actions.ts +5 -15
  25. package/src/interface/commands.ts +4 -4
  26. package/src/interface/format.ts +17 -6
  27. package/src/interface/gui-mappers.ts +18 -22
  28. package/src/interface/helpers.ts +9 -130
  29. package/src/interface/list-component.ts +5 -5
  30. package/src/interface/list-shared.ts +3 -3
  31. package/src/interface/list-view.ts +3 -3
  32. package/src/interface/subagent-actions.ts +66 -439
  33. package/src/interface/subagent-tool-schema.ts +21 -17
  34. package/src/interface/subagent-tool.ts +12 -7
  35. package/src/interface/subagents.ts +4 -4
  36. package/src/interface/tool-render.ts +37 -15
  37. package/src/interface/tool-workflow-script.ts +34 -76
  38. package/src/interface/tool-workflow.ts +57 -94
  39. package/src/interface/views/WorkflowsView.ts +8 -16
  40. package/src/interface/views/__tests__/WorkflowsView-signature.test.ts +3 -3
  41. package/src/interface/views/__tests__/detail-content-session-file.test.ts +2 -2
  42. package/src/interface/views/detail-content.ts +4 -4
  43. package/src/interface/views/format.ts +23 -62
  44. package/src/{orchestration/jsonl-run-store.ts → jsonl-run-store.ts} +137 -225
  45. package/agents/analyst.md +0 -61
  46. package/agents/coder.md +0 -70
  47. package/agents/debugger.md +0 -67
  48. package/agents/doc-reviewer.md +0 -50
  49. package/agents/explorer.md +0 -64
  50. package/agents/general-purpose.md +0 -32
  51. package/agents/orchestrator.md +0 -63
  52. package/agents/planner.md +0 -54
  53. package/agents/researcher.md +0 -65
  54. package/agents/reviewer.md +0 -74
  55. package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +0 -53
  56. package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +0 -1
  57. package/src/execution/__tests__/agent-registry.test.ts +0 -363
  58. package/src/execution/__tests__/agent-result-mapper.test.ts +0 -150
  59. package/src/execution/__tests__/alive-store.test.ts +0 -147
  60. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  61. package/src/execution/__tests__/before-agent-start-injection.test.ts +0 -132
  62. package/src/execution/__tests__/bg-notify-render.test.ts +0 -329
  63. package/src/execution/__tests__/channel-registry-handshake.test.ts +0 -243
  64. package/src/execution/__tests__/chat-engine-routing.test.ts +0 -601
  65. package/src/execution/__tests__/chatmode-first-round-closure-service.test.ts +0 -365
  66. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -190
  67. package/src/execution/__tests__/chatmode-round-notify-real-chain.test.ts +0 -215
  68. package/src/execution/__tests__/concurrency-pool.test.ts +0 -250
  69. package/src/execution/__tests__/config.test.ts +0 -110
  70. package/src/execution/__tests__/conversation-wiring.test.ts +0 -198
  71. package/src/execution/__tests__/crash-recovery.test.ts +0 -320
  72. package/src/execution/__tests__/delivery-methods.test.ts +0 -422
  73. package/src/execution/__tests__/dialog-queue.test.ts +0 -299
  74. package/src/execution/__tests__/epipe-fallback.test.ts +0 -241
  75. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -243
  76. package/src/execution/__tests__/execute-nesting.test.ts +0 -323
  77. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
  78. package/src/execution/__tests__/execution-record.test.ts +0 -1394
  79. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +0 -171
  80. package/src/execution/__tests__/finalize-record.test.ts +0 -368
  81. package/src/execution/__tests__/finalized-marker.test.ts +0 -82
  82. package/src/execution/__tests__/format-schema-instruction.test.ts +0 -169
  83. package/src/execution/__tests__/format.test.ts +0 -458
  84. package/src/execution/__tests__/gc-timer.test.ts +0 -184
  85. package/src/execution/__tests__/get-record-for-action-restart.test.ts +0 -254
  86. package/src/execution/__tests__/gui-mode-dispatch.test.ts +0 -59
  87. package/src/execution/__tests__/helpers/mock-extension-api.ts +0 -30
  88. package/src/execution/__tests__/helpers/spawn-mock.ts +0 -242
  89. package/src/execution/__tests__/host-mode.test.ts +0 -87
  90. package/src/execution/__tests__/index-session-start-identity.test.ts +0 -371
  91. package/src/execution/__tests__/index-session-start.test.ts +0 -672
  92. package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
  93. package/src/execution/__tests__/lifecycle-manager.test.ts +0 -383
  94. package/src/execution/__tests__/lifecycle-predicates.test.ts +0 -116
  95. package/src/execution/__tests__/list-component.test.ts +0 -401
  96. package/src/execution/__tests__/list-fields.test.ts +0 -140
  97. package/src/execution/__tests__/manifest-parentid.test.ts +0 -117
  98. package/src/execution/__tests__/model-resolver.test.ts +0 -465
  99. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +0 -287
  100. package/src/execution/__tests__/nested-visibility.test.ts +0 -325
  101. package/src/execution/__tests__/notifier-flush.test.ts +0 -612
  102. package/src/execution/__tests__/notifier-golden-snapshot.test.ts +0 -261
  103. package/src/execution/__tests__/notify-ledger.test.ts +0 -826
  104. package/src/execution/__tests__/one-shot-upgrade.test.ts +0 -205
  105. package/src/execution/__tests__/output-collector.test.ts +0 -358
  106. package/src/execution/__tests__/parent-child-matrix.test.ts +0 -336
  107. package/src/execution/__tests__/path-encoding.test.ts +0 -104
  108. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  109. package/src/execution/__tests__/record-store.test.ts +0 -1057
  110. package/src/execution/__tests__/records-cwd-isolation.test.ts +0 -91
  111. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +0 -339
  112. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -273
  113. package/src/execution/__tests__/relay-agent.test.ts +0 -448
  114. package/src/execution/__tests__/relay-env.test.ts +0 -42
  115. package/src/execution/__tests__/resource-policy.test.ts +0 -109
  116. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  117. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -267
  118. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -253
  119. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -687
  120. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  121. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  122. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  123. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -199
  124. package/src/execution/__tests__/sdk-contract.test.ts +0 -273
  125. package/src/execution/__tests__/session-context-resolver.test.ts +0 -167
  126. package/src/execution/__tests__/session-file-gc.test.ts +0 -293
  127. package/src/execution/__tests__/session-pending.test.ts +0 -197
  128. package/src/execution/__tests__/session-reconstructor.test.ts +0 -379
  129. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -178
  130. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -350
  131. package/src/execution/__tests__/session-start-reaper.test.ts +0 -233
  132. package/src/execution/__tests__/spawn-args.test.ts +0 -445
  133. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -189
  134. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  135. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -207
  136. package/src/execution/__tests__/spawned-children.test.ts +0 -92
  137. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  138. package/src/execution/__tests__/startup-config-declaration.test.ts +0 -35
  139. package/src/execution/__tests__/status-refactor.test.ts +0 -345
  140. package/src/execution/__tests__/stdin-writer.test.ts +0 -463
  141. package/src/execution/__tests__/stream-sink-retirement.test.ts +0 -261
  142. package/src/execution/__tests__/subagent-service-abort.test.ts +0 -60
  143. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -629
  144. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +0 -180
  145. package/src/execution/__tests__/subagent-service.test.ts +0 -788
  146. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -310
  147. package/src/execution/__tests__/subprocess-agent-runner.test.ts +0 -599
  148. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  149. package/src/execution/__tests__/timeout-integration.test.ts +0 -615
  150. package/src/execution/__tests__/tombstone-store.test.ts +0 -73
  151. package/src/execution/__tests__/tool-action.test.ts +0 -476
  152. package/src/execution/__tests__/truncline-snapshot.test.ts +0 -81
  153. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  154. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  155. package/src/execution/__tests__/ui-channels.test.ts +0 -187
  156. package/src/execution/__tests__/ui-interaction-model.test.ts +0 -67
  157. package/src/execution/__tests__/ui-request-handler-factory.test.ts +0 -370
  158. package/src/execution/__tests__/ui-request-handler.test.ts +0 -204
  159. package/src/execution/__tests__/ui-request-observability.test.ts +0 -114
  160. package/src/execution/__tests__/ui-request-queue.test.ts +0 -133
  161. package/src/execution/__tests__/worktree-manager.test.ts +0 -633
  162. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -229
  163. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +0 -181
  164. package/src/execution/__tests__/worktree-registry.test.ts +0 -199
  165. package/src/execution/agent-registry.ts +0 -199
  166. package/src/execution/agent-result-mapper.ts +0 -90
  167. package/src/execution/alive-store.ts +0 -92
  168. package/src/execution/argv-mirror.ts +0 -113
  169. package/src/execution/best-effort.ts +0 -38
  170. package/src/execution/channel-registry-access.ts +0 -144
  171. package/src/execution/concurrency-pool.ts +0 -116
  172. package/src/execution/config.ts +0 -96
  173. package/src/execution/dialog-queue.ts +0 -330
  174. package/src/execution/engine/__tests__/common/data-dir.test.ts +0 -53
  175. package/src/execution/engine/__tests__/common/errors.test.ts +0 -132
  176. package/src/execution/engine/__tests__/common/event-journal.test.ts +0 -177
  177. package/src/execution/engine/__tests__/common/kill-chain.test.ts +0 -192
  178. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +0 -81
  179. package/src/execution/engine/__tests__/common/persona-router.test.ts +0 -123
  180. package/src/execution/engine/__tests__/common/pool-manager.test.ts +0 -154
  181. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  182. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  183. package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +0 -141
  184. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +0 -109
  185. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +0 -101
  186. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +0 -77
  187. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +0 -104
  188. package/src/execution/engine/__tests__/conformance/contract.relay.test.ts +0 -342
  189. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +0 -201
  190. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +0 -76
  191. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +0 -79
  192. package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -87
  193. package/src/execution/engine/__tests__/engines-declaration.test.ts +0 -36
  194. package/src/execution/engine/__tests__/model-prompt.test.ts +0 -85
  195. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  196. package/src/execution/engine/__tests__/registry.test.ts +0 -120
  197. package/src/execution/engine/__tests__/routing.test.ts +0 -231
  198. package/src/execution/engine/common/data-dir.ts +0 -62
  199. package/src/execution/engine/common/errors.ts +0 -183
  200. package/src/execution/engine/common/event-journal.ts +0 -254
  201. package/src/execution/engine/common/journal-replay.ts +0 -62
  202. package/src/execution/engine/common/kill-chain.ts +0 -221
  203. package/src/execution/engine/common/nesting-guard.ts +0 -50
  204. package/src/execution/engine/common/persona-router.ts +0 -108
  205. package/src/execution/engine/common/pool-manager.ts +0 -226
  206. package/src/execution/engine/common/schema-emulation.ts +0 -189
  207. package/src/execution/engine/common/session-view-projection.ts +0 -51
  208. package/src/execution/engine/engine-discovery.ts +0 -65
  209. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -469
  210. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  211. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  212. package/src/execution/engine/engines/pi/pi-engine.ts +0 -415
  213. package/src/execution/engine/engines/pi/reader.ts +0 -48
  214. package/src/execution/engine/engines/pi/registration.ts +0 -35
  215. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  216. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  217. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  218. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -246
  219. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -228
  220. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  221. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -64
  222. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -127
  223. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -580
  224. package/src/execution/engine/engines/zcode/constants.ts +0 -43
  225. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -39
  226. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  227. package/src/execution/engine/engines/zcode/parser.ts +0 -436
  228. package/src/execution/engine/engines/zcode/preparer.ts +0 -363
  229. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  230. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  231. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -658
  232. package/src/execution/engine/host-task-spec.ts +0 -47
  233. package/src/execution/engine/model-prompt.ts +0 -59
  234. package/src/execution/engine/paths.ts +0 -42
  235. package/src/execution/engine/port.ts +0 -153
  236. package/src/execution/engine/registry.ts +0 -123
  237. package/src/execution/engine/routing.ts +0 -218
  238. package/src/execution/engine/types.ts +0 -309
  239. package/src/execution/execute-options-mapper.ts +0 -112
  240. package/src/execution/execution-record.ts +0 -965
  241. package/src/execution/finalize-record.ts +0 -251
  242. package/src/execution/finalized-marker.ts +0 -51
  243. package/src/execution/get-state-handshake.ts +0 -104
  244. package/src/execution/host-mode.ts +0 -56
  245. package/src/execution/idle-gc.ts +0 -47
  246. package/src/execution/lifecycle-manager.ts +0 -513
  247. package/src/execution/lifecycle-predicates.ts +0 -65
  248. package/src/execution/manifest-store.ts +0 -256
  249. package/src/execution/model-config-service.ts +0 -219
  250. package/src/execution/model-resolver.ts +0 -248
  251. package/src/execution/notifier.ts +0 -330
  252. package/src/execution/notify-ledger.ts +0 -580
  253. package/src/execution/output-collector.ts +0 -228
  254. package/src/execution/path-encoding.ts +0 -60
  255. package/src/execution/pi-invocation.ts +0 -120
  256. package/src/execution/record-entry.ts +0 -132
  257. package/src/execution/record-store.ts +0 -1234
  258. package/src/execution/relay-env.ts +0 -37
  259. package/src/execution/session-context-resolver.ts +0 -64
  260. package/src/execution/session-file-gc.ts +0 -120
  261. package/src/execution/session-pending.ts +0 -164
  262. package/src/execution/session-reconstructor.ts +0 -678
  263. package/src/execution/session-runner.ts +0 -1781
  264. package/src/execution/sessions-index.ts +0 -304
  265. package/src/execution/spawn-event-adapter.ts +0 -363
  266. package/src/execution/stdin-writer.ts +0 -198
  267. package/src/execution/stream-sink.ts +0 -126
  268. package/src/execution/subagent-service.ts +0 -2141
  269. package/src/execution/subprocess-agent-runner.ts +0 -317
  270. package/src/execution/temp-prompt.ts +0 -62
  271. package/src/execution/tombstone-store.ts +0 -72
  272. package/src/execution/turn-limiter.ts +0 -102
  273. package/src/execution/types.ts +0 -973
  274. package/src/execution/ui-channels.ts +0 -216
  275. package/src/execution/ui-interaction-model.ts +0 -48
  276. package/src/execution/ui-request-handler-factory.ts +0 -212
  277. package/src/execution/ui-request-observability.ts +0 -81
  278. package/src/execution/ui-request-queue.ts +0 -184
  279. package/src/execution/worktree-manager.ts +0 -688
  280. package/src/execution/worktree-registry.ts +0 -222
  281. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +0 -349
  282. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +0 -202
  283. package/src/orchestration/__tests__/agent-call-stream.test.ts +0 -152
  284. package/src/orchestration/__tests__/args-validator.test.ts +0 -143
  285. package/src/orchestration/__tests__/config-loader.test.ts +0 -503
  286. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +0 -809
  287. package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +0 -405
  288. package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +0 -56
  289. package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +0 -166
  290. package/src/orchestration/__tests__/execute-agent-call.test.ts +0 -451
  291. package/src/orchestration/__tests__/jsonl-run-store-corrupt-entry.test.ts +0 -150
  292. package/src/orchestration/__tests__/jsonl-run-store-loadall-sources.test.ts +0 -171
  293. package/src/orchestration/__tests__/jsonl-run-store-retention.test.ts +0 -202
  294. package/src/orchestration/__tests__/jsonl-run-store-session-file.test.ts +0 -1030
  295. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +0 -600
  296. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +0 -96
  297. package/src/orchestration/__tests__/lifecycle.test.ts +0 -659
  298. package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +0 -95
  299. package/src/orchestration/__tests__/review-fix-loop-e2e.test.ts +0 -2025
  300. package/src/orchestration/__tests__/script-lint.test.ts +0 -831
  301. package/src/orchestration/__tests__/skill-discovery.test.ts +0 -201
  302. package/src/orchestration/__tests__/test-mocks.ts +0 -197
  303. package/src/orchestration/__tests__/worker-exit-without-result.test.ts +0 -368
  304. package/src/orchestration/__tests__/worker-host.test.ts +0 -120
  305. package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +0 -164
  306. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +0 -563
  307. package/src/orchestration/__tests__/worker-script-builder.test.ts +0 -309
  308. package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +0 -129
  309. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +0 -317
  310. package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +0 -110
  311. package/src/orchestration/__tests__/workflows-e2e.test.ts +0 -537
  312. package/src/orchestration/agent-opts-resolver.ts +0 -174
  313. package/src/orchestration/args-validator.ts +0 -127
  314. package/src/orchestration/config-loader.ts +0 -315
  315. package/src/orchestration/error-recovery.ts +0 -1018
  316. package/src/orchestration/execute-agent-call.ts +0 -256
  317. package/src/orchestration/launcher.ts +0 -455
  318. package/src/orchestration/lifecycle.ts +0 -399
  319. package/src/orchestration/models/__tests__/budget.test.ts +0 -307
  320. package/src/orchestration/models/__tests__/trace.test.ts +0 -408
  321. package/src/orchestration/models/agent-call.ts +0 -83
  322. package/src/orchestration/models/budget.ts +0 -118
  323. package/src/orchestration/models/ports.ts +0 -164
  324. package/src/orchestration/models/run-runtime.ts +0 -104
  325. package/src/orchestration/models/run-spec.ts +0 -83
  326. package/src/orchestration/models/run-state.ts +0 -44
  327. package/src/orchestration/models/trace.ts +0 -183
  328. package/src/orchestration/models/types.ts +0 -301
  329. package/src/orchestration/models/workflow-run.ts +0 -254
  330. package/src/orchestration/models/workflow-script-registry.ts +0 -35
  331. package/src/orchestration/models/workflow-script.ts +0 -117
  332. package/src/orchestration/script-lint.ts +0 -766
  333. package/src/orchestration/skill-discovery.ts +0 -115
  334. package/src/orchestration/worker-handle.ts +0 -115
  335. package/src/orchestration/worker-host.ts +0 -98
  336. package/src/orchestration/worker-script-builder.ts +0 -421
  337. package/src/orchestration/workflow-files.ts +0 -85
  338. package/src/orchestration/workflow-script-registry-impl.ts +0 -133
  339. package/src/shared/__tests__/agent-ref.test.ts +0 -34
  340. package/src/shared/__tests__/meta-parser.test.ts +0 -304
  341. package/src/shared/__tests__/model-ref.test.ts +0 -306
  342. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -280
  343. package/src/shared/__tests__/resource-discovery.test.ts +0 -736
  344. package/src/shared/__tests__/resource-meta.test.ts +0 -51
  345. package/src/shared/__tests__/schema-jsonify.test.ts +0 -81
  346. package/src/shared/__tests__/timer-delay.test.ts +0 -61
  347. package/src/shared/agent-event.ts +0 -13
  348. package/src/shared/agent-ref.ts +0 -57
  349. package/src/shared/meta-parser.ts +0 -261
  350. package/src/shared/model-ref.ts +0 -286
  351. package/src/shared/resource-discovery.ts +0 -811
  352. package/src/shared/resource-meta.ts +0 -65
  353. package/src/shared/schema-env.ts +0 -44
  354. package/src/shared/schema-jsonify.ts +0 -58
  355. package/src/shared/timer-delay.ts +0 -54
  356. package/src/shared/xml-injection.ts +0 -35
  357. package/workflows/README.md +0 -81
  358. package/workflows/_shared/agent-refs.cjs +0 -40
  359. package/workflows/chain.js +0 -131
  360. package/workflows/map-reduce.js +0 -174
  361. package/workflows/parallel.js +0 -148
  362. package/workflows/review-fix-loop-utils.cjs +0 -1309
  363. package/workflows/review-fix-loop.js +0 -1404
  364. package/workflows/scatter-gather.js +0 -178
@@ -1,469 +0,0 @@
1
- // src/execution/engine/engines/pi/__tests__/pi-engine.test.ts
2
- //
3
- // PiEngine 适配层测试(P1 回填):capabilities 链路接通口径(D3)、run 委托与
4
- // 中立声明→ExecuteOptions 映射、interact 三 action 直通、read 三级降级、probe 形状
5
- // (C1:ok=false 时 error.recovery 非空)。fake PiEngineService 注入,不 spawn 真进程。
6
-
7
- import * as fs from "node:fs";
8
- import * as os from "node:os";
9
- import * as path from "node:path";
10
-
11
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
12
-
13
- import { createRecord } from "../../../../execution-record.ts";
14
- import type { ExecuteOptions, SubagentRecord } from "../../../../types.ts";
15
- import { IDENTITY_CUSTOM_TYPE } from "../../../../session-reconstructor.ts";
16
- import { SubagentStream } from "../../../../stream-sink.ts";
17
- import type { RunContext } from "../../../port.ts";
18
- import type { AgentTaskSpec, EngineHandle } from "../../../types.ts";
19
- import {
20
- PI_ADAPTER_VERSION,
21
- PI_ENGINE_ID,
22
- PiEngine,
23
- type PiEngineService,
24
- } from "../pi-engine.ts";
25
-
26
- // ── fake 编排服务(结构子集,记录调用) ──
27
-
28
- interface ServiceCalls {
29
- executeOpts?: ExecuteOptions;
30
- signal?: AbortSignal;
31
- onEvent?: (event: unknown) => void;
32
- stream?: unknown;
33
- deliverMessage?: { recordId: string; text: string; interrupt: boolean };
34
- close?: { recordId: string; force: boolean };
35
- cancelId?: string;
36
- getRecordId?: string;
37
- }
38
-
39
- /** 构造最小完整 SubagentRecord(collectRecords 返回项——resolveRecordId 只读 id/sessionFile)。 */
40
- function makeListedRecord(id: string, sessionFile: string | undefined): SubagentRecord {
41
- return {
42
- id,
43
- agent: "reviewer",
44
- task: "t",
45
- slug: "s",
46
- status: "running",
47
- mode: "background",
48
- startedAt: 1,
49
- rootSessionId: undefined,
50
- parentRecordId: undefined,
51
- depth: 0,
52
- endedAt: undefined,
53
- turns: 0,
54
- totalTokens: 0,
55
- model: "p/m",
56
- thinkingLevel: undefined,
57
- eventLog: [],
58
- displayItems: [],
59
- ...(sessionFile !== undefined ? { sessionFile } : {}),
60
- };
61
- }
62
-
63
- function makeFakeService(overrides?: {
64
- executeResult?: Awaited<ReturnType<PiEngineService["executeAndAwait"]>>;
65
- executeReject?: Error;
66
- recordsById?: Map<string, ReturnType<typeof createRecord>>;
67
- listed?: Array<{ id: string; sessionFile?: string }>;
68
- cancelResult?: boolean;
69
- deliverReject?: Error;
70
- }): { service: PiEngineService; calls: ServiceCalls } {
71
- const calls: ServiceCalls = {};
72
- const record = createRecord("sa-fake", {
73
- agent: "reviewer",
74
- model: "p/m",
75
- thinkingLevel: "high",
76
- mode: "background",
77
- task: "t",
78
- slug: "s",
79
- startedAt: 1,
80
- controller: new AbortController(),
81
- });
82
- const service: PiEngineService = {
83
- executeAndAwait: async (opts, signal, onEvent, stream) => {
84
- calls.executeOpts = opts;
85
- calls.signal = signal;
86
- calls.onEvent = onEvent;
87
- calls.stream = stream;
88
- if (overrides?.executeReject) throw overrides.executeReject;
89
- return (
90
- overrides?.executeResult ?? {
91
- content: "done",
92
- durationMs: 42,
93
- toolCalls: [],
94
- }
95
- );
96
- },
97
- getRecordForAction: (id) => {
98
- calls.getRecordId = id;
99
- // recordsById 提供时严格查表(模拟「record 不存在 → throw」路径);缺省返回默认 record
100
- if (overrides?.recordsById) {
101
- const found = overrides.recordsById.get(id);
102
- if (!found) {
103
- throw new Error(`subagent not found or not owned: ${id}`);
104
- }
105
- return found;
106
- }
107
- return record;
108
- },
109
- deliverMessage: async (rec, text, interrupt) => {
110
- calls.deliverMessage = { recordId: rec.id, text, interrupt };
111
- if (overrides?.deliverReject) throw overrides.deliverReject;
112
- },
113
- closeSubagent: async (rec, force) => {
114
- calls.close = { recordId: rec.id, force };
115
- },
116
- cancel: (id) => {
117
- calls.cancelId = id;
118
- return overrides?.cancelResult ?? true;
119
- },
120
- collectRecords: () =>
121
- (overrides?.listed ?? []).map(({ id, sessionFile }) => makeListedRecord(id, sessionFile)),
122
- };
123
- return { service, calls };
124
- }
125
-
126
- /** 全字段任务声明(覆盖全部泛化点)。 */
127
- function makeSpec(): AgentTaskSpec {
128
- return {
129
- task: "do the thing",
130
- slug: "do-thing",
131
- agent: "reviewer",
132
- model: "zai-coding-cn/glm-5.2",
133
- effort: "high",
134
- persona: { skillPath: "/skills/r/SKILL.md", appendSystemPrompt: ["extra"] },
135
- schema: { type: "object", properties: { ok: { type: "boolean" } } },
136
- maxTurns: 5,
137
- graceTurns: 2,
138
- fork: true,
139
- worktree: false,
140
- cwd: "/work",
141
- conversation: true,
142
- idleTimeoutMs: 99,
143
- };
144
- }
145
-
146
- function makeHandle(sessionRef: Record<string, string>): EngineHandle {
147
- return { data: { v: 1, engineId: PI_ENGINE_ID, sessionRef, poolKey: "shared", adapterVersion: PI_ADAPTER_VERSION } };
148
- }
149
-
150
- function makeRunCtx(overrides?: Partial<RunContext>): RunContext {
151
- return { taskId: "sa-test", poolKey: "shared", ...overrides };
152
- }
153
-
154
- // ── capabilities ──
155
-
156
- describe("PiEngine.capabilities(D3 链路接通口径)", () => {
157
- it("id = 'pi';声明本仓 subagent 链路实际接通的能力(非 RPC 理论能力)", () => {
158
- const engine = new PiEngine({ getService: () => null });
159
- expect(engine.id).toBe(PI_ENGINE_ID);
160
- expect(engine.capabilities()).toEqual({
161
- schemaEnforcement: "native", // PI_WORKFLOW_SCHEMA env 注入链路(方案 A 唯一权威)
162
- steer: "unsupported", // RPC 有 steer 但 spawn 链路未接通(session-runner no-op)
163
- conversation: "native", // chatMode idle 复用 + message/close/cancel 已接通
164
- personaInjection: "flag", // --skill / --append-system-prompt
165
- eventGranularity: "stream", // 30+ 事件流
166
- sandbox: "emulated", // 无 OS sandbox;worktree 隔离
167
- sessionRead: "full", // pi JSONL 完整重建
168
- resume: "native", // 同进程 idle 复用 + --session 冷续写
169
- interrupt: "kill-only", // 现链路 abort = SIGTERM,rpc abort 未接通
170
- permissionMode: "native", // argv-mirror 镜像主进程 flag
171
- });
172
- });
173
- });
174
-
175
- // ── run ──
176
-
177
- describe("PiEngine.run", () => {
178
- it("中立声明 → ExecuteOptions 映射 + signal/onEvent/stream/ctxModel 直通(行为零变化)", async () => {
179
- const { service, calls } = makeFakeService();
180
- const engine = new PiEngine({ getService: () => service });
181
- const spec = makeSpec();
182
- const ctxModel = { id: "m", name: "M", provider: "p", reasoning: false };
183
- const onEvent = (e: unknown) => void e;
184
- const stream = new SubagentStream("sa-test", { setWidget: () => {} });
185
- const signal = new AbortController().signal;
186
-
187
- const { handle, outcome } = await engine.run(spec, makeRunCtx({ signal, onEvent, ctxModel, stream }));
188
-
189
- // 传参恒等(SAR 接线前的直接调用形态)
190
- expect(calls.signal).toBe(signal);
191
- expect(calls.onEvent).toBe(onEvent);
192
- expect(calls.stream).toBe(stream);
193
- expect(calls.executeOpts).toEqual({
194
- task: "do the thing",
195
- slug: "do-thing",
196
- agent: "reviewer",
197
- model: "zai-coding-cn/glm-5.2",
198
- thinkingLevel: "high", // effort 恒等映射回
199
- skillPath: "/skills/r/SKILL.md", // persona 还原
200
- appendSystemPrompt: ["extra"],
201
- schema: spec.schema,
202
- schemaEnv: JSON.stringify(spec.schema), // schema 派生(D-A6 bridge)
203
- maxTurns: 5,
204
- graceTurns: 2,
205
- ctxModel,
206
- fork: true,
207
- worktree: false,
208
- cwd: "/work",
209
- conversation: true,
210
- idleTimeoutMs: 99,
211
- engine: "pi", // P4 引擎留痕(D9①):实际执行引擎 id 进 record 投影链
212
- });
213
-
214
- // outcome 字段全集映射(缺字段在此转红——SAR outcomeToRunnerResult 的完整性依赖)
215
- expect(outcome).toEqual({
216
- content: "done",
217
- parsedOutput: undefined,
218
- usage: undefined,
219
- durationMs: 42,
220
- error: undefined,
221
- sessionId: undefined,
222
- sessionFile: undefined,
223
- worktreePath: undefined,
224
- toolCalls: [],
225
- engineId: "pi",
226
- });
227
-
228
- // handle 自描述(engineId + sessionRef + poolKey + adapter 版本)
229
- expect(handle.data).toMatchObject({
230
- v: 1,
231
- engineId: "pi",
232
- poolKey: "shared",
233
- adapterVersion: PI_ADAPTER_VERSION,
234
- });
235
- });
236
-
237
- it("sessionFile 回填进 handle.sessionRef;ctx.poolKey 透传(空串兜底 'shared')", async () => {
238
- const { service } = makeFakeService({
239
- executeResult: { content: "x", sessionFile: "/tmp/s.jsonl", sessionId: "sess-1", toolCalls: [] },
240
- });
241
- const engine = new PiEngine({ getService: () => service });
242
- const r1 = await engine.run({ task: "t", slug: "s" }, makeRunCtx({ poolKey: "agent-reviewer" }));
243
- expect(r1.handle.data.sessionRef).toEqual({ sessionFile: "/tmp/s.jsonl" });
244
- expect(r1.handle.data.poolKey).toBe("agent-reviewer");
245
- expect(r1.outcome.sessionId).toBe("sess-1");
246
- const r2 = await engine.run({ task: "t", slug: "s" }, makeRunCtx({ poolKey: "" }));
247
- expect(r2.handle.data.poolKey).toBe("shared");
248
- });
249
-
250
- it("服务不可用(prepare 期)→ reject 且不产生 handle", async () => {
251
- const engine = new PiEngine({ getService: () => null });
252
- await expect(engine.run({ task: "t", slug: "s" }, makeRunCtx())).rejects.toThrow(/SubagentService unavailable/);
253
- });
254
-
255
- it("executeAndAwait throw(嵌套超限等创建期异常)→ 向上传播(SAR catch 兜底不变)", async () => {
256
- const { service } = makeFakeService({ executeReject: new Error("nesting depth exceeded") });
257
- const engine = new PiEngine({ getService: () => service });
258
- await expect(engine.run({ task: "t", slug: "s" }, makeRunCtx())).rejects.toThrow("nesting depth exceeded");
259
- });
260
- });
261
-
262
- // ── interact ──
263
-
264
- describe("PiEngine.interact(chatMode 交互面直通)", () => {
265
- it("message → deliverMessage(record, text, false)(interrupt 中立 action 未携带,P1 恒 followUp)", async () => {
266
- const { service, calls } = makeFakeService();
267
- const engine = new PiEngine({ getService: () => service });
268
- const res = await engine.interact(makeHandle({ recordId: "sa-fake" }), { kind: "message", payload: "next round" });
269
- expect(res).toEqual({ ok: true, delivered: true });
270
- expect(calls.deliverMessage).toEqual({ recordId: "sa-fake", text: "next round", interrupt: false });
271
- });
272
-
273
- it("close → closeSubagent(record, force);payload 缺省 force=false", async () => {
274
- const { service, calls } = makeFakeService();
275
- const engine = new PiEngine({ getService: () => service });
276
- await engine.interact(makeHandle({ recordId: "sa-fake" }), { kind: "close", payload: { force: true } });
277
- expect(calls.close).toEqual({ recordId: "sa-fake", force: true });
278
- await engine.interact(makeHandle({ recordId: "sa-fake" }), { kind: "close" });
279
- expect(calls.close).toEqual({ recordId: "sa-fake", force: false });
280
- });
281
-
282
- it("cancel → service.cancel(recordId)", async () => {
283
- const { service, calls } = makeFakeService();
284
- const engine = new PiEngine({ getService: () => service });
285
- const res = await engine.interact(makeHandle({ recordId: "sa-fake" }), { kind: "cancel" });
286
- expect(res).toEqual({ ok: true, delivered: true });
287
- expect(calls.cancelId).toBe("sa-fake");
288
- });
289
-
290
- it("cancel 返回 false → engine_interact_failed", async () => {
291
- const { service } = makeFakeService({ cancelResult: false });
292
- const engine = new PiEngine({ getService: () => service });
293
- const res = await engine.interact(makeHandle({ recordId: "sa-fake" }), { kind: "cancel" });
294
- expect(res.ok).toBe(false);
295
- if (!res.ok) {
296
- expect(res.code).toBe("engine_interact_failed");
297
- expect(res.message).toContain("sa-fake");
298
- }
299
- });
300
-
301
- it("recordId 缺席时按 sessionFile 扫描兜底定位(collectRecords 匹配)", async () => {
302
- const { service, calls } = makeFakeService({ listed: [{ id: "sa-scan-hit", sessionFile: "/x/s.jsonl" }] });
303
- const engine = new PiEngine({ getService: () => service });
304
- await engine.interact(makeHandle({ sessionFile: "/x/s.jsonl" }), { kind: "message", payload: "hi" });
305
- expect(calls.getRecordId).toBe("sa-scan-hit");
306
- });
307
-
308
- it("死 handle(无定位符 / record 不存在)→ engine_session_not_resumable(含 cold resume 指引)", async () => {
309
- const { service } = makeFakeService();
310
- const engine = new PiEngine({ getService: () => service });
311
- const res = await engine.interact(makeHandle({}), { kind: "message", payload: "hi" });
312
- expect(res.ok).toBe(false);
313
- if (!res.ok) {
314
- expect(res.code).toBe("engine_session_not_resumable");
315
- expect(res.message).toContain("--session");
316
- }
317
- });
318
-
319
- it("交互面 throw → engine_interact_failed(message 文案透传行动语言)", async () => {
320
- const { service } = makeFakeService({
321
- deliverReject: new Error("subagent sa-fake is not ready for a new message"),
322
- });
323
- const engine = new PiEngine({ getService: () => service });
324
- const res = await engine.interact(makeHandle({ recordId: "sa-fake" }), { kind: "message", payload: "hi" });
325
- expect(res).toEqual({
326
- ok: false,
327
- code: "engine_interact_failed",
328
- message: "subagent sa-fake is not ready for a new message",
329
- });
330
- });
331
-
332
- it("服务不可用 → reject", async () => {
333
- const engine = new PiEngine({ getService: () => null });
334
- await expect(
335
- engine.interact(makeHandle({ recordId: "x" }), { kind: "message", payload: "hi" }),
336
- ).rejects.toThrow(/SubagentService unavailable/);
337
- });
338
- });
339
-
340
- // ── read ──
341
-
342
- describe("PiEngine.read(D6 降级链)", () => {
343
- let tmpDir: string;
344
-
345
- beforeEach(() => {
346
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-engine-read-"));
347
- });
348
- afterEach(() => {
349
- fs.rmSync(tmpDir, { recursive: true, force: true });
350
- });
351
-
352
- it("无 sessionRef → outcome-only(turns 空)", async () => {
353
- const engine = new PiEngine({ getService: () => null });
354
- const view = await engine.read(makeHandle({}));
355
- expect(view).toEqual({ engineId: "pi", turns: [], source: "outcome-only" });
356
- });
357
-
358
- it("sessionFile 不存在/损坏 → outcome-only(不 throw)", async () => {
359
- const engine = new PiEngine({ getService: () => null });
360
- const view = await engine.read(makeHandle({ sessionFile: path.join(tmpDir, "missing.jsonl") }));
361
- expect(view.source).toBe("outcome-only");
362
- });
363
-
364
- it("pi JSONL 原生读取(第①级):turns 重建 + usage 聚合 + 内部态剥离", async () => {
365
- const file = path.join(tmpDir, "s.jsonl");
366
- const lines: string[] = [
367
- JSON.stringify({ type: "session", version: 3, id: "sess-uuid", timestamp: "2026-01-01T00:00:00.000Z", cwd: tmpDir }),
368
- JSON.stringify({
369
- type: "custom", id: "id-1", parentId: null, timestamp: "2026-01-01T00:00:00.000Z",
370
- customType: IDENTITY_CUSTOM_TYPE,
371
- data: { id: "bg-1", agent: "worker", mode: "background", task: "t", startedAt: 500 },
372
- }),
373
- JSON.stringify({
374
- type: "message", id: "msg-1", parentId: "id-1", timestamp: new Date(1000).toISOString(),
375
- message: {
376
- role: "assistant",
377
- content: [
378
- { type: "text", text: "hello" },
379
- { type: "toolCall", id: "tc-1", name: "bash", arguments: { cmd: "ls" } },
380
- ],
381
- usage: { input: 10, output: 20, cacheRead: 1, cacheWrite: 2, totalTokens: 33, cost: { total: 0.5 } },
382
- stopReason: "stop",
383
- timestamp: 1000,
384
- },
385
- }),
386
- JSON.stringify({
387
- type: "message", id: "tr-1", parentId: "msg-1", timestamp: new Date(2000).toISOString(),
388
- message: {
389
- role: "toolResult", toolCallId: "tc-1", toolName: "bash",
390
- content: [{ type: "text", text: "ok" }], timestamp: 2000,
391
- },
392
- }),
393
- ];
394
- fs.writeFileSync(file, lines.join("\n") + "\n");
395
-
396
- const engine = new PiEngine({ getService: () => null });
397
- const view = await engine.read(makeHandle({ sessionFile: file }));
398
- expect(view.source).toBe("native");
399
- expect(view.engineId).toBe("pi");
400
- expect(view.sessionId).toBe("bg-1");
401
- expect(view.turns).toHaveLength(1);
402
- expect(view.turns[0].text).toBe("hello");
403
- expect(view.turns[0].closed).toBe(true);
404
- // toolCall 纯净形状(无 _status/startedTs 内部态)
405
- expect(view.turns[0].toolCalls[0]).toMatchObject({ toolName: "bash" });
406
- expect("_status" in view.turns[0].toolCalls[0]).toBe(false);
407
- // usage 聚合(turn usageDelta → AgentUsageTotal)
408
- expect(view.usage).toEqual({ input: 10, output: 20, cacheRead: 1, cacheWrite: 2, cost: 0.5, total: 33 });
409
- });
410
- });
411
-
412
- // ── probe ──
413
-
414
- describe("PiEngine.probe(D7 + C1 形状)", () => {
415
- const originalArgv = process.argv;
416
- const originalExecPath = process.execPath;
417
- const originalPath = process.env.PATH;
418
-
419
- afterEach(() => {
420
- Object.defineProperty(process, "argv", { value: originalArgv, configurable: true });
421
- Object.defineProperty(process, "execPath", { value: originalExecPath, configurable: true });
422
- process.env.PATH = originalPath;
423
- });
424
-
425
- it("探针成功:invocation + version 两级 check,engineVersion 实测", async () => {
426
- const probeVersion = vi.fn(async () => "pi 0.84.1");
427
- const engine = new PiEngine({ getService: () => null, probeVersion });
428
- const report = await engine.probe();
429
- expect(report.ok).toBe(true);
430
- expect(report.engineVersion).toBe("pi 0.84.1");
431
- expect(report.checks.map((c) => c.name)).toEqual(["invocation", "version"]);
432
- expect(report.error).toBeUndefined();
433
- expect(probeVersion).toHaveBeenCalledTimes(1);
434
- });
435
-
436
- it("版本探测失败 → ok=false 且 error.recovery 非空(C1:恢复指引必填)", async () => {
437
- const engine = new PiEngine({ getService: () => null, probeVersion: async () => undefined });
438
- const report = await engine.probe();
439
- expect(report.ok).toBe(false);
440
- expect(report.error?.code).toBe("engine_probe_failed");
441
- expect(report.error?.recovery.length).toBeGreaterThan(0);
442
- });
443
-
444
- it("结果缓存:二次 probe 不重跑;force 强探重跑", async () => {
445
- const probeVersion = vi.fn(async () => "pi 1.0");
446
- const engine = new PiEngine({ getService: () => null, probeVersion });
447
- const first = await engine.probe();
448
- const second = await engine.probe();
449
- expect(second).toBe(first); // 缓存命中(同对象)
450
- expect(probeVersion).toHaveBeenCalledTimes(1);
451
- await engine.probe({ force: true });
452
- expect(probeVersion).toHaveBeenCalledTimes(2);
453
- });
454
-
455
- it("invocation 不可解析(PATH 无 pi)→ 第 1 check 失败,不再尝试版本探测", async () => {
456
- // bun 虚拟脚本 + 通用 runtime → 退化为 PATH 依赖形态(command === "pi")
457
- Object.defineProperty(process, "argv", { value: ["bun", "/$bunfs/root/pi"], configurable: true });
458
- Object.defineProperty(process, "execPath", { value: "/usr/bin/bun", configurable: true });
459
- process.env.PATH = path.join(os.tmpdir(), `no-pi-here-${Date.now()}`);
460
- const probeVersion = vi.fn(async () => "should-not-run");
461
- const engine = new PiEngine({ getService: () => null, probeVersion });
462
- const report = await engine.probe();
463
- expect(report.ok).toBe(false);
464
- expect(report.checks).toHaveLength(1);
465
- expect(report.checks[0].name).toBe("invocation");
466
- expect(report.checks[0].ok).toBe(false);
467
- expect(probeVersion).not.toHaveBeenCalled();
468
- });
469
- });
@@ -1,155 +0,0 @@
1
- // reader.test.ts —— PiEngine reader(P5):readPiSessionView 对 session-reconstructor
2
- // 的投影包装。断言三件事:①合法 JSONL → SessionView(turns/toolCalls strip 内部态/
3
- // usage 聚合/source='native');②reconstructor 降级条件(文件缺失/缺 identity/无
4
- // assistant)→ undefined 不 throw;③不泄漏 InternalToolCall 内部态(_status/startedTs)。
5
-
6
- import * as fs from "node:fs";
7
- import * as os from "node:os";
8
- import * as path from "node:path";
9
-
10
- import { beforeAll, describe, expect, it } from "vitest";
11
-
12
- import { readPiSessionView } from "../reader.ts";
13
-
14
- let tmpDir: string;
15
-
16
- beforeAll(() => {
17
- tmpDir = fs.mkdtempSync(join(os.tmpdir(), "pi-reader-"));
18
- });
19
-
20
- // node:path 的 join 在 ESM 测试里直接用(避免顶部 import 与 beforeAll 顺序问题)
21
- function join(...segs: string[]): string {
22
- return path.join(...segs);
23
- }
24
-
25
- /** 最小合法 subagent JSONL:header + identity + 一轮 assistant(text/thinking/toolCall)+ toolResult。 */
26
- function writeValidSession(file: string): void {
27
- const lines = [
28
- JSON.stringify({ type: "session", id: "pi-sess-1", cwd: "/proj", timestamp: "2026-08-25T10:00:00Z" }),
29
- JSON.stringify({
30
- type: "custom",
31
- customType: "subagent-identity",
32
- data: { id: "bg-1-abc", agent: "reviewer", mode: "background", task: "review code", slug: "rev", startedAt: 1756000000000 },
33
- }),
34
- JSON.stringify({
35
- type: "message",
36
- timestamp: "2026-08-25T10:00:01Z",
37
- message: {
38
- role: "assistant",
39
- timestamp: 1756000001000,
40
- content: [
41
- { type: "thinking", thinking: "let me look" },
42
- { type: "toolCall", id: "tc-1", name: "bash", arguments: { command: "ls" } },
43
- ],
44
- usage: { input: 10, output: 5, cacheRead: 1, cacheWrite: 2, cost: { total: 0.1 } },
45
- stopReason: "toolUse",
46
- },
47
- }),
48
- JSON.stringify({
49
- type: "message",
50
- timestamp: "2026-08-25T10:00:02Z",
51
- message: { role: "toolResult", toolCallId: "tc-1", toolName: "bash", content: [{ type: "text", text: "file-a" }], timestamp: 1756000002000 },
52
- }),
53
- JSON.stringify({
54
- type: "message",
55
- timestamp: "2026-08-25T10:00:03Z",
56
- message: {
57
- role: "assistant",
58
- timestamp: 1756000003000,
59
- content: [{ type: "text", text: "all good" }],
60
- usage: { input: 20, output: 8, cacheRead: 0, cacheWrite: 0, cost: { total: 0.05 } },
61
- stopReason: "stop",
62
- },
63
- }),
64
- ];
65
- fs.writeFileSync(file, `${lines.join("\n")}\n`, "utf8");
66
- }
67
-
68
- describe("readPiSessionView", () => {
69
- it("projects a valid subagent JSONL to a native SessionView", async () => {
70
- const file = join(tmpDir, "valid.jsonl");
71
- writeValidSession(file);
72
-
73
- const view = await readPiSessionView(file);
74
-
75
- expect(view).toBeDefined();
76
- expect(view?.engineId).toBe("pi");
77
- expect(view?.source).toBe("native");
78
- // 两轮 assistant message → 两个 turn(toolResult 不产 turn)
79
- expect(view?.turns).toHaveLength(2);
80
-
81
- const [turn1, turn2] = view?.turns ?? [];
82
- expect(turn1?.text).toBe("");
83
- expect(turn1?.thinking).toBe("let me look");
84
- expect(turn1?.toolCalls).toHaveLength(1);
85
- const tc = turn1?.toolCalls[0];
86
- expect(tc?.toolName).toBe("bash");
87
- expect(tc?.args).toEqual({ command: "ls" });
88
- expect(tc?.result).toEqual({ content: [{ type: "text", text: "file-a" }] });
89
- // InternalToolCall 内部态不泄漏(导出纯净形状)
90
- expect(tc).not.toHaveProperty("_status");
91
- expect(tc).not.toHaveProperty("startedTs");
92
- expect(turn1?.closed).toBe(true);
93
-
94
- expect(turn2?.text).toBe("all good");
95
- expect(turn2?.closed).toBe(true);
96
-
97
- // usage 聚合:两轮 usageDelta 之和(cost 浮点累加有精度噪声,用 toBeCloseTo)
98
- expect(view?.usage?.input).toBe(30)
99
- expect(view?.usage?.output).toBe(13)
100
- expect(view?.usage?.cacheRead).toBe(1)
101
- expect(view?.usage?.cacheWrite).toBe(2)
102
- expect(view?.usage?.cost).toBeCloseTo(0.15, 10)
103
- expect(view?.usage?.total).toBe(46);
104
- });
105
-
106
- it("returns undefined (no throw) when file is missing", async () => {
107
- await expect(readPiSessionView(join(tmpDir, "nope.jsonl"))).resolves.toBeUndefined();
108
- });
109
-
110
- it("returns undefined when identity entry is missing", async () => {
111
- const file = join(tmpDir, "no-identity.jsonl");
112
- fs.writeFileSync(
113
- file,
114
- `${JSON.stringify({ type: "session", id: "s" })}\n${JSON.stringify({
115
- type: "message",
116
- message: { role: "assistant", content: [{ type: "text", text: "hi" }], timestamp: 1 },
117
- })}\n`,
118
- "utf8",
119
- );
120
- await expect(readPiSessionView(file)).resolves.toBeUndefined();
121
- });
122
-
123
- it("returns undefined when no assistant message exists", async () => {
124
- const file = join(tmpDir, "no-assistant.jsonl");
125
- fs.writeFileSync(
126
- file,
127
- `${JSON.stringify({ type: "session", id: "s" })}\n${JSON.stringify({
128
- type: "custom",
129
- customType: "subagent-identity",
130
- data: { id: "bg-2", agent: "w", mode: "background", task: "t", startedAt: 1 },
131
- })}\n`,
132
- "utf8",
133
- );
134
- await expect(readPiSessionView(file)).resolves.toBeUndefined();
135
- });
136
-
137
- it("omits usage when no message carries it", async () => {
138
- const file = join(tmpDir, "no-usage.jsonl");
139
- fs.writeFileSync(
140
- file,
141
- `${JSON.stringify({ type: "session", id: "s" })}\n${JSON.stringify({
142
- type: "custom",
143
- customType: "subagent-identity",
144
- data: { id: "bg-3", agent: "w", mode: "background", task: "t", startedAt: 1 },
145
- })}\n${JSON.stringify({
146
- type: "message",
147
- message: { role: "assistant", content: [{ type: "text", text: "hi" }], stopReason: "stop", timestamp: 1 },
148
- })}\n`,
149
- "utf8",
150
- );
151
- const view = await readPiSessionView(file);
152
- expect(view?.turns).toHaveLength(1);
153
- expect(view?.usage).toBeUndefined();
154
- });
155
- });