@zhushanwen/subagent-core 0.2.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 (330) hide show
  1. package/README.md +114 -0
  2. package/dist/chunk-3VOERJPJ.js +22 -0
  3. package/dist/chunk-A4IVZWVX.js +31 -0
  4. package/dist/execution/engine/engines/zcode/constants.cjs +54 -0
  5. package/dist/execution/engine/engines/zcode/constants.d.cts +31 -0
  6. package/dist/execution/engine/engines/zcode/constants.d.ts +31 -0
  7. package/dist/execution/engine/engines/zcode/constants.js +22 -0
  8. package/dist/execution/engine/engines/zcode/reader.cjs +276 -0
  9. package/dist/execution/engine/engines/zcode/reader.d.cts +20 -0
  10. package/dist/execution/engine/engines/zcode/reader.d.ts +20 -0
  11. package/dist/execution/engine/engines/zcode/reader.js +239 -0
  12. package/dist/execution/engine/paths.cjs +55 -0
  13. package/dist/execution/engine/paths.d.cts +8 -0
  14. package/dist/execution/engine/paths.d.ts +8 -0
  15. package/dist/execution/engine/paths.js +26 -0
  16. package/dist/execution/relay-env.cjs +62 -0
  17. package/dist/execution/relay-env.d.cts +33 -0
  18. package/dist/execution/relay-env.d.ts +33 -0
  19. package/dist/execution/relay-env.js +20 -0
  20. package/dist/index.cjs +1852 -0
  21. package/dist/index.d.cts +1184 -0
  22. package/dist/index.d.ts +1184 -0
  23. package/dist/index.js +1810 -0
  24. package/dist/types-BxyAidGf.d.cts +875 -0
  25. package/dist/types-BxyAidGf.d.ts +875 -0
  26. package/package.json +99 -0
  27. package/src/__tests__/agent-opts-resolver-schema-prompt.test.ts +142 -0
  28. package/src/__tests__/append-system-prompt-assembly.test.ts +242 -0
  29. package/src/__tests__/builtin-workflows-structure.test.ts +180 -0
  30. package/src/__tests__/derive-closed-display-parity.test.ts +93 -0
  31. package/src/__tests__/fr4-get-state-handshake.test.ts +125 -0
  32. package/src/__tests__/fr8-orphan-recovery.test.ts +259 -0
  33. package/src/__tests__/m2-append-content-probe.test.ts +73 -0
  34. package/src/__tests__/manifest-store.test.ts +368 -0
  35. package/src/__tests__/record-store-cache.test.ts +335 -0
  36. package/src/__tests__/record-store-index.test.ts +560 -0
  37. package/src/__tests__/record-store-last-line.test.ts +129 -0
  38. package/src/__tests__/review-fix-loop-script.test.ts +288 -0
  39. package/src/__tests__/review-fix-loop-utils.test.ts +2377 -0
  40. package/src/__tests__/robustness-low-batch1.test.ts +286 -0
  41. package/src/__tests__/robustness-medium-batch1.test.ts +69 -0
  42. package/src/__tests__/robustness-medium-batch2.test.ts +65 -0
  43. package/src/__tests__/robustness-medium-batch3.test.ts +30 -0
  44. package/src/__tests__/robustness-medium-batch4.test.ts +358 -0
  45. package/src/__tests__/session-runner.test.ts +69 -0
  46. package/src/__tests__/smoke.test.ts +9 -0
  47. package/src/__tests__/stream-sink.test.ts +203 -0
  48. package/src/core/__tests__/host-services.test.ts +144 -0
  49. package/src/core/__tests__/logger.test.ts +78 -0
  50. package/src/core/__tests__/notify-ports.test.ts +104 -0
  51. package/src/core/host-services.ts +97 -0
  52. package/src/core/logger.ts +47 -0
  53. package/src/core/notify-ports.ts +126 -0
  54. package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +53 -0
  55. package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +1 -0
  56. package/src/execution/__tests__/agent-result-mapper.test.ts +150 -0
  57. package/src/execution/__tests__/alive-store.test.ts +147 -0
  58. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +490 -0
  59. package/src/execution/__tests__/channel-registry-handshake.test.ts +242 -0
  60. package/src/execution/__tests__/chat-engine-routing.test.ts +610 -0
  61. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +190 -0
  62. package/src/execution/__tests__/concurrency-pool.test.ts +250 -0
  63. package/src/execution/__tests__/config.test.ts +302 -0
  64. package/src/execution/__tests__/delivery-methods.test.ts +424 -0
  65. package/src/execution/__tests__/dialog-queue.test.ts +299 -0
  66. package/src/execution/__tests__/epipe-fallback.test.ts +241 -0
  67. package/src/execution/__tests__/execute-and-await-worktree.test.ts +243 -0
  68. package/src/execution/__tests__/execute-nesting.test.ts +323 -0
  69. package/src/execution/__tests__/execute-options-mapper.test.ts +200 -0
  70. package/src/execution/__tests__/execution-record.test.ts +1394 -0
  71. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +171 -0
  72. package/src/execution/__tests__/finalize-record.test.ts +367 -0
  73. package/src/execution/__tests__/finalized-marker.test.ts +104 -0
  74. package/src/execution/__tests__/format-schema-instruction.test.ts +169 -0
  75. package/src/execution/__tests__/gc-timer.test.ts +184 -0
  76. package/src/execution/__tests__/get-record-for-action-restart.test.ts +254 -0
  77. package/src/execution/__tests__/helpers/mock-extension-api.ts +30 -0
  78. package/src/execution/__tests__/helpers/spawn-mock.ts +242 -0
  79. package/src/execution/__tests__/host-mode.test.ts +87 -0
  80. package/src/execution/__tests__/lifecycle-manager-lock.test.ts +211 -0
  81. package/src/execution/__tests__/lifecycle-manager.test.ts +383 -0
  82. package/src/execution/__tests__/lifecycle-predicates.test.ts +116 -0
  83. package/src/execution/__tests__/manifest-parentid.test.ts +117 -0
  84. package/src/execution/__tests__/model-resolver.test.ts +465 -0
  85. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +287 -0
  86. package/src/execution/__tests__/nested-visibility.test.ts +325 -0
  87. package/src/execution/__tests__/output-collector.test.ts +358 -0
  88. package/src/execution/__tests__/path-encoding.test.ts +104 -0
  89. package/src/execution/__tests__/pi-invocation.test.ts +134 -0
  90. package/src/execution/__tests__/record-store.test.ts +1057 -0
  91. package/src/execution/__tests__/records-cwd-isolation.test.ts +91 -0
  92. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +339 -0
  93. package/src/execution/__tests__/recursive-visibility-env.test.ts +273 -0
  94. package/src/execution/__tests__/relay-env.test.ts +42 -0
  95. package/src/execution/__tests__/resource-policy.test.ts +109 -0
  96. package/src/execution/__tests__/rpc-mode.test.ts +89 -0
  97. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +267 -0
  98. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +253 -0
  99. package/src/execution/__tests__/run-spawn-edges.test.ts +687 -0
  100. package/src/execution/__tests__/run-spawn-integration.test.ts +933 -0
  101. package/src/execution/__tests__/run-spawn-resume.test.ts +322 -0
  102. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +196 -0
  103. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +199 -0
  104. package/src/execution/__tests__/session-context-resolver.test.ts +167 -0
  105. package/src/execution/__tests__/session-file-gc.test.ts +293 -0
  106. package/src/execution/__tests__/session-reconstructor.test.ts +379 -0
  107. package/src/execution/__tests__/session-runner-epipe.test.ts +178 -0
  108. package/src/execution/__tests__/session-runner-schema-env.test.ts +350 -0
  109. package/src/execution/__tests__/spawn-args.test.ts +445 -0
  110. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +189 -0
  111. package/src/execution/__tests__/spawn-event-adapter.test.ts +167 -0
  112. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +207 -0
  113. package/src/execution/__tests__/spawned-children.test.ts +92 -0
  114. package/src/execution/__tests__/start-sync-model-guard.test.ts +150 -0
  115. package/src/execution/__tests__/stdin-writer.test.ts +462 -0
  116. package/src/execution/__tests__/stream-sink-retirement.test.ts +261 -0
  117. package/src/execution/__tests__/subagent-service-abort.test.ts +60 -0
  118. package/src/execution/__tests__/subagent-service-message-close.test.ts +629 -0
  119. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +180 -0
  120. package/src/execution/__tests__/subagent-service.test.ts +788 -0
  121. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +310 -0
  122. package/src/execution/__tests__/subprocess-agent-runner.test.ts +612 -0
  123. package/src/execution/__tests__/temp-prompt.test.ts +53 -0
  124. package/src/execution/__tests__/timeout-integration.test.ts +615 -0
  125. package/src/execution/__tests__/tombstone-store.test.ts +73 -0
  126. package/src/execution/__tests__/turn-limiter-semantics.test.ts +194 -0
  127. package/src/execution/__tests__/turn-limiter.test.ts +65 -0
  128. package/src/execution/__tests__/ui-channels.test.ts +187 -0
  129. package/src/execution/__tests__/ui-interaction-model.test.ts +67 -0
  130. package/src/execution/__tests__/ui-request-handler-factory.test.ts +369 -0
  131. package/src/execution/__tests__/ui-request-handler.test.ts +204 -0
  132. package/src/execution/__tests__/ui-request-observability.test.ts +113 -0
  133. package/src/execution/__tests__/ui-request-queue.test.ts +133 -0
  134. package/src/execution/__tests__/worktree-manager.test.ts +633 -0
  135. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +229 -0
  136. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +181 -0
  137. package/src/execution/__tests__/worktree-registry.test.ts +199 -0
  138. package/src/execution/agent-registry.ts +199 -0
  139. package/src/execution/agent-result-mapper.ts +90 -0
  140. package/src/execution/alive-store.ts +119 -0
  141. package/src/execution/argv-mirror.ts +113 -0
  142. package/src/execution/best-effort.ts +38 -0
  143. package/src/execution/channel-registry-access.ts +144 -0
  144. package/src/execution/concurrency-pool.ts +116 -0
  145. package/src/execution/config.ts +165 -0
  146. package/src/execution/dialog-queue.ts +330 -0
  147. package/src/execution/engine/__tests__/common/data-dir.test.ts +78 -0
  148. package/src/execution/engine/__tests__/common/errors.test.ts +132 -0
  149. package/src/execution/engine/__tests__/common/event-journal.test.ts +177 -0
  150. package/src/execution/engine/__tests__/common/kill-chain.test.ts +192 -0
  151. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +81 -0
  152. package/src/execution/engine/__tests__/common/persona-router.test.ts +123 -0
  153. package/src/execution/engine/__tests__/common/pool-manager.test.ts +154 -0
  154. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +128 -0
  155. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +28 -0
  156. package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +141 -0
  157. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +109 -0
  158. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +101 -0
  159. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +77 -0
  160. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +104 -0
  161. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +201 -0
  162. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +76 -0
  163. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +79 -0
  164. package/src/execution/engine/__tests__/engine-discovery.test.ts +87 -0
  165. package/src/execution/engine/__tests__/model-prompt.test.ts +197 -0
  166. package/src/execution/engine/__tests__/paths.test.ts +39 -0
  167. package/src/execution/engine/__tests__/registry.test.ts +120 -0
  168. package/src/execution/engine/__tests__/routing.test.ts +231 -0
  169. package/src/execution/engine/common/data-dir.ts +66 -0
  170. package/src/execution/engine/common/errors.ts +183 -0
  171. package/src/execution/engine/common/event-journal.ts +254 -0
  172. package/src/execution/engine/common/journal-replay.ts +62 -0
  173. package/src/execution/engine/common/kill-chain.ts +221 -0
  174. package/src/execution/engine/common/nesting-guard.ts +50 -0
  175. package/src/execution/engine/common/persona-router.ts +108 -0
  176. package/src/execution/engine/common/pool-manager.ts +226 -0
  177. package/src/execution/engine/common/schema-emulation.ts +189 -0
  178. package/src/execution/engine/common/session-view-projection.ts +51 -0
  179. package/src/execution/engine/engine-discovery.ts +65 -0
  180. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +469 -0
  181. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +155 -0
  182. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +164 -0
  183. package/src/execution/engine/engines/pi/pi-engine.ts +415 -0
  184. package/src/execution/engine/engines/pi/reader.ts +48 -0
  185. package/src/execution/engine/engines/pi/registration.ts +35 -0
  186. package/src/execution/engine/engines/pi/task-spec-mapper.ts +100 -0
  187. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +39 -0
  188. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +150 -0
  189. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +246 -0
  190. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +228 -0
  191. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +210 -0
  192. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +71 -0
  193. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +127 -0
  194. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +580 -0
  195. package/src/execution/engine/engines/zcode/constants.ts +43 -0
  196. package/src/execution/engine/engines/zcode/golden-sample.ts +39 -0
  197. package/src/execution/engine/engines/zcode/launcher.ts +161 -0
  198. package/src/execution/engine/engines/zcode/parser.ts +436 -0
  199. package/src/execution/engine/engines/zcode/preparer.ts +363 -0
  200. package/src/execution/engine/engines/zcode/reader.ts +381 -0
  201. package/src/execution/engine/engines/zcode/registration.ts +37 -0
  202. package/src/execution/engine/engines/zcode/zcode-engine.ts +658 -0
  203. package/src/execution/engine/host-task-spec.ts +47 -0
  204. package/src/execution/engine/model-prompt.ts +158 -0
  205. package/src/execution/engine/paths.ts +42 -0
  206. package/src/execution/engine/port.ts +153 -0
  207. package/src/execution/engine/registry.ts +133 -0
  208. package/src/execution/engine/routing.ts +218 -0
  209. package/src/execution/engine/types.ts +309 -0
  210. package/src/execution/execute-options-mapper.ts +115 -0
  211. package/src/execution/execution-record.ts +984 -0
  212. package/src/execution/finalize-record.ts +254 -0
  213. package/src/execution/finalized-marker.ts +70 -0
  214. package/src/execution/get-state-handshake.ts +104 -0
  215. package/src/execution/host-mode.ts +56 -0
  216. package/src/execution/idle-gc.ts +47 -0
  217. package/src/execution/lifecycle-manager.ts +513 -0
  218. package/src/execution/lifecycle-predicates.ts +65 -0
  219. package/src/execution/manifest-store.ts +256 -0
  220. package/src/execution/model-config-service.ts +250 -0
  221. package/src/execution/model-resolver.ts +248 -0
  222. package/src/execution/notifier.ts +372 -0
  223. package/src/execution/notify-ledger.ts +580 -0
  224. package/src/execution/output-collector.ts +228 -0
  225. package/src/execution/path-encoding.ts +60 -0
  226. package/src/execution/pi-invocation.ts +120 -0
  227. package/src/execution/record-entry.ts +132 -0
  228. package/src/execution/record-store.ts +1265 -0
  229. package/src/execution/relay-env.ts +37 -0
  230. package/src/execution/session-context-resolver.ts +64 -0
  231. package/src/execution/session-file-gc.ts +120 -0
  232. package/src/execution/session-pending.ts +170 -0
  233. package/src/execution/session-reconstructor.ts +678 -0
  234. package/src/execution/session-runner.ts +1789 -0
  235. package/src/execution/sessions-index.ts +304 -0
  236. package/src/execution/spawn-event-adapter.ts +363 -0
  237. package/src/execution/stdin-writer.ts +198 -0
  238. package/src/execution/stream-sink.ts +126 -0
  239. package/src/execution/subagent-service.ts +2268 -0
  240. package/src/execution/subprocess-agent-runner.ts +317 -0
  241. package/src/execution/temp-prompt.ts +62 -0
  242. package/src/execution/tombstone-store.ts +72 -0
  243. package/src/execution/turn-limiter.ts +102 -0
  244. package/src/execution/types.ts +1023 -0
  245. package/src/execution/ui-channels.ts +216 -0
  246. package/src/execution/ui-interaction-model.ts +48 -0
  247. package/src/execution/ui-request-handler-factory.ts +243 -0
  248. package/src/execution/ui-request-observability.ts +81 -0
  249. package/src/execution/ui-request-queue.ts +184 -0
  250. package/src/execution/worktree-manager.ts +688 -0
  251. package/src/execution/worktree-registry.ts +279 -0
  252. package/src/index.ts +87 -0
  253. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +349 -0
  254. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +202 -0
  255. package/src/orchestration/__tests__/agent-call-stream.test.ts +152 -0
  256. package/src/orchestration/__tests__/args-validator.test.ts +143 -0
  257. package/src/orchestration/__tests__/config-loader.test.ts +503 -0
  258. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +809 -0
  259. package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +404 -0
  260. package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +56 -0
  261. package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +166 -0
  262. package/src/orchestration/__tests__/execute-agent-call.test.ts +451 -0
  263. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +600 -0
  264. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +96 -0
  265. package/src/orchestration/__tests__/lifecycle.test.ts +659 -0
  266. package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +95 -0
  267. package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +183 -0
  268. package/src/orchestration/__tests__/script-lint.test.ts +831 -0
  269. package/src/orchestration/__tests__/skill-discovery.test.ts +210 -0
  270. package/src/orchestration/__tests__/test-mocks.ts +197 -0
  271. package/src/orchestration/__tests__/worker-exit-without-result.test.ts +368 -0
  272. package/src/orchestration/__tests__/worker-host.test.ts +120 -0
  273. package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +164 -0
  274. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +563 -0
  275. package/src/orchestration/__tests__/worker-script-builder.test.ts +309 -0
  276. package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +129 -0
  277. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +317 -0
  278. package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +110 -0
  279. package/src/orchestration/agent-opts-resolver.ts +174 -0
  280. package/src/orchestration/args-validator.ts +127 -0
  281. package/src/orchestration/config-loader.ts +316 -0
  282. package/src/orchestration/error-recovery.ts +1018 -0
  283. package/src/orchestration/execute-agent-call.ts +256 -0
  284. package/src/orchestration/launcher.ts +455 -0
  285. package/src/orchestration/lifecycle.ts +399 -0
  286. package/src/orchestration/models/__tests__/budget.test.ts +307 -0
  287. package/src/orchestration/models/agent-call.ts +83 -0
  288. package/src/orchestration/models/budget.ts +118 -0
  289. package/src/orchestration/models/ports.ts +164 -0
  290. package/src/orchestration/models/run-runtime.ts +104 -0
  291. package/src/orchestration/models/run-spec.ts +83 -0
  292. package/src/orchestration/models/run-state.ts +44 -0
  293. package/src/orchestration/models/trace.ts +183 -0
  294. package/src/orchestration/models/types.ts +301 -0
  295. package/src/orchestration/models/workflow-run.ts +254 -0
  296. package/src/orchestration/models/workflow-script-registry.ts +35 -0
  297. package/src/orchestration/models/workflow-script.ts +117 -0
  298. package/src/orchestration/script-lint.ts +766 -0
  299. package/src/orchestration/skill-discovery.ts +135 -0
  300. package/src/orchestration/worker-handle.ts +115 -0
  301. package/src/orchestration/worker-host.ts +98 -0
  302. package/src/orchestration/worker-script-builder.ts +421 -0
  303. package/src/orchestration/workflow-files.ts +85 -0
  304. package/src/orchestration/workflow-script-registry-impl.ts +133 -0
  305. package/src/shared/__tests__/agent-ref.test.ts +34 -0
  306. package/src/shared/__tests__/meta-parser.test.ts +304 -0
  307. package/src/shared/__tests__/model-ref.test.ts +306 -0
  308. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +288 -0
  309. package/src/shared/__tests__/resource-discovery.test.ts +749 -0
  310. package/src/shared/__tests__/resource-meta.test.ts +51 -0
  311. package/src/shared/__tests__/schema-jsonify.test.ts +81 -0
  312. package/src/shared/__tests__/timer-delay.test.ts +61 -0
  313. package/src/shared/agent-event.ts +13 -0
  314. package/src/shared/agent-ref.ts +57 -0
  315. package/src/shared/meta-parser.ts +261 -0
  316. package/src/shared/model-ref.ts +286 -0
  317. package/src/shared/resource-discovery.ts +835 -0
  318. package/src/shared/resource-meta.ts +65 -0
  319. package/src/shared/schema-env.ts +44 -0
  320. package/src/shared/schema-jsonify.ts +58 -0
  321. package/src/shared/timer-delay.ts +54 -0
  322. package/src/shared/xml-injection.ts +35 -0
  323. package/workflows/README.md +81 -0
  324. package/workflows/_shared/agent-refs.cjs +40 -0
  325. package/workflows/chain.js +137 -0
  326. package/workflows/map-reduce.js +180 -0
  327. package/workflows/parallel.js +154 -0
  328. package/workflows/review-fix-loop-utils.cjs +1542 -0
  329. package/workflows/review-fix-loop.js +1605 -0
  330. package/workflows/scatter-gather.js +184 -0
