@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,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,148 +0,0 @@
1
- /**
2
- * Workflow Extension — Budget 值对象
3
- *
4
- * Token / cost 预算值对象(D-12)。纯数据 + 不变式守卫,无副作用。
5
- *
6
- * 设计:
7
- * - 无 onConsume 回调(值对象不应持可变回调)。
8
- * - soft limit 通知由 lifecycle 层 consume 后查 isSoftLimitReached 发出(职责分离)。
9
- * - 90% 预警用查询式 isThresholdReached(无状态,可重复查)。
10
- * - maxTokens===0 视为不限制(守卫,避免首个 agent 完成误判 budget_limited)。
11
- *
12
- * 层归属:Engine。
13
- *
14
- * 参考:domain-models.md §4(字段/不变式/操作)。
15
- */
16
- import type { AgentUsage } from "./types.ts";
17
-
18
- /** Soft limit:总调用数超此值发预警(FR-7,从 ConcurrencyGate 迁入)。 */
19
- export const SOFT_MAX_AGENTS_WARNING = 500;
20
-
21
- /**
22
- * Budget 加权系数(token 口径)。
23
- *
24
- * usedTokens 不再是四项原始 token 简单求和,而是加权后的「等效消耗」,
25
- * 反映不同 token 桶的真实计费/处理开销差异:
26
- * - input(非缓存新增):首次见到、需完整处理的新内容,权重 1(基准)
27
- * - cacheRead(命中缓存):读取历史,开销极低,按 1/50 折算(权重 0.02)
28
- * - cacheWrite(首次写入缓存):本版本不计入 budget(权重 0)
29
- * - output:模型自回归生成,开销最高,权重 2
30
- *
31
- * 这避免了长 session 中 cacheRead 随轮次单调累积导致 budget 被快速烧穿的失真
32
- * (详见讨论:cacheRead 在 N 轮里被报 N 次,去重上下文只有一份)。
33
- */
34
- export const INPUT_WEIGHT = 1;
35
- export const CACHE_READ_WEIGHT = 0.02;
36
- export const CACHE_WRITE_WEIGHT = 0;
37
- export const OUTPUT_WEIGHT = 2;
38
-
39
- /**
40
- * Budget 值对象。
41
- *
42
- * 不变式(domain-models.md §4):
43
- * - maxTokens > 0 守卫:maxTokens===0 或 undefined 视为不限制
44
- * - maxCost > 0 守卫:同上
45
- * - consume 只累加,不减;isExceeded 只读
46
- * - 无回调字段——所有副作用由调用方在 consume 后查询决定
47
- */
48
- export class Budget {
49
- readonly maxTokens?: number;
50
- readonly maxCost?: number;
51
- readonly maxTimeMs?: number;
52
- usedTokens = 0;
53
- usedCost = 0;
54
- /** 总调用计数(soft limit 用,从 ConcurrencyGate.totalCallCount 迁入)。 */
55
- totalCallCount = 0;
56
-
57
- constructor(opts: {
58
- maxTokens?: number;
59
- maxCost?: number;
60
- maxTimeMs?: number;
61
- usedTokens?: number;
62
- usedCost?: number;
63
- totalCallCount?: number;
64
- } = {}) {
65
- this.maxTokens = opts.maxTokens;
66
- this.maxCost = opts.maxCost;
67
- this.maxTimeMs = opts.maxTimeMs;
68
- this.usedTokens = opts.usedTokens ?? 0;
69
- this.usedCost = opts.usedCost ?? 0;
70
- this.totalCallCount = opts.totalCallCount ?? 0;
71
- }
72
-
73
- /**
74
- * 累加一次 agent 调用的 usage(加权口径)。
75
- *
76
- * 四项 token 按各自权重(INPUT/CACHE_READ/CACHE_WRITE/OUTPUT_WEIGHT)折算后求和,
77
- * 而非原始 token 数直接相加。retry 间的真实消耗如实记录,避免预算被低估。
78
- * 详见上方权重常量的口径说明。
79
- */
80
- consume(usage: AgentUsage): void {
81
- // NaN 守卫——非有限值当 0 处理,防 usedTokens 变 NaN 导致 isExceeded() 永远 false(预算限制失效)
82
- const numOrZero = (v: number | undefined): number =>
83
- typeof v === "number" && Number.isFinite(v) ? v : 0;
84
- this.usedTokens +=
85
- numOrZero(usage.input) * INPUT_WEIGHT +
86
- numOrZero(usage.output) * OUTPUT_WEIGHT +
87
- numOrZero(usage.cacheRead) * CACHE_READ_WEIGHT +
88
- numOrZero(usage.cacheWrite) * CACHE_WRITE_WEIGHT;
89
- this.usedCost += numOrZero(usage.cost);
90
- }
91
-
92
- /** 累加调用计数(每次 agent dispatch 后调用)。 */
93
- incrementCallCount(): void {
94
- this.totalCallCount += 1;
95
- }
96
-
97
- /**
98
- * 是否超 token / cost 预算(FR-3)。
99
- *
100
- * maxTokens===0 或 undefined 视为不限制(守卫);
101
- * maxCost===0 或 undefined 视为不限制。
102
- * 时间预算(maxTimeMs)不由本方法判断——它是 wall-clock 约束,需参照 startedAt,
103
- * 由 lifecycle 层的 scheduleTimeBudget(runWorkflow 内 setTimeout)
104
- * 独立调度,到期 abortRun(doneReason="time_limited")。
105
- */
106
- isExceeded(): boolean {
107
- if (this.maxTokens !== undefined && this.maxTokens > 0 && this.usedTokens >= this.maxTokens) {
108
- return true;
109
- }
110
- return this.maxCost !== undefined && this.maxCost > 0 && this.usedCost >= this.maxCost;
111
- }
112
-
113
- /**
114
- * 是否达到 soft limit(FR-7)。
115
- *
116
- * totalCallCount > SOFT_MAX_AGENTS_WARNING(500)。
117
- * 调用方(lifecycle)在 consume/incrementCallCount 后查询,
118
- * 命中时发通知(无状态——可重复查询)。
119
- */
120
- isSoftLimitReached(): boolean {
121
- return this.totalCallCount > SOFT_MAX_AGENTS_WARNING;
122
- }
123
-
124
- /**
125
- * 剩余 token 预算。maxTokens 未设或 ≤0 时返回 undefined(视为不限制)。
126
- *
127
- * 嵌套 workflow() 调用时由 executeNestedWorkflow 消费:子 run 的 budgetTokens
128
- * 继承父 run 的剩余预算,实现父子预算隔离下的总量约束。
129
- */
130
- remaining(): number | undefined {
131
- if (this.maxTokens === undefined || this.maxTokens <= 0) return undefined;
132
- return Math.max(0, this.maxTokens - this.usedTokens);
133
- }
134
-
135
- /**
136
- * 是否达到 token 预算的给定比例阈值(如 0.9 = 90% 预警)。
137
- *
138
- * 纯查询,无状态——调用方负责去重(旧 _budgetWarningSent 语义由 lifecycle 层用
139
- * 外部 Set 或 once-listener 实现)。maxTokens 未设或为 0 时返回 false。
140
- */
141
- isThresholdReached(ratio: number): boolean {
142
- return (
143
- this.maxTokens !== undefined &&
144
- this.maxTokens > 0 &&
145
- this.usedTokens >= this.maxTokens * ratio
146
- );
147
- }
148
- }