@zhushanwen/pi-subagent-workflow 8.6.0 → 8.7.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 (347) hide show
  1. package/package.json +9 -13
  2. package/relay/relay.mjs +1 -1
  3. package/src/host/__tests__/pi-host.test.ts +214 -0
  4. package/src/host/pi-host.ts +109 -0
  5. package/src/index.ts +89 -32
  6. package/src/injectors/__tests__/engine-awareness.test.ts +292 -0
  7. package/src/injectors/__tests__/engine-section-stability.test.ts +341 -0
  8. package/src/injectors/__tests__/subagent-list-injector.test.ts +5 -5
  9. package/src/injectors/__tests__/workflow-list-injector.test.ts +5 -5
  10. package/src/injectors/engine-awareness.ts +123 -0
  11. package/src/injectors/model-list-injector.ts +1 -1
  12. package/src/injectors/subagent-list-injector.ts +8 -8
  13. package/src/injectors/workflow-list-injector.ts +8 -8
  14. package/src/interface/__tests__/detectors.test.ts +3 -3
  15. package/src/interface/__tests__/subagent-tool-path-guard.test.ts +2 -2
  16. package/src/interface/__tests__/tool-workflow-script-generate.test.ts +2 -2
  17. package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +1 -1
  18. package/src/interface/bg-notify-render.ts +4 -4
  19. package/src/interface/commands.ts +3 -3
  20. package/src/interface/format.ts +2 -2
  21. package/src/interface/helpers.ts +1 -1
  22. package/src/interface/list-component.ts +4 -4
  23. package/src/interface/list-shared.ts +2 -2
  24. package/src/interface/list-view.ts +2 -2
  25. package/src/interface/subagent-actions.ts +263 -11
  26. package/src/interface/subagent-tool-schema.ts +20 -13
  27. package/src/interface/subagent-tool.ts +11 -6
  28. package/src/interface/subagents.ts +3 -3
  29. package/src/interface/tool-render.ts +34 -2
  30. package/src/interface/tool-workflow-script.ts +4 -4
  31. package/src/interface/tool-workflow.ts +6 -6
  32. package/src/interface/views/WorkflowsView.ts +5 -5
  33. package/src/interface/views/__tests__/WorkflowsView-signature.test.ts +3 -3
  34. package/src/interface/views/__tests__/detail-content-session-file.test.ts +2 -2
  35. package/src/interface/views/detail-content.ts +4 -4
  36. package/src/interface/views/format.ts +4 -4
  37. package/src/{orchestration/jsonl-run-store.ts → jsonl-run-store.ts} +11 -11
  38. package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +0 -53
  39. package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +0 -1
  40. package/src/execution/__tests__/agent-registry.test.ts +0 -363
  41. package/src/execution/__tests__/agent-result-mapper.test.ts +0 -150
  42. package/src/execution/__tests__/alive-store.test.ts +0 -147
  43. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  44. package/src/execution/__tests__/before-agent-start-injection.test.ts +0 -132
  45. package/src/execution/__tests__/bg-notify-render.test.ts +0 -329
  46. package/src/execution/__tests__/channel-registry-handshake.test.ts +0 -243
  47. package/src/execution/__tests__/chat-engine-routing.test.ts +0 -601
  48. package/src/execution/__tests__/chatmode-first-round-closure-service.test.ts +0 -365
  49. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -190
  50. package/src/execution/__tests__/chatmode-round-notify-real-chain.test.ts +0 -215
  51. package/src/execution/__tests__/concurrency-pool.test.ts +0 -250
  52. package/src/execution/__tests__/config.test.ts +0 -110
  53. package/src/execution/__tests__/conversation-wiring.test.ts +0 -198
  54. package/src/execution/__tests__/crash-recovery.test.ts +0 -320
  55. package/src/execution/__tests__/delivery-methods.test.ts +0 -422
  56. package/src/execution/__tests__/dialog-queue.test.ts +0 -299
  57. package/src/execution/__tests__/epipe-fallback.test.ts +0 -241
  58. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -243
  59. package/src/execution/__tests__/execute-nesting.test.ts +0 -323
  60. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
  61. package/src/execution/__tests__/execution-record.test.ts +0 -1394
  62. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +0 -171
  63. package/src/execution/__tests__/finalize-record.test.ts +0 -368
  64. package/src/execution/__tests__/finalized-marker.test.ts +0 -82
  65. package/src/execution/__tests__/format-schema-instruction.test.ts +0 -169
  66. package/src/execution/__tests__/format.test.ts +0 -458
  67. package/src/execution/__tests__/gc-timer.test.ts +0 -184
  68. package/src/execution/__tests__/get-record-for-action-restart.test.ts +0 -254
  69. package/src/execution/__tests__/gui-mode-dispatch.test.ts +0 -59
  70. package/src/execution/__tests__/helpers/mock-extension-api.ts +0 -30
  71. package/src/execution/__tests__/helpers/spawn-mock.ts +0 -242
  72. package/src/execution/__tests__/host-mode.test.ts +0 -87
  73. package/src/execution/__tests__/index-session-start-identity.test.ts +0 -371
  74. package/src/execution/__tests__/index-session-start.test.ts +0 -672
  75. package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
  76. package/src/execution/__tests__/lifecycle-manager.test.ts +0 -383
  77. package/src/execution/__tests__/lifecycle-predicates.test.ts +0 -116
  78. package/src/execution/__tests__/list-component.test.ts +0 -401
  79. package/src/execution/__tests__/list-fields.test.ts +0 -140
  80. package/src/execution/__tests__/manifest-parentid.test.ts +0 -117
  81. package/src/execution/__tests__/model-resolver.test.ts +0 -465
  82. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +0 -287
  83. package/src/execution/__tests__/nested-visibility.test.ts +0 -325
  84. package/src/execution/__tests__/notifier-flush.test.ts +0 -612
  85. package/src/execution/__tests__/notifier-golden-snapshot.test.ts +0 -261
  86. package/src/execution/__tests__/notify-ledger.test.ts +0 -826
  87. package/src/execution/__tests__/one-shot-upgrade.test.ts +0 -205
  88. package/src/execution/__tests__/output-collector.test.ts +0 -358
  89. package/src/execution/__tests__/parent-child-matrix.test.ts +0 -336
  90. package/src/execution/__tests__/path-encoding.test.ts +0 -104
  91. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  92. package/src/execution/__tests__/record-store.test.ts +0 -1057
  93. package/src/execution/__tests__/records-cwd-isolation.test.ts +0 -91
  94. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +0 -339
  95. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -273
  96. package/src/execution/__tests__/relay-agent.test.ts +0 -448
  97. package/src/execution/__tests__/relay-env.test.ts +0 -42
  98. package/src/execution/__tests__/resource-policy.test.ts +0 -109
  99. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  100. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -267
  101. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -253
  102. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -687
  103. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  104. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  105. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  106. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -199
  107. package/src/execution/__tests__/sdk-contract.test.ts +0 -273
  108. package/src/execution/__tests__/session-context-resolver.test.ts +0 -167
  109. package/src/execution/__tests__/session-file-gc.test.ts +0 -293
  110. package/src/execution/__tests__/session-pending.test.ts +0 -197
  111. package/src/execution/__tests__/session-reconstructor.test.ts +0 -379
  112. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -178
  113. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -350
  114. package/src/execution/__tests__/session-start-reaper.test.ts +0 -233
  115. package/src/execution/__tests__/spawn-args.test.ts +0 -445
  116. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -189
  117. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  118. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -207
  119. package/src/execution/__tests__/spawned-children.test.ts +0 -92
  120. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  121. package/src/execution/__tests__/startup-config-declaration.test.ts +0 -35
  122. package/src/execution/__tests__/status-refactor.test.ts +0 -345
  123. package/src/execution/__tests__/stdin-writer.test.ts +0 -463
  124. package/src/execution/__tests__/stream-sink-retirement.test.ts +0 -261
  125. package/src/execution/__tests__/subagent-service-abort.test.ts +0 -60
  126. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -629
  127. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +0 -180
  128. package/src/execution/__tests__/subagent-service.test.ts +0 -788
  129. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -310
  130. package/src/execution/__tests__/subprocess-agent-runner.test.ts +0 -599
  131. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  132. package/src/execution/__tests__/timeout-integration.test.ts +0 -615
  133. package/src/execution/__tests__/tombstone-store.test.ts +0 -73
  134. package/src/execution/__tests__/tool-action.test.ts +0 -476
  135. package/src/execution/__tests__/truncline-snapshot.test.ts +0 -81
  136. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  137. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  138. package/src/execution/__tests__/ui-channels.test.ts +0 -187
  139. package/src/execution/__tests__/ui-interaction-model.test.ts +0 -67
  140. package/src/execution/__tests__/ui-request-handler-factory.test.ts +0 -370
  141. package/src/execution/__tests__/ui-request-handler.test.ts +0 -204
  142. package/src/execution/__tests__/ui-request-observability.test.ts +0 -114
  143. package/src/execution/__tests__/ui-request-queue.test.ts +0 -133
  144. package/src/execution/__tests__/worktree-manager.test.ts +0 -633
  145. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -229
  146. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +0 -181
  147. package/src/execution/__tests__/worktree-registry.test.ts +0 -199
  148. package/src/execution/agent-registry.ts +0 -199
  149. package/src/execution/agent-result-mapper.ts +0 -90
  150. package/src/execution/alive-store.ts +0 -92
  151. package/src/execution/argv-mirror.ts +0 -113
  152. package/src/execution/best-effort.ts +0 -38
  153. package/src/execution/channel-registry-access.ts +0 -144
  154. package/src/execution/concurrency-pool.ts +0 -116
  155. package/src/execution/config.ts +0 -96
  156. package/src/execution/dialog-queue.ts +0 -330
  157. package/src/execution/engine/__tests__/common/data-dir.test.ts +0 -53
  158. package/src/execution/engine/__tests__/common/errors.test.ts +0 -132
  159. package/src/execution/engine/__tests__/common/event-journal.test.ts +0 -177
  160. package/src/execution/engine/__tests__/common/kill-chain.test.ts +0 -192
  161. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +0 -81
  162. package/src/execution/engine/__tests__/common/persona-router.test.ts +0 -123
  163. package/src/execution/engine/__tests__/common/pool-manager.test.ts +0 -154
  164. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  165. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  166. package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +0 -141
  167. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +0 -109
  168. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +0 -101
  169. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +0 -77
  170. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +0 -104
  171. package/src/execution/engine/__tests__/conformance/contract.relay.test.ts +0 -342
  172. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +0 -201
  173. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +0 -76
  174. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +0 -79
  175. package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -87
  176. package/src/execution/engine/__tests__/engines-declaration.test.ts +0 -36
  177. package/src/execution/engine/__tests__/model-prompt.test.ts +0 -85
  178. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  179. package/src/execution/engine/__tests__/registry.test.ts +0 -120
  180. package/src/execution/engine/__tests__/routing.test.ts +0 -231
  181. package/src/execution/engine/common/data-dir.ts +0 -62
  182. package/src/execution/engine/common/errors.ts +0 -183
  183. package/src/execution/engine/common/event-journal.ts +0 -254
  184. package/src/execution/engine/common/journal-replay.ts +0 -62
  185. package/src/execution/engine/common/kill-chain.ts +0 -221
  186. package/src/execution/engine/common/nesting-guard.ts +0 -50
  187. package/src/execution/engine/common/persona-router.ts +0 -108
  188. package/src/execution/engine/common/pool-manager.ts +0 -226
  189. package/src/execution/engine/common/schema-emulation.ts +0 -189
  190. package/src/execution/engine/common/session-view-projection.ts +0 -51
  191. package/src/execution/engine/engine-discovery.ts +0 -65
  192. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -469
  193. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  194. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  195. package/src/execution/engine/engines/pi/pi-engine.ts +0 -415
  196. package/src/execution/engine/engines/pi/reader.ts +0 -48
  197. package/src/execution/engine/engines/pi/registration.ts +0 -35
  198. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  199. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  200. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  201. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -246
  202. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -228
  203. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  204. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -64
  205. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -127
  206. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -580
  207. package/src/execution/engine/engines/zcode/constants.ts +0 -43
  208. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -39
  209. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  210. package/src/execution/engine/engines/zcode/parser.ts +0 -436
  211. package/src/execution/engine/engines/zcode/preparer.ts +0 -363
  212. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  213. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  214. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -658
  215. package/src/execution/engine/host-task-spec.ts +0 -47
  216. package/src/execution/engine/model-prompt.ts +0 -59
  217. package/src/execution/engine/paths.ts +0 -42
  218. package/src/execution/engine/port.ts +0 -153
  219. package/src/execution/engine/registry.ts +0 -123
  220. package/src/execution/engine/routing.ts +0 -218
  221. package/src/execution/engine/types.ts +0 -309
  222. package/src/execution/execute-options-mapper.ts +0 -112
  223. package/src/execution/execution-record.ts +0 -965
  224. package/src/execution/finalize-record.ts +0 -251
  225. package/src/execution/finalized-marker.ts +0 -51
  226. package/src/execution/get-state-handshake.ts +0 -104
  227. package/src/execution/host-mode.ts +0 -56
  228. package/src/execution/idle-gc.ts +0 -47
  229. package/src/execution/lifecycle-manager.ts +0 -513
  230. package/src/execution/lifecycle-predicates.ts +0 -65
  231. package/src/execution/manifest-store.ts +0 -256
  232. package/src/execution/model-config-service.ts +0 -219
  233. package/src/execution/model-resolver.ts +0 -248
  234. package/src/execution/notifier.ts +0 -330
  235. package/src/execution/notify-ledger.ts +0 -580
  236. package/src/execution/output-collector.ts +0 -228
  237. package/src/execution/path-encoding.ts +0 -60
  238. package/src/execution/pi-invocation.ts +0 -120
  239. package/src/execution/record-entry.ts +0 -132
  240. package/src/execution/record-store.ts +0 -1234
  241. package/src/execution/relay-env.ts +0 -37
  242. package/src/execution/session-context-resolver.ts +0 -64
  243. package/src/execution/session-file-gc.ts +0 -120
  244. package/src/execution/session-pending.ts +0 -164
  245. package/src/execution/session-reconstructor.ts +0 -678
  246. package/src/execution/session-runner.ts +0 -1781
  247. package/src/execution/sessions-index.ts +0 -304
  248. package/src/execution/spawn-event-adapter.ts +0 -363
  249. package/src/execution/stdin-writer.ts +0 -198
  250. package/src/execution/stream-sink.ts +0 -126
  251. package/src/execution/subagent-service.ts +0 -2141
  252. package/src/execution/subprocess-agent-runner.ts +0 -317
  253. package/src/execution/temp-prompt.ts +0 -62
  254. package/src/execution/tombstone-store.ts +0 -72
  255. package/src/execution/turn-limiter.ts +0 -102
  256. package/src/execution/types.ts +0 -973
  257. package/src/execution/ui-channels.ts +0 -216
  258. package/src/execution/ui-interaction-model.ts +0 -48
  259. package/src/execution/ui-request-handler-factory.ts +0 -212
  260. package/src/execution/ui-request-observability.ts +0 -81
  261. package/src/execution/ui-request-queue.ts +0 -184
  262. package/src/execution/worktree-manager.ts +0 -688
  263. package/src/execution/worktree-registry.ts +0 -222
  264. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +0 -349
  265. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +0 -202
  266. package/src/orchestration/__tests__/agent-call-stream.test.ts +0 -152
  267. package/src/orchestration/__tests__/args-validator.test.ts +0 -143
  268. package/src/orchestration/__tests__/config-loader.test.ts +0 -503
  269. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +0 -809
  270. package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +0 -405
  271. package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +0 -56
  272. package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +0 -166
  273. package/src/orchestration/__tests__/execute-agent-call.test.ts +0 -451
  274. package/src/orchestration/__tests__/jsonl-run-store-corrupt-entry.test.ts +0 -150
  275. package/src/orchestration/__tests__/jsonl-run-store-loadall-sources.test.ts +0 -171
  276. package/src/orchestration/__tests__/jsonl-run-store-retention.test.ts +0 -202
  277. package/src/orchestration/__tests__/jsonl-run-store-session-file.test.ts +0 -1030
  278. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +0 -600
  279. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +0 -96
  280. package/src/orchestration/__tests__/lifecycle.test.ts +0 -659
  281. package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +0 -95
  282. package/src/orchestration/__tests__/review-fix-loop-e2e.test.ts +0 -2025
  283. package/src/orchestration/__tests__/script-lint.test.ts +0 -831
  284. package/src/orchestration/__tests__/skill-discovery.test.ts +0 -201
  285. package/src/orchestration/__tests__/test-mocks.ts +0 -197
  286. package/src/orchestration/__tests__/worker-exit-without-result.test.ts +0 -368
  287. package/src/orchestration/__tests__/worker-host.test.ts +0 -120
  288. package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +0 -164
  289. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +0 -563
  290. package/src/orchestration/__tests__/worker-script-builder.test.ts +0 -309
  291. package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +0 -129
  292. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +0 -317
  293. package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +0 -110
  294. package/src/orchestration/__tests__/workflows-e2e.test.ts +0 -537
  295. package/src/orchestration/agent-opts-resolver.ts +0 -174
  296. package/src/orchestration/args-validator.ts +0 -127
  297. package/src/orchestration/config-loader.ts +0 -315
  298. package/src/orchestration/error-recovery.ts +0 -1018
  299. package/src/orchestration/execute-agent-call.ts +0 -256
  300. package/src/orchestration/launcher.ts +0 -455
  301. package/src/orchestration/lifecycle.ts +0 -399
  302. package/src/orchestration/models/__tests__/budget.test.ts +0 -307
  303. package/src/orchestration/models/__tests__/trace.test.ts +0 -408
  304. package/src/orchestration/models/agent-call.ts +0 -83
  305. package/src/orchestration/models/budget.ts +0 -118
  306. package/src/orchestration/models/ports.ts +0 -164
  307. package/src/orchestration/models/run-runtime.ts +0 -104
  308. package/src/orchestration/models/run-spec.ts +0 -83
  309. package/src/orchestration/models/run-state.ts +0 -44
  310. package/src/orchestration/models/trace.ts +0 -183
  311. package/src/orchestration/models/types.ts +0 -301
  312. package/src/orchestration/models/workflow-run.ts +0 -254
  313. package/src/orchestration/models/workflow-script-registry.ts +0 -35
  314. package/src/orchestration/models/workflow-script.ts +0 -117
  315. package/src/orchestration/script-lint.ts +0 -766
  316. package/src/orchestration/skill-discovery.ts +0 -115
  317. package/src/orchestration/worker-handle.ts +0 -115
  318. package/src/orchestration/worker-host.ts +0 -98
  319. package/src/orchestration/worker-script-builder.ts +0 -421
  320. package/src/orchestration/workflow-files.ts +0 -85
  321. package/src/orchestration/workflow-script-registry-impl.ts +0 -133
  322. package/src/shared/__tests__/agent-ref.test.ts +0 -34
  323. package/src/shared/__tests__/meta-parser.test.ts +0 -304
  324. package/src/shared/__tests__/model-ref.test.ts +0 -306
  325. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -280
  326. package/src/shared/__tests__/resource-discovery.test.ts +0 -736
  327. package/src/shared/__tests__/resource-meta.test.ts +0 -51
  328. package/src/shared/__tests__/schema-jsonify.test.ts +0 -81
  329. package/src/shared/__tests__/timer-delay.test.ts +0 -61
  330. package/src/shared/agent-event.ts +0 -13
  331. package/src/shared/agent-ref.ts +0 -57
  332. package/src/shared/meta-parser.ts +0 -261
  333. package/src/shared/model-ref.ts +0 -286
  334. package/src/shared/resource-discovery.ts +0 -811
  335. package/src/shared/resource-meta.ts +0 -65
  336. package/src/shared/schema-env.ts +0 -44
  337. package/src/shared/schema-jsonify.ts +0 -58
  338. package/src/shared/timer-delay.ts +0 -54
  339. package/src/shared/xml-injection.ts +0 -35
  340. package/workflows/README.md +0 -81
  341. package/workflows/_shared/agent-refs.cjs +0 -40
  342. package/workflows/chain.js +0 -131
  343. package/workflows/map-reduce.js +0 -174
  344. package/workflows/parallel.js +0 -148
  345. package/workflows/review-fix-loop-utils.cjs +0 -1309
  346. package/workflows/review-fix-loop.js +0 -1404
  347. package/workflows/scatter-gather.js +0 -178
