@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,336 +0,0 @@
1
- // src/execution/__tests__/parent-child-matrix.test.ts
2
- //
3
- // SP-4: 父子联动测试(真实 SubagentService + index.ts 事件接线)。
4
- //
5
- // [M2/M7 重写] 旧套件在测试内手写 tryTransition/completeRecord/recentlyCascaded 模拟
6
- // (平行复刻生产逻辑),生产代码任何回归恒绿。现改为两层真实驱动:
7
- // Block 1: 真实 SubagentService.onParentFork / onParentNew / disposeAllRecords
8
- // → 断言 record 转 closed + closedReason + archive + pending:unregister
9
- // Block 2: 真实 index.ts factory 注册的 session_before_fork / session_before_switch
10
- // handler 驱动同一真实 Service → 断言事件接线与 reason 门控
11
- //
12
- // 事件语义依据 SDK 0.82.1(core/agent-session-runtime.js + core/agent-session.js):
13
- // /fork → session_before_fork(entryId, position) → teardown("fork")
14
- // /new → session_before_switch(reason:"new") → teardown("new")
15
- // (/new 从不触发 session_before_tree——旧实现误挂即 M2 bug)
16
- // /resume /import → session_before_switch(reason:"resume")
17
- // /tree → session_before_tree(同 session 内分支导航,无 session 替换)
18
- // + session_tree(导航后)——均无级联关闭语义
19
-
20
- import * as fs from "node:fs";
21
- import * as os from "node:os";
22
- import * as path from "node:path";
23
-
24
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
25
-
26
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
27
-
28
- // mock logger(import 链需要 getLogger 存在;对齐 subagent-service-parent-guard.test.ts。
29
- // setPiHandle 是 index.ts factory 顶层调用(注入 pi handle 给全局 logger),需一并 stub)
30
- const { loggerMock } = vi.hoisted(() => ({
31
- loggerMock: { debug: vi.fn(), warn: vi.fn(), error: vi.fn(), info: vi.fn() },
32
- }));
33
- vi.mock("@zhushanwen/pi-extension-logger", () => ({
34
- getLogger: () => loggerMock,
35
- setPiHandle: vi.fn(),
36
- }));
37
-
38
- // mock session-runner(import 链需要 runSpawn/killAllSpawnedChildren/getChildByRecord;
39
- // 避免真实 kill,且 dispose 收割路径可断言)
40
- const { killAllSpawnedChildrenMock } = vi.hoisted(() => ({
41
- killAllSpawnedChildrenMock: vi.fn(),
42
- }));
43
- vi.mock("../session-runner.ts", () => ({
44
- runSpawn: vi.fn(),
45
- killAllSpawnedChildren: killAllSpawnedChildrenMock,
46
- getChildByRecord: vi.fn(() => undefined),
47
- }));
48
-
49
- import { createRecord } from "../execution-record.ts";
50
- import { ModelConfigService } from "../model-config-service.ts";
51
- import { RecordStore } from "../record-store.ts";
52
- import { SubagentService, setSubagentService } from "../subagent-service.ts";
53
- import type { PiLike } from "../subagent-service.ts";
54
- import type { ExecutionRecord } from "../types.ts";
55
- import subagentsExtension from "../../index.ts";
56
-
57
- // ── helpers ──
58
-
59
- function makeTmpAgentDir(): string {
60
- return fs.mkdtempSync(path.join(os.tmpdir(), "parent-child-matrix-"));
61
- }
62
-
63
- /** 最小 mock PiLike(appendEntry/events.emit/sendMessage 全部可断言)。 */
64
- function makePi(): { pi: PiLike; eventsEmit: ReturnType<typeof vi.fn> } {
65
- const eventsEmit = vi.fn();
66
- const pi = {
67
- appendEntry: vi.fn(),
68
- events: { emit: eventsEmit },
69
- sendMessage: vi.fn(),
70
- } as unknown as PiLike;
71
- return { pi, eventsEmit };
72
- }
73
-
74
- /** 暴露私有字段供测试注入 record(对齐 subagent-service-parent-guard.test.ts 模式)。 */
75
- interface ServiceInternals {
76
- store: RecordStore;
77
- }
78
-
79
- /** 构造一个 running 状态的 ExecutionRecord(内存态,register 进真实 store)。 */
80
- function makeRunningRecord(id: string, overrides: Partial<ExecutionRecord> = {}): ExecutionRecord {
81
- return createRecord(id, {
82
- agent: "general-purpose",
83
- model: "test/model",
84
- mode: "background",
85
- task: `task for ${id}`,
86
- slug: `slug-${id}`,
87
- startedAt: Date.now(),
88
- rootSessionId: "root-session",
89
- controller: new AbortController(),
90
- ...overrides,
91
- });
92
- }
93
-
94
- /** 重置进程级 SubagentService 单例槽(setSubagentService 不接受 null,测试清理用)。
95
- * key 与生产 getServiceSlot 的 SERVICE_SLOT_KEY(subagent-service.ts)一致。 */
96
- function resetServiceSlot(): void {
97
- const slot = Reflect.get(globalThis, Symbol.for("@zhushanwen/pi-subagents.service")) as
98
- | { current: SubagentService | null }
99
- | undefined;
100
- if (slot) slot.current = null;
101
- }
102
-
103
- /** 创建真实 SubagentService(tmp agentDir + mock pi),返回 service 与内部 store。 */
104
- function setupRealService(): { service: SubagentService; store: RecordStore } {
105
- const agentDir = makeTmpAgentDir();
106
- const modelService = new ModelConfigService({ agentDir });
107
- const service = new SubagentService({ cwd: agentDir, modelService });
108
- service.initSession({ pi: makePi().pi, sessionId: "root-session" });
109
- const store = (service as unknown as ServiceInternals).store;
110
- return { service, store, agentDir };
111
- }
112
-
113
- // ============================================================
114
- // Block 1: 真实 SubagentService 级联关闭
115
- // ============================================================
116
-
117
- describe("SP-4 级联关闭(真实 SubagentService)", () => {
118
- let agentDir: string;
119
- let service: SubagentService;
120
- let store: RecordStore;
121
- let eventsEmit: ReturnType<typeof vi.fn>;
122
-
123
- beforeEach(() => {
124
- agentDir = makeTmpAgentDir();
125
- const modelService = new ModelConfigService({ agentDir });
126
- const { pi, eventsEmit: emit } = makePi();
127
- eventsEmit = emit;
128
- service = new SubagentService({ cwd: agentDir, modelService });
129
- service.initSession({ pi, sessionId: "root-session" });
130
- store = (service as unknown as ServiceInternals).store;
131
- });
132
-
133
- afterEach(() => {
134
- service.dispose();
135
- fs.rmSync(agentDir, { recursive: true, force: true });
136
- });
137
-
138
- it("onParentFork:running record 转 closed + closedReason=parent-fork,并从内存归档", () => {
139
- const record = makeRunningRecord("sa-fork-1");
140
- store.register(record);
141
-
142
- const count = service.onParentFork();
143
-
144
- expect(count).toBe(1);
145
- expect(record.status).toBe("closed");
146
- expect(record.closedReason).toBe("parent-fork");
147
- expect(record.endedAt).toBeDefined();
148
- // completeRecord 冻结合成 AgentResult(disposeAllRecords 构造,无在途执行)
149
- expect(record.error).toBe("closed due to parent-fork");
150
- // archive 生效:终态 record 立即从内存移除(读时从 session.jsonl 重建)
151
- expect(store.getMutable("sa-fork-1")).toBeUndefined();
152
- expect(store.listAllActive()).toHaveLength(0);
153
- });
154
-
155
- it("onParentNew:running record 转 closed + closedReason=parent-new", () => {
156
- const record = makeRunningRecord("sa-new-1");
157
- store.register(record);
158
-
159
- const count = service.onParentNew();
160
-
161
- expect(count).toBe(1);
162
- expect(record.status).toBe("closed");
163
- expect(record.closedReason).toBe("parent-new");
164
- expect(store.getMutable("sa-new-1")).toBeUndefined();
165
- });
166
-
167
- it("多个 running record 全部级联关闭,返回 count 与 record 数一致", () => {
168
- const records = [
169
- makeRunningRecord("sa-multi-1"),
170
- makeRunningRecord("sa-multi-2"),
171
- makeRunningRecord("sa-multi-3"),
172
- ];
173
- for (const r of records) store.register(r);
174
-
175
- const count = service.onParentNew();
176
-
177
- expect(count).toBe(3);
178
- for (const r of records) {
179
- expect(r.status).toBe("closed");
180
- expect(r.closedReason).toBe("parent-new");
181
- }
182
- expect(store.listAllActive()).toHaveLength(0);
183
- });
184
-
185
- it("级联关闭对每个被关 record 发 pending:unregister(reason=closed)", () => {
186
- const record = makeRunningRecord("sa-pending-1");
187
- store.register(record);
188
-
189
- service.onParentFork();
190
-
191
- expect(eventsEmit).toHaveBeenCalledWith("pending:unregister", {
192
- id: "sa-pending-1",
193
- reason: "closed",
194
- });
195
- });
196
-
197
- it("幂等:无活跃 record 返回 0;级联后再次调用返回 0(record 已归档)", () => {
198
- expect(service.onParentNew()).toBe(0);
199
-
200
- const record = makeRunningRecord("sa-idem-1");
201
- store.register(record);
202
- expect(service.onParentFork()).toBe(1);
203
- expect(service.onParentFork()).toBe(0); // 已 closed + archived,不重复关
204
- });
205
- });
206
-
207
- // ============================================================
208
- // Block 2: index.ts 事件接线(真实 factory + 真实 Service)
209
- // ============================================================
210
-
211
- describe("SP-4 index.ts 事件接线", () => {
212
- type PiHandler = (...args: unknown[]) => void | Promise<void>;
213
- const registered = new Map<string, PiHandler>();
214
- let processOnSpy: ReturnType<typeof vi.spyOn>;
215
- let agentDir: string;
216
- let service: SubagentService;
217
- let store: RecordStore;
218
-
219
- /** 最小 mock ExtensionAPI:捕获 pi.on 注册的 handler(对齐 process-shutdown-hook.test.ts 模式)。 */
220
- function createMockPi(): ExtensionAPI {
221
- const noop = (): void => {
222
- /* mock */
223
- };
224
- return {
225
- registerTool: vi.fn(),
226
- registerCommand: vi.fn(),
227
- registerMessageRenderer: vi.fn(),
228
- on: (event: string, handler: PiHandler) => {
229
- registered.set(event, handler);
230
- },
231
- appendEntry: vi.fn(),
232
- events: { emit: vi.fn(), on: vi.fn() },
233
- } as unknown as ExtensionAPI;
234
- }
235
-
236
- beforeEach(() => {
237
- // 捕获 process.on 注册(不真实注册,防 listener 跨用例泄漏)——factory 顶层注册
238
- // SIGTERM/SIGINT/beforeExit 三个 process hook(见 process-shutdown-hook.test.ts)。
239
- processOnSpy = vi.spyOn(process, "on").mockImplementation((() => process) as never);
240
-
241
- registered.clear();
242
- killAllSpawnedChildrenMock.mockReset();
243
-
244
- const ctx = setupRealService();
245
- agentDir = ctx.agentDir;
246
- service = ctx.service;
247
- store = ctx.store;
248
- setSubagentService(service);
249
-
250
- subagentsExtension(createMockPi());
251
- });
252
-
253
- afterEach(() => {
254
- processOnSpy.mockRestore();
255
- service.dispose();
256
- fs.rmSync(agentDir, { recursive: true, force: true });
257
- resetServiceSlot();
258
- });
259
-
260
- it("factory 注册 session_before_fork 与 session_before_switch handler", () => {
261
- expect(registered.get("session_before_fork")).toBeTypeOf("function");
262
- expect(registered.get("session_before_switch")).toBeTypeOf("function");
263
- });
264
-
265
- it("[M2] 不注册 session_before_tree——/tree 同 session 分支导航不得级联杀 subagent", () => {
266
- // SDK 中 session_before_tree 只由 navigateTree(/tree)触发,与 /new 无关。
267
- // 旧实现误挂此事件当 /new 级联入口 → 普通 /tree 导航误杀全部活跃 subagent。
268
- // 本断言是 M2 回归守卫:该事件不得再注册级联 handler。
269
- expect(registered.has("session_before_tree")).toBe(false);
270
- });
271
-
272
- it("[M2] session_before_switch(reason:'new') 触发 /new 级联:record 转 closed + parent-new", () => {
273
- const record = makeRunningRecord("sa-wire-new-1");
274
- store.register(record);
275
- const onParentNewSpy = vi.spyOn(service, "onParentNew");
276
-
277
- registered.get("session_before_switch")!(
278
- { type: "session_before_switch", reason: "new" },
279
- undefined,
280
- );
281
-
282
- expect(onParentNewSpy).toHaveBeenCalledTimes(1);
283
- expect(record.status).toBe("closed");
284
- expect(record.closedReason).toBe("parent-new");
285
- expect(store.getMutable("sa-wire-new-1")).toBeUndefined();
286
- });
287
-
288
- it("[M2] session_before_switch(reason:'resume') 不级联:/resume 回到已有 session,record 保持 running", () => {
289
- const record = makeRunningRecord("sa-wire-resume-1");
290
- store.register(record);
291
- const onParentNewSpy = vi.spyOn(service, "onParentNew");
292
-
293
- registered.get("session_before_switch")!(
294
- {
295
- type: "session_before_switch",
296
- reason: "resume",
297
- targetSessionFile: "/tmp/other-session.jsonl",
298
- },
299
- undefined,
300
- );
301
-
302
- expect(onParentNewSpy).not.toHaveBeenCalled();
303
- expect(record.status).toBe("running");
304
- expect(store.getMutable("sa-wire-resume-1")).toBe(record);
305
- });
306
-
307
- it("session_before_fork 触发 /fork 级联:record 转 closed + parent-fork", () => {
308
- const record = makeRunningRecord("sa-wire-fork-1");
309
- store.register(record);
310
- const onParentForkSpy = vi.spyOn(service, "onParentFork");
311
-
312
- registered.get("session_before_fork")!(
313
- { type: "session_before_fork", entryId: "entry-1", position: "before" },
314
- undefined,
315
- );
316
-
317
- expect(onParentForkSpy).toHaveBeenCalledTimes(1);
318
- expect(record.status).toBe("closed");
319
- expect(record.closedReason).toBe("parent-fork");
320
- expect(store.getMutable("sa-wire-fork-1")).toBeUndefined();
321
- });
322
-
323
- it("service 单例未初始化(getSubagentService()=null)时 handler 安全 no-op", () => {
324
- resetServiceSlot();
325
- expect(() => {
326
- registered.get("session_before_switch")!(
327
- { type: "session_before_switch", reason: "new" },
328
- undefined,
329
- );
330
- registered.get("session_before_fork")!(
331
- { type: "session_before_fork", entryId: "e", position: "before" },
332
- undefined,
333
- );
334
- }).not.toThrow();
335
- });
336
- });
@@ -1,104 +0,0 @@
1
- // src/__tests__/path-encoding.test.ts
2
- //
3
- // 锁定 encodeCwd 契约:session-runner 与 session-file-gc 共用此编码,
4
- // 漂移会导致同一 cwd 落到两个不同目录(见 path-encoding.ts 顶部注释)。
5
- import * as path from "node:path";
6
-
7
- import { describe, expect, it } from "vitest";
8
-
9
- import { encodeCwd, getSubagentRecordsDir, getSubagentSessionDir } from "../path-encoding.ts";
10
-
11
- describe("encodeCwd", () => {
12
- it("encodes a normal unix absolute path", () => {
13
- expect(encodeCwd("/Users/x/proj")).toBe("--Users-x-proj--");
14
- });
15
-
16
- it("strips a single leading backslash", () => {
17
- expect(encodeCwd("\\foo")).toBe("--foo--");
18
- });
19
-
20
- it("encodes Windows drive letter (colon + backslash)", () => {
21
- // C:\proj → 去掉无前导分隔符 → C:\proj → : 和 \ 都替换为 - → C--proj
22
- expect(encodeCwd("C:\\proj")).toBe("--C--proj--");
23
- });
24
-
25
- it("encodes empty string to bare delimiter pair", () => {
26
- expect(encodeCwd("")).toBe("----");
27
- });
28
-
29
- it("encodes relative path with no leading separator", () => {
30
- expect(encodeCwd("relative/path")).toBe("--relative-path--");
31
- });
32
-
33
- it("collapses consecutive separators (forward slash)", () => {
34
- expect(encodeCwd("/a//b")).toBe("--a--b--");
35
- });
36
-
37
- it("collapses consecutive separators (backslash)", () => {
38
- expect(encodeCwd("a\\b\\c")).toBe("--a-b-c--");
39
- });
40
-
41
- it("encodes mixed separators and colon", () => {
42
- // /x:y\\z → 去前导 / → x:y\z → : \ → - - → x-y-z
43
- expect(encodeCwd("/x:y\\z")).toBe("--x-y-z--");
44
- });
45
- });
46
-
47
- describe("getSubagentSessionDir", () => {
48
- it("returns agentDir/subagents/<encodedCwd>/sessions", () => {
49
- // [MF#1] 既有布局:subagents/<enc>/sessions/(不改,避免升级用户既有数据 orphan)
50
- const result = getSubagentSessionDir("/home/user/.pi/agent", "/home/user/project");
51
- expect(result).toBe(
52
- path.join("/home/user/.pi/agent", "subagents", "--home-user-project--", "sessions")
53
- );
54
- });
55
-
56
- it("uses mainCwd encoding (not effectiveCwd)", () => {
57
- // D-004: 用主 cwd 编码,保证同一主 cwd 下所有 subagent 存同一目录
58
- const mainCwd = "/Users/zhushanwen/Code/my-project";
59
- const result = getSubagentSessionDir("~/.pi/agent", mainCwd);
60
- const encoded = encodeCwd(mainCwd);
61
- expect(result).toBe(path.join("~/.pi/agent", "subagents", encoded, "sessions"));
62
- });
63
-
64
- it("produces consistent path for same inputs", () => {
65
- const a = getSubagentSessionDir("/agent", "/cwd");
66
- const b = getSubagentSessionDir("/agent", "/cwd");
67
- expect(a).toBe(b);
68
- });
69
-
70
- it("produces different path for different mainCwd", () => {
71
- const a = getSubagentSessionDir("/agent", "/cwd1");
72
- const b = getSubagentSessionDir("/agent", "/cwd2");
73
- expect(a).not.toBe(b);
74
- });
75
- });
76
-
77
- describe("getSubagentRecordsDir", () => {
78
- it("returns agentDir/subagents/<encodedCwd>/records", () => {
79
- const result = getSubagentRecordsDir("/home/user/.pi/agent", "/Users/x/proj");
80
- expect(result).toBe(
81
- path.join("/home/user/.pi/agent", "subagents", "--Users-x-proj--", "records")
82
- );
83
- });
84
-
85
- it("shares the same <enc> segment with getSubagentSessionDir for same cwd", () => {
86
- // F1:records 与 sessions 在同一 <enc> 段下,仅尾段不同(records vs sessions)。
87
- // worktree 场景三者恒等的前提就靠这个共享 enc。
88
- const agentDir = "/home/user/.pi/agent";
89
- const cwd = "/Users/x/proj";
90
- const sessions = getSubagentSessionDir(agentDir, cwd);
91
- const records = getSubagentRecordsDir(agentDir, cwd);
92
- // 共享 enc:去掉尾段后剩同一路径前缀
93
- expect(path.dirname(sessions)).toBe(path.dirname(records));
94
- // 尾段不同
95
- expect(path.basename(sessions)).toBe("sessions");
96
- expect(path.basename(records)).toBe("records");
97
- });
98
-
99
- it("produces different path for different mainCwd", () => {
100
- const a = getSubagentRecordsDir("/agent", "/cwd1");
101
- const b = getSubagentRecordsDir("/agent", "/cwd2");
102
- expect(a).not.toBe(b);
103
- });
104
- });
@@ -1,134 +0,0 @@
1
- // src/__tests__/pi-invocation.test.ts
2
- import * as fs from "node:fs";
3
- import * as os from "node:os";
4
- import * as path from "node:path";
5
-
6
- import { afterEach, describe, expect, it } from "vitest";
7
-
8
- import { getPiInvocation } from "../pi-invocation.ts";
9
- import { RELAY_ENV_NODE, RELAY_ENV_SCRIPT, RELAY_ENV_SOCKET } from "../relay-env.ts";
10
-
11
- describe("getPiInvocation", () => {
12
- const originalArgv = process.argv;
13
- const originalExecPath = process.execPath;
14
- let tmpScript: string;
15
-
16
- afterEach(() => {
17
- Object.defineProperty(process, "argv", { value: originalArgv, configurable: true });
18
- Object.defineProperty(process, "execPath", { value: originalExecPath, configurable: true });
19
- if (tmpScript && fs.existsSync(tmpScript)) fs.unlinkSync(tmpScript);
20
- });
21
-
22
- it("真实脚本路径存在 → node <script> <userArgs>", () => {
23
- // 创建真实临时脚本文件(避免 ESM spy 限制)
24
- tmpScript = path.join(os.tmpdir(), `pi-inv-test-${Date.now()}.mjs`);
25
- fs.writeFileSync(tmpScript, "// test");
26
- Object.defineProperty(process, "argv", { value: ["node", tmpScript], configurable: true });
27
- Object.defineProperty(process, "execPath", { value: "/usr/bin/node", configurable: true });
28
-
29
- const result = getPiInvocation(["--mode", "json", "Task: x"]);
30
- expect(result.command).toBe("/usr/bin/node");
31
- expect(result.args).toEqual([tmpScript, "--mode", "json", "Task: x"]);
32
- });
33
-
34
- it("bun 虚拟脚本(/$bunfs/root/)→ 退化到 pi-in-PATH", () => {
35
- tmpScript = "";
36
- const virtualScript = "/$bunfs/root/pi";
37
- Object.defineProperty(process, "argv", { value: ["bun", virtualScript], configurable: true });
38
- Object.defineProperty(process, "execPath", { value: "/usr/bin/bun", configurable: true });
39
-
40
- const result = getPiInvocation(["--mode", "json"]);
41
- expect(result.command).toBe("pi");
42
- expect(result.args).toEqual(["--mode", "json"]);
43
- });
44
-
45
- it("非通用 runtime(pi standalone binary)→ 直接 execPath", () => {
46
- tmpScript = "";
47
- Object.defineProperty(process, "argv", { value: ["/usr/bin/pi", "/nonexistent"], configurable: true });
48
- Object.defineProperty(process, "execPath", { value: "/usr/local/bin/pi-binary", configurable: true });
49
-
50
- const result = getPiInvocation(["--mode", "json"]);
51
- expect(result.command).toBe("/usr/local/bin/pi-binary");
52
- expect(result.args).toEqual(["--mode", "json"]);
53
- });
54
-
55
- it("node 通用 runtime + 脚本不存在 → pi-in-PATH", () => {
56
- tmpScript = "";
57
- Object.defineProperty(process, "argv", { value: ["node", "/nonexistent"], configurable: true });
58
- Object.defineProperty(process, "execPath", { value: "/usr/bin/node", configurable: true });
59
-
60
- const result = getPiInvocation(["--mode", "json"]);
61
- expect(result.command).toBe("pi");
62
- expect(result.args).toEqual(["--mode", "json"]);
63
- });
64
-
65
- it("空 userArgs 合法(仅 command + 空 args)", () => {
66
- tmpScript = "";
67
- Object.defineProperty(process, "argv", { value: ["node"], configurable: true });
68
- Object.defineProperty(process, "execPath", { value: "/usr/bin/node", configurable: true });
69
-
70
- const result = getPiInvocation([]);
71
- expect(result.command).toBe("pi");
72
- expect(result.args).toEqual([]);
73
- });
74
- });
75
-
76
- describe("getPiInvocation relay 分支(E 方案 §5.1)", () => {
77
- const originalArgv = process.argv;
78
- const originalExecPath = process.execPath;
79
- const RELAY_ENVS = [RELAY_ENV_SOCKET, RELAY_ENV_NODE, RELAY_ENV_SCRIPT] as const;
80
- /** 三 env 齐备的基准值(改 argv/execPath 隔离直连分支,只测 relay 判定本身)。 */
81
- const RELAY_FULL: Record<string, string> = {
82
- [RELAY_ENV_SOCKET]: "/tmp/relay-test.sock",
83
- [RELAY_ENV_NODE]: "/usr/bin/relay-node",
84
- [RELAY_ENV_SCRIPT]: "/opt/relay/relay.mjs",
85
- };
86
-
87
- afterEach(() => {
88
- Object.defineProperty(process, "argv", { value: originalArgv, configurable: true });
89
- Object.defineProperty(process, "execPath", { value: originalExecPath, configurable: true });
90
- for (const key of RELAY_ENVS) delete process.env[key];
91
- });
92
-
93
- /** 形态 1:三 env 齐备 + 默认 opts → relay invocation(command=NODE、args[0]=SCRIPT)。 */
94
- it("三 env 齐备(无 opts)→ 代理形态 <NODE> <SCRIPT> <userArgs>", () => {
95
- Object.assign(process.env, RELAY_FULL);
96
- const result = getPiInvocation(["--mode", "rpc"]);
97
- expect(result.command).toBe(RELAY_FULL[RELAY_ENV_NODE]);
98
- expect(result.args).toEqual([RELAY_FULL[RELAY_ENV_SCRIPT], "--mode", "rpc"]);
99
- });
100
-
101
- /** 形态 1 变体:opts.relay === true 显式开启,行为与缺省一致。 */
102
- it("三 env 齐备 + opts.relay=true → 同缺省(显式开启非必填)", () => {
103
- Object.assign(process.env, RELAY_FULL);
104
- const result = getPiInvocation(["--mode", "rpc"], { relay: true });
105
- expect(result.command).toBe(RELAY_FULL[RELAY_ENV_NODE]);
106
- expect(result.args[0]).toBe(RELAY_FULL[RELAY_ENV_SCRIPT]);
107
- });
108
-
109
- /** 形态 2:三缺一逐个枚举 → 回落现状直连(全有或全无,E-TUI 零回归)。 */
110
- it("三缺一(逐个枚举)→ 现状直连分支", () => {
111
- // 直连分支落到「node + 不存在脚本 → pi-in-PATH」可稳定断言(不依赖测试机 execPath 形态)
112
- Object.defineProperty(process, "argv", { value: ["node", "/nonexistent"], configurable: true });
113
- Object.defineProperty(process, "execPath", { value: "/usr/bin/node", configurable: true });
114
- for (const missing of RELAY_ENVS) {
115
- const partial = { ...RELAY_FULL };
116
- delete partial[missing];
117
- for (const key of RELAY_ENVS) delete process.env[key];
118
- Object.assign(process.env, partial);
119
- const result = getPiInvocation(["--mode", "rpc"]);
120
- expect(result.command).toBe("pi"); // 分支 3:通用 runtime + 脚本不存在 → PATH
121
- expect(result.args).toEqual(["--mode", "rpc"]);
122
- }
123
- });
124
-
125
- /** 形态 3:probe 排除——显式 relay:false 时即便三 env 齐备也直连。 */
126
- it("relay:false 强制直连(probe 语义:探 pi 本体,不探 runtime 健康)", () => {
127
- Object.assign(process.env, RELAY_FULL);
128
- Object.defineProperty(process, "argv", { value: ["node", "/nonexistent"], configurable: true });
129
- Object.defineProperty(process, "execPath", { value: "/usr/bin/node", configurable: true });
130
- const result = getPiInvocation(["--version"], { relay: false });
131
- expect(result.command).toBe("pi");
132
- expect(result.args).toEqual(["--version"]);
133
- });
134
- });