@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,408 +0,0 @@
1
- // 测试框架:vitest
2
- // 运行命令:npx vitest run src/orchestration/models/__tests__/trace.test.ts
3
- //
4
- // Trace 首个直接单测(W1TC1-W1TC12,.cw/swf-perf-impl/rt-w1-design.json):
5
- // - W1TC1-3/9:byIndex 倒排索引一致性与 no-op 防御语义
6
- // - W1TC4-8:result.content 裁剪(append/update 入口、8000 边界、patch 缺省、fromArray 原样保留)
7
- // - W1TC10-11:集成——executeAgentCall 真链路 / jsonl save-load round-trip
8
- // - W1TC12:重复 stepIndex 违规语义锚定(last-wins + remove 后 desync 孤儿)
9
-
10
- import * as fs from "node:fs";
11
- import * as os from "node:os";
12
- import * as path from "node:path";
13
-
14
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
15
-
16
- import { TRACE_RESULT_MAX_CHARS, Trace } from "../trace.js";
17
- import { AgentCall } from "../agent-call.js";
18
- import { Budget } from "../budget.js";
19
- import { WorkflowRun } from "../workflow-run.js";
20
- import type { ExecutionTraceNode, AgentResult, RunSpec } from "../types.js";
21
- import type { AgentRunner } from "../ports.js";
22
- import { executeAgentCall } from "../../execute-agent-call.js";
23
- import { JsonlRunStore } from "../../jsonl-run-store.js";
24
-
25
- // ── 测试辅助 ─────────────────────────────────────────────────
26
-
27
- /** 构造最小 ExecutionTraceNode(status 默认 pending,无 result)。 */
28
- function makeTraceNode(stepIndex: number): ExecutionTraceNode {
29
- return {
30
- stepIndex,
31
- agent: "test-agent",
32
- task: "test task",
33
- model: "default",
34
- status: "pending",
35
- };
36
- }
37
-
38
- /** 构造指定长度 content 的 AgentResult(sessionId 等可选字段透传)。 */
39
- function makeResult(content: string, extras: Partial<AgentResult> = {}): AgentResult {
40
- return { content, ...extras };
41
- }
42
-
43
- // ── byIndex 索引一致性 ────────────────────────────────────────
44
-
45
- describe("Trace byIndex 索引一致性", () => {
46
- it("W1TC1: append/update/remove 后 find 命中且引用共享", () => {
47
- const trace = new Trace();
48
- const node0 = makeTraceNode(0);
49
- const node1 = makeTraceNode(1);
50
- const node2 = makeTraceNode(2);
51
- trace.append(node0);
52
- trace.append(node1);
53
- trace.append(node2);
54
-
55
- trace.update(1, { status: "completed" });
56
-
57
- // byIndex 与 nodes 引用共享非拷贝
58
- expect(trace.find(0)).toBe(node0);
59
- expect(trace.find(1)).toBe(node1);
60
- expect(trace.find(2)).toBe(node2);
61
- // Map 值是节点引用,update 字段 mutate 可见
62
- expect(trace.find(1)!.status).toBe("completed");
63
-
64
- trace.removeByStepIndex(1);
65
- expect(trace.find(1)).toBeUndefined();
66
- expect(trace.length).toBe(2);
67
- // 其余节点不受影响
68
- expect(trace.find(0)).toBe(node0);
69
- expect(trace.find(2)).toBe(node2);
70
- });
71
- });
72
-
73
- // ── remove 后 re-append 同 stepIndex 覆盖 ─────────────────────
74
-
75
- describe("Trace remove 后 re-append 同 stepIndex", () => {
76
- it("W1TC2: rebuild discard 清理后重跑重发同 callId——旧节点不再可达", () => {
77
- const trace = new Trace();
78
- const nodeA = makeTraceNode(0);
79
- trace.append(nodeA);
80
- trace.removeByStepIndex(0);
81
-
82
- const nodeB = makeTraceNode(0);
83
- trace.append(nodeB);
84
-
85
- expect(trace.find(0)).toBe(nodeB);
86
- expect(trace.toArray()).toHaveLength(1);
87
- expect(trace.toArray()[0]).toBe(nodeB);
88
- });
89
- });
90
-
91
- // ── 重复 stepIndex 违规语义锚定(W1TC12)──────────────────────
92
-
93
- describe("Trace 重复 stepIndex 违规语义锚定(W1TC12)", () => {
94
- it("W1TC12: 重复 append find last-wins;重复 append 后 remove 呈 desync 孤儿", () => {
95
- // ① 重复 append 同 stepIndex 且未 remove:find 返回第二个节点(Map
96
- // last-wins;旧线性扫 first-match 会返回第一个)
97
- const t1 = new Trace();
98
- const first = makeTraceNode(0);
99
- const second = makeTraceNode(0);
100
- t1.append(first);
101
- t1.append(second);
102
- expect(t1.find(0)).toBe(second);
103
- expect(t1.length).toBe(2);
104
-
105
- // ② 重复 append 后 removeByStepIndex:findIndex 命中首个旧节点 splice、
106
- // byIndex.delete 删掉整个键——第二个节点残留为孤儿(find 不可达但
107
- // nodes.length=1)。desync 行为锚定:防未来改回线性扫时静默漂移
108
- // (线性扫实现下 find(0) 会命中残留节点 second,本断言即失败)
109
- const t2 = new Trace();
110
- const a = makeTraceNode(0);
111
- const b = makeTraceNode(0);
112
- t2.append(a);
113
- t2.append(b);
114
- t2.removeByStepIndex(0);
115
- expect(t2.find(0)).toBeUndefined();
116
- expect(t2.length).toBe(1);
117
- expect(t2.toArray()[0]).toBe(b);
118
- });
119
- });
120
-
121
- // ── fromArray 重建 ───────────────────────────────────────────
122
-
123
- describe("Trace.fromArray 重建", () => {
124
- it("W1TC3: 索引全命中 + 防御性拷贝语义保持", () => {
125
- const node0 = makeTraceNode(0);
126
- const node1 = makeTraceNode(1);
127
- const node2 = makeTraceNode(2);
128
- const src = [node0, node1, node2];
129
-
130
- const trace = Trace.fromArray(src);
131
-
132
- expect(trace.length).toBe(3);
133
- // fromArray push {...node} 副本——find(i) 与 toArray()[i] 同引用(byIndex 命中副本)
134
- for (let i = 0; i < 3; i++) {
135
- expect(trace.find(i)).toBe(trace.toArray()[i]);
136
- }
137
-
138
- // 传入数组后续 mutate 不影响 trace(浅拷贝语义保持)
139
- src.push(makeTraceNode(3));
140
- expect(trace.length).toBe(3);
141
- src[0]!.status = "failed";
142
- expect(trace.find(0)!.status).toBe("pending");
143
- });
144
- });
145
-
146
- // ── append 入口裁剪 ──────────────────────────────────────────
147
-
148
- describe("Trace append 入口超长 result 裁剪", () => {
149
- it("W1TC4: 标记含原始长度,节点引用不变,其余字段浅拷贝保留", () => {
150
- const content = "x".repeat(10000);
151
- const node = {
152
- ...makeTraceNode(0),
153
- result: makeResult(content, { sessionId: "s1", parsedOutput: { a: 1 } }),
154
- };
155
-
156
- const trace = new Trace();
157
- trace.append(node);
158
-
159
- const stored = trace.toArray()[0]!;
160
- // 节点对象引用不变(mutate result 字段,不 push 副本——D-10 traceNode 引用共享)
161
- expect(stored).toBe(node);
162
-
163
- const marker = `\n…[trace result truncated, original 10000 chars]…\n`;
164
- expect(stored.result!.content).toBe(content.slice(0, 4000) + marker + content.slice(-4000));
165
- // 头尾与标记子串
166
- expect(stored.result!.content.startsWith(content.slice(0, 4000))).toBe(true);
167
- expect(stored.result!.content.endsWith(content.slice(-4000))).toBe(true);
168
- expect(stored.result!.content).toContain("[trace result truncated, original 10000 chars]");
169
- // result 其余字段浅拷贝保留
170
- expect(stored.result!.sessionId).toBe("s1");
171
- expect(stored.result!.parsedOutput).toEqual({ a: 1 });
172
- });
173
- });
174
-
175
- // ── update 入口裁剪 ──────────────────────────────────────────
176
-
177
- describe("Trace update patch.result 超长裁剪", () => {
178
- it("W1TC5: 节点持裁剪副本,patch 原对象不被污染(call.result 保真)", () => {
179
- const trace = new Trace();
180
- trace.append(makeTraceNode(0));
181
-
182
- const full = makeResult("y".repeat(9000), { sessionId: "s1" });
183
- trace.update(0, { result: full });
184
-
185
- const stored = trace.find(0)!.result!;
186
- const marker = `\n…[trace result truncated, original 9000 chars]…\n`;
187
- expect(stored.content.length).toBe(4000 + marker.length + 4000);
188
- expect(stored.content).toContain("original 9000 chars");
189
- // 节点持裁剪副本新对象,与 patch.result 脱钩
190
- expect(stored).not.toBe(full);
191
- // 浅拷贝保留其他字段
192
- expect(stored.sessionId).toBe("s1");
193
- // AgentCall.result 保真——原对象不被污染(replay 数据源)
194
- expect(full.content).toHaveLength(9000);
195
- });
196
- });
197
-
198
- // ── 边界:恰好 8000 不裁 / 8001 裁 ────────────────────────────
199
-
200
- describe("Trace 裁剪边界(严格大于 TRACE_RESULT_MAX_CHARS)", () => {
201
- it("W1TC6: 恰好 8000 引用透传零拷贝;8001 触发裁剪", () => {
202
- const trace = new Trace();
203
- trace.append(makeTraceNode(0));
204
- trace.append(makeTraceNode(1));
205
-
206
- // 恰好 8000:不裁
207
- const exact = makeResult("a".repeat(TRACE_RESULT_MAX_CHARS));
208
- trace.update(0, { result: exact });
209
- expect(trace.find(0)!.result).toBe(exact);
210
- expect(trace.find(0)!.result!.content).toHaveLength(8000);
211
- expect(trace.find(0)!.result!.content).not.toContain("truncated");
212
-
213
- // 8001:裁剪(head/tail 固定 4000 比例,重叠段属预期)
214
- const over = makeResult("b".repeat(TRACE_RESULT_MAX_CHARS + 1));
215
- trace.update(1, { result: over });
216
- expect(trace.find(1)!.result!.content).toContain("original 8001 chars");
217
- expect(trace.find(1)!.result!.content).not.toBe(over.content);
218
- });
219
- });
220
-
221
- // ── patch.result 未提供不触发裁剪 ────────────────────────────
222
-
223
- describe("Trace update patch.result 缺省", () => {
224
- it("W1TC7: 只改 status/completedAt 等字段——已持 result 不被触碰", () => {
225
- const origResult = makeResult("keep");
226
- const node = { ...makeTraceNode(0), result: origResult };
227
- const trace = new Trace();
228
- trace.append(node);
229
-
230
- trace.update(0, { status: "completed", completedAt: "2026-08-15T00:00:00Z" });
231
- expect(trace.find(0)!.result!.content).toBe("keep");
232
- expect(trace.find(0)!.result).toBe(origResult);
233
-
234
- // 其他字段路径同样不影响 result
235
- trace.update(0, { sessionId: "s9" });
236
- expect(trace.find(0)!.result).toBe(origResult);
237
- });
238
- });
239
-
240
- // ── fromArray 原样保留(read 路径不二次裁剪)──────────────────
241
-
242
- describe("Trace.fromArray 原样保留", () => {
243
- it("W1TC8: 超长 content 不被二次裁剪;已含标记的形态逐字节不变", () => {
244
- // 旧版本未裁剪的快照重水合:20000 字符全长保留
245
- const long = {
246
- ...makeTraceNode(0),
247
- result: makeResult("z".repeat(20000)),
248
- };
249
- const trace = Trace.fromArray([long]);
250
- expect(trace.find(0)!.result!.content).toHaveLength(20000);
251
- expect(trace.find(0)!.result!.content).not.toContain("truncated");
252
-
253
- // 新快照 round-trip:已裁剪含标记的 content 经 fromArray 后逐字节不变(无标记嵌套)
254
- const marker = `\n…[trace result truncated, original 10000 chars]…\n`;
255
- const trimmed = "x".repeat(4000) + marker + "x".repeat(4000);
256
- const trace2 = Trace.fromArray([{ ...makeTraceNode(0), result: makeResult(trimmed) }]);
257
- expect(trace2.find(0)!.result!.content).toBe(trimmed);
258
- });
259
- });
260
-
261
- // ── no-op 防御语义回归 ───────────────────────────────────────
262
-
263
- describe("Trace no-op 防御语义", () => {
264
- it("W1TC9: update/remove 不存在的 stepIndex 不抛错、状态不变", () => {
265
- const trace = new Trace();
266
- trace.append(makeTraceNode(0));
267
-
268
- expect(() => trace.update(999, { status: "completed" })).not.toThrow();
269
- expect(() => trace.removeByStepIndex(999)).not.toThrow();
270
- expect(trace.length).toBe(1);
271
- expect(trace.find(999)).toBeUndefined();
272
- });
273
- });
274
-
275
- // ── 集成:executeAgentCall 真链路(W1TC10)────────────────────
276
-
277
- describe("W1TC10: executeAgentCall 真链路——call.result 全量、trace 节点持裁剪副本", () => {
278
- it("W1TC10: runner.run 返回 12000 字符 → 两形态并存(AgentCall.result 不裁)", async () => {
279
- const content = "w".repeat(12000);
280
- const runner: AgentRunner = {
281
- run: vi.fn().mockResolvedValue(makeResult(content, { sessionId: "s1" })),
282
- };
283
-
284
- const trace = new Trace();
285
- const traceNode = makeTraceNode(0);
286
- trace.append(traceNode);
287
- const call = new AgentCall(0, { prompt: "test task", agent: "worker" }, traceNode);
288
-
289
- await executeAgentCall(call, runner, new Budget(), new AbortController().signal, trace);
290
-
291
- // AgentCall.result 全量(worker cached replay 数据源保真)
292
- expect(call.result!.content).toHaveLength(12000);
293
- // trace 节点持裁剪副本
294
- const stored = trace.find(0)!.result!;
295
- const marker = `\n…[trace result truncated, original 12000 chars]…\n`;
296
- expect(stored.content).toBe(content.slice(0, 4000) + marker + content.slice(-4000));
297
- expect(stored.content.length).toBe(4000 + marker.length + 4000);
298
- expect(stored.sessionId).toBe("s1");
299
- expect(trace.find(0)!.status).toBe("completed");
300
- });
301
- });
302
-
303
- // ── 集成:jsonl save/load round-trip(W1TC11)─────────────────
304
-
305
- describe("W1TC11: jsonl save/load round-trip——落盘裁剪形态 + 重水合不二次裁", () => {
306
- let tmpDir: string;
307
-
308
- beforeEach(() => {
309
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "wf-trace-trim-test-"));
310
- });
311
-
312
- afterEach(() => {
313
- fs.rmSync(tmpDir, { recursive: true, force: true });
314
- });
315
-
316
- function makeSpec(): RunSpec {
317
- return {
318
- scriptSource: "module.exports = async () => {};",
319
- args: {},
320
- scriptName: "test-script",
321
- scriptPath: "/tmp/test.js",
322
- description: "test",
323
- };
324
- }
325
-
326
- /** 构造含 10000 字符 result 已完成 call 的 WorkflowRun(模式对齐 jsonl-run-store-session-file.test.ts)。 */
327
- function makeRunWithDoneCall(): WorkflowRun {
328
- const trace = new Trace();
329
- const node = makeTraceNode(0);
330
- trace.append(node);
331
- const call = new AgentCall(0, { prompt: "task", agent: "worker" }, node);
332
- call.markRunning();
333
- // markDone 存全量 result(AgentCall.result 不裁)
334
- call.markDone(makeResult("q".repeat(10000), { sessionId: "session-abc" }));
335
- call.setSessionId("session-abc");
336
- // trace.update 经入口裁剪——节点持裁剪副本
337
- trace.update(0, {
338
- status: "completed",
339
- result: call.result,
340
- completedAt: new Date().toISOString(),
341
- sessionId: "session-abc",
342
- });
343
-
344
- return new WorkflowRun(
345
- "run-trim-001",
346
- makeSpec(),
347
- {
348
- status: "done",
349
- reason: "completed",
350
- budget: new Budget(),
351
- calls: new Map([[0, call]]),
352
- trace,
353
- errorLogs: [],
354
- },
355
- { startedAt: new Date().toISOString(), completedAt: new Date().toISOString() },
356
- );
357
- }
358
-
359
- it("W1TC11: save 落盘 trace 裁剪 + calls[].result 全量;loadAll 回读逐字节一致", async () => {
360
- const entries: Array<{ type: string; customType?: string; data?: unknown }> = [];
361
- const mockPi = {
362
- appendEntry: vi.fn((type: string, data: unknown) => {
363
- entries.push({ type: "custom", customType: type, data });
364
- }),
365
- };
366
- const mockCtx = {
367
- sessionManager: { getEntries: () => entries },
368
- };
369
- const store = new JsonlRunStore({
370
- sessionDir: tmpDir,
371
- pi: mockPi as never,
372
- ctx: mockCtx as never,
373
- });
374
-
375
- const run = makeRunWithDoneCall();
376
- await store.save(run);
377
-
378
- // 读磁盘快照验证落盘形态
379
- const raw = fs.readFileSync(
380
- path.join(tmpDir, "workflow-state", "run-trim-001.jsonl"),
381
- "utf8",
382
- );
383
- const snapshot = JSON.parse(raw.trim()) as {
384
- state: {
385
- trace: Array<{ result?: { content: string } }>;
386
- calls: Array<{ result?: { content: string }; traceNode: { result?: { content: string } } }>;
387
- };
388
- };
389
-
390
- // trace 投影瘦身生效:trace[0] 含标记
391
- expect(snapshot.state.trace[0]!.result!.content).toContain(
392
- "[trace result truncated, original 10000 chars]",
393
- );
394
- // calls[].traceNode 是同一裁剪后节点引用(剥 live 后的 rest),亦含标记
395
- expect(snapshot.state.calls[0]!.traceNode.result!.content).toContain(
396
- "[trace result truncated, original 10000 chars]",
397
- );
398
- // 顶层 calls[].result 字段不裁——全量 10000
399
- expect(snapshot.state.calls[0]!.result!.content).toHaveLength(10000);
400
-
401
- // loadAll 回读:fromArray 不再裁,与落盘形态逐字节一致(无标记嵌套)
402
- const loaded = await store.loadAll();
403
- expect(loaded).toHaveLength(1);
404
- const restoredContent = loaded[0]!.state.trace.toArray()[0]!.result!.content;
405
- expect(restoredContent).toBe(snapshot.state.trace[0]!.result!.content);
406
- expect(restoredContent.match(/truncated/g)).toHaveLength(1);
407
- });
408
- });
@@ -1,83 +0,0 @@
1
- /**
2
- * Workflow Extension — AgentCall 实体
3
- *
4
- * 单次 agent 调用的数据 + 不变式守卫(D-12)。纯数据,无 execute 上帝方法——
5
- * 执行编排(重试+预算+stale 检测)在 execute-agent-call.ts 的 free function。
6
- *
7
- * - 状态机:pending → running → done(不可逆)
8
- * - markRunning 进入 running 并 attempts++(每次 retry 前调用)
9
- * - markDone(result) 进入 done 并记录结果
10
- * - traceNode 持有引用,但 AgentCall 不直接改其字段——trace 同步由
11
- * Trace.update 负责(D-10 单一来源),AgentCall 只持有引用供 executeAgentCall 读取
12
- *
13
- * 层归属:Engine。
14
- *
15
- * 参考:domain-models.md §5(字段/不变式/设计决策)。
16
- */
17
- import type { AgentCallOpts, AgentResult, ExecutionTraceNode } from "./types.ts";
18
-
19
- /** AgentCall 生命周期状态。pending→running→done,不可逆。 */
20
- export type AgentCallStatus = "pending" | "running" | "done";
21
-
22
- /**
23
- * AgentCall 实体(在 RunState.calls Map 内)。
24
- *
25
- * 不变式:
26
- * - status 转换严格 pending→running→done,反向抛错
27
- * - done 时 result 必须已设置(markDone(result) 前置保证)
28
- * - attempts 反映 dispatch 次数(markRunning 累加,含首次)
29
- * - **无 execute 方法**(D-12:执行编排由 Engine executeAgentCall 函数承担)
30
- */
31
- export class AgentCall {
32
- readonly id: number;
33
- readonly opts: AgentCallOpts;
34
- status: AgentCallStatus = "pending";
35
- attempts = 0;
36
- result?: AgentResult;
37
- /** Pi subprocess session ID(uuidv7,G-017 归此)。 */
38
- sessionId?: string;
39
- /** Session JSONL 绝对路径(finalizeCall 后从 result.sessionFile 填入,对齐 sessionId 模式)。 */
40
- sessionFile?: string;
41
- /** 与 Trace 共享的节点引用(D-10 单源)。AgentCall 不直接改其字段。 */
42
- readonly traceNode: ExecutionTraceNode;
43
-
44
- constructor(id: number, opts: AgentCallOpts, traceNode: ExecutionTraceNode) {
45
- this.id = id;
46
- this.opts = opts;
47
- this.traceNode = traceNode;
48
- }
49
-
50
- /**
51
- * 标记进入 running 状态(dispatch 前)。attempts++(含首次)。
52
- * @throws 若已 done(不可重启)
53
- */
54
- markRunning(): void {
55
- if (this.status === "done") {
56
- throw new Error(`AgentCall ${this.id} already done — cannot mark running`);
57
- }
58
- this.status = "running";
59
- this.attempts += 1;
60
- }
61
-
62
- /**
63
- * 标记完成(成功或失败均调用——result.error 区分)。
64
- * @throws 若当前非 running(pending 不能直接跳 done,必须先 markRunning)
65
- */
66
- markDone(result: AgentResult): void {
67
- if (this.status !== "running") {
68
- throw new Error(`AgentCall ${this.id} must be running to mark done (was ${this.status})`);
69
- }
70
- this.result = result;
71
- this.status = "done";
72
- }
73
-
74
- /** 记录 pi subprocess session ID(dispatch 成功后)。 */
75
- setSessionId(sessionId: string): void {
76
- this.sessionId = sessionId;
77
- }
78
-
79
- /** 记录 session JSONL 绝对路径(finalizeCall 后,对齐 setSessionId 模式)。 */
80
- setSessionFile(sessionFile: string): void {
81
- this.sessionFile = sessionFile;
82
- }
83
- }
@@ -1,118 +0,0 @@
1
- /**
2
- * Workflow Extension — Budget 值对象
3
- *
4
- * Token / cost 预算值对象(D-12)。纯数据 + 不变式守卫,无副作用。
5
- *
6
- * maxTokens===0 视为不限制(守卫,避免首个 agent 完成误判 budget_limited)。
7
- * (预算语义对齐 2026-08:soft-limit 常量(500 调用数预警)与 90% 阈值预警方法
8
- * 已删——全库无生产消费方,仅测试锁定。)
9
- *
10
- * 层归属:Engine。
11
- *
12
- * 参考:domain-models.md §4(字段/不变式/操作)。
13
- */
14
- import type { AgentUsage } from "./types.ts";
15
-
16
- /**
17
- * Budget 加权系数(token 口径)。
18
- *
19
- * usedTokens 不再是四项原始 token 简单求和,而是加权后的「等效消耗」,
20
- * 反映不同 token 桶的真实计费/处理开销差异:
21
- * - input(非缓存新增):首次见到、需完整处理的新内容,权重 1(基准)
22
- * - cacheRead(命中缓存):读取历史,开销极低,按 1/50 折算(权重 0.02)
23
- * - cacheWrite(首次写入缓存):本版本不计入 budget(权重 0)
24
- * - output:模型自回归生成,开销最高,权重 2
25
- *
26
- * 这避免了长 session 中 cacheRead 随轮次单调累积导致 budget 被快速烧穿的失真
27
- * (详见讨论:cacheRead 在 N 轮里被报 N 次,去重上下文只有一份)。
28
- */
29
- export const INPUT_WEIGHT = 1;
30
- export const CACHE_READ_WEIGHT = 0.02;
31
- export const CACHE_WRITE_WEIGHT = 0;
32
- export const OUTPUT_WEIGHT = 2;
33
-
34
- /**
35
- * Budget 值对象。
36
- *
37
- * 不变式(domain-models.md §4):
38
- * - maxTokens > 0 守卫:maxTokens===0 或 undefined 视为不限制
39
- * - maxCost > 0 守卫:同上
40
- * - consume 只累加,不减;isExceeded 只读
41
- * - 无回调字段——所有副作用由调用方在 consume 后查询决定
42
- */
43
- export class Budget {
44
- readonly maxTokens?: number;
45
- readonly maxCost?: number;
46
- readonly maxTimeMs?: number;
47
- usedTokens = 0;
48
- usedCost = 0;
49
- /** 总调用计数(持久化/诊断用;execute-agent-call 每次 dispatch 后 increment)。 */
50
- totalCallCount = 0;
51
-
52
- constructor(opts: {
53
- maxTokens?: number;
54
- maxCost?: number;
55
- maxTimeMs?: number;
56
- usedTokens?: number;
57
- usedCost?: number;
58
- totalCallCount?: number;
59
- } = {}) {
60
- this.maxTokens = opts.maxTokens;
61
- this.maxCost = opts.maxCost;
62
- this.maxTimeMs = opts.maxTimeMs;
63
- this.usedTokens = opts.usedTokens ?? 0;
64
- this.usedCost = opts.usedCost ?? 0;
65
- this.totalCallCount = opts.totalCallCount ?? 0;
66
- }
67
-
68
- /**
69
- * 累加一次 agent 调用的 usage(加权口径)。
70
- *
71
- * 四项 token 按各自权重(INPUT/CACHE_READ/CACHE_WRITE/OUTPUT_WEIGHT)折算后求和,
72
- * 而非原始 token 数直接相加。retry 间的真实消耗如实记录,避免预算被低估。
73
- * 详见上方权重常量的口径说明。
74
- */
75
- consume(usage: AgentUsage): void {
76
- // NaN 守卫——非有限值当 0 处理,防 usedTokens 变 NaN 导致 isExceeded() 永远 false(预算限制失效)
77
- const numOrZero = (v: number | undefined): number =>
78
- typeof v === "number" && Number.isFinite(v) ? v : 0;
79
- this.usedTokens +=
80
- numOrZero(usage.input) * INPUT_WEIGHT +
81
- numOrZero(usage.output) * OUTPUT_WEIGHT +
82
- numOrZero(usage.cacheRead) * CACHE_READ_WEIGHT +
83
- numOrZero(usage.cacheWrite) * CACHE_WRITE_WEIGHT;
84
- this.usedCost += numOrZero(usage.cost);
85
- }
86
-
87
- /** 累加调用计数(每次 agent dispatch 后调用;持久化快照同步)。 */
88
- incrementCallCount(): void {
89
- this.totalCallCount += 1;
90
- }
91
-
92
- /**
93
- * 是否超 token / cost 预算(FR-3)。
94
- *
95
- * maxTokens===0 或 undefined 视为不限制(守卫);
96
- * maxCost===0 或 undefined 视为不限制。
97
- * 时间预算(maxTimeMs)不由本方法判断——它是 wall-clock 约束,需参照 startedAt,
98
- * 由 lifecycle 层的 scheduleTimeBudget(runWorkflow 内 setTimeout)
99
- * 独立调度,到期 abortRun(doneReason="time_limited")。
100
- */
101
- isExceeded(): boolean {
102
- if (this.maxTokens !== undefined && this.maxTokens > 0 && this.usedTokens >= this.maxTokens) {
103
- return true;
104
- }
105
- return this.maxCost !== undefined && this.maxCost > 0 && this.usedCost >= this.maxCost;
106
- }
107
-
108
- /**
109
- * 剩余 token 预算。maxTokens 未设或 ≤0 时返回 undefined(视为不限制)。
110
- *
111
- * 嵌套 workflow() 调用时由 executeNestedWorkflow 消费:子 run 的 budgetTokens
112
- * 继承父 run 的剩余预算,实现父子预算隔离下的总量约束。
113
- */
114
- remaining(): number | undefined {
115
- if (this.maxTokens === undefined || this.maxTokens <= 0) return undefined;
116
- return Math.max(0, this.maxTokens - this.usedTokens);
117
- }
118
- }