@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,599 +0,0 @@
1
- // src/execution/__tests__/subprocess-agent-runner.test.ts
2
- //
3
- // Wave 4: SubprocessAgentRunner 委托重写测试
4
- //
5
- // 覆盖 test-matrix 用例:
6
- // T3.1 (正常): SAR 委托 executeAndAwait 返回 content
7
- // T3.2 (正常): parsedOutput 透传
8
- // T3.4 (边界): cwd 透传(非 git worktree)
9
- // T3.5 (边界): model 填底(opts.model 空 → ctxModel)
10
- // T3.6 (异常): timeoutMs 超时 → signal abort → error
11
- // T3.7 (正常): onEvent 桥接 AgentEvent 透传
12
- // T3.17 (NFR): mergeTimeoutSignal listener 清理
13
- // T3.18 (NFR): dispose 兜底覆盖(delegate 后子进程进 spawnedChildren)
14
- // T3.19 (NFR): AgentCallOpts→ExecuteOptions 映射保真
15
-
16
- import { mkdtempSync, readdirSync, rmSync } from "node:fs";
17
- import { tmpdir } from "node:os";
18
- import { join } from "node:path";
19
-
20
- import { afterEach, describe, expect, it, vi } from "vitest";
21
-
22
- import type { AgentCallOpts, AgentResult } from "../../orchestration/models/types.ts";
23
- import { ModelConfigService, setModelConfigService } from "../model-config-service.ts";
24
- import type { ModelRegistryLike } from "../model-resolver.ts";
25
- import { replayJournal } from "../engine/common/event-journal.ts";
26
- import type { SubprocessAgentRunnerDeps } from "../subprocess-agent-runner.ts";
27
- import { SubprocessAgentRunner } from "../subprocess-agent-runner.ts";
28
-
29
- // ── 测试辅助 ──
30
-
31
- /** 构造 mock SubagentService.executeAndAwait 返回值 */
32
- function makeMockResult(overrides: Partial<AgentResult> = {}): AgentResult {
33
- return {
34
- content: "OK",
35
- parsedOutput: undefined,
36
- durationMs: 100,
37
- error: undefined,
38
- sessionId: undefined,
39
- toolCalls: [],
40
- ...overrides,
41
- };
42
- }
43
-
44
- /** 创建 mock SubagentService(只实现 executeAndAwait) */
45
- function createMockService(impl?: typeof vi.fn) {
46
- const executeAndAwait = impl ?? vi.fn().mockResolvedValue(makeMockResult());
47
- return { executeAndAwait } as unknown as {
48
- executeAndAwait: (
49
- opts: Record<string, unknown>,
50
- signal?: AbortSignal,
51
- onEvent?: (e: Record<string, unknown>) => void,
52
- stream?: unknown,
53
- ) => Promise<AgentResult>;
54
- };
55
- }
56
-
57
- function makeBaseOpts(): AgentCallOpts {
58
- return {
59
- prompt: "test task",
60
- agent: "worker",
61
- cwd: "/some/path",
62
- schema: undefined,
63
- model: undefined,
64
- scene: undefined,
65
- description: undefined,
66
- timeoutMs: undefined,
67
- skill: undefined,
68
- skillPath: undefined,
69
- appendSystemPrompt: undefined,
70
- schemaEnv: undefined,
71
- };
72
- }
73
-
74
- // ── T3.1: 正常路径 ──
75
-
76
- describe("SubprocessAgentRunner (wave-4 delegate)", () => {
77
- // ────────────────────────────────────────────────
78
- // T3.1: 正常路径 — SAR 委托 executeAndAwait 返回 content
79
- // ────────────────────────────────────────────────
80
- describe("T3.1 主流程", () => {
81
- it("委托 executeAndAwait 并返回 content", async () => {
82
- const mockService = createMockService(
83
- vi.fn().mockResolvedValue(makeMockResult({ content: "hello world" })),
84
- );
85
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
86
- const sar = new SubprocessAgentRunner(deps);
87
-
88
- const opts = makeBaseOpts();
89
- const signal = new AbortController().signal;
90
-
91
- const result = await sar.run(opts, signal);
92
-
93
- expect(result.content).toBe("hello world");
94
- expect(mockService.executeAndAwait).toHaveBeenCalledTimes(1);
95
- });
96
-
97
- it("不 reject — 失败信息入 result.error", async () => {
98
- const mockService = createMockService(
99
- vi.fn().mockResolvedValue(makeMockResult({ error: "some error" })),
100
- );
101
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
102
- const sar = new SubprocessAgentRunner(deps);
103
-
104
- const result = await sar.run(makeBaseOpts(), new AbortController().signal);
105
- expect(result.error).toBe("some error");
106
- });
107
- });
108
-
109
- // ────────────────────────────────────────────────
110
- // T3.2: parsedOutput 透传
111
- // ────────────────────────────────────────────────
112
- describe("T3.2 parsedOutput 透传", () => {
113
- it("parsedOutput 直通", async () => {
114
- const parsedData = { x: 1, y: 2 };
115
- const mockService = createMockService(
116
- vi.fn().mockResolvedValue(makeMockResult({ content: "ok", parsedOutput: parsedData })),
117
- );
118
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
119
- const sar = new SubprocessAgentRunner(deps);
120
-
121
- const result = await sar.run(makeBaseOpts(), new AbortController().signal);
122
- expect(result.parsedOutput).toEqual(parsedData);
123
- });
124
- });
125
-
126
- // ────────────────────────────────────────────────
127
- // T3.4: cwd 透传
128
- // ────────────────────────────────────────────────
129
- describe("T3.4 cwd 透传", () => {
130
- it("cwd 传入 executeAndAwait 的 ExecuteOptions", async () => {
131
- let capturedOpts: Record<string, unknown> | undefined;
132
- const mockService = createMockService(
133
- vi.fn().mockImplementation((opts: Record<string, unknown>) => {
134
- capturedOpts = opts;
135
- return Promise.resolve(makeMockResult());
136
- }),
137
- );
138
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
139
- const sar = new SubprocessAgentRunner(deps);
140
-
141
- const opts = { ...makeBaseOpts(), cwd: "/custom/cwd" };
142
- await sar.run(opts, new AbortController().signal);
143
-
144
- expect(capturedOpts).toBeDefined();
145
- expect(capturedOpts!.cwd).toBe("/custom/cwd");
146
- });
147
- });
148
-
149
- // ────────────────────────────────────────────────
150
- // T3.5: model 填底
151
- // ────────────────────────────────────────────────
152
- describe("T3.5 model 填底 (D-008)", () => {
153
- it("opts.model 优先", async () => {
154
- let capturedOpts: Record<string, unknown> | undefined;
155
- const mockService = createMockService(
156
- vi.fn().mockImplementation((opts: Record<string, unknown>) => {
157
- capturedOpts = opts;
158
- return Promise.resolve(makeMockResult());
159
- }),
160
- );
161
- const ctxModel = { id: "ctx-model", provider: "test", input: [] };
162
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService, ctxModel };
163
- const sar = new SubprocessAgentRunner(deps);
164
-
165
- const opts = { ...makeBaseOpts(), model: "explicit-model" };
166
- await sar.run(opts, new AbortController().signal);
167
-
168
- expect(capturedOpts!.model).toBe("explicit-model");
169
- });
170
-
171
- it("opts.model 空 → ctxModel", async () => {
172
- let capturedOpts: Record<string, unknown> | undefined;
173
- const mockService = createMockService(
174
- vi.fn().mockImplementation((opts: Record<string, unknown>) => {
175
- capturedOpts = opts;
176
- return Promise.resolve(makeMockResult());
177
- }),
178
- );
179
- const ctxModel = { id: "ctx-model", provider: "test", input: [] };
180
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService, ctxModel };
181
- const sar = new SubprocessAgentRunner(deps);
182
-
183
- const opts = { ...makeBaseOpts(), model: undefined };
184
- await sar.run(opts, new AbortController().signal);
185
-
186
- // 修复后:opts.model 不再从 ctxModel.id 填底,ctxModel 作为完整对象透传
187
- expect(capturedOpts!.model).toBeUndefined();
188
- expect(capturedOpts!.ctxModel).toBe(ctxModel);
189
- });
190
- });
191
-
192
- // ────────────────────────────────────────────────
193
- // [U1 D2] RunContext.modelRef 接入:ctxModel 继承路径孪生守卫
194
- // ────────────────────────────────────────────────
195
- describe("U1 ctxModel twin guard (RunContext.modelRef 接入)", () => {
196
- const prevDataDir = process.env["XYZ_AGENT_DATA_DIR"];
197
- let tmpRoot = "";
198
-
199
- /** 装配含指定快照的 ModelConfigService 单例(initModel 注入 registry)。 */
200
- function installModelService(registry: ModelRegistryLike): void {
201
- tmpRoot = mkdtempSync(join(tmpdir(), "sar-model-ref-"));
202
- process.env["XYZ_AGENT_DATA_DIR"] = join(tmpRoot, "engine-data");
203
- const svc = new ModelConfigService({ agentDir: join(tmpRoot, "agent"), cwd: tmpRoot });
204
- svc.initModel({ modelRegistry: registry, sessionId: "sar-guard" });
205
- setModelConfigService(svc);
206
- }
207
-
208
- afterEach(() => {
209
- // 单例 slot 无 reset API,重装一个空注册服务隔离后续用例(同文件后续
210
- // describe 不消费 ctxModel 守卫,getGlobalConfig 对空目录返回默认值)
211
- if (tmpRoot) {
212
- const svc = new ModelConfigService({ agentDir: join(tmpRoot, "agent"), cwd: tmpRoot });
213
- svc.initModel({ modelRegistry: { getAvailable: () => [], find: () => undefined, hasConfiguredAuth: () => false }, sessionId: "cleanup" });
214
- setModelConfigService(svc);
215
- rmSync(tmpRoot, { recursive: true, force: true });
216
- tmpRoot = "";
217
- }
218
- if (prevDataDir === undefined) delete process.env["XYZ_AGENT_DATA_DIR"];
219
- else process.env["XYZ_AGENT_DATA_DIR"] = prevDataDir;
220
- });
221
-
222
- it("P-A2 拒单路径:ctxModel 命中但 registry 含孪生 → run 返回 error(ambiguous),executeAndAwait 未被调", async () => {
223
- const models = [
224
- { id: "GLM-5.3-Flash", name: "flash", provider: "zai-coding-cn", reasoning: false },
225
- { id: "glm-5.3-flash", name: "flash lower", provider: "zai-coding-cn", reasoning: false },
226
- ];
227
- installModelService({
228
- getAvailable: () => models,
229
- find: (p, id) => models.find((m) => m.provider === p && m.id === id),
230
- hasConfiguredAuth: () => true,
231
- });
232
- const mockService = createMockService();
233
- const sar = new SubprocessAgentRunner({
234
- subagentService: mockService as unknown as SubprocessAgentRunnerDeps["subagentService"],
235
- ctxModel: { id: "GLM-5.3-Flash", name: "flash", provider: "zai-coding-cn", reasoning: false },
236
- });
237
-
238
- const result = await sar.run(makeBaseOpts(), new AbortController().signal);
239
-
240
- expect(result.error).toMatch(/ambiguous case variants/);
241
- expect(result.content).toBe("");
242
- // 守卫在 engine.run 之前:不产生任何 record/spawn(委托零发生)
243
- expect(mockService.executeAndAwait).not.toHaveBeenCalled();
244
- });
245
-
246
- it("P-A2 放行路径:无孪生 registry 下同 ctxModel 正常委托(守卫零误伤)", async () => {
247
- const models = [
248
- { id: "GLM-5.3-Flash", name: "flash", provider: "zai-coding-cn", reasoning: false },
249
- ];
250
- installModelService({
251
- getAvailable: () => models,
252
- find: (p, id) => models.find((m) => m.provider === p && m.id === id),
253
- hasConfiguredAuth: () => true,
254
- });
255
- const mockService = createMockService(
256
- vi.fn().mockResolvedValue(makeMockResult({ content: "ok" })),
257
- );
258
- const sar = new SubprocessAgentRunner({
259
- subagentService: mockService as unknown as SubprocessAgentRunnerDeps["subagentService"],
260
- ctxModel: { id: "GLM-5.3-Flash", name: "flash", provider: "zai-coding-cn", reasoning: false },
261
- });
262
-
263
- const result = await sar.run(makeBaseOpts(), new AbortController().signal);
264
-
265
- expect(result.error).toBeUndefined();
266
- expect(result.content).toBe("ok");
267
- expect(mockService.executeAndAwait).toHaveBeenCalledTimes(1);
268
- });
269
-
270
- it("ctxModel 未指定时守卫跳过(无单例也不阻断)", async () => {
271
- const mockService = createMockService(
272
- vi.fn().mockResolvedValue(makeMockResult({ content: "ok" })),
273
- );
274
- const sar = new SubprocessAgentRunner({
275
- subagentService: mockService as unknown as SubprocessAgentRunnerDeps["subagentService"],
276
- });
277
- const result = await sar.run(makeBaseOpts(), new AbortController().signal);
278
- expect(result.content).toBe("ok");
279
- expect(mockService.executeAndAwait).toHaveBeenCalledTimes(1);
280
- });
281
- });
282
-
283
- // ────────────────────────────────────────────────
284
- // H1: SAR ctxModel 刷新(model_select 后不再 stale)
285
- // ────────────────────────────────────────────────
286
- describe("H1 ctxModel refresh via updateCtxModel", () => {
287
- it("updateCtxModel 后 run() 传入新的 ctxModel 而非旧值", async () => {
288
- let capturedOpts: Record<string, unknown> | undefined;
289
- const mockService = createMockService(
290
- vi.fn().mockImplementation((opts: Record<string, unknown>) => {
291
- capturedOpts = opts;
292
- return Promise.resolve(makeMockResult());
293
- }),
294
- );
295
- const oldModel = { id: "old-model", provider: "test", input: [] };
296
- const newModel = { id: "new-model", provider: "test", input: [] };
297
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService, ctxModel: oldModel };
298
- const sar = new SubprocessAgentRunner(deps);
299
-
300
- // 模拟 model_select:刷新 ctxModel
301
- sar.updateCtxModel(newModel);
302
-
303
- const opts = { ...makeBaseOpts(), model: undefined };
304
- await sar.run(opts, new AbortController().signal);
305
-
306
- expect(capturedOpts!.ctxModel).toBe(newModel);
307
- expect(capturedOpts!.ctxModel).not.toBe(oldModel);
308
- });
309
- });
310
-
311
- // ────────────────────────────────────────────────
312
- // T3.6: timeoutMs 超时 → signal abort → error
313
- // ────────────────────────────────────────────────
314
- describe("T3.6 timeoutMs 超时", () => {
315
- it("timeoutMs > 0 → merged signal 传给 executeAndAwait", async () => {
316
- let capturedSignal: AbortSignal | undefined;
317
- const mockService = createMockService(
318
- vi.fn().mockImplementation((_opts: Record<string, unknown>, signal?: AbortSignal) => {
319
- capturedSignal = signal;
320
- return Promise.resolve(makeMockResult());
321
- }),
322
- );
323
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
324
- const sar = new SubprocessAgentRunner(deps);
325
-
326
- const opts = { ...makeBaseOpts(), timeoutMs: 5000 };
327
- await sar.run(opts, new AbortController().signal);
328
-
329
- // 有 timeoutMs 时 merged signal 不等于原始 signal
330
- expect(capturedSignal).toBeDefined();
331
- });
332
-
333
- it("timeoutMs 到期 → merged signal.aborted=true", async () => {
334
- vi.useFakeTimers();
335
- let capturedSignal: AbortSignal | undefined;
336
- const mockService = createMockService(
337
- vi.fn().mockImplementation((_opts: Record<string, unknown>, signal?: AbortSignal) => {
338
- capturedSignal = signal;
339
- return Promise.resolve(makeMockResult());
340
- }),
341
- );
342
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
343
- const sar = new SubprocessAgentRunner(deps);
344
-
345
- const opts = { ...makeBaseOpts(), timeoutMs: 50 };
346
- sar.run(opts, new AbortController().signal);
347
-
348
- // 推进 51ms 后 merged signal 应 abort
349
- vi.advanceTimersByTime(51);
350
-
351
- expect(capturedSignal?.aborted).toBe(true);
352
- vi.useRealTimers();
353
- });
354
- });
355
-
356
- // ────────────────────────────────────────────────
357
- // T3.7: onEvent 桥接
358
- // ────────────────────────────────────────────────
359
- describe("T3.7 onEvent 桥接", () => {
360
- it("executeAndAwait 的 onEvent 透传到 workflow onEvent", async () => {
361
- const mockService = createMockService(
362
- vi.fn().mockImplementation(
363
- (_opts: Record<string, unknown>, _signal?: AbortSignal, onEvent?: (e: Record<string, unknown>) => void) => {
364
- // 模拟 executeAndAwait 触发 onEvent
365
- onEvent?.({ type: "tool_start", toolName: "read", args: { path: "/a.txt" } });
366
- return Promise.resolve(makeMockResult());
367
- },
368
- ),
369
- );
370
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
371
- const sar = new SubprocessAgentRunner(deps);
372
-
373
- const workflowOnEvent = vi.fn();
374
- await sar.run(makeBaseOpts(), new AbortController().signal, workflowOnEvent);
375
-
376
- // workflow 的 onEvent 应被调用
377
- expect(workflowOnEvent).toHaveBeenCalledTimes(1);
378
- expect(workflowOnEvent).toHaveBeenCalledWith({
379
- type: "tool_start",
380
- toolName: "read",
381
- args: { path: "/a.txt" },
382
- });
383
- });
384
-
385
- it("无 workflow onEvent → 引擎仍收到包装 onEvent(P2 journal 通道恒开)", async () => {
386
- let engineOnEvent: ((e: Record<string, unknown>) => void) | undefined;
387
- const mockService = createMockService(
388
- vi.fn().mockImplementation(
389
- (_opts: Record<string, unknown>, _signal?: AbortSignal, onEvent?: (e: Record<string, unknown>) => void) => {
390
- engineOnEvent = onEvent;
391
- return Promise.resolve(makeMockResult());
392
- },
393
- ),
394
- );
395
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
396
- const sar = new SubprocessAgentRunner(deps);
397
-
398
- await sar.run(makeBaseOpts(), new AbortController().signal);
399
-
400
- // P2 接线(设计 D6 第②级):SAR 包装 onEvent 写 journal 后转发——原 onEvent
401
- // 未传时也恒传包装版(全引擎免费获得 journal;P1「undefined 透传」细节已被
402
- // 有意变更,本用例锁定新语义:引擎侧 onEvent 通道恒开)
403
- expect(typeof engineOnEvent).toBe("function");
404
- // 包装版不向外抛(journal append 是同步入队)
405
- expect(() => engineOnEvent?.({ type: "turn_end" })).not.toThrow();
406
- });
407
-
408
- it("P2 journal 接线:run 期间事件落盘 journal-<taskId>.jsonl(中立格式,可重放)", async () => {
409
- vi.useFakeTimers({ toFake: [] }); // 真实 timers:journal 写盘走真实 fs
410
- const dataDir = mkdtempSync(join(tmpdir(), "sar-journal-test-"));
411
- const prevEnv = process.env.XYZ_AGENT_DATA_DIR;
412
- process.env.XYZ_AGENT_DATA_DIR = dataDir;
413
- try {
414
- const mockService = createMockService(
415
- vi.fn().mockImplementation(
416
- (_opts: Record<string, unknown>, _signal?: AbortSignal, onEvent?: (e: Record<string, unknown>) => void) => {
417
- onEvent?.({ type: "tool_start", toolName: "bash", args: { cmd: "ls" } });
418
- onEvent?.({ type: "turn_end" });
419
- return Promise.resolve(makeMockResult());
420
- },
421
- ),
422
- );
423
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
424
- const sar = new SubprocessAgentRunner(deps);
425
-
426
- const workflowOnEvent = vi.fn();
427
- await sar.run(makeBaseOpts(), new AbortController().signal, workflowOnEvent);
428
-
429
- // journal 落在 <dataDir>/engines/pi/shared/journal-<taskId>.jsonl
430
- const journalFile = join(dataDir, "engines", "pi", "shared");
431
- const files = readdirSync(journalFile).filter((f) => f.startsWith("journal-") && f.endsWith(".jsonl"));
432
- expect(files.length).toBe(1);
433
- const replayed = replayJournal(join(journalFile, files[0] ?? ""));
434
- expect(replayed).toEqual([
435
- { type: "tool_start", toolName: "bash", args: { cmd: "ls" } },
436
- { type: "turn_end" },
437
- ]);
438
- // workflow onEvent 照常透传(journal 包装不吞事件)
439
- expect(workflowOnEvent).toHaveBeenCalledTimes(2);
440
- } finally {
441
- if (prevEnv === undefined) delete process.env.XYZ_AGENT_DATA_DIR;
442
- else process.env.XYZ_AGENT_DATA_DIR = prevEnv;
443
- rmSync(dataDir, { recursive: true, force: true });
444
- }
445
- });
446
- });
447
-
448
- // ────────────────────────────────────────────────
449
- // T3.17: mergeTimeoutSignal listener 清理
450
- // ────────────────────────────────────────────────
451
- describe("T3.17 mergeTimeoutSignal listener 清理", () => {
452
- it("外部 signal abort → timer 清理", async () => {
453
- vi.useFakeTimers();
454
- const mockService = createMockService(
455
- vi.fn().mockResolvedValue(makeMockResult()),
456
- );
457
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
458
- const sar = new SubprocessAgentRunner(deps);
459
-
460
- const ctrl = new AbortController();
461
- const opts = { ...makeBaseOpts(), timeoutMs: 5000 };
462
-
463
- // 启动 run(不 await,让它在后台)
464
- const runPromise = sar.run(opts, ctrl.signal);
465
-
466
- // 外部 abort
467
- ctrl.abort();
468
-
469
- await runPromise;
470
-
471
- // 推进时间——timer 应已清理,不会造成副作用
472
- vi.advanceTimersByTime(6000);
473
- // 无异常 = listener 已正确清理
474
- vi.useRealTimers();
475
- });
476
- });
477
-
478
- // ────────────────────────────────────────────────
479
- // T3.19: AgentCallOpts → ExecuteOptions 映射保真
480
- // ────────────────────────────────────────────────
481
- describe("T3.19 映射保真", () => {
482
- it("prompt → task, agent → agent, schemaEnv 透传", async () => {
483
- let capturedOpts: Record<string, unknown> | undefined;
484
- const mockService = createMockService(
485
- vi.fn().mockImplementation((opts: Record<string, unknown>) => {
486
- capturedOpts = opts;
487
- return Promise.resolve(makeMockResult());
488
- }),
489
- );
490
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
491
- const sar = new SubprocessAgentRunner(deps);
492
-
493
- const opts: AgentCallOpts = {
494
- ...makeBaseOpts(),
495
- prompt: "do the thing",
496
- agent: "code-reviewer",
497
- schemaEnv: '{"type":"object"}',
498
- skillPath: "/skills/code-review.md",
499
- };
500
- await sar.run(opts, new AbortController().signal);
501
-
502
- expect(capturedOpts).toBeDefined();
503
- expect(capturedOpts!.task).toBe("do the thing");
504
- expect(capturedOpts!.agent).toBe("code-reviewer");
505
- expect(capturedOpts!.skillPath).toBe("/skills/code-review.md");
506
- // schemaEnv 应通过 ExecuteOptions 透传
507
- expect((capturedOpts as Record<string, unknown>).schemaEnv).toBe('{"type":"object"}');
508
- });
509
-
510
- it("schema 透传为原始对象", async () => {
511
- let capturedOpts: Record<string, unknown> | undefined;
512
- const mockService = createMockService(
513
- vi.fn().mockImplementation((opts: Record<string, unknown>) => {
514
- capturedOpts = opts;
515
- return Promise.resolve(makeMockResult());
516
- }),
517
- );
518
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
519
- const sar = new SubprocessAgentRunner(deps);
520
-
521
- const opts = {
522
- ...makeBaseOpts(),
523
- schema: { type: "object", properties: { name: { type: "string" } } },
524
- };
525
- await sar.run(opts, new AbortController().signal);
526
-
527
- expect(capturedOpts!.schema).toEqual({
528
- type: "object",
529
- properties: { name: { type: "string" } },
530
- });
531
- });
532
- });
533
-
534
- // ────────────────────────────────────────────────
535
- // T3.18: executeAndAwait throw → catch → error
536
- // ────────────────────────────────────────────────
537
- describe("T3.18 异常处理", () => {
538
- it("executeAndAwait throw → 不 reject,返回 error", async () => {
539
- const mockService = createMockService(
540
- vi.fn().mockRejectedValue(new Error("nesting depth exceeded")),
541
- );
542
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
543
- const sar = new SubprocessAgentRunner(deps);
544
-
545
- const result = await sar.run(makeBaseOpts(), new AbortController().signal);
546
- expect(result.error).toContain("nesting depth exceeded");
547
- expect(result.content).toBe("");
548
- });
549
-
550
- it("非 Error throw → error 字段含 message", async () => {
551
- const mockService = createMockService(
552
- vi.fn().mockRejectedValue("raw string error"),
553
- );
554
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
555
- const sar = new SubprocessAgentRunner(deps);
556
-
557
- const result = await sar.run(makeBaseOpts(), new AbortController().signal);
558
- expect(result.error).toBe("raw string error");
559
- });
560
- });
561
-
562
- // ────────────────────────────────────────────────
563
- // U1: stream 透传给 executeAndAwait
564
- // ────────────────────────────────────────────────
565
- describe("U1 stream 透传", () => {
566
- it("SAR.run 传 stream → executeAndAwait 第 4 参收到同一 stream 对象", async () => {
567
- let capturedStream: unknown;
568
- const mockService = createMockService(
569
- vi.fn().mockImplementation((_opts, _sig, _onEvt, stream) => {
570
- capturedStream = stream;
571
- return Promise.resolve(makeMockResult());
572
- }),
573
- );
574
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
575
- const sar = new SubprocessAgentRunner(deps);
576
-
577
- const fakeStream = { onDelta: vi.fn(), dispose: vi.fn() };
578
- await sar.run(makeBaseOpts(), new AbortController().signal, undefined, fakeStream as never);
579
-
580
- expect(capturedStream).toBe(fakeStream);
581
- });
582
-
583
- it("SAR.run 不传 stream → executeAndAwait 第 4 参为 undefined", async () => {
584
- let capturedStream: unknown = "sentinel";
585
- const mockService = createMockService(
586
- vi.fn().mockImplementation((_opts, _sig, _onEvt, stream) => {
587
- capturedStream = stream;
588
- return Promise.resolve(makeMockResult());
589
- }),
590
- );
591
- const deps: SubprocessAgentRunnerDeps = { subagentService: mockService };
592
- const sar = new SubprocessAgentRunner(deps);
593
-
594
- await sar.run(makeBaseOpts(), new AbortController().signal);
595
-
596
- expect(capturedStream).toBeUndefined();
597
- });
598
- });
599
- });
@@ -1,53 +0,0 @@
1
- // src/__tests__/temp-prompt.test.ts
2
- import * as fs from "node:fs";
3
- import * as path from "node:path";
4
-
5
- import { describe, expect, it } from "vitest";
6
-
7
- import { cleanupTempPrompt, writePromptToTempFile } from "../temp-prompt.ts";
8
-
9
- describe("writePromptToTempFile", () => {
10
- it("创建临时目录 + 写入 prompt 文件", async () => {
11
- const result = await writePromptToTempFile("test-agent", "You are a helper.");
12
- expect(result.dir).toBeTruthy();
13
- expect(result.filePath).toBeTruthy();
14
- expect(fs.existsSync(result.dir)).toBe(true);
15
- expect(fs.existsSync(result.filePath)).toBe(true);
16
-
17
- const content = fs.readFileSync(result.filePath, "utf-8");
18
- expect(content).toBe("You are a helper.");
19
-
20
- // 清理
21
- await cleanupTempPrompt(result);
22
- expect(fs.existsSync(result.dir)).toBe(false);
23
- });
24
-
25
- it("agentName 非法字符替换为下划线", async () => {
26
- const result = await writePromptToTempFile("my agent/v2:spec", "prompt");
27
- expect(path.basename(result.filePath)).toBe("prompt-my_agent_v2_spec.md");
28
- await cleanupTempPrompt(result);
29
- });
30
-
31
- it("文件权限 0o600(仅 owner 读写)", async () => {
32
- const result = await writePromptToTempFile("secure", "secret prompt");
33
- const stat = fs.statSync(result.filePath);
34
- // 只取低 9 位(rwxrwxrwx),忽略文件类型位
35
- const mode = stat.mode & 0o777;
36
- expect(mode).toBe(0o600);
37
- await cleanupTempPrompt(result);
38
- });
39
-
40
- it("多字节内容(中文)正确写入", async () => {
41
- const result = await writePromptToTempFile("cn", "你是一个助手。");
42
- const content = fs.readFileSync(result.filePath, "utf-8");
43
- expect(content).toBe("你是一个助手。");
44
- await cleanupTempPrompt(result);
45
- });
46
- });
47
-
48
- describe("cleanupTempPrompt", () => {
49
- it("不存在的目录不抛错(best-effort)", async () => {
50
- const fake = { dir: "/nonexistent/path/xyz", filePath: "/nonexistent/path/xyz/p.md" };
51
- await expect(cleanupTempPrompt(fake)).resolves.not.toThrow();
52
- });
53
- });