@zhushanwen/subagent-core 0.4.0 → 0.6.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.
- package/dist/{chunk-4KN4TTG7.js → chunk-43ONBFZX.js} +1 -1
- package/dist/{chunk-X7SZ5HLQ.js → chunk-V3VHZ2VX.js} +20 -27
- package/dist/execution/engine/engines/zcode/constants.cjs +29 -41
- package/dist/execution/engine/engines/zcode/constants.d.cts +65 -53
- package/dist/execution/engine/engines/zcode/constants.d.ts +65 -53
- package/dist/execution/engine/engines/zcode/constants.js +17 -27
- package/dist/execution/engine/engines/zcode/reader.d.cts +2 -1
- package/dist/execution/engine/engines/zcode/reader.d.ts +2 -1
- package/dist/execution/engine/engines/zcode/reader.js +2 -2
- package/dist/index.cjs +17100 -14082
- package/dist/index.d.cts +5336 -4033
- package/dist/index.d.ts +5336 -4033
- package/dist/index.js +17020 -14055
- package/dist/{types-DpUO16pj.d.cts → types-C3fE3R9x.d.cts} +280 -112
- package/dist/{types-DpUO16pj.d.ts → types-C3fE3R9x.d.ts} +280 -112
- package/dist.bundle/index.cjs +34933 -0
- package/package.json +3 -3
- package/src/__tests__/agent-opts-resolver-schema-prompt.test.ts +0 -1
- package/src/__tests__/append-system-prompt-assembly.test.ts +8 -7
- package/src/__tests__/fr4-get-state-handshake.test.ts +2 -2
- package/src/__tests__/m2-append-content-probe.test.ts +0 -1
- package/src/__tests__/manifest-store.test.ts +10 -9
- package/src/__tests__/record-store-cache.test.ts +0 -2
- package/src/__tests__/record-store-index.test.ts +1 -2
- package/src/__tests__/review-fix-loop-script.test.ts +4 -2
- package/src/__tests__/review-fix-loop-utils.test.ts +10 -10
- package/src/__tests__/robustness-low-batch1.test.ts +6 -5
- package/src/__tests__/robustness-medium-batch1.test.ts +2 -2
- package/src/__tests__/robustness-medium-batch2.test.ts +17 -6
- package/src/__tests__/robustness-medium-batch4.test.ts +2 -2
- package/src/__tests__/session-runner.test.ts +1 -1
- package/src/core/__tests__/host-services.test.ts +2 -2
- package/src/core/__tests__/logger.test.ts +1 -1
- package/src/core/error-message.ts +9 -0
- package/src/core/host-services.ts +21 -5
- package/src/core/notify-ports.ts +18 -5
- package/src/execution/__tests__/agent-profile.test.ts +4 -4
- package/src/execution/__tests__/agent-registry.test.ts +370 -0
- package/src/execution/__tests__/agent-result-mapper.test.ts +18 -2
- package/src/execution/__tests__/agents-assembly.test.ts +2 -2
- package/src/execution/__tests__/alive-store.test.ts +1 -1
- package/src/execution/__tests__/ask-user-transit-e2e.test.ts +6 -6
- package/src/execution/__tests__/chat-engine-routing.test.ts +68 -33
- package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +4 -4
- package/src/execution/__tests__/cold-resurrect.test.ts +283 -0
- package/src/execution/__tests__/collect-budget.test.ts +291 -0
- package/src/execution/__tests__/collect-coordinator-service.test.ts +327 -0
- package/src/execution/__tests__/collect-coordinator.test.ts +371 -0
- package/src/execution/__tests__/collect-mixed-dispatch.test.ts +262 -0
- package/src/execution/__tests__/config-collect-sync.test.ts +120 -0
- package/src/execution/__tests__/config.test.ts +1 -1
- package/src/execution/__tests__/delivery-methods.test.ts +75 -62
- package/src/execution/__tests__/descendant-sweep-guards.test.ts +220 -0
- package/src/execution/__tests__/descendant-sweep.test.ts +6 -6
- package/src/execution/__tests__/dialog-queue.test.ts +2 -2
- package/src/execution/__tests__/engine-model-validation.test.ts +741 -0
- package/src/execution/__tests__/epipe-fallback.test.ts +29 -24
- package/src/execution/__tests__/execute-and-await-worktree.test.ts +21 -91
- package/src/execution/__tests__/execute-nesting.test.ts +34 -188
- package/src/execution/__tests__/execution-record.test.ts +217 -60
- package/src/execution/__tests__/execution-runtime-face.test.ts +5 -5
- package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +4 -4
- package/src/execution/__tests__/finalize-record.test.ts +173 -17
- package/src/execution/__tests__/finalized-marker.test.ts +1 -1
- package/src/execution/__tests__/gc-timer.test.ts +56 -3
- package/src/execution/__tests__/get-record-for-action-restart.test.ts +12 -12
- package/src/execution/__tests__/get-state-handshake.test.ts +1 -1
- package/src/execution/__tests__/helpers/mock-extension-api.ts +1 -1
- package/src/execution/__tests__/helpers/session-runner-mocks.ts +113 -0
- package/src/execution/__tests__/helpers/spawn-mock.ts +150 -3
- package/src/execution/__tests__/helpers/subagent-service-mocks.ts +137 -0
- package/src/execution/__tests__/keep-alive-no-progress.test.ts +50 -148
- package/src/execution/__tests__/kill-all-escalation.test.ts +2 -2
- package/src/execution/__tests__/lifecycle-predicates.test.ts +1 -2
- package/src/execution/__tests__/manifest-parentid.test.ts +4 -4
- package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +1 -1
- package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +1 -1
- package/src/execution/__tests__/model-resolver.test.ts +2 -2
- package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +23 -121
- package/src/execution/__tests__/nested-visibility.test.ts +2 -0
- package/src/execution/__tests__/notify-batch.test.ts +500 -0
- package/src/execution/__tests__/notify-ledger.test.ts +1000 -18
- package/src/execution/__tests__/output-collector.test.ts +117 -6
- package/src/execution/__tests__/pi-invocation.test.ts +36 -4
- package/src/execution/__tests__/record-entry-collect.test.ts +102 -0
- package/src/execution/__tests__/record-store.test.ts +10 -9
- package/src/execution/__tests__/records-cwd-isolation.test.ts +2 -2
- package/src/execution/__tests__/recursive-visibility-baseline.test.ts +29 -132
- package/src/execution/__tests__/recursive-visibility-env.test.ts +55 -179
- package/src/execution/__tests__/relay-env.test.ts +12 -1
- package/src/execution/__tests__/rpc-mode.test.ts +2 -2
- package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +387 -0
- package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +15 -9
- package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +4 -4
- package/src/execution/__tests__/run-spawn-edges.test.ts +17 -15
- package/src/execution/__tests__/run-spawn-integration.test.ts +2 -2
- package/src/execution/__tests__/run-spawn-resume.test.ts +2 -2
- package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +2 -2
- package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +4 -4
- package/src/execution/__tests__/service-kill-escalation.test.ts +7 -5
- package/src/execution/__tests__/session-context-resolver.test.ts +0 -2
- package/src/execution/__tests__/session-file-gc.test.ts +36 -1
- package/src/execution/__tests__/session-pending.test.ts +257 -14
- package/src/execution/__tests__/session-reconstructor.test.ts +366 -15
- package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +1 -1
- package/src/execution/__tests__/session-runner-close-prune.test.ts +2 -2
- package/src/execution/__tests__/session-runner-dispatch.test.ts +489 -0
- package/src/execution/__tests__/session-runner-epipe.test.ts +3 -3
- package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +5 -4
- package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +290 -0
- package/src/execution/__tests__/session-runner-schema-env.test.ts +7 -5
- package/src/execution/__tests__/settled-watchdog.test.ts +282 -47
- package/src/execution/__tests__/spawn-args.test.ts +11 -10
- package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +26 -23
- package/src/execution/__tests__/spawn-event-adapter.test.ts +3 -3
- package/src/execution/__tests__/spawn-worktree-guidance.test.ts +5 -4
- package/src/execution/__tests__/spawned-children.test.ts +2 -1
- package/src/execution/__tests__/start-collect-guard.test.ts +255 -0
- package/src/execution/__tests__/start-sync-model-guard.test.ts +5 -5
- package/src/execution/__tests__/stdin-writer.test.ts +6 -4
- package/src/execution/__tests__/stream-sink-retirement.test.ts +6 -6
- package/src/execution/__tests__/subagent-actions-core.test.ts +48 -22
- package/src/execution/__tests__/subagent-service-message-close.test.ts +29 -26
- package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +21 -8
- package/src/execution/__tests__/subagent-service-notify-gate.test.ts +27 -22
- package/src/execution/__tests__/subagent-service-parent-guard.test.ts +30 -29
- package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +45 -20
- package/src/execution/__tests__/subagent-service.test.ts +37 -30
- package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +88 -12
- package/src/execution/__tests__/subprocess-agent-runner-timeout.test.ts +75 -0
- package/src/execution/__tests__/subprocess-agent-runner.test.ts +22 -20
- package/src/execution/__tests__/sync-collect-recovery.test.ts +1117 -0
- package/src/execution/__tests__/temp-prompt.test.ts +1 -1
- package/src/execution/__tests__/timeout-integration.test.ts +6 -5
- package/src/execution/__tests__/tombstone-store.test.ts +1 -1
- package/src/execution/__tests__/turn-limiter-semantics.test.ts +1 -1
- package/src/execution/__tests__/turn-limiter.test.ts +1 -1
- package/src/execution/__tests__/ui-request-handler-factory.test.ts +12 -6
- package/src/execution/__tests__/ui-request-handler.test.ts +4 -3
- package/src/execution/__tests__/ui-request-queue.test.ts +142 -2
- package/src/execution/__tests__/worktree-git-ops.test.ts +1 -1
- package/src/execution/__tests__/worktree-manager.test.ts +14 -5
- package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +4 -3
- package/src/execution/__tests__/worktree-reconcile-aging.test.ts +2 -2
- package/src/execution/__tests__/worktree-reconcile.integration.test.ts +1 -1
- package/src/execution/__tests__/worktree-registry.test.ts +1 -1
- package/src/execution/agent-registry.ts +74 -30
- package/src/execution/agent-result-mapper.ts +3 -0
- package/src/execution/cold-resurrect.ts +199 -0
- package/src/execution/collect-coordinator.ts +200 -0
- package/src/execution/config.ts +77 -5
- package/src/execution/engine/__tests__/common/capability-gate.test.ts +91 -0
- package/src/execution/engine/__tests__/common/data-dir.test.ts +1 -1
- package/src/execution/engine/__tests__/common/event-journal.test.ts +1 -1
- package/src/execution/engine/__tests__/common/journal-wiring.test.ts +84 -0
- package/src/execution/engine/__tests__/common/kill-chain.test.ts +34 -7
- package/src/execution/engine/__tests__/common/persona-router.test.ts +4 -5
- package/src/execution/engine/__tests__/common/pool-manager.test.ts +213 -53
- package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +149 -0
- package/src/execution/engine/__tests__/common/session-view-service.test.ts +499 -0
- package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +22 -112
- package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +15 -28
- package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +1 -1
- package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +12 -12
- package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +2 -2
- package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +21 -82
- package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +4 -7
- package/src/execution/engine/__tests__/engine-discovery.test.ts +15 -3
- package/src/execution/engine/__tests__/model-prompt.test.ts +15 -3
- package/src/execution/engine/__tests__/registry.test.ts +4 -2
- package/src/execution/engine/__tests__/routing.test.ts +115 -6
- package/src/execution/engine/common/capability-gate.ts +92 -0
- package/src/execution/engine/common/journal-wiring.ts +97 -0
- package/src/execution/engine/common/kill-chain.ts +42 -10
- package/src/execution/engine/common/nesting-guard.ts +66 -0
- package/src/execution/engine/common/persona-router.ts +18 -8
- package/src/execution/engine/common/pool-manager.ts +332 -78
- package/src/execution/engine/common/session-view-service.ts +506 -0
- package/src/execution/engine/common/session-view-types.ts +125 -0
- package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +174 -28
- package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +257 -0
- package/src/execution/{argv-mirror.ts → engine/engines/pi/argv-mirror.ts} +43 -21
- package/src/execution/{get-state-handshake.ts → engine/engines/pi/get-state-handshake.ts} +1 -1
- package/src/execution/{output-collector.ts → engine/engines/pi/output-collector.ts} +108 -19
- package/src/execution/engine/engines/pi/pi-engine.ts +434 -38
- package/src/execution/{pi-invocation.ts → engine/engines/pi/pi-invocation.ts} +2 -2
- package/src/execution/engine/engines/pi/reader.ts +11 -0
- package/src/execution/engine/engines/pi/registration.ts +4 -2
- package/src/execution/{session-runner.ts → engine/engines/pi/session-runner.ts} +617 -412
- package/src/execution/{spawn-event-adapter.ts → engine/engines/pi/spawn-event-adapter.ts} +75 -34
- package/src/execution/{stdin-writer.ts → engine/engines/pi/stdin-writer.ts} +10 -9
- package/src/execution/{temp-prompt.ts → engine/engines/pi/temp-prompt.ts} +2 -2
- package/src/execution/{turn-limiter.ts → engine/engines/pi/turn-limiter.ts} +1 -1
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +54 -27
- package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +321 -0
- package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +13 -12
- package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +7 -210
- package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +6 -110
- package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +247 -0
- package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +451 -0
- package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +20 -8
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +77 -110
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +26 -320
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +210 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +353 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +282 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +372 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +48 -148
- package/src/execution/engine/engines/zcode/appserver-launcher.ts +167 -0
- package/src/execution/engine/engines/zcode/connection.ts +24 -11
- package/src/execution/engine/engines/zcode/constants.ts +75 -71
- package/src/execution/engine/engines/zcode/golden-sample.ts +8 -46
- package/src/execution/engine/engines/zcode/parser.ts +12 -346
- package/src/execution/engine/engines/zcode/preparer.ts +12 -143
- package/src/execution/engine/engines/zcode/session-channel.ts +351 -39
- package/src/execution/engine/engines/zcode/zcode-engine.ts +665 -760
- package/src/execution/engine/host-task-spec.ts +32 -36
- package/src/execution/engine/model-validation.ts +177 -0
- package/src/execution/engine/port.ts +24 -6
- package/src/execution/engine/routing.ts +75 -1
- package/src/execution/engine/types.ts +30 -103
- package/src/execution/execution-record.ts +229 -144
- package/src/execution/finalize-record.ts +141 -99
- package/src/execution/idle-gc.ts +28 -0
- package/src/execution/lifecycle-predicates.ts +1 -1
- package/src/execution/notifier.ts +234 -25
- package/src/execution/notify-host.ts +232 -0
- package/src/execution/record-entry.ts +16 -0
- package/src/execution/record-store.ts +280 -103
- package/src/execution/round-settlement.ts +93 -0
- package/src/execution/session-file-gc.ts +96 -62
- package/src/execution/session-reconstructor.ts +256 -143
- package/src/execution/sessions-index.ts +117 -47
- package/src/execution/settled-watchdog.ts +264 -52
- package/src/execution/subagent-actions-core.ts +84 -28
- package/src/execution/subagent-service.ts +1225 -964
- package/src/execution/subprocess-agent-runner.ts +144 -97
- package/src/execution/sync-rebuild.ts +87 -0
- package/src/execution/types.ts +72 -0
- package/src/execution/ui-request-handler-factory.ts +102 -74
- package/src/execution/ui-request-queue.ts +50 -19
- package/src/index.ts +442 -316
- package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +1 -1
- package/src/orchestration/__tests__/agent-call-stream.test.ts +2 -2
- package/src/orchestration/__tests__/args-validator.test.ts +14 -0
- package/src/orchestration/__tests__/config-loader.test.ts +1 -1
- package/src/orchestration/__tests__/error-recovery-rebuild-failure.test.ts +1 -1
- package/src/orchestration/__tests__/error-recovery-terminal-hardening.test.ts +11 -9
- package/src/orchestration/__tests__/execute-agent-call.test.ts +151 -11
- package/src/orchestration/__tests__/file-run-store-prune.test.ts +1 -1
- package/src/orchestration/__tests__/file-run-store-throttle.test.ts +1 -1
- package/src/orchestration/__tests__/file-run-store.test.ts +7 -6
- package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +2 -2
- package/src/orchestration/__tests__/lifecycle-abort-broadcast-signal.test.ts +1 -1
- package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +3 -3
- package/src/orchestration/__tests__/lifecycle.test.ts +7 -5
- package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +1 -1
- package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +1 -1
- package/src/orchestration/__tests__/run-snapshot.test.ts +8 -5
- package/src/orchestration/__tests__/script-generate.test.ts +5 -5
- package/src/orchestration/__tests__/script-lint.test.ts +17 -0
- package/src/orchestration/__tests__/skill-discovery.test.ts +2 -2
- package/src/orchestration/__tests__/test-mocks.ts +2 -0
- package/src/orchestration/__tests__/worker-exit-without-result.test.ts +7 -6
- package/src/orchestration/__tests__/worker-message-pump-finalize-run.test.ts +229 -0
- package/src/orchestration/__tests__/{error-recovery-handlers.test.ts → worker-message-pump-handlers.test.ts} +27 -19
- package/src/orchestration/__tests__/{error-recovery-postmessage-defense.test.ts → worker-message-pump-postmessage-defense.test.ts} +8 -8
- package/src/orchestration/__tests__/{error-recovery-serialize-failed-result.test.ts → worker-message-pump-serialize-failed-result.test.ts} +2 -2
- package/src/orchestration/__tests__/{error-recovery-workflow-call.test.ts → worker-message-pump-workflow-call.test.ts} +1 -1
- package/src/orchestration/__tests__/worker-pending-timeout-abort.test.ts +1 -1
- package/src/orchestration/__tests__/worker-script-builder.test.ts +1 -1
- package/src/orchestration/__tests__/workflow-files.test.ts +10 -10
- package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +1 -1
- package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +1 -1
- package/src/orchestration/agent-opts-resolver.ts +1 -1
- package/src/orchestration/args-validator.ts +53 -31
- package/src/orchestration/execute-agent-call.ts +19 -73
- package/src/orchestration/launcher.ts +128 -81
- package/src/orchestration/lifecycle.ts +43 -45
- package/src/orchestration/models/ports.ts +4 -4
- package/src/orchestration/models/run-runtime.ts +2 -2
- package/src/orchestration/models/trace.ts +1 -1
- package/src/orchestration/models/types.ts +111 -22
- package/src/orchestration/models/workflow-run.ts +1 -1
- package/src/orchestration/script-lint.ts +91 -58
- package/src/orchestration/{error-recovery.ts → worker-message-pump.ts} +157 -150
- package/src/shared/__tests__/atomic-write.test.ts +1 -1
- package/src/shared/__tests__/meta-parser.test.ts +151 -0
- package/src/shared/__tests__/resource-discovery-host-roots.test.ts +5 -5
- package/src/shared/__tests__/resource-discovery.test.ts +258 -215
- package/src/shared/atomic-write.ts +12 -9
- package/src/shared/meta-parser.ts +158 -84
- package/src/shared/model-ref.ts +15 -2
- package/src/shared/resource-discovery.ts +9 -183
- package/src/shared/schema-jsonify.ts +1 -1
- package/workflows/review-fix-loop-utils.cjs +151 -89
- package/workflows/review-fix-loop-utils.d.cts +287 -0
- package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
- package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
- package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
- package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
- package/src/execution/engine/engines/zcode/__tests__/preparer-appserver.test.ts +0 -387
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -710
- package/src/execution/engine/engines/zcode/appserver-home.ts +0 -442
- package/src/execution/engine/engines/zcode/appserver-probe.ts +0 -141
- package/src/execution/engine/engines/zcode/launcher.ts +0 -161
- package/src/execution/execute-options-mapper.ts +0 -115
- package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -288
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Workflow Extension — error-recovery
|
|
2
|
+
* Workflow Extension — worker-message-pump(原 error-recovery,D5-① 更名)
|
|
3
3
|
*
|
|
4
|
-
* Worker
|
|
4
|
+
* Worker 消息泵 + 失败恢复 free functions(D-12)。承载四类职责:
|
|
5
|
+
* 1. 消息路由:handleWorkerMessage 分发 agent-call / workflow-call / return / error
|
|
6
|
+
* 2. IPC 序列化防御:postMessage 的 DataCloneError 拦截 + fallback 回发(W2)
|
|
7
|
+
* 3. retry/重建:worker/script 错误的指数退避重试 + rebuildRuntime(G3-001)
|
|
8
|
+
* 4. 终态化:finalizeRun ——「transition → closeOut in-flight → save →
|
|
9
|
+
* pending:unregister → onRunDone」终态序列的唯一定义点(D5-② 单点化,收敛原
|
|
10
|
+
* 8 处逐字复制;OR-8 收口步骤与 OR-4/B-4 双围栏内化于本函数)
|
|
5
11
|
*
|
|
6
12
|
* 4 个导出函数(domain-models.md §失败处理矩阵):
|
|
7
13
|
* - handleWorkerMessage(run, raw, deps, handlers) — 路由 agent_call/return/error/log
|
|
@@ -33,7 +39,7 @@
|
|
|
33
39
|
|
|
34
40
|
import { getLogger } from "../core/logger.ts";
|
|
35
41
|
|
|
36
|
-
import { SLUG_MAX_LENGTH } from "
|
|
42
|
+
import { SLUG_MAX_LENGTH } from "./models/types.ts";
|
|
37
43
|
import { createRecord, updateFromEvent } from "../execution/execution-record.ts";
|
|
38
44
|
import { SubagentStream } from "../execution/stream-sink.ts";
|
|
39
45
|
import type { AgentEvent } from "../shared/agent-event.ts";
|
|
@@ -43,9 +49,10 @@ import { AgentCall } from "./models/agent-call.ts";
|
|
|
43
49
|
import type { LifecycleDeps, WorkerHandlers } from "./models/ports.ts";
|
|
44
50
|
import { RunRuntime } from "./models/run-runtime.ts";
|
|
45
51
|
import type { WorkerLogEntry } from "./models/types.ts";
|
|
46
|
-
import type { AgentCallOpts, AgentResult, ExecutionTraceNode } from "./models/types.ts";
|
|
52
|
+
import type { AgentCallOpts, AgentResult, DoneReason, ExecutionTraceNode } from "./models/types.ts";
|
|
47
53
|
import type { WorkflowRun } from "./models/workflow-run.ts";
|
|
48
54
|
import type { WorkerHandle } from "./worker-handle.ts";
|
|
55
|
+
import { toErrorMessage } from "../core/error-message.ts";
|
|
49
56
|
|
|
50
57
|
const logger = getLogger("subagents");
|
|
51
58
|
|
|
@@ -191,7 +198,7 @@ async function saveRunBestEffort(
|
|
|
191
198
|
try {
|
|
192
199
|
await deps.store.save(run);
|
|
193
200
|
} catch (err) {
|
|
194
|
-
const m =
|
|
201
|
+
const m = toErrorMessage(err);
|
|
195
202
|
logger.error(
|
|
196
203
|
`[workflow] store.save failed (${context}, runId=${run.runId}): ${m}. ` +
|
|
197
204
|
"Continuing state-machine finalization (in-memory state already terminal).",
|
|
@@ -199,55 +206,106 @@ async function saveRunBestEffort(
|
|
|
199
206
|
}
|
|
200
207
|
}
|
|
201
208
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
209
|
+
// ── finalizeRun(D5-② 终态 coda 单写点) ──────────────────────
|
|
210
|
+
|
|
211
|
+
/** finalizeRun 的可调项。 */
|
|
212
|
+
export interface FinalizeRunOptions {
|
|
213
|
+
/** store.save 失败日志的上下文标记(OB3 排障定位,如 "handleReturn (done,completed)")。 */
|
|
214
|
+
context: string;
|
|
215
|
+
/**
|
|
216
|
+
* 是否调 deps.onRunDone(Interface 层完成通知)。缺省 true。
|
|
217
|
+
* terminateRunningRuns 传 false——session 切换/关闭语境下主 agent 已离开本
|
|
218
|
+
* session,注入完成通知只会把消息发给已离开的 session(对齐 session_start
|
|
219
|
+
* 恢复先例:只发 unregister、不发 onRunDone)。
|
|
220
|
+
*/
|
|
221
|
+
notifyDone?: boolean;
|
|
207
222
|
}
|
|
208
223
|
|
|
209
224
|
/**
|
|
210
|
-
*
|
|
225
|
+
* Run 终态五步 coda 的唯一定义点(D5-② + OR-8 收口内化):
|
|
226
|
+
* transition(done) → closeOutInFlightCalls → save(best-effort)→
|
|
227
|
+
* pending:unregister → onRunDone。
|
|
211
228
|
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
* onRunDone
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* [OR-4] 终态收尾副作用围栏:emit pending:unregister + onRunDone,各自独立 M12 同款
|
|
230
|
-
* try 围栏。
|
|
229
|
+
* 收敛前 8 处逐字复制(本文件 6 处 + lifecycle 2 处)已全部改走本函数。原各副本
|
|
230
|
+
* 的三处微差统一为规范形态(收敛裁决,非行为回归):
|
|
231
|
+
* - transition 失败(M12):一律吞掉并中止后续步骤——并发 abort/terminate 抢先
|
|
232
|
+
* 终态化时 illegal-transition 是预期事件,本路径的 unregister/onRunDone 语义已
|
|
233
|
+
* 由抢先方兑现,重复执行只会造成重复注销/重复通知。
|
|
234
|
+
* - save 失败(SW-DATA-3):一律 best-effort——save 抛错若向上抛,handle* 的
|
|
235
|
+
* 调用方(worker-host 绑定处 `void handlers.onXxx(...)`)无人接 →
|
|
236
|
+
* unhandledRejection + pending:unregister / onRunDone 不执行 → pending 通知
|
|
237
|
+
* 幽灵注销(列表残留永不清理的 running 条目)。
|
|
238
|
+
* - unregister reason:`run.state.reason ?? doneReason`——transition 成功后
|
|
239
|
+
* reason 恒有值(不变式 I2),兜底仅防御异常形态,取本路径的 doneReason 语义
|
|
240
|
+
* 最贴近(原各副本 `?? "completed"` / 固定 "failed" / `?? "time_limited"` 三种
|
|
241
|
+
* 死兜底等价收敛)。
|
|
231
242
|
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
243
|
+
* [OR-8] transition 成功后、save 之前 closeOutInFlightCalls——终态收口残留
|
|
244
|
+
* in-flight call(fire-and-forget agent() 未 await / worker 死亡时已 dispatch 的
|
|
245
|
+
* call),先收口再落盘,内存态与持久化快照同一时点收敛(快照不再含 running 节点)。
|
|
235
246
|
*
|
|
236
|
-
* [B-4]
|
|
237
|
-
*
|
|
238
|
-
*
|
|
247
|
+
* [OR-4][B-4] unregister 与 onRunDone 各自独立 try 围栏(不共用一个 try——emit
|
|
248
|
+
* 抛错会跳过 onRunDone):这两个是真实副作用,任一同步抛错不得经 worker-host 的
|
|
249
|
+
* `void handlers.onXxx(...)` 变 unhandledRejection 崩宿主;通知总线故障也不得吞掉
|
|
250
|
+
* Interface 层完成回调(runAndWait 轮询依赖 onRunDone 语义收口,被跳过即悬挂)。
|
|
239
251
|
*
|
|
240
|
-
*
|
|
241
|
-
* handleWorkerExit 的终态路径)与 budget 分支的内联围栏不对称——统一收敛到本函数。
|
|
252
|
+
* @returns 是否成功 transition(false = 转移前已被并发终态化,后续步骤未执行)
|
|
242
253
|
*/
|
|
243
|
-
export function
|
|
244
|
-
|
|
254
|
+
export async function finalizeRun(
|
|
255
|
+
run: WorkflowRun,
|
|
256
|
+
deps: LifecycleDeps,
|
|
257
|
+
doneReason: DoneReason,
|
|
258
|
+
options: FinalizeRunOptions,
|
|
259
|
+
): Promise<boolean> {
|
|
260
|
+
try {
|
|
261
|
+
run.transition("done", doneReason);
|
|
262
|
+
} catch (te: unknown) {
|
|
263
|
+
// M12:并发 abort/terminate 导致 illegal-transition 是预期的,可忽略——
|
|
264
|
+
// 抢先方已兑现 unregister/onRunDone,本路径让位(debug 日志留痕)。
|
|
265
|
+
void te;
|
|
266
|
+
deps.log?.("debug", "workflow:worker-message-pump", "finalize skipped: run already terminal", {
|
|
267
|
+
runId: run.runId,
|
|
268
|
+
doneReason,
|
|
269
|
+
context: options.context,
|
|
270
|
+
});
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
// [OR-8] 终态收口残留 in-flight call(先收口再落盘——快照不再含 running 节点)
|
|
274
|
+
closeOutInFlightCalls(run);
|
|
275
|
+
await saveRunBestEffort(run, deps, options.context);
|
|
276
|
+
deps.log?.("debug", "workflow:worker-message-pump", "run finalized", {
|
|
277
|
+
runId: run.runId,
|
|
278
|
+
reason: run.state.reason,
|
|
279
|
+
context: options.context,
|
|
280
|
+
});
|
|
281
|
+
// [OR-4] emit pending:unregister 独立围栏(M12 同款)——listener 同步抛错 error
|
|
282
|
+
// 留痕后继续,不崩宿主、不跳过 onRunDone
|
|
245
283
|
try {
|
|
246
|
-
deps.
|
|
284
|
+
deps.eventBus?.emit("pending:unregister", {
|
|
285
|
+
id: run.runId,
|
|
286
|
+
reason: run.state.reason ?? doneReason,
|
|
287
|
+
});
|
|
247
288
|
} catch (err) {
|
|
248
|
-
const m =
|
|
249
|
-
logger.error(`[workflow]
|
|
289
|
+
const m = toErrorMessage(err);
|
|
290
|
+
logger.error(`[workflow] pending:unregister emit failed (${options.context}): ${m}`);
|
|
250
291
|
}
|
|
292
|
+
// [OR-4][B-4] onRunDone 独立围栏(与 emit 拆分——emit 抛错不得吞掉完成回调)
|
|
293
|
+
if (options.notifyDone !== false) {
|
|
294
|
+
try {
|
|
295
|
+
deps.onRunDone?.(run);
|
|
296
|
+
} catch (err) {
|
|
297
|
+
const m = toErrorMessage(err);
|
|
298
|
+
logger.error(`[workflow] onRunDone failed (${options.context}): ${m}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function delay(ms: number): Promise<void> {
|
|
305
|
+
return new Promise((resolve) => {
|
|
306
|
+
const timer = setTimeout(resolve, ms);
|
|
307
|
+
timer.unref();
|
|
308
|
+
});
|
|
251
309
|
}
|
|
252
310
|
|
|
253
311
|
// ── rebuildRuntime(G3-001 整重建) ─────────────────────────
|
|
@@ -395,29 +453,15 @@ function remainingTimeBudgetMs(run: WorkflowRun): number | undefined {
|
|
|
395
453
|
* 重试前发现时间预算已耗尽的收尾:不 rebuild,直接 done,time_limited 终态。
|
|
396
454
|
*
|
|
397
455
|
* 副作用与 handleWorkerError 超限路径对齐:transition + 持久化 + 注销
|
|
398
|
-
* pending-notification + onRunDone
|
|
399
|
-
* illegal-transition 是预期的,可忽略。
|
|
456
|
+
* pending-notification + onRunDone(D5-② 收敛为 finalizeRun 单写点)。
|
|
400
457
|
*/
|
|
401
458
|
async function finalizeTimeBudgetExhausted(run: WorkflowRun, deps: LifecycleDeps): Promise<void> {
|
|
402
|
-
deps.log?.("debug", "workflow:
|
|
459
|
+
deps.log?.("debug", "workflow:worker-message-pump", "time budget exhausted on rebuild, transition done", {
|
|
403
460
|
runId: run.runId,
|
|
404
461
|
budgetTimeMs: run.spec.budgetTimeMs,
|
|
405
462
|
});
|
|
406
463
|
run.state.error = run.state.error ?? `Time budget exhausted (${run.spec.budgetTimeMs} ms wall clock) before retry rebuild`;
|
|
407
|
-
|
|
408
|
-
try {
|
|
409
|
-
run.transition("done", "time_limited");
|
|
410
|
-
transitioned = true;
|
|
411
|
-
} catch (te: unknown) {
|
|
412
|
-
// run 可能在检查后、transition 前被并发 abort——预期,不记错
|
|
413
|
-
void te;
|
|
414
|
-
}
|
|
415
|
-
if (!transitioned) return;
|
|
416
|
-
// [OR-8] 终态收口残留 in-flight call(先收口再落盘)
|
|
417
|
-
closeOutInFlightCalls(run);
|
|
418
|
-
await saveRunBestEffort(run, deps, "finalizeTimeBudgetExhausted (done,time_limited)");
|
|
419
|
-
// [OR-4] M12 同款围栏(终态副作用不经 void 变 unhandledRejection)
|
|
420
|
-
emitTerminalSideEffects(run, deps, "finalizeTimeBudgetExhausted (done,time_limited)");
|
|
464
|
+
await finalizeRun(run, deps, "time_limited", { context: "time budget exhausted on rebuild" });
|
|
421
465
|
}
|
|
422
466
|
|
|
423
467
|
/**
|
|
@@ -455,7 +499,7 @@ export function rebuildRuntime(
|
|
|
455
499
|
}
|
|
456
500
|
// OB3(可观察性):rebuild 关键节点 debug 日志——此前函数体 0 处 deps.log,
|
|
457
501
|
// 崩溃自愈只能靠行为证据诊断(L1 入口 / L2 重排 / L3 discard / L4 完成)。
|
|
458
|
-
deps.log?.("debug", "workflow:
|
|
502
|
+
deps.log?.("debug", "workflow:worker-message-pump", "runtime rebuild start", {
|
|
459
503
|
runId: run.runId,
|
|
460
504
|
budgetTimeMs: run.spec.budgetTimeMs,
|
|
461
505
|
});
|
|
@@ -477,7 +521,7 @@ export function rebuildRuntime(
|
|
|
477
521
|
const remainingBudgetMs = remainingTimeBudgetMs(run);
|
|
478
522
|
if (remainingBudgetMs !== undefined && remainingBudgetMs > 0 && deps.scheduleTimeBudget) {
|
|
479
523
|
timeBudgetTimer = deps.scheduleTimeBudget(run.runId, remainingBudgetMs);
|
|
480
|
-
deps.log?.("debug", "workflow:
|
|
524
|
+
deps.log?.("debug", "workflow:worker-message-pump", "time budget rescheduled", {
|
|
481
525
|
runId: run.runId,
|
|
482
526
|
budgetTimeMs: remainingBudgetMs,
|
|
483
527
|
});
|
|
@@ -499,12 +543,12 @@ export function rebuildRuntime(
|
|
|
499
543
|
// 孤儿守卫(isOrphanedCall)拦截,trace.update 的瞬时污染由 executeAgentCall
|
|
500
544
|
// 的 isOrphaned 谓词(OB2)拦截,此处不重复设防。
|
|
501
545
|
const discardedCallIds = discardInFlightCalls(run);
|
|
502
|
-
deps.log?.("debug", "workflow:
|
|
546
|
+
deps.log?.("debug", "workflow:worker-message-pump", "in-flight calls discarded", {
|
|
503
547
|
runId: run.runId,
|
|
504
548
|
callIds: discardedCallIds,
|
|
505
549
|
count: discardedCallIds.length,
|
|
506
550
|
});
|
|
507
|
-
deps.log?.("debug", "workflow:
|
|
551
|
+
deps.log?.("debug", "workflow:worker-message-pump", "runtime rebuild complete", {
|
|
508
552
|
runId: run.runId,
|
|
509
553
|
});
|
|
510
554
|
}
|
|
@@ -574,7 +618,7 @@ export async function handleWorkerMessage(
|
|
|
574
618
|
`[workflow] unknown worker message type dropped (runId=${run.runId}): ` +
|
|
575
619
|
`${JSON.stringify((msg as { type?: unknown }).type)}`,
|
|
576
620
|
);
|
|
577
|
-
deps.log?.("warn", "workflow:
|
|
621
|
+
deps.log?.("warn", "workflow:worker-message-pump", "unknown worker message type", {
|
|
578
622
|
runId: run.runId,
|
|
579
623
|
type: (msg as { type?: unknown }).type,
|
|
580
624
|
});
|
|
@@ -596,7 +640,7 @@ function handleWorkerLog(run: WorkflowRun, msg: LogMsg, deps: LifecycleDeps): vo
|
|
|
596
640
|
if (run.state.errorLogs.length > MAX_ERROR_LOGS) {
|
|
597
641
|
run.state.errorLogs = run.state.errorLogs.slice(-MAX_ERROR_LOGS);
|
|
598
642
|
}
|
|
599
|
-
deps.log?.("debug", "workflow:
|
|
643
|
+
deps.log?.("debug", "workflow:worker-message-pump", "worker log", {
|
|
600
644
|
runId: run.runId,
|
|
601
645
|
phase: msg.phase,
|
|
602
646
|
message,
|
|
@@ -623,6 +667,16 @@ function handleWorkerLog(run: WorkflowRun, msg: LogMsg, deps: LifecycleDeps): vo
|
|
|
623
667
|
* completion 不投递——rebuild 不改 status,第 1 层拦不住跨 runtime 代际的迟到
|
|
624
668
|
* 结果(S7-second 竞态:旧失败结果投给新 worker 劫持重跑 pending → 假成功)。
|
|
625
669
|
*/
|
|
670
|
+
/**
|
|
671
|
+
* M4: agent-call 消息 IPC 字段校验谓词——畸形(opts 非对象/缺失、callId 非数字、
|
|
672
|
+
* prompt 缺失)= true。提取为谓词保持 dispatchAgentCall 主流程可读(圈复杂度门禁)。
|
|
673
|
+
*/
|
|
674
|
+
function isMalformedAgentCallMsg(msg: AgentCallMsg): boolean {
|
|
675
|
+
return typeof msg.callId !== "number" || !Number.isFinite(msg.callId) ||
|
|
676
|
+
typeof msg.opts !== "object" || msg.opts === null ||
|
|
677
|
+
typeof msg.opts.prompt !== "string";
|
|
678
|
+
}
|
|
679
|
+
|
|
626
680
|
function dispatchAgentCall(
|
|
627
681
|
run: WorkflowRun,
|
|
628
682
|
msg: AgentCallMsg,
|
|
@@ -631,9 +685,7 @@ function dispatchAgentCall(
|
|
|
631
685
|
// M4: IPC 字段校验——畸形 agent-call 消息(opts 非对象/缺失、callId 非数字、prompt 缺失)
|
|
632
686
|
// 不写 trace / 不 postAgentResult——这类消息通常意味着 worker 模块版本不匹配或内存损坏,
|
|
633
687
|
// 回发结果给 worker 也没意义(worker 可能已崩)。仅记日志,让 worker timeout/exit 路径接管。
|
|
634
|
-
if (
|
|
635
|
-
typeof msg.opts !== "object" || msg.opts === null ||
|
|
636
|
-
typeof msg.opts.prompt !== "string") {
|
|
688
|
+
if (isMalformedAgentCallMsg(msg)) {
|
|
637
689
|
logger.error(`[workflow] malformed agent-call message: callId=${JSON.stringify(msg.callId)}, opts=${JSON.stringify(msg.opts)?.slice(0, MALFORMED_MSG_LOG_PREVIEW_CHARS)}`);
|
|
638
690
|
return;
|
|
639
691
|
}
|
|
@@ -650,12 +702,14 @@ function dispatchAgentCall(
|
|
|
650
702
|
// slug 复用 agentName(超长截断),live record 的 slug 仅用于 TUI 展示。
|
|
651
703
|
const liveSlug = agentName.length > SLUG_MAX_LENGTH ? agentName.slice(0, SLUG_MAX_LENGTH) : agentName;
|
|
652
704
|
const now = new Date().toISOString();
|
|
705
|
+
// 未显式指定 model 的展示口径(live record 与 trace node 共用,两处一致)。
|
|
706
|
+
const model = msg.opts.model ?? "default";
|
|
653
707
|
// live record:收口 agent 执行过程中的 text/thinking/toolCalls/usage,
|
|
654
708
|
// 供 TUI 在 agent 运行期间显示进度(getEventLog/getCurrentActivity)。
|
|
655
709
|
// 完成时由下方 .then 清除(终态由 node.result 承载)。
|
|
656
710
|
const liveRecord = createRecord(String(msg.callId), {
|
|
657
711
|
agent: agentName,
|
|
658
|
-
model
|
|
712
|
+
model,
|
|
659
713
|
mode: "background",
|
|
660
714
|
task: msg.opts.prompt,
|
|
661
715
|
slug: liveSlug,
|
|
@@ -665,7 +719,7 @@ function dispatchAgentCall(
|
|
|
665
719
|
stepIndex: msg.callId,
|
|
666
720
|
agent: agentName,
|
|
667
721
|
task: msg.opts.prompt,
|
|
668
|
-
model
|
|
722
|
+
model,
|
|
669
723
|
status: "running" as const,
|
|
670
724
|
phase: msg.phase,
|
|
671
725
|
startedAt: now,
|
|
@@ -705,7 +759,7 @@ function dispatchAgentCall(
|
|
|
705
759
|
});
|
|
706
760
|
postAgentResult(run, msg.callId, errorResult, false);
|
|
707
761
|
deps.store.save(run).catch((e: unknown) => {
|
|
708
|
-
logger.error(`[workflow] store.save failed (resolveAgentOpts): ${
|
|
762
|
+
logger.error(`[workflow] store.save failed (resolveAgentOpts): ${toErrorMessage(e)}`);
|
|
709
763
|
});
|
|
710
764
|
return;
|
|
711
765
|
}
|
|
@@ -768,7 +822,7 @@ function dispatchAgentCall(
|
|
|
768
822
|
// budget 同步 / 持久化,仅留日志。executeAgentCall 内 finalizeCall 的
|
|
769
823
|
// trace.update 若已命中重跑新节点(瞬时污染),由重跑完成时的 update 覆盖。
|
|
770
824
|
if (isOrphanedCall(run, msg.callId, call)) {
|
|
771
|
-
deps.log?.("debug", "workflow:
|
|
825
|
+
deps.log?.("debug", "workflow:worker-message-pump", "orphan agent call completion dropped", { runId: run.runId, callId: msg.callId });
|
|
772
826
|
return;
|
|
773
827
|
}
|
|
774
828
|
if (call.result) postAgentResult(run, msg.callId, call.result, false);
|
|
@@ -776,44 +830,24 @@ function dispatchAgentCall(
|
|
|
776
830
|
// 后同步 worker $BUDGET(否则 $BUDGET.spent()/remaining() 恒为 0)
|
|
777
831
|
postBudgetUpdate(run);
|
|
778
832
|
deps.store.save(run).catch((e: unknown) => {
|
|
779
|
-
const m =
|
|
833
|
+
const m = toErrorMessage(e);
|
|
780
834
|
logger.error(`[workflow] store.save failed (agent call ${msg.callId}): ${m}`);
|
|
781
835
|
});
|
|
782
836
|
|
|
783
837
|
// C-2:budget 超限 → 终止整个 run(避免继续 spawn 烧预算)
|
|
784
838
|
// 内联 terminate(不调 lifecycle.abortRun 避免 engine 内循环依赖):
|
|
785
839
|
// 若 run 仍非终态,transition done,budget_limited + 持久化。
|
|
786
|
-
// 上方 status !== "running" 已保证此处非 done(且
|
|
840
|
+
// 上方 status !== "running" 已保证此处非 done(且 finalizeRun 内含 done 让位守卫)。
|
|
787
841
|
if (run.state.budget.isExceeded()) {
|
|
788
842
|
run.state.error = run.state.error ?? "Budget exceeded";
|
|
789
|
-
deps.log?.("debug", "workflow:
|
|
790
|
-
|
|
791
|
-
let transitioned = false;
|
|
792
|
-
try {
|
|
793
|
-
run.transition("done", "budget_limited");
|
|
794
|
-
transitioned = true;
|
|
795
|
-
} catch (te: unknown) {
|
|
796
|
-
// run 可能在 budget 检查后、transition 前被并发 abort——预期,不记错
|
|
797
|
-
void te;
|
|
798
|
-
}
|
|
799
|
-
if (transitioned) {
|
|
800
|
-
// [OR-8] 终态收口残留 in-flight call(先收口再落盘)
|
|
801
|
-
closeOutInFlightCalls(run);
|
|
802
|
-
deps.store.save(run).catch((e: unknown) => {
|
|
803
|
-
const m = e instanceof Error ? e.message : String(e);
|
|
804
|
-
logger.error(`[workflow] store.save failed (budget done): ${m}`);
|
|
805
|
-
});
|
|
806
|
-
deps.log?.("debug", "workflow:error-recovery", "run saved after budget done", { runId: run.runId, reason: run.state.reason });
|
|
807
|
-
// M12: onRunDone/emit 单独 try——这些是真实副作用,错误不应被静默吞掉
|
|
808
|
-
//([OR-4] 围栏收敛到共享 helper,语义与原内联围栏一致)
|
|
809
|
-
emitTerminalSideEffects(run, deps, "budget done");
|
|
810
|
-
}
|
|
843
|
+
deps.log?.("debug", "workflow:worker-message-pump", "budget exceeded, transition done", { runId: run.runId });
|
|
844
|
+
void finalizeRun(run, deps, "budget_limited", { context: "agent call budget done" });
|
|
811
845
|
}
|
|
812
846
|
})
|
|
813
847
|
.catch((err: unknown) => {
|
|
814
848
|
// pre-abort 检查(原 gate.withSlot 语义)在 dispatchCall 入口 reject AbortError——预期,不记错。
|
|
815
849
|
if (err instanceof Error && err.name === "AbortError") return;
|
|
816
|
-
const message =
|
|
850
|
+
const message = toErrorMessage(err);
|
|
817
851
|
logger.error(`[workflow] agent call ${msg.callId} failed: ${message}`);
|
|
818
852
|
// 兜底回发:executeAgentCall 抛非 Abort 异常时(如 runner undefined 的 TypeError、
|
|
819
853
|
// dispatchCall 内部 bug)原 catch 仅 console.error,worker 内对 callId 的 pending
|
|
@@ -826,7 +860,7 @@ function dispatchAgentCall(
|
|
|
826
860
|
// 留日志,全部跳过。node.live 无条件先清(旧节点已脱离 trace,防御性统一)。
|
|
827
861
|
node.live = undefined;
|
|
828
862
|
if (isOrphanedCall(run, msg.callId, call)) {
|
|
829
|
-
deps.log?.("debug", "workflow:
|
|
863
|
+
deps.log?.("debug", "workflow:worker-message-pump", "orphan agent call failure dropped", { runId: run.runId, callId: msg.callId });
|
|
830
864
|
return;
|
|
831
865
|
}
|
|
832
866
|
const errorResult: AgentResult = { content: "", error: message };
|
|
@@ -850,7 +884,7 @@ function dispatchAgentCall(
|
|
|
850
884
|
// S2: 与 .then 对称——catch 路径也同步 worker $BUDGET(幂等)
|
|
851
885
|
postBudgetUpdate(run);
|
|
852
886
|
deps.store.save(run).catch((e: unknown) => {
|
|
853
|
-
logger.error(`[workflow] store.save failed (catch fallback): ${
|
|
887
|
+
logger.error(`[workflow] store.save failed (catch fallback): ${toErrorMessage(e)}`);
|
|
854
888
|
});
|
|
855
889
|
});
|
|
856
890
|
}
|
|
@@ -861,7 +895,7 @@ function dispatchAgentCall(
|
|
|
861
895
|
* postResult(workflow-call)与 postAgentResult(agent-call)各自前缀不同,故 prefix 参数化,
|
|
862
896
|
* 共享返回类型与构造逻辑,避免字面量重复导致形状漂移。
|
|
863
897
|
*
|
|
864
|
-
* W2 防御关键纯函数——export 供独立单测(
|
|
898
|
+
* W2 防御关键纯函数——export 供独立单测(worker-message-pump-serialize-failed-result.test.ts)验证
|
|
865
899
|
* 返回 shape `{content:"", error:"<prefix>: <errMsg>"}`,确保两条 fallback 路径(workflow-call /
|
|
866
900
|
* agent-call)共享同一构造逻辑不漂移。
|
|
867
901
|
*/
|
|
@@ -905,7 +939,7 @@ function dispatchWorkflowCall(
|
|
|
905
939
|
result,
|
|
906
940
|
});
|
|
907
941
|
} catch (err) {
|
|
908
|
-
const errMsg =
|
|
942
|
+
const errMsg = toErrorMessage(err);
|
|
909
943
|
logger.error(`[workflow] postResult (workflow-call callId=${msg.callId}) failed: ${errMsg}. Sending error fallback.`);
|
|
910
944
|
// 回发纯字符串 fallback result(必可克隆),让 worker pending resolve
|
|
911
945
|
try {
|
|
@@ -935,7 +969,7 @@ function dispatchWorkflowCall(
|
|
|
935
969
|
.catch((err: unknown) => {
|
|
936
970
|
postResult({
|
|
937
971
|
content: "",
|
|
938
|
-
error:
|
|
972
|
+
error: toErrorMessage(err),
|
|
939
973
|
});
|
|
940
974
|
});
|
|
941
975
|
}
|
|
@@ -958,7 +992,7 @@ function postAgentResult(
|
|
|
958
992
|
try {
|
|
959
993
|
run.runtime?.worker.postMessage({ type: "agent-result", callId, result, cached });
|
|
960
994
|
} catch (err) {
|
|
961
|
-
const msg =
|
|
995
|
+
const msg = toErrorMessage(err);
|
|
962
996
|
logger.error(`[workflow] postAgentResult failed (callId=${callId}): ${msg}. Result likely contains non-cloneable value.`);
|
|
963
997
|
// 回发纯字符串 fallback result(必可克隆),让 worker pending resolve(避免永久挂起)
|
|
964
998
|
try {
|
|
@@ -981,7 +1015,7 @@ function postAgentResult(
|
|
|
981
1015
|
* 更新 spent()/remaining())。每次 agent 调用消费 usage 后发送,保持 worker 内 $BUDGET
|
|
982
1016
|
* 与主线程 Budget 值对象同步。
|
|
983
1017
|
*
|
|
984
|
-
* D-12 regression fix (round-2 #1):重建 budget-update 发送方。被
|
|
1018
|
+
* D-12 regression fix (round-2 #1):重建 budget-update 发送方。被 worker-message-pump 主路径调用
|
|
985
1019
|
* (dispatch 后同步 worker $BUDGET)——单一实现,避免消息形状漂移。
|
|
986
1020
|
*/
|
|
987
1021
|
export function postBudgetUpdate(run: WorkflowRun): void {
|
|
@@ -994,7 +1028,7 @@ export function postBudgetUpdate(run: WorkflowRun): void {
|
|
|
994
1028
|
},
|
|
995
1029
|
});
|
|
996
1030
|
} catch (err) {
|
|
997
|
-
const msg =
|
|
1031
|
+
const msg = toErrorMessage(err);
|
|
998
1032
|
// budget 是纯 number 不太可能失败,但防御性兜底——budget 同步非关键(worker 仍可
|
|
999
1033
|
// 基于 $BUDGET.spent() 自行累计),失败仅记日志,不中断调用方流程。
|
|
1000
1034
|
logger.error(`[workflow] postBudgetUpdate failed: ${msg}. Budget sync to worker skipped (non-critical).`);
|
|
@@ -1009,7 +1043,7 @@ async function handleReturn(
|
|
|
1009
1043
|
msg: ReturnMsg,
|
|
1010
1044
|
deps: LifecycleDeps,
|
|
1011
1045
|
): Promise<void> {
|
|
1012
|
-
deps.log?.("debug", "workflow:
|
|
1046
|
+
deps.log?.("debug", "workflow:worker-message-pump", "handleReturn", { runId: run.runId, status: run.state.status });
|
|
1013
1047
|
// 捕获 worker 诊断日志(P2-2)
|
|
1014
1048
|
// L9: 追加而非覆盖——保留重试历史的诊断日志(各 worker 实例的 console 输出)
|
|
1015
1049
|
if (msg.workerLogs && msg.workerLogs.length > 0) {
|
|
@@ -1019,16 +1053,9 @@ async function handleReturn(
|
|
|
1019
1053
|
}
|
|
1020
1054
|
}
|
|
1021
1055
|
run.state.scriptResult = msg.result;
|
|
1022
|
-
run.transition("done", "completed");
|
|
1023
|
-
// [OR-8] 脚本 return 时可能仍有 fire-and-forget 的 in-flight call(不 await)——
|
|
1024
|
-
// 终态收口为 cancelled,先收口再落盘(快照不再含 running 节点)
|
|
1025
|
-
closeOutInFlightCalls(run);
|
|
1026
|
-
// [SW-DATA-3] save 失败不阻断终态推进(原 await 裸抛 → unhandledRejection + 幽灵注销)
|
|
1027
|
-
await saveRunBestEffort(run, deps, "handleReturn (done,completed)");
|
|
1028
|
-
deps.log?.("debug", "workflow:error-recovery", "run saved after return", { runId: run.runId, reason: run.state.reason });
|
|
1029
1056
|
// C-4: run 到达 done 终态 → 注销 pending-notification + 通知 Interface 层
|
|
1030
|
-
//
|
|
1031
|
-
|
|
1057
|
+
// (D5-② 四步 coda 收敛为 finalizeRun 单写点,含 SW-DATA-3 save 兜底)
|
|
1058
|
+
await finalizeRun(run, deps, "completed", { context: "handleReturn (done,completed)" });
|
|
1032
1059
|
}
|
|
1033
1060
|
|
|
1034
1061
|
// ── handleWorkerError ────────────────────────────────────────
|
|
@@ -1076,16 +1103,10 @@ export async function handleWorkerError(
|
|
|
1076
1103
|
|
|
1077
1104
|
// 超限 → failed
|
|
1078
1105
|
run.state.error = err.message;
|
|
1079
|
-
deps.log?.("debug", "workflow:
|
|
1080
|
-
run.transition("done", "failed");
|
|
1081
|
-
// [OR-8] 终态收口残留 in-flight call(先收口再落盘)
|
|
1082
|
-
closeOutInFlightCalls(run);
|
|
1083
|
-
// [SW-DATA-3] save 失败不阻断终态推进
|
|
1084
|
-
await saveRunBestEffort(run, deps, "handleWorkerError (done,failed)");
|
|
1085
|
-
deps.log?.("debug", "workflow:error-recovery", "run saved after worker error", { runId: run.runId, reason: run.state.reason });
|
|
1106
|
+
deps.log?.("debug", "workflow:worker-message-pump", "handleWorkerError retries exceeded, transition done", { runId: run.runId, count });
|
|
1086
1107
|
// C-4: run 到达 done 终态 → 注销 pending-notification + 通知 Interface 层
|
|
1087
|
-
//
|
|
1088
|
-
|
|
1108
|
+
// (D5-② 四步 coda 收敛为 finalizeRun 单写点)
|
|
1109
|
+
await finalizeRun(run, deps, "failed", { context: "handleWorkerError (done,failed)" });
|
|
1089
1110
|
}
|
|
1090
1111
|
|
|
1091
1112
|
// ── handleWorkerExit ─────────────────────────────────────────
|
|
@@ -1123,16 +1144,11 @@ export async function handleWorkerExit(
|
|
|
1123
1144
|
// [F1] 无终态消息的 exit(0) = worker 静默退出(不可克隆 return 被吞 / 脚本直调
|
|
1124
1145
|
// process.exit(0) 等)。置 failed 保证 runAndWait 必有终态。不重试:rebuild 重跑
|
|
1125
1146
|
// 脚本对确定性根因(不可克隆 return)无意义,且 belt 路径优先给用户明确归因。
|
|
1126
|
-
deps.log?.("debug", "workflow:
|
|
1147
|
+
deps.log?.("debug", "workflow:worker-message-pump", "worker exited without terminal message, transition done", { runId: run.runId });
|
|
1127
1148
|
run.state.error = WORKER_EXITED_WITHOUT_RESULT_MSG;
|
|
1128
|
-
run.transition("done", "failed");
|
|
1129
|
-
// [OR-8] 终态收口残留 in-flight call(先收口再落盘)
|
|
1130
|
-
closeOutInFlightCalls(run);
|
|
1131
|
-
await saveRunBestEffort(run, deps, "handleWorkerExit (done,failed, no terminal message)");
|
|
1132
|
-
deps.log?.("debug", "workflow:error-recovery", "run saved after exit without result", { runId: run.runId, reason: run.state.reason });
|
|
1133
1149
|
// C-4: run 到达 done 终态 → 注销 pending-notification + 通知 Interface 层
|
|
1134
|
-
//
|
|
1135
|
-
|
|
1150
|
+
// (D5-② 四步 coda 收敛为 finalizeRun 单写点)
|
|
1151
|
+
await finalizeRun(run, deps, "failed", { context: "handleWorkerExit (done,failed, no terminal message)" });
|
|
1136
1152
|
return;
|
|
1137
1153
|
}
|
|
1138
1154
|
|
|
@@ -1185,16 +1201,10 @@ export async function handleScriptError(
|
|
|
1185
1201
|
|
|
1186
1202
|
// 超限 → failed
|
|
1187
1203
|
run.state.error = `Workflow failed after ${MAX_WORKER_RETRIES} retries: ${errorMsg}`;
|
|
1188
|
-
deps.log?.("debug", "workflow:
|
|
1189
|
-
run.transition("done", "failed");
|
|
1190
|
-
// [OR-8] 终态收口残留 in-flight call(先收口再落盘)
|
|
1191
|
-
closeOutInFlightCalls(run);
|
|
1192
|
-
// [SW-DATA-3] save 失败不阻断终态推进
|
|
1193
|
-
await saveRunBestEffort(run, deps, "handleScriptError (done,failed)");
|
|
1194
|
-
deps.log?.("debug", "workflow:error-recovery", "run saved after script error", { runId: run.runId, reason: run.state.reason });
|
|
1204
|
+
deps.log?.("debug", "workflow:worker-message-pump", "handleScriptError retries exceeded, transition done", { runId: run.runId, count });
|
|
1195
1205
|
// C-4: run 到达 done 终态 → 注销 pending-notification + 通知 Interface 层
|
|
1196
|
-
//
|
|
1197
|
-
|
|
1206
|
+
// (D5-② 四步 coda 收敛为 finalizeRun 单写点)
|
|
1207
|
+
await finalizeRun(run, deps, "failed", { context: "handleScriptError (done,failed)" });
|
|
1198
1208
|
}
|
|
1199
1209
|
|
|
1200
1210
|
// ── scheduleRebuild(退避 + 重建) ──────────────────────────
|
|
@@ -1264,7 +1274,7 @@ async function handleRebuildStartFailure(
|
|
|
1264
1274
|
handlers: WorkerHandlers,
|
|
1265
1275
|
): Promise<void> {
|
|
1266
1276
|
if (isTerminal(run)) return;
|
|
1267
|
-
const message =
|
|
1277
|
+
const message = toErrorMessage(err);
|
|
1268
1278
|
const count = (run.meta.workerErrorCount ?? 0) + 1;
|
|
1269
1279
|
run.meta.workerErrorCount = count;
|
|
1270
1280
|
logger.error(
|
|
@@ -1278,11 +1288,8 @@ async function handleRebuildStartFailure(
|
|
|
1278
1288
|
|
|
1279
1289
|
// 耗尽 → 收敛 done,failed(不卡 running)
|
|
1280
1290
|
run.state.error = `Runtime rebuild failed after ${MAX_WORKER_RETRIES} retries: ${message}`;
|
|
1281
|
-
deps.log?.("debug", "workflow:
|
|
1282
|
-
|
|
1283
|
-
//
|
|
1284
|
-
|
|
1285
|
-
await saveRunBestEffort(run, deps, "handleRebuildStartFailure (done,failed)");
|
|
1286
|
-
// [OR-4] M12 同款围栏
|
|
1287
|
-
emitTerminalSideEffects(run, deps, "handleRebuildStartFailure (done,failed)");
|
|
1291
|
+
deps.log?.("debug", "workflow:worker-message-pump", "rebuild retries exhausted, transition done", { runId: run.runId, count });
|
|
1292
|
+
// 终态序列与其余 handle* 对齐:transition → closeOut → save → 围栏 emit/onRunDone
|
|
1293
|
+
// (D5-② 收敛为 finalizeRun 单写点)
|
|
1294
|
+
await finalizeRun(run, deps, "failed", { context: "handleRebuildStartFailure (done,failed)" });
|
|
1288
1295
|
}
|