@@ -0,0 +1,451 @@
1
+ // src/orchestration/__tests__/execute-agent-call.test.ts
2
+ //
3
+ // U2: executeAgentCall 透传 stream 给 runner.run
4
+ // U3: executeAgentCall retry 递归也透传 stream(不丢、不重建)
5
+
6
+ import { describe, expect, it, vi } from "vitest";
7
+
8
+ import {
9
+ DETERMINISTIC_SCHEMA_FAILURE_PREFIX,
10
+ executeAgentCall,
11
+ isDeterministicSchemaFailureMsg,
12
+ isStaleContextErrorMsg,
13
+ STALE_CONTEXT_PATTERNS,
14
+ } from "../execute-agent-call.ts";
15
+ import { AgentCall } from "../models/agent-call.ts";
16
+ import { Budget } from "../models/budget.ts";
17
+ import type { AgentRunner } from "../models/ports.ts";
18
+ import { describeMissingParsedOutput } from "../../execution/output-collector.ts";
19
+ import type { ToolCall } from "../../execution/types.ts";
20
+ import { Trace } from "../models/trace.ts";
21
+ import type { ExecutionTraceNode } from "../models/types.ts";
22
+ import type { AgentCallOpts, AgentResult } from "../models/types.ts";
23
+
24
+ // ── 测试辅助 ──
25
+
26
+ function makeMockResult(overrides: Partial<AgentResult> = {}): AgentResult {
27
+ return {
28
+ content: "OK",
29
+ durationMs: 100,
30
+ error: undefined,
31
+ toolCalls: [],
32
+ ...overrides,
33
+ };
34
+ }
35
+
36
+ function makeBaseOpts(): AgentCallOpts {
37
+ return {
38
+ prompt: "test task",
39
+ agent: "worker",
40
+ cwd: "/some/path",
41
+ } as AgentCallOpts;
42
+ }
43
+
44
+ /** 构造一个 traceNode(ExecutionTraceNode 最小子集) */
45
+ function makeTraceNode(stepIndex = 0): ExecutionTraceNode {
46
+ return {
47
+ stepIndex,
48
+ agent: "test-agent",
49
+ task: "test task",
50
+ model: "default",
51
+ status: "pending",
52
+ };
53
+ }
54
+
55
+ /** 构造 AgentCall + 关联的 Trace(call.id 与 trace 节点 stepIndex 对齐) */
56
+ function makeAgentCallAndTrace(): { call: AgentCall; trace: Trace } {
57
+ const trace = new Trace();
58
+ const traceNode = makeTraceNode(0);
59
+ trace.append(traceNode);
60
+ const call = new AgentCall(0, makeBaseOpts(), traceNode);
61
+ return { call, trace };
62
+ }
63
+
64
+ /** 创建 mock AgentRunner(只实现 run) */
65
+ function createMockRunner(impl?: ReturnType<typeof vi.fn>): AgentRunner & { run: ReturnType<typeof vi.fn> } {
66
+ const run = impl ?? vi.fn().mockResolvedValue(makeMockResult());
67
+ return { run } as unknown as AgentRunner & { run: ReturnType<typeof vi.fn> };
68
+ }
69
+
70
+ // ── U2: executeAgentCall 透传 stream 给 runner.run ──
71
+
72
+ describe("U2: executeAgentCall 透传 stream", () => {
73
+ it("executeAgentCall 传 stream → runner.run 第 4 参收到同一 stream", async () => {
74
+ let capturedStream: unknown;
75
+ const runner = createMockRunner(
76
+ vi.fn().mockImplementation((_opts, _sig, _onEvt, stream) => {
77
+ capturedStream = stream;
78
+ return Promise.resolve(makeMockResult());
79
+ }),
80
+ );
81
+
82
+ const fakeStream = { onDelta: vi.fn(), dispose: vi.fn() };
83
+ const { call, trace } = makeAgentCallAndTrace();
84
+ const budget = new Budget();
85
+
86
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace, undefined, fakeStream as never);
87
+
88
+ expect(capturedStream).toBe(fakeStream);
89
+ });
90
+
91
+ it("executeAgentCall 不传 stream → runner.run 第 4 参为 undefined", async () => {
92
+ let capturedStream: unknown = "sentinel";
93
+ const runner = createMockRunner(
94
+ vi.fn().mockImplementation((_opts, _sig, _onEvt, stream) => {
95
+ capturedStream = stream;
96
+ return Promise.resolve(makeMockResult());
97
+ }),
98
+ );
99
+
100
+ const { call, trace } = makeAgentCallAndTrace();
101
+ const budget = new Budget();
102
+
103
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace);
104
+
105
+ expect(capturedStream).toBeUndefined();
106
+ });
107
+ });
108
+
109
+ // ── U1: finalizeCall 透传 sessionFile 到 trace 节点(方案 A)──
110
+
111
+ describe("U1: finalizeCall sessionFile → trace 节点", () => {
112
+ it("runner.run 返回带 sessionFile 的 result → trace 节点携带 sessionFile", async () => {
113
+ const sessionFilePath = "/abs/.pi/agent/subagents/enc/sessions/2026-07-15T_session-abc.jsonl";
114
+ const runner = createMockRunner(
115
+ vi.fn().mockResolvedValue(
116
+ makeMockResult({ sessionId: "session-abc", sessionFile: sessionFilePath }),
117
+ ),
118
+ );
119
+ const { call, trace } = makeAgentCallAndTrace();
120
+ const budget = new Budget();
121
+
122
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace);
123
+
124
+ const node = trace.find(0);
125
+ expect(node).toBeDefined();
126
+ expect(node!.sessionFile).toBe(sessionFilePath);
127
+ expect(node!.sessionId).toBe("session-abc");
128
+ });
129
+
130
+ it("runner.run 返回无 sessionFile 的 result → trace 节点 sessionFile undefined", async () => {
131
+ const runner = createMockRunner(
132
+ vi.fn().mockResolvedValue(makeMockResult({ sessionId: "session-xyz" })),
133
+ );
134
+ const { call, trace } = makeAgentCallAndTrace();
135
+ const budget = new Budget();
136
+
137
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace);
138
+
139
+ const node = trace.find(0);
140
+ expect(node).toBeDefined();
141
+ expect(node!.sessionFile).toBeUndefined();
142
+ });
143
+ });
144
+
145
+ // ── U3: retry 递归也透传 stream ──
146
+
147
+ describe("U3: executeAgentCall retry 透传 stream", () => {
148
+ it("首次 runner.run 返回 error → retry 时第 4 参仍是同一 stream", async () => {
149
+ vi.useFakeTimers();
150
+
151
+ const capturedStreams: unknown[] = [];
152
+ const runner = createMockRunner(
153
+ vi.fn().mockImplementation((_opts, _sig, _onEvt, stream) => {
154
+ capturedStreams.push(stream);
155
+ // 首次 error,第二次成功
156
+ if (capturedStreams.length === 1) {
157
+ return Promise.resolve(makeMockResult({ error: "transient error" }));
158
+ }
159
+ return Promise.resolve(makeMockResult());
160
+ }),
161
+ );
162
+
163
+ const fakeStream = { onDelta: vi.fn(), dispose: vi.fn() };
164
+ const { call, trace } = makeAgentCallAndTrace();
165
+ const budget = new Budget();
166
+
167
+ const promise = executeAgentCall(call, runner, budget, new AbortController().signal, trace, undefined, fakeStream as never);
168
+ // 推进 retry 退避定时器(BACKOFF_BASE_MS = 1000,首退避 1s)
169
+ await vi.advanceTimersByTimeAsync(2000);
170
+ await promise;
171
+
172
+ expect(runner.run).toHaveBeenCalledTimes(2);
173
+ // 两次调用的第 4 参都是同一 stream 对象
174
+ expect(capturedStreams[0]).toBe(fakeStream);
175
+ expect(capturedStreams[1]).toBe(fakeStream);
176
+
177
+ vi.useRealTimers();
178
+ });
179
+ });
180
+
181
+ // ── isOrphaned 守卫(OB2:S7 残留瞬时污染根除) ──
182
+ //
183
+ // 谓词为 true 时 finalizeCall 跳过 trace.update,但 markDone 与
184
+ // sessionId/sessionFile 同步保留。U4 锁定不传谓词时的现状回归。
185
+
186
+ describe("isOrphaned 守卫", () => {
187
+ it("U1: 谓词 () => true + 终态成功路径 → trace.update 0 次,markDone 保留(status done + result 已设置)", async () => {
188
+ const { call, trace } = makeAgentCallAndTrace();
189
+ const updateSpy = vi.spyOn(trace, "update");
190
+ const runner = createMockRunner(); // 默认成功 result
191
+ const budget = new Budget();
192
+
193
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace, undefined, undefined, () => true);
194
+
195
+ expect(updateSpy).not.toHaveBeenCalled();
196
+ expect(call.status).toBe("done");
197
+ expect(call.result).toBeDefined();
198
+ expect(call.result?.content).toBe("OK");
199
+ });
200
+
201
+ it("U2: 谓词 true + stale-context 失败路径 → trace.update 0 次,markDone 保留(覆盖 stale finalize 调用点)", async () => {
202
+ const { call, trace } = makeAgentCallAndTrace();
203
+ const updateSpy = vi.spyOn(trace, "update");
204
+ const runner = createMockRunner(
205
+ vi.fn().mockResolvedValue(makeMockResult({ error: "context canceled" })),
206
+ );
207
+ const budget = new Budget();
208
+
209
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace, undefined, undefined, () => true);
210
+
211
+ expect(updateSpy).not.toHaveBeenCalled();
212
+ expect(call.status).toBe("done");
213
+ expect(call.result?.error).toBe("context canceled");
214
+ });
215
+
216
+ it("U3: 谓词 true + 信号 abort 路径 → trace.update 0 次,markDone 保留(覆盖 abort finalize 调用点)", async () => {
217
+ const { call, trace } = makeAgentCallAndTrace();
218
+ const updateSpy = vi.spyOn(trace, "update");
219
+ // 错误文案不含 stale 模式词,确保走 signal.aborted 分支而非 stale 分支
220
+ const runner = createMockRunner(
221
+ vi.fn().mockResolvedValue(makeMockResult({ error: "old generation failure" })),
222
+ );
223
+ const controller = new AbortController();
224
+ controller.abort();
225
+ const budget = new Budget();
226
+
227
+ await executeAgentCall(call, runner, budget, controller.signal, trace, undefined, undefined, () => true);
228
+
229
+ expect(updateSpy).not.toHaveBeenCalled();
230
+ expect(call.status).toBe("done");
231
+ expect(call.result?.error).toBe("old generation failure");
232
+ });
233
+
234
+ it("U4: 谓词 undefined(不传)→ trace.update 恰被调用 1 次(现状回归锁定)", async () => {
235
+ const { call, trace } = makeAgentCallAndTrace();
236
+ const updateSpy = vi.spyOn(trace, "update");
237
+ const runner = createMockRunner();
238
+ const budget = new Budget();
239
+
240
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace);
241
+
242
+ expect(updateSpy).toHaveBeenCalledTimes(1);
243
+ expect(trace.find(0)?.status).toBe("completed");
244
+ expect(call.status).toBe("done");
245
+ });
246
+
247
+ it("U5: 递归重试透传——可重试失败后成功,谓词 true → 重试后终态 trace.update 仍 0 次", async () => {
248
+ vi.useFakeTimers();
249
+ try {
250
+ const { call, trace } = makeAgentCallAndTrace();
251
+ const updateSpy = vi.spyOn(trace, "update");
252
+ const runner = createMockRunner(
253
+ vi.fn()
254
+ .mockResolvedValueOnce(makeMockResult({ error: "transient error" }))
255
+ .mockResolvedValueOnce(makeMockResult()),
256
+ );
257
+ const budget = new Budget();
258
+
259
+ const promise = executeAgentCall(call, runner, budget, new AbortController().signal, trace, undefined, undefined, () => true);
260
+ // 推进首退避 1s(BACKOFF_BASE_MS = 1000)
261
+ await vi.advanceTimersByTimeAsync(2000);
262
+ await promise;
263
+
264
+ expect(runner.run).toHaveBeenCalledTimes(2);
265
+ expect(call.attempts).toBe(2);
266
+ // 谓词穿透递归层:重试后终态也不写 trace
267
+ expect(updateSpy).not.toHaveBeenCalled();
268
+ expect(call.status).toBe("done");
269
+ expect(call.result?.error).toBeUndefined();
270
+ } finally {
271
+ vi.useRealTimers();
272
+ }
273
+ });
274
+ });
275
+
276
+ // ── W4b: STALE_CONTEXT_PATTERNS 对齐 pi 真实文案(stale 分诊) ──
277
+ //
278
+ // pi 0.84.x 真实 stale 文案(extensions/runner.ts:531,dist runner.js:567):
279
+ // "This extension ctx is stale after session replacement or reload. Do not use
280
+ // a captured pi or command ctx after ctx.newSession(), ..."
281
+ // 旧 patterns("stale context"/"stalecontext")与该文案零匹配(词序相反),
282
+ // stale 错误曾退化为普通错误照常重试 3 次——W4b 词序修正 + 对齐 scheduler
283
+ // 已验证 marker 'stale after session replacement'(runtime.ts STALE_CTX_MARKER)。
284
+
285
+ /** pi 真实 stale 文案前半(含 marker 全文前缀,锚定真实串而非自造缩写)。 */
286
+ const PI_REAL_STALE_MESSAGE =
287
+ "This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload().";
288
+
289
+ describe("W4b: stale 分诊对齐 pi 真实文案", () => {
290
+ it("真实文案全文 → isStaleContextErrorMsg true('ctx is stale' 词序 + scheduler marker 双命中)", () => {
291
+ expect(isStaleContextErrorMsg(PI_REAL_STALE_MESSAGE)).toBe(true);
292
+ });
293
+
294
+ it("patterns 含 scheduler 已验证 marker 'stale after session replacement'", () => {
295
+ expect(STALE_CONTEXT_PATTERNS).toContain("stale after session replacement");
296
+ expect(STALE_CONTEXT_PATTERNS).toContain("ctx is stale");
297
+ });
298
+
299
+ it("真实文案 → executeAgentCall 不重试(runner.run 恰 1 次)+ markDone failed", async () => {
300
+ const { call, trace } = makeAgentCallAndTrace();
301
+ const runner = createMockRunner(
302
+ vi.fn().mockResolvedValue(makeMockResult({ error: PI_REAL_STALE_MESSAGE })),
303
+ );
304
+ const budget = new Budget();
305
+
306
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace);
307
+
308
+ expect(runner.run).toHaveBeenCalledTimes(1);
309
+ expect(call.status).toBe("done");
310
+ expect(call.result?.error).toBe(PI_REAL_STALE_MESSAGE);
311
+ expect(trace.find(0)?.status).toBe("failed");
312
+ });
313
+
314
+ it("普通 transient 错误 → 不命中 stale(照常进入重试路径,现状回归)", () => {
315
+ expect(isStaleContextErrorMsg("transient network error")).toBe(false);
316
+ expect(isStaleContextErrorMsg(undefined)).toBe(false);
317
+ });
318
+ });
319
+
320
+ // ── MF-1: 确定性 schema 失败不重试 ──
321
+ //
322
+ // 回归背景(第五轮实测):gate 终止子进程后 collectResult F-1 置归因 error →
323
+ // executeAgentCall 判非 stale 走可重试分支 → 不可满足 schema 下循环至
324
+ // MAX_ATTEMPTS=3(实测 attempts=3、4 子进程、235s vs 修复前 67.3s)。
325
+ // 修复:归因 error 带机器标记(SSOT = DETERMINISTIC_SCHEMA_FAILURE_PREFIX),
326
+ // 分诊短路。用真实链路产物(describeMissingParsedOutput)作 error 输入,锁定
327
+ // collectResult → executeAgentCall 全链路分诊行为。
328
+ //
329
+ // 三态可重试性矩阵(完整锁定在 output-collector.test 的 MF-1 describe):
330
+ // 态① 从未调用 SO → 不可重试;态② isError(gate 终止/不可满足 schema)→ 不可重试;
331
+ // 态③ 调用过但无 details → 可重试(保留既有重试语义)。
332
+
333
+ /** 构造态②真实产物(isError SO 调用,schema 校验失败——gate 终止回归场景)。 */
334
+ function state2Attribution(): string {
335
+ const soCalls: ToolCall[] = [
336
+ {
337
+ toolName: "structured-output",
338
+ isError: true,
339
+ result: { details: {}, content: [{ type: "text", text: "Schema validation failed: /target is required" }] },
340
+ },
341
+ ];
342
+ const msg = describeMissingParsedOutput(soCalls);
343
+ expect(msg).toBeDefined();
344
+ return msg!;
345
+ }
346
+
347
+ describe("MF-1: 确定性 schema 失败不重试", () => {
348
+ it("态②真实产物(gate 终止/schema 校验失败归因)→ runner.run 恰 1 次 + 终态 failed", async () => {
349
+ const attribution = state2Attribution();
350
+ expect(isDeterministicSchemaFailureMsg(attribution)).toBe(true);
351
+
352
+ const { call, trace } = makeAgentCallAndTrace();
353
+ const runner = createMockRunner(
354
+ vi.fn().mockResolvedValue(makeMockResult({ error: attribution })),
355
+ );
356
+ const budget = new Budget();
357
+
358
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace);
359
+
360
+ // 修复前:循环至 MAX_ATTEMPTS=3(4 次子进程);修复后:恰 1 次
361
+ expect(runner.run).toHaveBeenCalledTimes(1);
362
+ expect(call.attempts).toBe(1);
363
+ expect(call.status).toBe("done");
364
+ expect(trace.find(0)?.status).toBe("failed");
365
+ });
366
+
367
+ it("态①真实产物(never called,缺 extension 环境确定性)→ 同样不重试", async () => {
368
+ const attribution = describeMissingParsedOutput([])!;
369
+ const { call, trace } = makeAgentCallAndTrace();
370
+ const runner = createMockRunner(
371
+ vi.fn().mockResolvedValue(makeMockResult({ error: attribution })),
372
+ );
373
+ const budget = new Budget();
374
+
375
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace);
376
+
377
+ expect(runner.run).toHaveBeenCalledTimes(1);
378
+ expect(call.attempts).toBe(1);
379
+ expect(trace.find(0)?.status).toBe("failed");
380
+ });
381
+
382
+ it("MF-2 计数不再低估:retry 不发生 → usage consume 恰一次、totalCallCount=1", async () => {
383
+ const attribution = state2Attribution();
384
+ const { call, trace } = makeAgentCallAndTrace();
385
+ const runner = createMockRunner(
386
+ vi.fn().mockResolvedValue(
387
+ makeMockResult({ error: attribution, usage: { input: 100, output: 50, cost: 0.01 } }),
388
+ ),
389
+ );
390
+ const budget = new Budget();
391
+
392
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace);
393
+
394
+ // 修复前:3 attempts → consume×3(usedTokens×3);修复后:恰一次加权消耗
395
+ // (input×1 + output×2 = 100 + 100 = 200,权重见 budget.ts)
396
+ expect(budget.usedTokens).toBe(200);
397
+ expect(budget.usedCost).toBeCloseTo(0.01);
398
+ expect(budget.totalCallCount).toBe(1);
399
+ });
400
+
401
+ it("MF-3 归因不再混合:终态 error 保持归因原文(不被重试轮次覆盖)", async () => {
402
+ const attribution = state2Attribution();
403
+ const { call, trace } = makeAgentCallAndTrace();
404
+ const runner = createMockRunner(
405
+ vi.fn().mockResolvedValue(makeMockResult({ error: attribution })),
406
+ );
407
+ const budget = new Budget();
408
+
409
+ await executeAgentCall(call, runner, budget, new AbortController().signal, trace);
410
+
411
+ expect(call.result?.error).toBe(attribution);
412
+ });
413
+
414
+ it("态③(no details,无标记)→ 照常重试(可重试语义保留)", async () => {
415
+ vi.useFakeTimers();
416
+ try {
417
+ // 态③真实文案(不带确定性标记)——矩阵执行面锁定:无标记 = 可重试
418
+ const msg = describeMissingParsedOutput([
419
+ { toolName: "structured-output", result: { content: [] } },
420
+ ])!;
421
+ expect(isDeterministicSchemaFailureMsg(msg)).toBe(false);
422
+
423
+ const { call, trace } = makeAgentCallAndTrace();
424
+ const runner = createMockRunner(
425
+ vi.fn()
426
+ .mockResolvedValueOnce(makeMockResult({ error: msg }))
427
+ .mockResolvedValueOnce(makeMockResult()),
428
+ );
429
+ const budget = new Budget();
430
+
431
+ const promise = executeAgentCall(call, runner, budget, new AbortController().signal, trace);
432
+ await vi.advanceTimersByTimeAsync(2000);
433
+ await promise;
434
+
435
+ expect(runner.run).toHaveBeenCalledTimes(2);
436
+ expect(call.status).toBe("done");
437
+ } finally {
438
+ vi.useRealTimers();
439
+ }
440
+ });
441
+
442
+ it("分诊交叉锁定:标记词不命中任何 STALE_CONTEXT_PATTERNS(stale 分诊在前也不误吞)", () => {
443
+ const lower = DETERMINISTIC_SCHEMA_FAILURE_PREFIX.toLowerCase();
444
+ for (const pattern of STALE_CONTEXT_PATTERNS) {
445
+ expect(lower.includes(pattern)).toBe(false);
446
+ }
447
+ // 两个分诊只命中确定性分支,互不污染
448
+ expect(isStaleContextErrorMsg(DETERMINISTIC_SCHEMA_FAILURE_PREFIX)).toBe(false);
449
+ expect(isDeterministicSchemaFailureMsg(DETERMINISTIC_SCHEMA_FAILURE_PREFIX)).toBe(true);
450
+ });
451
+ });