@@ -1,254 +0,0 @@
1
- // src/execution/engine/common/event-journal.ts
2
- //
3
- // 宿主 event journal(P2 公共降级层)。设计权威源:
4
- // docs/architecture/subagent-engine-abstraction.md D6(第②级归属宿主——host 统一落盘
5
- // 则全引擎免费获得、格式唯一)+ §3.3.6 event journal 格式(JSONL 中立 v1)。
6
- //
7
- // 为什么 host 落盘而非各 adapter 缓存:adapter 各自缓存会演变出六种格式;host 消费
8
- // onEvent 统一落盘,read 第②级(journal 重放)与探针 golden 语料共用同一份产物。
9
- //
10
- // 写入纪律(§3.3.6):onEvent 回调内追加写(有界缓冲 + 批量 flush),run 终态后
11
- // flush 并 fsync 一次。journal 不随池删(D5),生命周期跟随 record。
12
- //
13
- // 失败语义:journal 是降级链第②级(尽力而为的数据源)——写失败不炸主流程:
14
- // warn 一次 + 置 failed,后续 append 丢弃、close 立即返回(不静默:warn 有留痕)。
15
-
16
- import { appendFile, mkdir, open } from "node:fs/promises";
17
- import { readFileSync } from "node:fs";
18
- import { dirname } from "node:path";
19
-
20
- import { getLogger } from "@zhushanwen/pi-extension-logger";
21
-
22
- import type { AgentEvent } from "../../types.ts";
23
-
24
- const logger = getLogger("subagents");
25
-
26
- // ============================================================
27
- // 中立行格式(§3.3.6 v1)
28
- // ============================================================
29
-
30
- /** journal 单行(JSONL)。seq 是 host 侧单调递增序号——重放顺序权威。 */
31
- export interface JournalLine {
32
- v: 1;
33
- /** host 落盘时刻(Date.now(),ms)。 */
34
- ts: number;
35
- /** = RunContext.taskId = record.id(journal 文件名与池引用计数 key)。 */
36
- taskId: string;
37
- engineId: string;
38
- seq: number;
39
- /** AgentEvent 原样(onEvent 回调对象的 JSON.stringify 直接产物,无二次变换)。 */
40
- event: AgentEvent;
41
- }
42
-
43
- // ============================================================
44
- // JournalWriter
45
- // ============================================================
46
-
47
- /** flush 触发的缓冲阈值:行数与字节数任一到达即批量落盘(有界缓冲)。 */
48
- const FLUSH_THRESHOLD_LINES = 64;
49
- // eslint-disable-next-line no-magic-numbers -- 32KB = 32 * 1024 bytes 缓冲字节换算常数
50
- const FLUSH_THRESHOLD_BYTES = 32 * 1024;
51
-
52
- /** FileHandle 的结构子集(close 期 fsync 用;注入 fake 可测)。 */
53
- export interface FileHandleLike {
54
- sync(): Promise<void>;
55
- close(): Promise<void>;
56
- }
57
-
58
- /** writer 的文件系统依赖面(结构接口:测试注入 fake,免 vi.mock 整个 fs 模块)。 */
59
- export interface JournalFsDeps {
60
- mkdir(path: string, opts: { recursive: boolean }): Promise<unknown>;
61
- appendFile(path: string, data: string): Promise<void>;
62
- open(path: string, flags: string): Promise<FileHandleLike>;
63
- }
64
-
65
- const defaultFs: JournalFsDeps = {
66
- mkdir: (p, o) => mkdir(p, o),
67
- appendFile: (p, d) => appendFile(p, d, "utf8"),
68
- open: (p, f) => open(p, f),
69
- };
70
-
71
- /** JournalWriter 构造参数。 */
72
- export interface JournalWriterOpts {
73
- /** journal 文件绝对路径(经 paths.ts resolveJournalPath 派生,禁自拼)。 */
74
- path: string;
75
- taskId: string;
76
- engineId: string;
77
- }
78
-
79
- /**
80
- * 追加写 writer:append 同步入队(onEvent 是同步回调,不阻塞事件流),批量异步
81
- * flush;close = flush 全部 + fsync 一次(§3.3.6 写入纪律)。
82
- *
83
- * 文件惰性创建:首个 flush 才 mkdir + appendFile——无事件的任务不产生空 journal。
84
- */
85
- export class JournalWriter {
86
- private readonly opts: JournalWriterOpts;
87
- private readonly fs: JournalFsDeps;
88
- private readonly warn: (msg: string) => void;
89
-
90
- private buffer: string[] = [];
91
- private bufferedBytes = 0;
92
- private seq = 0;
93
- /** 串行化异步写(promise 链),防交错 append。 */
94
- private chain: Promise<void> = Promise.resolve();
95
- private failed = false;
96
- private closed = false;
97
- /** 是否成功落过盘——close 的 fsync 只对已存在的文件做(无事件任务不产生空文件)。 */
98
- private wrote = false;
99
-
100
- constructor(opts: JournalWriterOpts, fs: JournalFsDeps = defaultFs, warn: (msg: string) => void = defaultWarn) {
101
- this.opts = opts;
102
- this.fs = fs;
103
- this.warn = warn;
104
- }
105
-
106
- /** 追加一个事件(同步入队;缓冲达阈值自动排队 flush)。closed/failed 后丢弃。 */
107
- append(event: AgentEvent): void {
108
- if (this.failed || this.closed) return;
109
- const line: JournalLine = {
110
- v: 1,
111
- ts: Date.now(),
112
- taskId: this.opts.taskId,
113
- engineId: this.opts.engineId,
114
- seq: this.seq++,
115
- event,
116
- };
117
- const serialized = JSON.stringify(line);
118
- this.buffer.push(serialized);
119
- this.bufferedBytes += serialized.length;
120
- if (this.buffer.length >= FLUSH_THRESHOLD_LINES || this.bufferedBytes >= FLUSH_THRESHOLD_BYTES) {
121
- void this.flush();
122
- }
123
- }
124
-
125
- /** 把缓冲写入磁盘(串行排队;等待此前所有排队写完成)。 */
126
- flush(): Promise<void> {
127
- if (this.failed || this.buffer.length === 0) return this.chain;
128
- const chunk = `${this.buffer.join("\n")}\n`;
129
- this.buffer = [];
130
- this.bufferedBytes = 0;
131
- this.chain = this.chain.then(() => this.writeChunk(chunk));
132
- return this.chain;
133
- }
134
-
135
- /** run 终态后调用:flush 全部 + fsync 一次 + 关闭(幂等)。 */
136
- async close(): Promise<void> {
137
- if (this.closed) return;
138
- this.closed = true;
139
- await this.flush();
140
- if (this.failed || !this.wrote) return;
141
- // fsync 一次(§3.3.6):进程崩溃后已 flush 的行不丢——record 读第②级的一致性依据
142
- this.chain = this.chain.then(async () => {
143
- const fh = await this.fs.open(this.opts.path, "r");
144
- try {
145
- await fh.sync();
146
- } finally {
147
- await fh.close();
148
- }
149
- });
150
- await this.chain;
151
- }
152
-
153
- /** 是否已写失败(降级诊断用;failed 后 journal 不可作为②级数据源)。 */
154
- get isFailed(): boolean {
155
- return this.failed;
156
- }
157
-
158
- /**
159
- * 重定向落盘路径(对齐点③:journal 路径权威 = 引擎声明的池 key)。
160
- * 仅在尚未落盘(wrote=false)时允许——已 flush 过的文件搬家会制造两份半截 journal,
161
- * 重放语义破坏;已落盘时 warn 拒绝(不静默)。事件在重定向前到达的场景由调用方
162
- * 契约保证(RunContext.onPoolResolved 注释:引擎须在首个事件 emit 前回调)。
163
- */
164
- retarget(path: string): void {
165
- if (this.closed || this.failed) return;
166
- if (this.wrote) {
167
- this.warn(
168
- `[event-journal] retarget ignored for task ${this.opts.taskId}: journal already flushed to ` +
169
- `${this.opts.path} (events must not precede onPoolResolved)`,
170
- );
171
- return;
172
- }
173
- this.opts.path = path;
174
- }
175
-
176
- /** 当前落盘路径(handle.journalPath 回填数据源)。 */
177
- get path(): string {
178
- return this.opts.path;
179
- }
180
-
181
- private async writeChunk(chunk: string): Promise<void> {
182
- try {
183
- await this.fs.mkdir(dirname(this.opts.path), { recursive: true });
184
- await this.fs.appendFile(this.opts.path, chunk);
185
- this.wrote = true;
186
- } catch (err) {
187
- // 尽力而为语义:一次写失败即永久放弃(重试追写会产生乱序行),warn 留痕不静默
188
- this.failed = true;
189
- this.buffer = [];
190
- this.warn(
191
- `[event-journal] write failed, journal for task ${this.opts.taskId} is unavailable ` +
192
- `(read falls back to lower tiers): ${err instanceof Error ? err.message : String(err)}`,
193
- );
194
- }
195
- }
196
- }
197
-
198
- function defaultWarn(msg: string): void {
199
- logger.warn(msg);
200
- }
201
-
202
- // ============================================================
203
- // 重放
204
- // ============================================================
205
-
206
- /**
207
- * 重放 journal:读取路径下全部事件,重放即得 AgentEvent 流(read 第②级)。
208
- *
209
- * - 文件不存在 → [](降级链语义:②级不可达不算错误,调用方落 ③级);
210
- * - 损坏行跳过(追加写产物末行可能截断;跳过优于整体失败——设计 C5「三级都不 throw」);
211
- * - 按 seq 稳定排序后返回(重放顺序权威是 seq,不依赖文件行序的隐式保证,§3.3.6)。
212
- */
213
- export function replayJournal(path: string): AgentEvent[] {
214
- let raw: string;
215
- try {
216
- raw = readFileSync(path, "utf8");
217
- } catch {
218
- return [];
219
- }
220
- const lines: JournalLine[] = [];
221
- for (const row of raw.split("\n")) {
222
- const trimmed = row.trim();
223
- if (trimmed === "") continue;
224
- const parsed = parseLine(trimmed);
225
- if (parsed !== undefined) lines.push(parsed);
226
- }
227
- lines.sort((a, b) => a.seq - b.seq);
228
- return lines.map((l) => l.event);
229
- }
230
-
231
- /** 单行 parse + 结构 guard(v=1 + event 形状最小判别:object 且 type 为 string)。 */
232
- function parseLine(trimmed: string): JournalLine | undefined {
233
- let parsed: unknown;
234
- try {
235
- parsed = JSON.parse(trimmed);
236
- } catch {
237
- return undefined;
238
- }
239
- if (typeof parsed !== "object" || parsed === null) return undefined;
240
- const rec = parsed as Record<string, unknown>;
241
- const event = rec.event;
242
- if (rec.v !== 1 || typeof rec.ts !== "number" || typeof rec.seq !== "number") return undefined;
243
- if (typeof event !== "object" || event === null || typeof (event as Record<string, unknown>).type !== "string") {
244
- return undefined;
245
- }
246
- return {
247
- v: 1,
248
- ts: rec.ts,
249
- taskId: typeof rec.taskId === "string" ? rec.taskId : "",
250
- engineId: typeof rec.engineId === "string" ? rec.engineId : "",
251
- seq: rec.seq,
252
- event: event as AgentEvent,
253
- };
254
- }
@@ -1,62 +0,0 @@
1
- // src/execution/engine/common/journal-replay.ts
2
- //
3
- // read 第②级(宿主 event journal 重放)的公共实现(P4,对齐点①接线)。设计权威源:
4
- // docs/architecture/subagent-engine-abstraction.md D6 + §3.3.6「重放等价性」——
5
- // journal 重放与 live 通路共用同一 reducer(updateFromEvent 范式),不引入第二套
6
- // 解析器;conformance C5 断言重放 turns 与 live 一致。
7
- //
8
- // 为什么放 common:zcode/pi 的 read() ②级降级是同一段逻辑(replayJournal 拿事件流 →
9
- // live reducer 累积 turns → 投影 SessionView)——放引擎各自实现会漂移出两份形状。
10
-
11
- import { createRecord, updateFromEvent } from "../../execution-record.ts";
12
- import type { AgentEvent } from "../../types.ts";
13
- import type { EngineHandle, SessionView } from "../types.ts";
14
- import { replayJournal } from "./event-journal.ts";
15
- import { aggregateUsage, toReplayedTurn } from "./session-view-projection.ts";
16
-
17
- /**
18
- * journal → SessionView(read 第②级)。
19
- * 返回 undefined = ②级不可达(journal 路径缺省 / 文件不存在 / 无事件),调用方落 ③级。
20
- * coarse 引擎(zcode)journal 只含合成事件,重放退化为摘要级——D6 已声明的保真度
21
- * 下限,非缺陷。
22
- */
23
- export function replayJournalToSessionView(
24
- handle: EngineHandle,
25
- engineId: string,
26
- ): SessionView | undefined {
27
- const journalPath = handle.data.journalPath;
28
- if (journalPath === undefined) return undefined;
29
- const events = replayJournal(journalPath);
30
- if (events.length === 0) return undefined;
31
- return eventsToSessionView(events, engineId, sessionIdFromHandle(handle));
32
- }
33
-
34
- /** 事件流 → SessionView(live reducer 累积 turns——重放等价性的实现体)。 */
35
- export function eventsToSessionView(
36
- events: readonly AgentEvent[],
37
- engineId: string,
38
- sessionId?: string,
39
- ): SessionView {
40
- const record = createRecord("journal-replay", {
41
- agent: "journal-replay",
42
- model: "",
43
- mode: "background",
44
- task: "",
45
- slug: "",
46
- startedAt: 0,
47
- });
48
- for (const ev of events) updateFromEvent(record, ev);
49
- return {
50
- engineId,
51
- ...(sessionId !== undefined ? { sessionId } : {}),
52
- turns: record.turns.map(toReplayedTurn),
53
- usage: aggregateUsage(record.turns),
54
- source: "journal",
55
- };
56
- }
57
-
58
- /** handle.sessionRef 的 sessionId 提取(引擎自定义键,运行时 guard)。 */
59
- function sessionIdFromHandle(handle: EngineHandle): string | undefined {
60
- const v = handle.data.sessionRef["sessionId"];
61
- return typeof v === "string" ? v : undefined;
62
- }
@@ -1,221 +0,0 @@
1
- // src/execution/engine/common/kill-chain.ts
2
- //
3
- // 超时杀链与 abort 两级中断(P2 公共降级层)。设计权威源:
4
- // docs/architecture/subagent-engine-abstraction.md D1(abort 分级:引擎原生中断 →
5
- // 公共杀链兜底;CLI-only 引擎直接杀链,杀死后宿主合成终态)+ §3.3.3 engine_timeout /
6
- // engine_run_failed 行 + 附录 A「CLI 超时」行(6/6 引擎全缺 → 宿主公共层全补)。
7
- //
8
- // 为什么放公共层:没有任何引擎有 CLI 级超时(§2.2 表),杀链写一次全引擎复用(D4)。
9
-
10
- import { getLogger } from "@zhushanwen/pi-extension-logger";
11
-
12
- import { engineTimeoutDetail } from "./errors.ts";
13
- import type { AgentOutcome, AgentTaskSpec } from "../types.ts";
14
- import { DEFAULT_ENGINE_ID } from "../registry.ts";
15
-
16
- const logger = getLogger("subagents");
17
-
18
- // ============================================================
19
- // 杀链(SIGTERM → grace → SIGKILL)
20
- // ============================================================
21
-
22
- /**
23
- * 可杀子进程的结构形状(Node ChildProcess 的结构子集)。
24
- * 用结构接口而非 ChildProcess 类型:测试可注入 fake(ChildProcess 全字段构造过重),
25
- * 且未来 driver host 的常驻进程句柄只要满足此形状即可复用杀链。
26
- */
27
- export interface KillableChild {
28
- /** 非 null = 进程已退出(自然退出码)。 */
29
- readonly exitCode: number | null;
30
- /** 非 null = 进程被信号杀死。exitCode/signalCode 任一非 null 即已退出。 */
31
- readonly signalCode: string | null;
32
- /** 发信号。返回 false = 进程已不存在(kill no-op)。 */
33
- kill(signal?: NodeJS.Signals | number): boolean;
34
- once(event: "exit", listener: (code: number | null, signal: NodeJS.Signals | null) => void): unknown;
35
- }
36
-
37
- /** SIGTERM 优雅窗口默认值(ms)。实测校准点:设计 §5 待验证检查点⑤(zcode 对 SIGTERM 的响应时序)。 */
38
- export const DEFAULT_KILL_GRACE_MS = 5_000;
39
-
40
- /** SIGKILL 发出后的收尸等待上限(ms)——SIGKILL 后进程必死(D 状态罕见),有界等待防挂死。 */
41
- const SIGKILL_REAP_TIMEOUT_MS = 10_000;
42
-
43
- /**
44
- * 宿主超时 abort 的 signal.reason 标记(对齐点④)。mergeTimeoutSignal(SAR 侧超时
45
- * 合并链)产出;引擎 abort 合成终态时判别「超时 vs 用户 cancel」——超时统一走
46
- * synthesizeTimeoutOutcome(engine_timeout),cancel 维持中止标记(engine_run_failed)。
47
- */
48
- export const HOST_TIMEOUT_ABORT_REASON = "agent-call-timeout";
49
-
50
- /**
51
- * 杀链:SIGTERM → 等待 graceMs → 仍存活则 SIGKILL。
52
- *
53
- * @returns 'terminated' = SIGTERM 优雅退出(或进程已自行退出);'killed' = 走了 SIGKILL。
54
- */
55
- export async function killChain(
56
- child: KillableChild,
57
- opts: { graceMs: number },
58
- ): Promise<"terminated" | "killed"> {
59
- // 已退出(自然/已被杀)→ 无需发信号,按优雅终止口径返回
60
- if (child.exitCode !== null || child.signalCode !== null) return "terminated";
61
-
62
- const exited = waitForExit(child);
63
- safeKill(child, "SIGTERM");
64
-
65
- const graceful = await raceTimeout(exited, opts.graceMs);
66
- if (graceful === "settled") return "terminated";
67
- // grace 超时后进程可能恰好在检查前一刻退出——复核退出态,避免误杀已死进程
68
- if (child.exitCode !== null || child.signalCode !== null) return "terminated";
69
-
70
- safeKill(child, "SIGKILL");
71
- // 有界收尸:无论等到与否都返回 'killed'(信号已发出,返回值表达「走了 SIGKILL」)
72
- await raceTimeout(exited, SIGKILL_REAP_TIMEOUT_MS);
73
- return "killed";
74
- }
75
-
76
- /**
77
- * 发信号兜底包裹:进程恰在退出态检查与 kill 之间自退时,ChildProcess.kill 可能抛
78
- * (zsub 实测经验)——幂等吞掉并 debug 留痕,不阻断杀链语义(对已退进程信号本就是
79
- * no-op)。收口自 zcode launcher 的内联实现(对齐点②:单一权威)。
80
- */
81
- function safeKill(child: KillableChild, signal: NodeJS.Signals): void {
82
- try {
83
- child.kill(signal);
84
- } catch (err) {
85
- logger.debug(
86
- `[kill-chain] ${signal} on exited process: ${err instanceof Error ? err.message : String(err)}`,
87
- );
88
- }
89
- }
90
-
91
- // ============================================================
92
- // 超时终态合成
93
- // ============================================================
94
-
95
- /**
96
- * 合成 engine_timeout 终态(宿主超时杀链走完后的 AgentOutcome)。
97
- * 含 stdout 尾部 2000 字 + 「可用 engine: pi 重跑」建议(§3.3.3 第 6 行);
98
- * exitCode: null = 被信号杀死(AgentOutcome 的杀链判据,§3.3.5)。
99
- */
100
- export function synthesizeTimeoutOutcome(
101
- task: AgentTaskSpec,
102
- stdoutTail: string,
103
- engineId: string = DEFAULT_ENGINE_ID,
104
- ): AgentOutcome {
105
- return {
106
- content: "",
107
- // slug 进错误信息:单看 outcome(record 之外)也能定位是哪个任务超时
108
- error: `engine_timeout: [slug=${task.slug}] ${engineTimeoutDetail(stdoutTail)}`,
109
- // 被信号杀死:退出码语义为 null(§3.3.5 AgentOutcome.exitCode 注释)
110
- exitCode: null,
111
- engineId,
112
- };
113
- }
114
-
115
- // ============================================================
116
- // abort 两级编排
117
- // ============================================================
118
-
119
- /** 原生中断后的宽限窗口默认值(ms):中断指令送达 → 引擎自行收尾的等待上限。 */
120
- export const DEFAULT_NATIVE_INTERRUPT_GRACE_MS = 3_000;
121
-
122
- /**
123
- * abort 两级编排 helper(D1 abort 分级的公共实现):
124
- * signal abort 时 ①先调引擎原生中断(tryNativeInterrupt,若有)并给宽限窗口,
125
- * 窗口内未停(或无原生中断——CLI-only 引擎)则 ②走杀链兜底。
126
- *
127
- * 进程自然退出时以 'terminated' settle(挂在 exit 事件上,杀链对已退进程是 no-op),
128
- * 调用方可安全 await;signal 永不 abort 且进程已退时也会 settle,不悬挂。
129
- */
130
- export function abortWithFallback(
131
- child: KillableChild,
132
- signal: AbortSignal,
133
- tryNativeInterrupt?: () => Promise<void>,
134
- opts?: { graceMs?: number; nativeGraceMs?: number },
135
- ): Promise<"terminated" | "killed"> {
136
- const graceMs = opts?.graceMs ?? DEFAULT_KILL_GRACE_MS;
137
- const nativeGraceMs = opts?.nativeGraceMs ?? DEFAULT_NATIVE_INTERRUPT_GRACE_MS;
138
-
139
- return new Promise<"terminated" | "killed">((resolve) => {
140
- let settled = false;
141
- // 三个 handler 互相引用(finish 移除 onAbort / onAbort 触发 runChain / runChain
142
- // 兜底 finish),用函数声明 + 提升消解声明环,避免 use-before-define。
143
- function finish(result: "terminated" | "killed"): void {
144
- if (settled) return;
145
- settled = true;
146
- signal.removeEventListener("abort", onAbort);
147
- resolve(result);
148
- }
149
-
150
- function onExit(): void {
151
- finish("terminated");
152
- }
153
-
154
- function runChain(): void {
155
- void (async () => {
156
- if (tryNativeInterrupt) {
157
- try {
158
- await tryNativeInterrupt();
159
- } catch (err) {
160
- // 原生中断失败(协议错/管道断)→ 直接落杀链,中断失败不阻断兜底。
161
- // debug 级留诊断线索:这不是错误终态,只是该引擎优雅中断不可用
162
- logger.debug(
163
- `[kill-chain] native interrupt failed, falling back to kill chain: ${
164
- err instanceof Error ? err.message : String(err)
165
- }`,
166
- );
167
- }
168
- const stopped = await raceTimeout(waitForExit(child), nativeGraceMs);
169
- if (stopped === "settled" || settled) return; // 原生中断生效,进程已停
170
- }
171
- finish(await killChain(child, { graceMs }));
172
- })();
173
- }
174
-
175
- function onAbort(): void {
176
- runChain();
177
- }
178
-
179
- // 进程自然退出(含原生中断生效)→ 优雅终止口径。
180
- // once listener 不显式移除:触发时 finish 已幂等,单 child 单 listener 无堆积。
181
- child.once("exit", onExit);
182
- if (child.exitCode !== null || child.signalCode !== null) {
183
- finish("terminated");
184
- return;
185
- }
186
-
187
- if (signal.aborted) runChain();
188
- else signal.addEventListener("abort", onAbort, { once: true });
189
- });
190
- }
191
-
192
- // ── 内部工具 ────────────────────────────────────────────────────
193
-
194
- /** 等 child 退出(已退出立即 settle;否则挂一次性 exit listener)。 */
195
- function waitForExit(child: KillableChild): Promise<void> {
196
- return new Promise<void>((resolve) => {
197
- if (child.exitCode !== null || child.signalCode !== null) {
198
- resolve();
199
- return;
200
- }
201
- child.once("exit", () => resolve());
202
- });
203
- }
204
-
205
- /** promise vs 超时:超时先到返回 'timeout'(promise 继续但被放弃等待)。 */
206
- function raceTimeout(p: Promise<void>, ms: number): Promise<"settled" | "timeout"> {
207
- return new Promise<"settled" | "timeout">((resolve) => {
208
- const timer = setTimeout(() => resolve("timeout"), ms);
209
- p.then(
210
- () => {
211
- clearTimeout(timer);
212
- resolve("settled");
213
- },
214
- () => {
215
- // 被 await 的 exit promise 不会 reject;防御分支保持语义完整(超时口径胜出前出错按 settled 处理)
216
- clearTimeout(timer);
217
- resolve("settled");
218
- },
219
- );
220
- });
221
- }
@@ -1,50 +0,0 @@
1
- // src/execution/engine/common/nesting-guard.ts
2
- //
3
- // 嵌套防护(P2 公共降级层)。设计权威源:
4
- // docs/architecture/subagent-engine-abstraction.md D8(嵌套防护双层):
5
- // 统一 XYZ_AGENT_SUBAGENT=1 标记(所有引擎 spawn 都注入,引擎 adapter 检测到即拒绝
6
- // 递归派发)+ 剥离各引擎原生标记(CC 的 CLAUDECODE / zsub 的 ZSW_NESTED / pi 的
7
- // PI_SUBAGENT_*)防继承泄漏——子代理环境的旧标记会让孙代理误判自己已在嵌套层。
8
- //
9
- // 为什么 env 标记是唯一跨引擎可靠手段(被否方案见设计):「隔离目录里不装扩展」
10
- // 依赖配置洁癖,且 opencode/CC 会吃项目级配置;env 由宿主显式控制,随 spawn 必达。
11
-
12
- import { nestedSpawnRejectedError } from "./errors.ts";
13
-
14
- /** 统一嵌套标记 env 名(D8)。值恒 '1'。 */
15
- export const NESTED_SPAWN_ENV = "XYZ_AGENT_SUBAGENT";
16
-
17
- /** 需剥离的引擎原生嵌套标记(精确名)。 */
18
- const NATIVE_NESTED_KEYS: readonly string[] = ["CLAUDECODE", "ZSW_NESTED"];
19
-
20
- /** 需剥离的引擎原生嵌套标记前缀(pi 家族)。 */
21
- const NATIVE_NESTED_PREFIXES: readonly string[] = ["PI_SUBAGENT_"];
22
-
23
- /** env 对象形状(NodeJS.ProcessEnv 的结构子集,测试可传普通对象)。 */
24
- export type SpawnEnv = Record<string, string | undefined>;
25
-
26
- /**
27
- * 构造子代理 spawn env:注入 XYZ_AGENT_SUBAGENT=1 + 剥离引擎原生嵌套标记。
28
- * 返回新对象,不改入参(spawn env 组装链中的多层 spread 安全)。
29
- */
30
- export function buildNestedSpawnEnv(baseEnv: SpawnEnv): SpawnEnv {
31
- const env: SpawnEnv = {};
32
- for (const [key, value] of Object.entries(baseEnv)) {
33
- if (NATIVE_NESTED_KEYS.includes(key)) continue;
34
- if (NATIVE_NESTED_PREFIXES.some((prefix) => key.startsWith(prefix))) continue;
35
- env[key] = value;
36
- }
37
- env[NESTED_SPAWN_ENV] = "1";
38
- return env;
39
- }
40
-
41
- /**
42
- * 嵌套 spawn 防护断言:检测到统一标记(本进程已是 subagent)抛
43
- * EngineError(nested_spawn_rejected)——文案说明防护规则、指向 task 内自行完成。
44
- * 调用点:subagent 工具入口(进程创建前拒绝,D11 处置三级)。
45
- */
46
- export function assertNotNestedSpawn(env: SpawnEnv): void {
47
- if (env[NESTED_SPAWN_ENV] === "1") {
48
- throw nestedSpawnRejectedError();
49
- }
50
- }