@zhushanwen/pi-subagent-workflow 8.5.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 (336) hide show
  1. package/package.json +13 -16
  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 +142 -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 +157 -0
  16. package/src/interface/__tests__/subagent-tool-prompt.test.ts +12 -0
  17. package/src/interface/__tests__/tool-workflow-script-generate.test.ts +2 -2
  18. package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +1 -1
  19. package/src/interface/bg-notify-render.ts +34 -13
  20. package/src/interface/commands.ts +3 -3
  21. package/src/interface/format.ts +2 -2
  22. package/src/interface/helpers.ts +3 -3
  23. package/src/interface/list-component.ts +4 -4
  24. package/src/interface/list-shared.ts +2 -2
  25. package/src/interface/list-view.ts +2 -2
  26. package/src/interface/subagent-actions.ts +288 -19
  27. package/src/interface/subagent-tool-schema.ts +163 -0
  28. package/src/interface/subagent-tool.ts +65 -129
  29. package/src/interface/subagents.ts +5 -5
  30. package/src/interface/tool-render.ts +34 -2
  31. package/src/interface/tool-workflow-script.ts +4 -4
  32. package/src/interface/tool-workflow.ts +6 -6
  33. package/src/interface/views/WorkflowsView.ts +5 -5
  34. package/src/interface/views/__tests__/WorkflowsView-signature.test.ts +3 -3
  35. package/src/interface/views/__tests__/detail-content-session-file.test.ts +2 -2
  36. package/src/interface/views/detail-content.ts +4 -4
  37. package/src/interface/views/format.ts +4 -4
  38. package/src/{orchestration/jsonl-run-store.ts → jsonl-run-store.ts} +132 -18
  39. package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +0 -53
  40. package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +0 -1
  41. package/src/execution/__tests__/agent-registry.test.ts +0 -363
  42. package/src/execution/__tests__/agent-result-mapper.test.ts +0 -150
  43. package/src/execution/__tests__/alive-store.test.ts +0 -147
  44. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  45. package/src/execution/__tests__/before-agent-start-injection.test.ts +0 -132
  46. package/src/execution/__tests__/bg-notify-render.test.ts +0 -256
  47. package/src/execution/__tests__/channel-registry-handshake.test.ts +0 -243
  48. package/src/execution/__tests__/chat-engine-routing.test.ts +0 -597
  49. package/src/execution/__tests__/chatmode-first-round-closure-service.test.ts +0 -365
  50. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -190
  51. package/src/execution/__tests__/chatmode-round-notify-real-chain.test.ts +0 -215
  52. package/src/execution/__tests__/concurrency-pool.test.ts +0 -250
  53. package/src/execution/__tests__/config.test.ts +0 -110
  54. package/src/execution/__tests__/conversation-wiring.test.ts +0 -198
  55. package/src/execution/__tests__/crash-recovery.test.ts +0 -320
  56. package/src/execution/__tests__/delivery-methods.test.ts +0 -385
  57. package/src/execution/__tests__/dialog-queue.test.ts +0 -299
  58. package/src/execution/__tests__/epipe-fallback.test.ts +0 -241
  59. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -243
  60. package/src/execution/__tests__/execute-nesting.test.ts +0 -323
  61. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -189
  62. package/src/execution/__tests__/execution-record.test.ts +0 -1284
  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 -138
  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 -238
  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 -593
  75. package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
  76. package/src/execution/__tests__/lifecycle-manager.test.ts +0 -337
  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 -109
  80. package/src/execution/__tests__/manifest-parentid.test.ts +0 -117
  81. package/src/execution/__tests__/model-resolver.test.ts +0 -413
  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 -574
  85. package/src/execution/__tests__/notifier-golden-snapshot.test.ts +0 -261
  86. package/src/execution/__tests__/one-shot-upgrade.test.ts +0 -205
  87. package/src/execution/__tests__/output-collector.test.ts +0 -61
  88. package/src/execution/__tests__/parent-child-matrix.test.ts +0 -336
  89. package/src/execution/__tests__/path-encoding.test.ts +0 -104
  90. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  91. package/src/execution/__tests__/record-store.test.ts +0 -1057
  92. package/src/execution/__tests__/records-cwd-isolation.test.ts +0 -91
  93. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +0 -339
  94. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -273
  95. package/src/execution/__tests__/relay-agent.test.ts +0 -448
  96. package/src/execution/__tests__/relay-env.test.ts +0 -42
  97. package/src/execution/__tests__/resource-policy.test.ts +0 -109
  98. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  99. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -267
  100. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -253
  101. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -644
  102. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  103. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  104. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  105. package/src/execution/__tests__/sdk-contract.test.ts +0 -273
  106. package/src/execution/__tests__/session-context-resolver.test.ts +0 -167
  107. package/src/execution/__tests__/session-file-gc.test.ts +0 -293
  108. package/src/execution/__tests__/session-pending.test.ts +0 -197
  109. package/src/execution/__tests__/session-reconstructor.test.ts +0 -379
  110. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -178
  111. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -311
  112. package/src/execution/__tests__/session-start-reaper.test.ts +0 -233
  113. package/src/execution/__tests__/spawn-args.test.ts +0 -434
  114. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -189
  115. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  116. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -207
  117. package/src/execution/__tests__/spawned-children.test.ts +0 -92
  118. package/src/execution/__tests__/startup-config-declaration.test.ts +0 -35
  119. package/src/execution/__tests__/status-refactor.test.ts +0 -345
  120. package/src/execution/__tests__/stdin-writer.test.ts +0 -463
  121. package/src/execution/__tests__/stream-sink-retirement.test.ts +0 -261
  122. package/src/execution/__tests__/subagent-service-abort.test.ts +0 -60
  123. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -629
  124. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +0 -180
  125. package/src/execution/__tests__/subagent-service.test.ts +0 -788
  126. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -310
  127. package/src/execution/__tests__/subprocess-agent-runner.test.ts +0 -506
  128. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  129. package/src/execution/__tests__/timeout-integration.test.ts +0 -397
  130. package/src/execution/__tests__/tombstone-store.test.ts +0 -73
  131. package/src/execution/__tests__/tool-action.test.ts +0 -385
  132. package/src/execution/__tests__/truncline-snapshot.test.ts +0 -81
  133. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  134. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  135. package/src/execution/__tests__/ui-channels.test.ts +0 -187
  136. package/src/execution/__tests__/ui-interaction-model.test.ts +0 -67
  137. package/src/execution/__tests__/ui-request-handler-factory.test.ts +0 -370
  138. package/src/execution/__tests__/ui-request-handler.test.ts +0 -204
  139. package/src/execution/__tests__/ui-request-observability.test.ts +0 -114
  140. package/src/execution/__tests__/ui-request-queue.test.ts +0 -133
  141. package/src/execution/__tests__/worktree-manager.test.ts +0 -633
  142. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -229
  143. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +0 -181
  144. package/src/execution/__tests__/worktree-registry.test.ts +0 -199
  145. package/src/execution/agent-registry.ts +0 -193
  146. package/src/execution/agent-result-mapper.ts +0 -90
  147. package/src/execution/alive-store.ts +0 -92
  148. package/src/execution/argv-mirror.ts +0 -109
  149. package/src/execution/best-effort.ts +0 -38
  150. package/src/execution/channel-registry-access.ts +0 -144
  151. package/src/execution/concurrency-pool.ts +0 -116
  152. package/src/execution/config.ts +0 -96
  153. package/src/execution/dialog-queue.ts +0 -330
  154. package/src/execution/engine/__tests__/common/data-dir.test.ts +0 -53
  155. package/src/execution/engine/__tests__/common/errors.test.ts +0 -132
  156. package/src/execution/engine/__tests__/common/event-journal.test.ts +0 -177
  157. package/src/execution/engine/__tests__/common/kill-chain.test.ts +0 -192
  158. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +0 -81
  159. package/src/execution/engine/__tests__/common/persona-router.test.ts +0 -123
  160. package/src/execution/engine/__tests__/common/pool-manager.test.ts +0 -154
  161. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  162. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  163. package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +0 -141
  164. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +0 -109
  165. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +0 -101
  166. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +0 -77
  167. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +0 -104
  168. package/src/execution/engine/__tests__/conformance/contract.relay.test.ts +0 -342
  169. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +0 -201
  170. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +0 -76
  171. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +0 -79
  172. package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -87
  173. package/src/execution/engine/__tests__/engines-declaration.test.ts +0 -36
  174. package/src/execution/engine/__tests__/model-prompt.test.ts +0 -85
  175. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  176. package/src/execution/engine/__tests__/registry.test.ts +0 -120
  177. package/src/execution/engine/__tests__/routing.test.ts +0 -231
  178. package/src/execution/engine/common/data-dir.ts +0 -62
  179. package/src/execution/engine/common/errors.ts +0 -183
  180. package/src/execution/engine/common/event-journal.ts +0 -254
  181. package/src/execution/engine/common/journal-replay.ts +0 -62
  182. package/src/execution/engine/common/kill-chain.ts +0 -221
  183. package/src/execution/engine/common/nesting-guard.ts +0 -50
  184. package/src/execution/engine/common/persona-router.ts +0 -108
  185. package/src/execution/engine/common/pool-manager.ts +0 -226
  186. package/src/execution/engine/common/schema-emulation.ts +0 -189
  187. package/src/execution/engine/common/session-view-projection.ts +0 -51
  188. package/src/execution/engine/engine-discovery.ts +0 -65
  189. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -469
  190. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  191. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  192. package/src/execution/engine/engines/pi/pi-engine.ts +0 -415
  193. package/src/execution/engine/engines/pi/reader.ts +0 -48
  194. package/src/execution/engine/engines/pi/registration.ts +0 -35
  195. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  196. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  197. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  198. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -246
  199. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -228
  200. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  201. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -64
  202. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -127
  203. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -567
  204. package/src/execution/engine/engines/zcode/constants.ts +0 -43
  205. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -39
  206. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  207. package/src/execution/engine/engines/zcode/parser.ts +0 -436
  208. package/src/execution/engine/engines/zcode/preparer.ts +0 -363
  209. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  210. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  211. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -648
  212. package/src/execution/engine/host-task-spec.ts +0 -47
  213. package/src/execution/engine/model-prompt.ts +0 -59
  214. package/src/execution/engine/paths.ts +0 -42
  215. package/src/execution/engine/port.ts +0 -153
  216. package/src/execution/engine/registry.ts +0 -123
  217. package/src/execution/engine/routing.ts +0 -218
  218. package/src/execution/engine/types.ts +0 -304
  219. package/src/execution/execute-options-mapper.ts +0 -111
  220. package/src/execution/execution-record.ts +0 -906
  221. package/src/execution/finalize-record.ts +0 -251
  222. package/src/execution/finalized-marker.ts +0 -51
  223. package/src/execution/get-state-handshake.ts +0 -104
  224. package/src/execution/host-mode.ts +0 -56
  225. package/src/execution/idle-gc.ts +0 -47
  226. package/src/execution/lifecycle-manager.ts +0 -491
  227. package/src/execution/lifecycle-predicates.ts +0 -65
  228. package/src/execution/manifest-store.ts +0 -256
  229. package/src/execution/model-config-service.ts +0 -204
  230. package/src/execution/model-resolver.ts +0 -276
  231. package/src/execution/notifier.ts +0 -260
  232. package/src/execution/output-collector.ts +0 -88
  233. package/src/execution/path-encoding.ts +0 -60
  234. package/src/execution/pi-invocation.ts +0 -120
  235. package/src/execution/record-entry.ts +0 -132
  236. package/src/execution/record-store.ts +0 -1234
  237. package/src/execution/relay-env.ts +0 -37
  238. package/src/execution/session-context-resolver.ts +0 -64
  239. package/src/execution/session-file-gc.ts +0 -120
  240. package/src/execution/session-pending.ts +0 -164
  241. package/src/execution/session-reconstructor.ts +0 -678
  242. package/src/execution/session-runner.ts +0 -1548
  243. package/src/execution/sessions-index.ts +0 -304
  244. package/src/execution/spawn-event-adapter.ts +0 -363
  245. package/src/execution/stdin-writer.ts +0 -198
  246. package/src/execution/stream-sink.ts +0 -126
  247. package/src/execution/subagent-service.ts +0 -2119
  248. package/src/execution/subprocess-agent-runner.ts +0 -303
  249. package/src/execution/temp-prompt.ts +0 -62
  250. package/src/execution/tombstone-store.ts +0 -72
  251. package/src/execution/turn-limiter.ts +0 -102
  252. package/src/execution/types.ts +0 -910
  253. package/src/execution/ui-channels.ts +0 -216
  254. package/src/execution/ui-interaction-model.ts +0 -48
  255. package/src/execution/ui-request-handler-factory.ts +0 -212
  256. package/src/execution/ui-request-observability.ts +0 -81
  257. package/src/execution/ui-request-queue.ts +0 -174
  258. package/src/execution/worktree-manager.ts +0 -688
  259. package/src/execution/worktree-registry.ts +0 -222
  260. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +0 -336
  261. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +0 -208
  262. package/src/orchestration/__tests__/agent-call-stream.test.ts +0 -157
  263. package/src/orchestration/__tests__/args-validator.test.ts +0 -143
  264. package/src/orchestration/__tests__/concurrency-gate.test.ts +0 -125
  265. package/src/orchestration/__tests__/config-loader.test.ts +0 -503
  266. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +0 -724
  267. package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +0 -405
  268. package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +0 -56
  269. package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +0 -166
  270. package/src/orchestration/__tests__/execute-agent-call.test.ts +0 -314
  271. package/src/orchestration/__tests__/jsonl-run-store-loadall-sources.test.ts +0 -171
  272. package/src/orchestration/__tests__/jsonl-run-store-session-file.test.ts +0 -1030
  273. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +0 -277
  274. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +0 -96
  275. package/src/orchestration/__tests__/lifecycle.test.ts +0 -625
  276. package/src/orchestration/__tests__/review-fix-loop-e2e.test.ts +0 -1971
  277. package/src/orchestration/__tests__/script-lint.test.ts +0 -831
  278. package/src/orchestration/__tests__/skill-discovery.test.ts +0 -157
  279. package/src/orchestration/__tests__/test-mocks.ts +0 -197
  280. package/src/orchestration/__tests__/worker-host.test.ts +0 -120
  281. package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +0 -164
  282. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +0 -520
  283. package/src/orchestration/__tests__/worker-script-builder.test.ts +0 -309
  284. package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +0 -110
  285. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +0 -317
  286. package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +0 -110
  287. package/src/orchestration/__tests__/workflows-e2e.test.ts +0 -537
  288. package/src/orchestration/agent-opts-resolver.ts +0 -93
  289. package/src/orchestration/args-validator.ts +0 -127
  290. package/src/orchestration/concurrency-gate.ts +0 -69
  291. package/src/orchestration/config-loader.ts +0 -315
  292. package/src/orchestration/error-recovery.ts +0 -862
  293. package/src/orchestration/execute-agent-call.ts +0 -217
  294. package/src/orchestration/launcher.ts +0 -410
  295. package/src/orchestration/lifecycle.ts +0 -396
  296. package/src/orchestration/models/__tests__/budget.test.ts +0 -367
  297. package/src/orchestration/models/__tests__/trace.test.ts +0 -408
  298. package/src/orchestration/models/agent-call.ts +0 -83
  299. package/src/orchestration/models/budget.ts +0 -148
  300. package/src/orchestration/models/ports.ts +0 -164
  301. package/src/orchestration/models/run-runtime.ts +0 -89
  302. package/src/orchestration/models/run-spec.ts +0 -83
  303. package/src/orchestration/models/run-state.ts +0 -44
  304. package/src/orchestration/models/trace.ts +0 -183
  305. package/src/orchestration/models/types.ts +0 -292
  306. package/src/orchestration/models/workflow-run.ts +0 -254
  307. package/src/orchestration/models/workflow-script-registry.ts +0 -35
  308. package/src/orchestration/models/workflow-script.ts +0 -117
  309. package/src/orchestration/script-lint.ts +0 -766
  310. package/src/orchestration/skill-discovery.ts +0 -92
  311. package/src/orchestration/worker-handle.ts +0 -115
  312. package/src/orchestration/worker-host.ts +0 -98
  313. package/src/orchestration/worker-script-builder.ts +0 -408
  314. package/src/orchestration/workflow-files.ts +0 -85
  315. package/src/orchestration/workflow-script-registry-impl.ts +0 -133
  316. package/src/shared/__tests__/agent-ref.test.ts +0 -34
  317. package/src/shared/__tests__/meta-parser.test.ts +0 -304
  318. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -280
  319. package/src/shared/__tests__/resource-discovery.test.ts +0 -736
  320. package/src/shared/__tests__/resource-meta.test.ts +0 -51
  321. package/src/shared/__tests__/schema-jsonify.test.ts +0 -81
  322. package/src/shared/agent-event.ts +0 -13
  323. package/src/shared/agent-ref.ts +0 -57
  324. package/src/shared/meta-parser.ts +0 -261
  325. package/src/shared/resource-discovery.ts +0 -811
  326. package/src/shared/resource-meta.ts +0 -65
  327. package/src/shared/schema-jsonify.ts +0 -56
  328. package/src/shared/xml-injection.ts +0 -35
  329. package/workflows/README.md +0 -81
  330. package/workflows/_shared/agent-refs.cjs +0 -40
  331. package/workflows/chain.js +0 -131
  332. package/workflows/map-reduce.js +0 -174
  333. package/workflows/parallel.js +0 -148
  334. package/workflows/review-fix-loop-utils.cjs +0 -1307
  335. package/workflows/review-fix-loop.js +0 -1396
  336. package/workflows/scatter-gather.js +0 -178
@@ -1,157 +0,0 @@
1
- /**
2
- * skill-discovery — resolveSkillPath 结果缓存(IF8/#14)+ 搜索序测试。
3
- *
4
- * 现状该文件此前零测试,本文件为首个测试(design IF8 契约):
5
- * - hit 不再 existsSync(计数 wrapper 观察,spyOn ESM namespace 不可配置的既有教训)
6
- * - 未命中 undefined 也缓存(不存在的名字二次调用零 stat)
7
- * - clearSkillPathCache 后重扫
8
- * - project 优先于 user/npm 的搜索序
9
- *
10
- * [merge 注] main 侧同名文件(mock-fs 版)的 5 用例语义均已覆盖:搜索序三用例
11
- * 同名等价;「npm 候选路径构造含 agentDir」= 本文件各用例断言 join(homeRoot,
12
- * ".pi/agent/npm/...") 完整路径 + npm 兜底用例的多包枚举;「全 miss undefined 含
13
- * readdirSync ENOENT 兜底」= 「未命中 undefined 也缓存」用例(homeRoot 无 npm 目录,
14
- * 真实 fs 下 ENOENT 由实现 catch)。mock 版被本集成版取代。
15
- *
16
- * 隔离:node:fs 的 existsSync 用 vi.mock 包一层计数(委托真实实现);
17
- * getAgentDir 用 vi.mock 覆盖为临时 home(vitest alias 指向 mocks/pi-coding-agent.ts
18
- * 的硬编码桩 "/home/user/.pi/agent",桩不读 os.homedir——mock node:os 无法影响它);
19
- * process.cwd 用 spyOn。
20
- */
21
- import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
22
- import { mkdtempSync, mkdirSync, rmSync } from "node:fs";
23
- import { tmpdir } from "node:os";
24
- import { join } from "node:path";
25
-
26
- const { existsSyncCalls, osHome } = vi.hoisted(() => ({
27
- existsSyncCalls: { count: 0 },
28
- osHome: { dir: "/nonexistent-home-skill-tests" },
29
- }));
30
-
31
- vi.mock("node:fs", async (importOriginal) => {
32
- const actual = await importOriginal<typeof import("node:fs")>();
33
- const realExistsSync = actual.existsSync;
34
- // 计数 wrapper(委托真实实现)——vi.spyOn(fs, "existsSync") 在 ESM 模块
35
- // 命名空间不可配置(record-store-index.test.ts:419 同款教训),改用 mock 工厂。
36
- const countingExistsSync = ((p: string) => {
37
- existsSyncCalls.count++;
38
- return realExistsSync(p);
39
- }) as typeof actual.existsSync;
40
- return { ...actual, existsSync: countingExistsSync };
41
- });
42
-
43
- vi.mock("@earendil-works/pi-coding-agent", async (importOriginal) => {
44
- const actual = await importOriginal<typeof import("@earendil-works/pi-coding-agent")>();
45
- const { join } = await import("node:path");
46
- // 桩不读 os.homedir,必须在此把 agentDir 指向 hoisted 临时 home(beforeEach 注入 homeRoot)
47
- return { ...actual, getAgentDir: () => join(osHome.dir, ".pi", "agent") };
48
- });
49
-
50
- import { clearSkillPathCache, resolveSkillPath } from "../skill-discovery.ts";
51
-
52
- // ── 临时目录工具 ──────────────────────────────────────────────
53
-
54
- let projRoot: string;
55
- let homeRoot: string;
56
-
57
- beforeEach(() => {
58
- clearSkillPathCache();
59
- existsSyncCalls.count = 0;
60
- projRoot = mkdtempSync(join(tmpdir(), "skill-proj-"));
61
- homeRoot = mkdtempSync(join(tmpdir(), "skill-home-"));
62
- osHome.dir = homeRoot;
63
- });
64
-
65
- afterEach(() => {
66
- vi.restoreAllMocks();
67
- rmSync(projRoot, { recursive: true, force: true });
68
- rmSync(homeRoot, { recursive: true, force: true });
69
- });
70
-
71
- /** mkdir -p(目录存在即 resolveSkillPath 命中——检查的是目录而非 SKILL.md)。 */
72
- function mkdirp(dir: string): void {
73
- mkdirSync(dir, { recursive: true });
74
- }
75
-
76
- describe("resolveSkillPath — 搜索序(project > user > npm)", () => {
77
- it("project 优先:同名 skill 同时存在于 project/user/npm 时返回 project 路径", () => {
78
- const cwdSpy = vi.spyOn(process, "cwd").mockReturnValue(projRoot);
79
- const name = "dup-skill";
80
- mkdirp(join(projRoot, ".agents/skills", name));
81
- mkdirp(join(homeRoot, ".pi/agent/skills", name));
82
- mkdirp(join(homeRoot, ".pi/agent/npm/node_modules/some-pkg/skills", name));
83
-
84
- const resolved = resolveSkillPath(name);
85
-
86
- expect(resolved).toBe(join(projRoot, ".agents/skills", name));
87
- expect(cwdSpy).toHaveBeenCalled();
88
- });
89
-
90
- it("user 次之:仅 user/npm 存在时返回 user 路径", () => {
91
- vi.spyOn(process, "cwd").mockReturnValue(projRoot);
92
- const name = "user-skill";
93
- mkdirp(join(homeRoot, ".pi/agent/skills", name));
94
- mkdirp(join(homeRoot, ".pi/agent/npm/node_modules/some-pkg/skills", name));
95
-
96
- expect(resolveSkillPath(name)).toBe(join(homeRoot, ".pi/agent/skills", name));
97
- });
98
-
99
- it("npm 兜底:仅 npm 包内存在时返回包内 skills 路径(readdirSync 枚举多包候选)", () => {
100
- vi.spyOn(process, "cwd").mockReturnValue(projRoot);
101
- const name = "npm-skill";
102
- // 两个包并存:断言实现枚举 npm/node_modules 下每个包(S-6 语义,防只查首个包的回退)
103
- mkdirp(join(homeRoot, ".pi/agent/npm/node_modules/pkg-a/other", "x"));
104
- mkdirp(join(homeRoot, ".pi/agent/npm/node_modules/some-pkg/skills", name));
105
-
106
- expect(resolveSkillPath(name)).toBe(
107
- join(homeRoot, ".pi/agent/npm/node_modules/some-pkg/skills", name),
108
- );
109
- });
110
- });
111
-
112
- describe("resolveSkillPath — 结果缓存(IF8/DM3)", () => {
113
- it("hit 不再 existsSync:二次调用零 stat", () => {
114
- vi.spyOn(process, "cwd").mockReturnValue(projRoot);
115
- const name = "cache-hit";
116
- const expected = join(projRoot, ".agents/skills", name);
117
- mkdirp(expected);
118
-
119
- const first = resolveSkillPath(name);
120
- const callsAfterFirst = existsSyncCalls.count;
121
- expect(first).toBe(expected);
122
- expect(callsAfterFirst).toBeGreaterThan(0);
123
-
124
- const second = resolveSkillPath(name);
125
- expect(second).toBe(expected);
126
- expect(existsSyncCalls.count).toBe(callsAfterFirst); // 零增量
127
- });
128
-
129
- it("未命中 undefined 也缓存:不存在的名字二次调用零 stat", () => {
130
- vi.spyOn(process, "cwd").mockReturnValue(projRoot);
131
- const name = "no-such-skill-xyz";
132
-
133
- const first = resolveSkillPath(name);
134
- expect(first).toBeUndefined();
135
- const callsAfterFirst = existsSyncCalls.count;
136
- expect(callsAfterFirst).toBeGreaterThan(0);
137
-
138
- const second = resolveSkillPath(name);
139
- expect(second).toBeUndefined();
140
- expect(existsSyncCalls.count).toBe(callsAfterFirst); // 零增量(未命中也缓存)
141
- });
142
-
143
- it("clearSkillPathCache 后重扫:计数恢复增长且结果一致", () => {
144
- vi.spyOn(process, "cwd").mockReturnValue(projRoot);
145
- const name = "cache-clear";
146
- const expected = join(projRoot, ".agents/skills", name);
147
- mkdirp(expected);
148
-
149
- expect(resolveSkillPath(name)).toBe(expected);
150
- const callsAfterFirst = existsSyncCalls.count;
151
- expect(callsAfterFirst).toBeGreaterThan(0);
152
-
153
- clearSkillPathCache();
154
- expect(resolveSkillPath(name)).toBe(expected);
155
- expect(existsSyncCalls.count).toBeGreaterThan(callsAfterFirst); // 重扫发生
156
- });
157
- });
@@ -1,197 +0,0 @@
1
- // src/orchestration/__tests__/test-mocks.ts
2
- //
3
- // Pi ExtensionAPI / ExtensionContext 测试 mock 工厂(PR #173 review S8)。
4
- //
5
- // 为什么需要工厂:此前测试用 `as never` 注入残缺 mock(如 `{ appendEntry: vi.fn() }`
6
- // 直接塞进 `JsonlRunStoreOptions.pi`)。`as never` 是 bottom type 断言,mock 缺字段时
7
- // 编译期零报错,比 `as unknown as T` 更危险。工厂返回**类型完整**的对象——被 mock
8
- // 接口(真实 SDK 类型,tsc 按根 tsconfig 排除规则不检查 __tests__,但编辑器 LSP 与
9
- // 显式 tsc 文件级检查会检查)新增成员时,这里补默认值即暴露,用例侧不再有断言后门。
10
- //
11
- // 语义约定:
12
- // - 默认值贴近真实行为:sessionManager.getEntries 返回浅拷贝(真实 SessionManager
13
- // 契约);appendEntry 捕获变体追加完整 CustomEntry(真实 pi.appendEntry 即向 session
14
- // 追加 CustomEntry);isIdle → true、hasPendingMessages → false 等按真实语义取值。
15
- // - 测试真正消费的成员(jsonl-run-store 只读 ctx.sessionManager.getEntries 与
16
- // pi.appendEntry)行为真实;其余成员为 no-op spy(vi.fn()),调用不炸但返回
17
- // undefined——本包测试不消费它们。
18
- // - modelRegistry / ui.theme 是含 private 字段的 nominal class:真实构造需
19
- // ModelRuntime.create()(async + 读用户级 models.json)/ loadTheme 读包文件,且
20
- // vitest 把 @earendil-works/pi-coding-agent alias 到 mocks/(无这些值导出),结构
21
- // 构造又被 private 字段阻断。二者经 fail-loud Proxy 提供:误用时立即抛错(而非
22
- // 静默 undefined),把「缺 mock」变成显式失败。这是本文件仅有的两处断言收敛点。
23
-
24
- import { vi } from "vitest";
25
-
26
- import type {
27
- CustomEntry,
28
- ExtensionAPI,
29
- ExtensionContext,
30
- ExtensionUIContext,
31
- ModelRegistry,
32
- Theme,
33
- } from "@earendil-works/pi-coding-agent";
34
-
35
- /**
36
- * 误用即抛错的占位成员:比静默返回 undefined 的 no-op 更早暴露「缺 mock」。
37
- *
38
- * T 收窄为 object:调用点(ModelRegistry/Theme)均为对象类型;Proxy 静态类型是 `{}`,
39
- * 目标是 nominal class(private 字段阻断结构构造),单重 `as T` 断言已足够表达
40
- * 「结构上无法构造,运行时 fail-loud 兜底」的意图,无需 `as unknown as T` 双重断言。
41
- */
42
- function failLoud<T extends object>(memberPath: string): T {
43
- return new Proxy(
44
- {},
45
- {
46
- get(_target, prop) {
47
- throw new Error(
48
- `[test-mocks] ${memberPath}.${String(prop)} 未提供 mock 实现——` +
49
- `本测试不应消费该成员;确需消费时经 overrides 显式提供`,
50
- );
51
- },
52
- },
53
- ) as T;
54
- }
55
-
56
- /**
57
- * 构造类型完整的 ExtensionContext。
58
- *
59
- * @param entries sessionManager.getEntries 的返回源(浅拷贝返回)。与 mkPi(entries)
60
- * 共享同一数组时可复现真实 pi 行为:appendEntry 写入 ↔ getEntries 读出。
61
- * @param overrides 覆写任意 ctx 字段(浅合并,整体替换成员,最后应用)。
62
- */
63
- export function mkCtx(
64
- entries: CustomEntry[] = [],
65
- overrides: Partial<ExtensionContext> = {},
66
- ): ExtensionContext {
67
- const ctx: ExtensionContext = {
68
- ui: mkUi(),
69
- // pi 在 xyz-agent 下以 rpc 子进程模式运行;rpc 模式 hasUI 为 true(SDK 契约注释)
70
- mode: "rpc",
71
- hasUI: true,
72
- cwd: "/tmp",
73
- sessionManager: {
74
- getCwd: () => "/tmp",
75
- getSessionDir: () => "/tmp/sessions-test",
76
- getSessionId: () => "session-test",
77
- // 真实语义:首条 assistant 消息前 session 文件未落盘,返回 undefined
78
- getSessionFile: () => undefined,
79
- getLeafId: () => null,
80
- getLeafEntry: () => undefined,
81
- getEntry: () => undefined,
82
- getLabel: () => undefined,
83
- getBranch: () => [],
84
- buildContextEntries: () => [],
85
- getHeader: () => null,
86
- // 真实 SessionManager.getEntries 返回浅拷贝
87
- getEntries: () => [...entries],
88
- getTree: () => [],
89
- getSessionName: () => undefined,
90
- },
91
- modelRegistry: failLoud<ModelRegistry>("ctx.modelRegistry"),
92
- // SDK 契约:model / signal 在 agent 未流式输出时合法为 undefined
93
- model: undefined,
94
- isIdle: vi.fn(() => true),
95
- isProjectTrusted: vi.fn(() => true),
96
- signal: undefined,
97
- abort: vi.fn(),
98
- hasPendingMessages: vi.fn(() => false),
99
- shutdown: vi.fn(),
100
- getContextUsage: vi.fn(() => undefined),
101
- compact: vi.fn(),
102
- getSystemPrompt: vi.fn(() => ""),
103
- };
104
- return Object.assign(ctx, overrides);
105
- }
106
-
107
- /** ExtensionUIContext 完整 no-op mock(theme 为 fail-loud 占位,见文件头说明)。 */
108
- function mkUi(): ExtensionUIContext {
109
- return {
110
- select: vi.fn(async () => undefined),
111
- confirm: vi.fn(async () => false),
112
- input: vi.fn(async () => undefined),
113
- notify: vi.fn(),
114
- onTerminalInput: vi.fn(() => () => {}),
115
- setStatus: vi.fn(),
116
- setWorkingMessage: vi.fn(),
117
- setWorkingVisible: vi.fn(),
118
- setWorkingIndicator: vi.fn(),
119
- setHiddenThinkingLabel: vi.fn(),
120
- setWidget: vi.fn(),
121
- setFooter: vi.fn(),
122
- setHeader: vi.fn(),
123
- setTitle: vi.fn(),
124
- custom: vi.fn(),
125
- pasteToEditor: vi.fn(),
126
- setEditorText: vi.fn(),
127
- getEditorText: vi.fn(() => ""),
128
- editor: vi.fn(async () => undefined),
129
- addAutocompleteProvider: vi.fn(),
130
- setEditorComponent: vi.fn(),
131
- getEditorComponent: vi.fn(() => undefined),
132
- theme: failLoud<Theme>("ctx.ui.theme"),
133
- getAllThemes: vi.fn(() => []),
134
- getTheme: vi.fn(() => undefined),
135
- setTheme: vi.fn(() => ({ success: true })),
136
- getToolsExpanded: vi.fn(() => false),
137
- setToolsExpanded: vi.fn(),
138
- };
139
- }
140
-
141
- /**
142
- * 构造类型完整的 ExtensionAPI。
143
- *
144
- * @param entries 给定时,appendEntry 追加完整 CustomEntry 到该数组(真实
145
- * pi.appendEntry 语义:向 session 追加 custom entry);缺省为纯 spy(可断言
146
- * 调用次数、无副作用)。
147
- * @param overrides 覆写任意 pi 字段(浅合并,最后应用)。
148
- */
149
- export function mkPi(
150
- entries?: CustomEntry[],
151
- overrides: Partial<ExtensionAPI> = {},
152
- ): ExtensionAPI {
153
- const appendEntry =
154
- entries === undefined
155
- ? vi.fn()
156
- : vi.fn((customType: string, data?: unknown) => {
157
- entries.push({
158
- type: "custom",
159
- customType,
160
- data,
161
- id: `entry-${entries.length}`,
162
- parentId: null,
163
- timestamp: new Date().toISOString(),
164
- });
165
- });
166
- const pi: ExtensionAPI = {
167
- on: vi.fn(),
168
- registerTool: vi.fn(),
169
- registerCommand: vi.fn(),
170
- registerShortcut: vi.fn(),
171
- registerFlag: vi.fn(),
172
- getFlag: vi.fn(() => undefined),
173
- registerMessageRenderer: vi.fn(),
174
- registerEntryRenderer: vi.fn(),
175
- sendMessage: vi.fn(),
176
- sendUserMessage: vi.fn(),
177
- appendEntry,
178
- setSessionName: vi.fn(),
179
- getSessionName: vi.fn(() => undefined),
180
- setLabel: vi.fn(),
181
- exec: vi.fn(),
182
- getActiveTools: vi.fn(() => []),
183
- getAllTools: vi.fn(() => []),
184
- setActiveTools: vi.fn(),
185
- getCommands: vi.fn(() => []),
186
- setModel: vi.fn(async () => true),
187
- getThinkingLevel: vi.fn(),
188
- setThinkingLevel: vi.fn(),
189
- registerProvider: vi.fn(),
190
- unregisterProvider: vi.fn(),
191
- events: {
192
- emit: vi.fn(),
193
- on: vi.fn(() => () => {}),
194
- },
195
- };
196
- return Object.assign(pi, overrides);
197
- }
@@ -1,120 +0,0 @@
1
- /**
2
- * WorkerHostImpl — workerData 映射测试。
3
- *
4
- * Option B(run-level model/thinkingLevel)的映射点在 WorkerHostImpl.start:
5
- * RunSpec.model/thinkingLevel → workerData.model/thinkingLevel → worker 内
6
- * $MODEL/$THINKING_LEVEL globals(worker-script-builder 注入)→ agent() fallback。
7
- *
8
- * 本测试 mock node:worker_threads.Worker,捕获构造 options.workerData,
9
- * 直接断言映射(lifecycle.test.ts 的 workerHost.start 是 mock,看不到 workerData)。
10
- */
11
- import { describe, expect, it, vi } from "vitest";
12
-
13
- const { workerMock } = vi.hoisted(() => ({
14
- workerMock: vi.fn(),
15
- }));
16
-
17
- vi.mock("node:worker_threads", () => ({
18
- Worker: workerMock,
19
- }));
20
-
21
- import { WorkerHostImpl } from "../worker-host.ts";
22
- import type { RunSpec } from "../models/run-spec.ts";
23
- import type { WorkerHandlers } from "../models/ports.ts";
24
-
25
- interface WorkerOptions {
26
- eval?: boolean;
27
- workerData?: Record<string, unknown>;
28
- }
29
-
30
- /** mock Worker 实例(WorkerHandle 依赖 on/postMessage/terminate)。 */
31
- function fakeWorkerInstance() {
32
- return { on: vi.fn(), postMessage: vi.fn(), terminate: vi.fn() };
33
- }
34
-
35
- function makeSpec(overrides: Partial<RunSpec> = {}): RunSpec {
36
- return {
37
- scriptSource: "execute() {}",
38
- args: { autoCommit: true },
39
- scriptName: "test-wf",
40
- scriptPath: "/fake/test.js",
41
- description: "test desc",
42
- ...overrides,
43
- };
44
- }
45
-
46
- function makeHandlers(): WorkerHandlers {
47
- return {
48
- onMessage: vi.fn(),
49
- onError: vi.fn(),
50
- onExit: vi.fn(),
51
- };
52
- }
53
-
54
- describe("WorkerHostImpl.start — workerData 映射", () => {
55
- it("Option B: RunSpec.model/thinkingLevel 映射进 workerData(其余字段不破坏)", () => {
56
- const spec = makeSpec({
57
- model: "anthropic/claude-3.5-sonnet",
58
- thinkingLevel: "high",
59
- budgetTokens: 5000,
60
- });
61
- let captured: WorkerOptions | undefined;
62
- workerMock.mockImplementation(function (
63
- this: unknown,
64
- _code: string,
65
- options: WorkerOptions,
66
- ) {
67
- captured = options;
68
- return fakeWorkerInstance();
69
- });
70
-
71
- new WorkerHostImpl().start(spec, spec.args, makeHandlers());
72
-
73
- expect(workerMock).toHaveBeenCalledTimes(1);
74
- expect(captured).toBeDefined();
75
- const wd = captured!.workerData;
76
- expect(wd).toBeDefined();
77
- // Option B 核心:run-level override 经 workerData 进入 worker globals
78
- expect(wd!.model).toBe("anthropic/claude-3.5-sonnet");
79
- expect(wd!.thinkingLevel).toBe("high");
80
- // workerData 契约其余字段(防未来重构破坏 worker 启动链路)
81
- expect(wd!.scriptPath).toBe("/fake/test.js");
82
- expect(wd!.args).toEqual({ autoCommit: true });
83
- expect(wd!.meta).toEqual({ name: "test-wf", description: "test desc" });
84
- expect(wd!.budget).toEqual({ maxTokens: 5000, usedTokens: 0, usedCost: 0 });
85
- expect(captured!.eval).toBe(true);
86
- });
87
-
88
- it("model/thinkingLevel 未设:workerData 字段为 undefined(继承主 agent 语义,不污染)", () => {
89
- let captured: WorkerOptions | undefined;
90
- workerMock.mockImplementation(function (
91
- this: unknown,
92
- _code: string,
93
- options: WorkerOptions,
94
- ) {
95
- captured = options;
96
- return fakeWorkerInstance();
97
- });
98
-
99
- new WorkerHostImpl().start(makeSpec(), {}, makeHandlers());
100
-
101
- expect(captured!.workerData!.model).toBeUndefined();
102
- expect(captured!.workerData!.thinkingLevel).toBeUndefined();
103
- });
104
-
105
- it("handlers 绑定:message/error/exit 三类事件注册到 worker", () => {
106
- const instance = fakeWorkerInstance();
107
- workerMock.mockImplementation(function (this: unknown) {
108
- return instance;
109
- });
110
-
111
- const handle = new WorkerHostImpl().start(makeSpec(), {}, makeHandlers());
112
-
113
- expect(instance.on).toHaveBeenCalledTimes(3);
114
- expect(instance.on).toHaveBeenCalledWith("message", expect.any(Function));
115
- expect(instance.on).toHaveBeenCalledWith("error", expect.any(Function));
116
- expect(instance.on).toHaveBeenCalledWith("exit", expect.any(Function));
117
- // handle 持底层 worker(RunRuntime 直接访问 ref/href)
118
- expect(handle.raw).toBe(instance);
119
- });
120
- });
@@ -1,164 +0,0 @@
1
- /**
2
- * rfl 仪表 T1(tier-1 §7.1):returnMeta 透传 usage/durationMs/sessionId。
3
- *
4
- * 两个对称点的运行时验证(worker-script-builder 模板字符串断言无法证明
5
- * 「真实 Worker 线程里 resolve 对象字段齐全」):
6
- * A1 live resolve——agent-result 消息回发完整 AgentResult,returnMeta:true
7
- * 时 resolve 对象 = {value, sessionFile, worktreePath, error, usage, durationMs, sessionId}
8
- * A2 缓存重放——workerData.callCache 命中时重建对象同样含三字段(对称点)
9
- *
10
- * 模式与 worker-script-builder-runtime.test.ts 相同:真实 Worker 线程执行
11
- * buildWorkerScript 产物,主线程模拟 runtime 回发消息。
12
- */
13
- import { Worker } from "node:worker_threads";
14
-
15
- import { afterEach, describe, expect, it } from "vitest";
16
-
17
- import { buildWorkerScript } from "../worker-script-builder.ts";
18
-
19
- const USAGE = { input: 100, output: 50, cacheRead: 700, cacheWrite: 30, cost: 0.012, contextTokens: 850, turns: 3 };
20
-
21
- const createdWorkers: Worker[] = [];
22
-
23
- afterEach(() => {
24
- for (const w of createdWorkers.splice(0)) {
25
- w.terminate().catch(() => {});
26
- }
27
- });
28
-
29
- interface RunOutcome {
30
- returnValue?: unknown;
31
- errorMessage?: string;
32
- exitCode?: number;
33
- }
34
-
35
- /**
36
- * 起 Worker 跑 userScript;收到首个 agent-call 即回发 agentResult(调用方提供),
37
- * 等脚本 return。callCache 命中路径不会发出 agent-call(直接从缓存重建返回)。
38
- */
39
- function runWorker(
40
- userScript: string,
41
- opts: { agentResult?: Record<string, unknown>; callCache?: Record<number, unknown>; timeoutMs?: number },
42
- ): Promise<RunOutcome> {
43
- const timeoutMs = opts.timeoutMs ?? 4000;
44
- return new Promise((resolve, reject) => {
45
- const worker = new Worker(buildWorkerScript(userScript), {
46
- eval: true,
47
- workerData: {
48
- scriptPath: "test.js",
49
- args: {},
50
- workspace: process.cwd(),
51
- budget: { maxTokens: 0, usedTokens: 0, usedCost: 0 },
52
- callCache: opts.callCache ?? {},
53
- },
54
- });
55
- createdWorkers.push(worker);
56
- const out: RunOutcome = {};
57
- let settled = false;
58
- const timer = setTimeout(() => {
59
- worker.terminate().catch(() => {});
60
- reject(new Error("Worker timed out — likely hung"));
61
- }, timeoutMs);
62
- const finish = (r: RunOutcome): void => {
63
- if (settled) return;
64
- settled = true;
65
- clearTimeout(timer);
66
- resolve(r);
67
- };
68
- worker.on("message", (raw: unknown) => {
69
- const msg = raw as { type?: string; callId?: number };
70
- if (msg.type === "agent-call" && typeof msg.callId === "number") {
71
- worker.postMessage({
72
- type: "agent-result",
73
- callId: msg.callId,
74
- result: opts.agentResult ?? { content: "fallback", parsedOutput: { ok: true } },
75
- cached: false,
76
- });
77
- } else if (msg.type === "return") {
78
- out.returnValue = (raw as { result?: unknown }).result;
79
- finish(out);
80
- } else if (msg.type === "error") {
81
- out.errorMessage = (raw as { error?: string }).error;
82
- finish(out);
83
- }
84
- });
85
- worker.on("exit", (code: number) => {
86
- out.exitCode = code;
87
- if (code !== 0) finish(out);
88
- });
89
- worker.on("error", (err: Error) => {
90
- out.errorMessage = err.message;
91
- finish(out);
92
- });
93
- });
94
- }
95
-
96
- const META_SCRIPT = "const meta = await agent({ prompt: 'passthrough probe', returnMeta: true }); return meta;";
97
-
98
- describe("A1 returnMeta live resolve 透传(tier-1 §7.1)", () => {
99
- it("A1 agent-result 回发完整 AgentResult 时 resolve 对象含 usage/durationMs/sessionId(七字段全集)", async () => {
100
- const outcome = await runWorker(META_SCRIPT, {
101
- agentResult: {
102
- content: "raw text",
103
- parsedOutput: { ok: true },
104
- sessionFile: "/tmp/sess.jsonl",
105
- worktreePath: "/tmp/wt",
106
- error: undefined,
107
- usage: USAGE,
108
- durationMs: 83_000,
109
- sessionId: "sess-abc-1",
110
- },
111
- });
112
- expect(outcome.errorMessage).toBeUndefined();
113
- expect(outcome.returnValue).toEqual({
114
- value: { ok: true },
115
- sessionFile: "/tmp/sess.jsonl",
116
- worktreePath: "/tmp/wt",
117
- error: undefined,
118
- usage: USAGE,
119
- durationMs: 83_000,
120
- sessionId: "sess-abc-1",
121
- });
122
- });
123
-
124
- it("A1 旧主线程(AgentResult 无三字段)时 resolve 对象三字段为 undefined(向后兼容不抛错)", async () => {
125
- const outcome = await runWorker(META_SCRIPT, {
126
- agentResult: { content: "raw", parsedOutput: { v: 1 }, sessionFile: "/tmp/s.jsonl" },
127
- });
128
- expect(outcome.returnValue).toMatchObject({
129
- value: { v: 1 },
130
- sessionFile: "/tmp/s.jsonl",
131
- usage: undefined,
132
- durationMs: undefined,
133
- sessionId: undefined,
134
- });
135
- });
136
- });
137
-
138
- describe("A2 returnMeta 缓存重放重建透传(对称点,tier-1 §7.1)", () => {
139
- it("A2 workerData.callCache 命中时重建对象含 usage/durationMs/sessionId(不回发 agent-call)", async () => {
140
- const outcome = await runWorker(META_SCRIPT, {
141
- callCache: {
142
- 0: {
143
- content: "cached raw",
144
- parsedOutput: { cached: true },
145
- sessionFile: "/tmp/cached.jsonl",
146
- worktreePath: "/tmp/cwt",
147
- usage: USAGE,
148
- durationMs: 42_000,
149
- sessionId: "sess-cache-9",
150
- },
151
- },
152
- });
153
- expect(outcome.errorMessage).toBeUndefined();
154
- expect(outcome.returnValue).toEqual({
155
- value: { cached: true },
156
- sessionFile: "/tmp/cached.jsonl",
157
- worktreePath: "/tmp/cwt",
158
- error: undefined,
159
- usage: USAGE,
160
- durationMs: 42_000,
161
- sessionId: "sess-cache-9",
162
- });
163
- });
164
- });