@zhushanwen/subagent-core 0.5.1 → 0.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.
- package/README.md +1 -1
- package/dist/chunk-KXVBIVOU.js +16 -0
- package/dist/chunk-T2SYBW3I.js +24 -0
- package/dist/chunk-VURUAGMM.js +2305 -0
- package/dist/{types-Dv4QhSJ_.d.cts → engine-discovery-scan-ocpM8FmI.d.cts} +835 -668
- package/dist/{types-Dv4QhSJ_.d.ts → engine-discovery-scan-ocpM8FmI.d.ts} +835 -668
- package/dist/execution/engine/engine-discovery-scan.cjs +2210 -0
- package/dist/execution/engine/engine-discovery-scan.d.cts +4 -0
- package/dist/execution/engine/engine-discovery-scan.d.ts +4 -0
- package/dist/execution/engine/engine-discovery-scan.js +20 -0
- package/dist/execution/engine/paths.cjs +6 -23
- package/dist/execution/engine/paths.d.cts +1 -8
- package/dist/execution/engine/paths.d.ts +1 -8
- package/dist/execution/engine/paths.js +1 -1
- package/dist/execution/relay-env.cjs +12 -28
- package/dist/execution/relay-env.d.cts +1 -33
- package/dist/execution/relay-env.d.ts +1 -33
- package/dist/execution/relay-env.js +5 -3
- package/dist/index.cjs +14123 -15467
- package/dist/index.d.cts +1179 -1540
- package/dist/index.d.ts +1179 -1540
- package/dist/index.js +7694 -10986
- package/dist.bundle/index.cjs +33485 -0
- package/package.json +20 -26
- package/src/__tests__/record-store-last-line.test.ts +16 -7
- package/src/core/error-message.ts +7 -6
- package/src/core/host-services.ts +8 -2
- package/src/core/notify-ports.ts +17 -2
- package/src/execution/__tests__/agent-registry.test.ts +1 -1
- package/src/execution/__tests__/alive-store.test.ts +1 -1
- package/src/execution/__tests__/chat-engine-routing.test.ts +62 -28
- package/src/execution/__tests__/chat-round-first-round-watchdog.test.ts +255 -0
- package/src/execution/__tests__/collect-budget.test.ts +291 -0
- package/src/execution/__tests__/collect-coordinator-service.test.ts +316 -0
- package/src/execution/__tests__/collect-coordinator.test.ts +371 -0
- package/src/execution/__tests__/collect-mixed-dispatch.test.ts +229 -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 +179 -237
- package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -2
- package/src/execution/__tests__/execute-nesting.test.ts +20 -13
- package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +21 -34
- package/src/execution/__tests__/finalized-marker.test.ts +1 -1
- package/src/execution/__tests__/gc-timer.test.ts +8 -23
- package/src/execution/__tests__/get-record-for-action-restart.test.ts +20 -10
- package/src/execution/__tests__/helpers/fake-engine-port.ts +187 -0
- package/src/execution/__tests__/helpers/spawn-mock.ts +36 -9
- package/src/execution/__tests__/helpers/subagent-service-mocks.ts +1 -1
- package/src/execution/__tests__/idle-gc.test.ts +200 -0
- package/src/execution/__tests__/lifecycle-predicates.test.ts +26 -21
- package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +1 -1
- package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +5 -2
- package/src/execution/__tests__/notify-batch.test.ts +500 -0
- package/src/execution/__tests__/notify-ledger.test.ts +27 -0
- package/src/execution/__tests__/reconcile-sweep.test.ts +200 -0
- package/src/execution/__tests__/record-entry-collect.test.ts +102 -0
- package/src/execution/__tests__/record-store.test.ts +60 -6
- package/src/execution/__tests__/recursive-visibility-baseline.test.ts +20 -13
- package/src/execution/__tests__/relay-env.test.ts +12 -1
- package/src/execution/__tests__/round-supervisor.test.ts +293 -0
- package/src/execution/__tests__/session-file-gc.test.ts +1 -1
- package/src/execution/__tests__/session-pending.test.ts +119 -17
- package/src/execution/__tests__/start-collect-guard.test.ts +255 -0
- package/src/execution/__tests__/stream-sink-retirement.test.ts +10 -10
- package/src/execution/__tests__/subagent-actions-core.test.ts +6 -0
- package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +14 -11
- package/src/execution/__tests__/subagent-service-notify-gate.test.ts +33 -30
- package/src/execution/__tests__/subagent-service-parent-guard.test.ts +2 -9
- package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +59 -129
- package/src/execution/__tests__/subagent-service.test.ts +2 -2
- package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +109 -7
- package/src/execution/__tests__/subprocess-agent-runner.test.ts +108 -36
- package/src/execution/__tests__/sync-collect-recovery.test.ts +1102 -0
- package/src/execution/__tests__/tombstone-store.test.ts +1 -1
- package/src/execution/__tests__/workflow-state-root.test.ts +232 -0
- package/src/execution/__tests__/worktree-git-ops.test.ts +1 -1
- 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 +6 -2
- package/src/execution/collect-coordinator.ts +200 -0
- package/src/execution/config.ts +77 -5
- package/src/execution/dialog-queue.ts +6 -73
- package/src/execution/engine/__tests__/common/capability-gate.test.ts +115 -15
- package/src/execution/engine/__tests__/common/errors.test.ts +11 -18
- package/src/execution/engine/__tests__/common/event-journal.test.ts +1 -1
- package/src/execution/engine/__tests__/common/kill-chain.test.ts +7 -0
- package/src/execution/engine/__tests__/common/nesting-guard.test.ts +9 -3
- package/src/execution/engine/__tests__/common/pool-manager.test.ts +2 -2
- package/src/execution/engine/__tests__/common/session-view-service.test.ts +90 -3
- package/src/execution/engine/__tests__/conformance/H9-test-disposition.md +116 -0
- package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/fake-engine-protocol.mjs +377 -0
- package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/recorded.fixture.json +331 -0
- package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/smoke-run.fixture.json +213 -0
- package/src/execution/engine/__tests__/conformance/chat-round-protocol.test.ts +230 -0
- package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +69 -42
- package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +4 -81
- package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +67 -44
- package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +82 -55
- package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +133 -70
- package/src/execution/engine/__tests__/conformance/engine-crash.test.ts +143 -0
- package/src/execution/engine/__tests__/conformance/fake-engine-capabilities.ts +19 -0
- package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +8 -3
- package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +6 -5
- package/src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts +398 -0
- package/src/execution/engine/__tests__/conformance/registry-fork-filter.test.ts +221 -0
- package/src/execution/engine/__tests__/conformance/round-liveness-supervisor.test.ts +302 -0
- package/src/execution/engine/__tests__/conformance/static-spawn-guard.test.ts +58 -0
- package/src/execution/engine/__tests__/engine-discovery-scan.test.ts +558 -0
- package/src/execution/engine/__tests__/host-task-spec.test.ts +45 -0
- package/src/execution/engine/__tests__/model-ref-split.test.ts +74 -0
- package/src/execution/engine/__tests__/registry.test.ts +206 -1
- package/src/execution/engine/__tests__/routing.test.ts +97 -0
- package/src/execution/engine/__tests__/run-failure-worktree-cleanup.test.ts +97 -0
- package/src/execution/engine/client/__tests__/__fixtures__/fake-engine.mjs +294 -0
- package/src/execution/engine/client/__tests__/engine-client.test.ts +516 -0
- package/src/execution/engine/client/__tests__/mirror.test.ts +67 -0
- package/src/execution/engine/client/__tests__/pid-file.test.ts +257 -0
- package/src/execution/engine/client/__tests__/protocol-closure.test.ts +95 -0
- package/src/execution/engine/client/__tests__/remote-engine.test.ts +457 -0
- package/src/execution/engine/client/client-options.ts +103 -0
- package/src/execution/engine/client/engine-client.ts +687 -0
- package/src/execution/engine/client/mirror.ts +167 -0
- package/src/execution/engine/client/pid-file.ts +392 -0
- package/src/execution/engine/client/reaper.ts +95 -0
- package/src/execution/engine/client/remote-engine.ts +441 -0
- package/src/execution/engine/client/reverse-router.ts +255 -0
- package/src/execution/engine/common/capability-gate.ts +109 -22
- package/src/execution/engine/common/errors.ts +9 -25
- package/src/execution/engine/common/event-journal.ts +4 -50
- package/src/execution/engine/common/journal-replay.ts +3 -1
- package/src/execution/engine/common/kill-chain.ts +18 -251
- package/src/execution/engine/common/nesting-guard.ts +18 -114
- package/src/execution/engine/common/pool-manager.ts +4 -0
- package/src/execution/engine/common/session-view-service.ts +56 -84
- package/src/execution/engine/config.ts +151 -0
- package/src/execution/engine/d8-compat.ts +346 -0
- package/src/execution/engine/engine-discovery-roots.ts +107 -0
- package/src/execution/engine/engine-discovery-scan.ts +269 -0
- package/src/execution/engine/engine-discovery.ts +30 -7
- package/src/execution/engine/engine-inspect-package.ts +282 -0
- package/src/execution/engine/engine-manifest.ts +244 -0
- package/src/execution/engine/host/__tests__/host-askuser-endpoint.test.ts +123 -0
- package/src/execution/engine/host/__tests__/host-bridge.test.ts +135 -0
- package/src/execution/engine/host/__tests__/spawned-children.test.ts +73 -0
- package/src/execution/engine/host/host-bridge.ts +150 -0
- package/src/execution/engine/host/host-ui-endpoint.ts +47 -0
- package/src/execution/engine/host/pi-host-binding.ts +91 -0
- package/src/execution/engine/host/spawned-children.ts +139 -0
- package/src/execution/engine/host-task-spec.ts +29 -2
- package/src/execution/engine/model-validation.ts +55 -2
- package/src/execution/engine/paths.ts +16 -41
- package/src/execution/engine/port.ts +48 -2
- package/src/execution/engine/registry.ts +153 -34
- package/src/execution/engine/routing.ts +225 -52
- package/src/execution/engine/types.ts +25 -200
- package/src/execution/execution-record.ts +7 -0
- package/src/execution/finalize-record.ts +40 -11
- package/src/execution/idle-gc.ts +89 -14
- package/src/execution/lifecycle-manager.ts +10 -7
- package/src/execution/lifecycle-predicates.ts +10 -8
- package/src/execution/notifier.ts +234 -25
- package/src/execution/notify-host.ts +21 -1
- package/src/execution/record-entry.ts +16 -0
- package/src/execution/record-store.ts +189 -31
- package/src/execution/relay-env.ts +19 -36
- package/src/execution/round-supervisor/domain.ts +89 -0
- package/src/execution/round-supervisor/index.ts +33 -0
- package/src/execution/round-supervisor/notify-accounting.ts +87 -0
- package/src/execution/round-supervisor/reconcile-sweep.ts +235 -0
- package/src/execution/round-supervisor/service-binding.test.ts +661 -0
- package/src/execution/round-supervisor/service-binding.ts +273 -0
- package/src/execution/round-supervisor/supervisor.ts +426 -0
- package/src/execution/session-pending.ts +68 -74
- package/src/execution/settled-watchdog.ts +39 -0
- package/src/execution/subagent-actions-core.ts +62 -6
- package/src/execution/subagent-service.ts +1161 -406
- package/src/execution/subprocess-agent-runner.ts +16 -8
- package/src/execution/sync-rebuild.ts +87 -0
- package/src/execution/types.ts +104 -117
- package/src/execution/ui-channels.ts +13 -214
- package/src/execution/ui-request-handler-factory.ts +7 -4
- package/src/execution/ui-request-observability.ts +2 -2
- package/src/execution/workflow-state-root.ts +67 -0
- package/src/execution/worktree-git-ops.ts +5 -0
- package/src/execution/worktree-manager.ts +11 -1
- package/src/index.ts +55 -26
- package/src/orchestration/__tests__/config-loader.test.ts +1 -1
- package/src/orchestration/__tests__/execute-agent-call.test.ts +1 -1
- 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__/review-fix-loop-scriptpath-failfast.test.ts +1 -1
- package/src/orchestration/__tests__/script-generate.test.ts +5 -5
- package/src/orchestration/__tests__/skill-discovery.test.ts +2 -2
- package/src/orchestration/__tests__/workflow-files.test.ts +10 -10
- package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +1 -1
- package/src/orchestration/execute-agent-call.ts +1 -1
- package/src/orchestration/file-run-store.ts +144 -59
- package/src/orchestration/models/types.ts +43 -42
- package/src/shared/__tests__/atomic-write.test.ts +1 -1
- package/src/shared/__tests__/resource-discovery-host-roots.test.ts +5 -5
- package/src/shared/zcode-model-ref.ts +31 -0
- package/dist/chunk-43ONBFZX.js +0 -240
- package/dist/chunk-A4IVZWVX.js +0 -31
- package/dist/chunk-APZY4IME.js +0 -27
- package/dist/chunk-V3VHZ2VX.js +0 -59
- package/dist/execution/engine/engines/zcode/constants.cjs +0 -107
- package/dist/execution/engine/engines/zcode/constants.d.cts +0 -135
- package/dist/execution/engine/engines/zcode/constants.d.ts +0 -135
- package/dist/execution/engine/engines/zcode/constants.js +0 -54
- package/dist/execution/engine/engines/zcode/reader.cjs +0 -276
- package/dist/execution/engine/engines/zcode/reader.d.cts +0 -21
- package/dist/execution/engine/engines/zcode/reader.d.ts +0 -21
- package/dist/execution/engine/engines/zcode/reader.js +0 -9
- package/src/__tests__/append-system-prompt-assembly.test.ts +0 -243
- package/src/__tests__/fr4-get-state-handshake.test.ts +0 -125
- package/src/__tests__/session-runner.test.ts +0 -69
- package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
- package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -191
- package/src/execution/__tests__/descendant-sweep-guards.test.ts +0 -220
- package/src/execution/__tests__/descendant-sweep.test.ts +0 -269
- package/src/execution/__tests__/engine-model-validation.test.ts +0 -741
- package/src/execution/__tests__/epipe-fallback.test.ts +0 -248
- package/src/execution/__tests__/execution-runtime-face.test.ts +0 -272
- package/src/execution/__tests__/get-state-handshake.test.ts +0 -127
- package/src/execution/__tests__/helpers/session-runner-mocks.ts +0 -113
- package/src/execution/__tests__/keep-alive-no-progress.test.ts +0 -280
- package/src/execution/__tests__/kill-all-escalation.test.ts +0 -196
- package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +0 -113
- package/src/execution/__tests__/output-collector.test.ts +0 -469
- package/src/execution/__tests__/pi-invocation.test.ts +0 -134
- package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -149
- package/src/execution/__tests__/rpc-mode.test.ts +0 -89
- package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +0 -387
- package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -277
- package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -254
- package/src/execution/__tests__/run-spawn-edges.test.ts +0 -1079
- package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
- package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
- package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
- package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -207
- package/src/execution/__tests__/service-kill-escalation.test.ts +0 -91
- package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +0 -110
- package/src/execution/__tests__/session-runner-close-prune.test.ts +0 -181
- package/src/execution/__tests__/session-runner-dispatch.test.ts +0 -489
- package/src/execution/__tests__/session-runner-epipe.test.ts +0 -179
- package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +0 -227
- package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +0 -290
- package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -352
- package/src/execution/__tests__/settled-watchdog.test.ts +0 -524
- package/src/execution/__tests__/spawn-args.test.ts +0 -446
- package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -192
- package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
- package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -208
- package/src/execution/__tests__/spawned-children.test.ts +0 -236
- package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
- package/src/execution/__tests__/stdin-writer.test.ts +0 -464
- package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -693
- package/src/execution/__tests__/temp-prompt.test.ts +0 -53
- package/src/execution/__tests__/timeout-integration.test.ts +0 -616
- package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
- package/src/execution/__tests__/turn-limiter.test.ts +0 -65
- package/src/execution/__tests__/ui-request-handler.test.ts +0 -205
- package/src/execution/__tests__/ui-request-queue.test.ts +0 -298
- package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -230
- package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
- package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +0 -149
- package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
- package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +0 -128
- package/src/execution/engine/__tests__/paths.test.ts +0 -39
- package/src/execution/engine/common/schema-emulation.ts +0 -189
- package/src/execution/engine/common/session-view-projection.ts +0 -51
- package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -615
- package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
- package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +0 -257
- package/src/execution/engine/engines/pi/argv-mirror.ts +0 -135
- package/src/execution/engine/engines/pi/get-state-handshake.ts +0 -179
- package/src/execution/engine/engines/pi/output-collector.ts +0 -317
- package/src/execution/engine/engines/pi/pi-engine.ts +0 -811
- package/src/execution/engine/engines/pi/pi-invocation.ts +0 -120
- package/src/execution/engine/engines/pi/reader.ts +0 -59
- package/src/execution/engine/engines/pi/registration.ts +0 -37
- package/src/execution/engine/engines/pi/session-runner.ts +0 -2840
- package/src/execution/engine/engines/pi/spawn-event-adapter.ts +0 -404
- package/src/execution/engine/engines/pi/stdin-writer.ts +0 -199
- package/src/execution/engine/engines/pi/temp-prompt.ts +0 -62
- package/src/execution/engine/engines/pi/turn-limiter.ts +0 -102
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +0 -301
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +0 -36
- package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +0 -321
- package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +0 -473
- package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -43
- package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -124
- package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
- package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -71
- package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +0 -247
- package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +0 -451
- package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +0 -792
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +0 -782
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +0 -168
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +0 -210
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +0 -353
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +0 -282
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +0 -372
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -145
- package/src/execution/engine/engines/zcode/appserver-launcher.ts +0 -167
- package/src/execution/engine/engines/zcode/connection.ts +0 -598
- package/src/execution/engine/engines/zcode/constants.ts +0 -176
- package/src/execution/engine/engines/zcode/golden-sample.ts +0 -47
- package/src/execution/engine/engines/zcode/parser.ts +0 -102
- package/src/execution/engine/engines/zcode/preparer.ts +0 -235
- package/src/execution/engine/engines/zcode/reader.ts +0 -381
- package/src/execution/engine/engines/zcode/registration.ts +0 -37
- package/src/execution/engine/engines/zcode/session-channel.ts +0 -968
- package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -1431
- package/src/execution/round-settlement.ts +0 -93
- package/src/execution/ui-request-queue.ts +0 -215
- package/src/shared/schema-env.ts +0 -44
|
@@ -43,7 +43,7 @@ describe("saveWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
43
43
|
expect(existsSync(join(tmpDir, "alpha.js"))).toBe(false);
|
|
44
44
|
expect(readFileSync(join(savedDir, "alpha.js"), "utf-8")).toBe("// alpha body");
|
|
45
45
|
} finally {
|
|
46
|
-
rmSync(root, { recursive: true, force: true });
|
|
46
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
47
47
|
}
|
|
48
48
|
});
|
|
49
49
|
|
|
@@ -56,7 +56,7 @@ describe("saveWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
56
56
|
expect(existsSync(join(savedDir, "alpha.js"))).toBe(false);
|
|
57
57
|
expect(existsSync(join(savedDir, "beta.js"))).toBe(true);
|
|
58
58
|
} finally {
|
|
59
|
-
rmSync(root, { recursive: true, force: true });
|
|
59
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
62
|
|
|
@@ -72,7 +72,7 @@ describe("saveWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
72
72
|
// 原文件不动
|
|
73
73
|
expect(existsSync(join(tmpDir, "alpha.js"))).toBe(true);
|
|
74
74
|
} finally {
|
|
75
|
-
rmSync(root, { recursive: true, force: true });
|
|
75
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
76
76
|
}
|
|
77
77
|
});
|
|
78
78
|
|
|
@@ -83,7 +83,7 @@ describe("saveWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
83
83
|
"Temporary workflow 'ghost' not found",
|
|
84
84
|
);
|
|
85
85
|
} finally {
|
|
86
|
-
rmSync(root, { recursive: true, force: true });
|
|
86
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
87
87
|
}
|
|
88
88
|
});
|
|
89
89
|
});
|
|
@@ -104,7 +104,7 @@ describe("deleteWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
104
104
|
expect(existsSync(join(tmpDir, "dup.js"))).toBe(false);
|
|
105
105
|
expect(existsSync(join(savedDir, "dup.js"))).toBe(true);
|
|
106
106
|
} finally {
|
|
107
|
-
rmSync(root, { recursive: true, force: true });
|
|
107
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
108
108
|
}
|
|
109
109
|
});
|
|
110
110
|
|
|
@@ -117,7 +117,7 @@ describe("deleteWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
117
117
|
expect(msg).toBe(`Deleted workflow 'gamma' (${join(savedDir, "gamma.js")})`);
|
|
118
118
|
expect(existsSync(join(savedDir, "gamma.js"))).toBe(false);
|
|
119
119
|
} finally {
|
|
120
|
-
rmSync(root, { recursive: true, force: true });
|
|
120
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
121
121
|
}
|
|
122
122
|
});
|
|
123
123
|
|
|
@@ -130,7 +130,7 @@ describe("deleteWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
130
130
|
).toThrow("Cannot delete 'busy': workflow is currently running. Abort it first.");
|
|
131
131
|
expect(existsSync(join(tmpDir, "busy.js"))).toBe(true);
|
|
132
132
|
} finally {
|
|
133
|
-
rmSync(root, { recursive: true, force: true });
|
|
133
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
134
134
|
}
|
|
135
135
|
});
|
|
136
136
|
|
|
@@ -141,7 +141,7 @@ describe("deleteWorkflow 目录注入(非 .pi 布局)", () => {
|
|
|
141
141
|
"Workflow file 'void' not found",
|
|
142
142
|
);
|
|
143
143
|
} finally {
|
|
144
|
-
rmSync(root, { recursive: true, force: true });
|
|
144
|
+
rmSync(root, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
145
145
|
}
|
|
146
146
|
});
|
|
147
147
|
});
|
|
@@ -164,7 +164,7 @@ describe("缺省目录 = pi 布局(向后兼容回归)", () => {
|
|
|
164
164
|
expect(existsSync(join(fakeCwd, ".pi", "workflows", "pi-wf.js"))).toBe(true);
|
|
165
165
|
} finally {
|
|
166
166
|
cwdSpy.mockRestore();
|
|
167
|
-
rmSync(fakeCwd, { recursive: true, force: true });
|
|
167
|
+
rmSync(fakeCwd, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
168
168
|
}
|
|
169
169
|
});
|
|
170
170
|
|
|
@@ -180,7 +180,7 @@ describe("缺省目录 = pi 布局(向后兼容回归)", () => {
|
|
|
180
180
|
expect(existsSync(join(savedDir, "saved-only.js"))).toBe(false);
|
|
181
181
|
} finally {
|
|
182
182
|
cwdSpy.mockRestore();
|
|
183
|
-
rmSync(fakeCwd, { recursive: true, force: true });
|
|
183
|
+
rmSync(fakeCwd, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
184
184
|
}
|
|
185
185
|
});
|
|
186
186
|
});
|
|
@@ -59,7 +59,7 @@ describe("loadWorkflowScriptByPath / WorkflowScript 导出形态(U1)", () =>
|
|
|
59
59
|
afterEach(async () => {
|
|
60
60
|
invalidateCache();
|
|
61
61
|
for (const dir of tempDirs) {
|
|
62
|
-
await rm(dir, { recursive: true, force: true });
|
|
62
|
+
await rm(dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* - 成功:consume usage + incrementCallCount + markDone + trace.update(completed)
|
|
15
15
|
*
|
|
16
16
|
* [D5-③ 结构化分诊] 失败分诊读 AgentResult.failureKind 字段(产出侧唯一识别点 =
|
|
17
|
-
* execution/engine/
|
|
17
|
+
* execution/engine/inproc pi 引擎目录/output-collector.ts 的 classifyFailureKind,词表归属
|
|
18
18
|
* 见其文件头)。本模块不再扫 error 文案子串——**语义守恒(r1 MF4)**:unknown
|
|
19
19
|
* (含字段缺省)= 可重试,保持收敛前的默认重试语义;仅 stale_context(不重试、
|
|
20
20
|
* 换参重发场景由调用方编排)与 schema_deterministic 维持特判。
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
// workflow run 快照是宿主编排状态,语义归属宿主数据根本身,宿主 configureCore
|
|
20
20
|
// 注入什么就落什么,不引入第二条 env 覆盖链。
|
|
21
21
|
|
|
22
|
+
import { readFileSync } from "node:fs";
|
|
22
23
|
import { appendFile, mkdir, readdir, readFile, stat, unlink } from "node:fs/promises";
|
|
23
24
|
import { join } from "node:path";
|
|
24
25
|
|
|
@@ -71,6 +72,13 @@ export interface FileRunStoreOptions {
|
|
|
71
72
|
* {@link DEFAULT_SAVE_MIN_INTERVAL_MS}。测试经此注入小窗口(fake timers 推进)。
|
|
72
73
|
*/
|
|
73
74
|
saveMinIntervalMs?: number;
|
|
75
|
+
/**
|
|
76
|
+
* [F-1 修复] run 状态目录覆盖。缺省 = `<dataRoot>/workflow-state`(zcode 宿主布局,
|
|
77
|
+
* 见 stateDir());pi 宿主的读侧装配点(round-supervisor sweep / idle-gc)必须传
|
|
78
|
+
* resolvePiWorkflowStateDir()(execution/workflow-state-root.ts)——pi 宿主 run state
|
|
79
|
+
* 由 JsonlRunStore 落 `<sessionDir>/workflow-state/`,与缺省根不相交。
|
|
80
|
+
*/
|
|
81
|
+
stateDir?: string;
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
/** Node fs 错误 code 判定(ENOENT = 路径不存在,并发删除场景;对齐 pi isEnoentError)。 */
|
|
@@ -87,6 +95,77 @@ function isEnoentError(err: unknown): boolean {
|
|
|
87
95
|
// 匹配 warn 可见性」在此实现——不内聚进 codec,保 pi 侧「v1 存量静默跳过」
|
|
88
96
|
// 语义不被宽容化误读。
|
|
89
97
|
|
|
98
|
+
// ── 磁盘保留原语(C1,两宿主单源)──────────────────────────
|
|
99
|
+
//
|
|
100
|
+
// pruneStateFilesBeyondCap 主体是宿主无关的目录裁剪原语(S4-A7 收口为导出单源):
|
|
101
|
+
// pi 宿主(subagent-workflow 扩展的 jsonl-run-store)此前持有一份逐段同构的私有实现,
|
|
102
|
+
// retention 语义(glob 命中才删 / mtime 升序裁最旧 / 任何失败不抛)双份各自演化是
|
|
103
|
+
// 漂移隐患——现在两宿主消费同一实现,日志与错误字符串化经 deps 注入(宿主各自的
|
|
104
|
+
// logger tag / error 工具保持自治,行为差异仅 log tag 文案)。
|
|
105
|
+
|
|
106
|
+
/** pruneStateFilesBeyondCap 的宿主注入依赖(日志与错误字符串化——tag 前缀由注入方决定)。 */
|
|
107
|
+
export interface PruneStateDeps {
|
|
108
|
+
/** warn 通道(readdir / unlink 失败留证;清理是旁路维护,失败不抛) */
|
|
109
|
+
warn: (msg: string) => void;
|
|
110
|
+
/** debug 通道(成功裁剪记录) */
|
|
111
|
+
debug: (msg: string) => void;
|
|
112
|
+
/** error → 可读字符串(core 侧 err.message 兜底 String,宿主可用自有 error 工具) */
|
|
113
|
+
toMsg: (err: unknown) => string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 把 state 目录裁剪到 cap 个最新 state 文件(mtime 升序删最旧,C1)。
|
|
118
|
+
*
|
|
119
|
+
* 语义(OR-5,两宿主单源):
|
|
120
|
+
* - 只删目录内命中 {@link STATE_FILE_GLOB} 的文件;任何失败都不抛(清理是旁路
|
|
121
|
+
* 维护,不能拖垮持久化主链路):readdir 失败静默放弃本轮(ENOENT = 从未持久化,
|
|
122
|
+
* 正常态),单个 unlink 失败(非 ENOENT)warn 留证后继续删其余——ENOENT 视为
|
|
123
|
+
* 并发删除竞态下的已达成目标,不告警;
|
|
124
|
+
* - stat 全集取 mtime,allSettled 部分降级——单文件 stat 失败(并发删除 ENOENT
|
|
125
|
+
* 等)静默跳过该文件,不阻断本轮裁剪。
|
|
126
|
+
*
|
|
127
|
+
* cap 解析(env 通道等)归调用方:FileRunStore 方法含 envName 通道超集;
|
|
128
|
+
* pi 宿主 jsonl-run-store 经 getEnvStateMaxRuns 解析后直传。
|
|
129
|
+
*/
|
|
130
|
+
export async function pruneStateFilesBeyondCap(
|
|
131
|
+
stateDir: string,
|
|
132
|
+
cap: number,
|
|
133
|
+
deps: PruneStateDeps,
|
|
134
|
+
): Promise<void> {
|
|
135
|
+
let names: string[];
|
|
136
|
+
try {
|
|
137
|
+
names = await readdir(stateDir);
|
|
138
|
+
} catch (err) {
|
|
139
|
+
if (!isEnoentError(err)) {
|
|
140
|
+
deps.warn(`state retention: readdir ${stateDir} failed: ${deps.toMsg(err)}`);
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const stateFiles = names.filter((n) => STATE_FILE_GLOB.test(n)).sort();
|
|
145
|
+
if (stateFiles.length <= cap) return;
|
|
146
|
+
|
|
147
|
+
// stat 全集取 mtime;allSettled 部分降级(单文件失败静默跳过,不阻断本轮)
|
|
148
|
+
const settled = await Promise.allSettled(
|
|
149
|
+
stateFiles.map(async (name) => {
|
|
150
|
+
const full = join(stateDir, name);
|
|
151
|
+
return { full, mtimeMs: (await stat(full)).mtimeMs };
|
|
152
|
+
}),
|
|
153
|
+
);
|
|
154
|
+
const byMtimeAsc = settled
|
|
155
|
+
.flatMap((r) => (r.status === "fulfilled" ? [r.value] : []))
|
|
156
|
+
.sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
157
|
+
const victims = byMtimeAsc.slice(0, byMtimeAsc.length - cap);
|
|
158
|
+
for (const victim of victims) {
|
|
159
|
+
try {
|
|
160
|
+
await unlink(victim.full);
|
|
161
|
+
deps.debug(`state retention: pruned ${victim.full}`);
|
|
162
|
+
} catch (err) {
|
|
163
|
+
if (isEnoentError(err)) continue; // 并发删除已达成目标
|
|
164
|
+
deps.warn(`state retention: failed to delete ${victim.full}: ${deps.toMsg(err)}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
90
169
|
// ── FileRunStore ────────────────────────────────────────────
|
|
91
170
|
|
|
92
171
|
/**
|
|
@@ -101,18 +180,25 @@ function isEnoentError(err: unknown): boolean {
|
|
|
101
180
|
* warn——单行损坏不拖垮整个 run 的恢复(与 pi 壳 kill-9 恢复同容忍度)。
|
|
102
181
|
* 版本衔接(快照 codec 归 run-snapshot.ts 单源,D4):存量无 v 行按当前版本
|
|
103
182
|
* 宽容读、写入恒补 v、v 不匹配跳过 + warn(三裁决明细见 parseLine 注释)。
|
|
104
|
-
* - stateFilePath
|
|
183
|
+
* - stateFilePath:纯路径计算(<状态目录>/<runId>.jsonl),不建目录。状态目录 =
|
|
184
|
+
* 构造注入的 stateDir 覆盖,或缺省 <dataRoot>/workflow-state(pi 宿主读侧装配点
|
|
185
|
+
* 必须传 resolvePiWorkflowStateDir()——见 FileRunStoreOptions.stateDir 与
|
|
186
|
+
* execution/workflow-state-root.ts 的同源布局论证)。
|
|
105
187
|
*
|
|
106
188
|
* 未 configureCore 即 save/loadAll 会抛 core_host_not_configured(dataRoot 端口
|
|
107
189
|
* 语义,host-services.ts §3.4)——宿主壳必须在初始化最早期注入。
|
|
108
190
|
*/
|
|
109
191
|
export class FileRunStore implements RunStore {
|
|
110
|
-
/** run
|
|
111
|
-
* data-dir.ts
|
|
192
|
+
/** run 状态目录绝对路径(显式覆盖优先——pi 宿主读侧装配点;缺省 dataRoot 每次现取
|
|
193
|
+
* ——宿主覆盖配置即刻生效,对齐 data-dir.ts「不缓存路径防测试/宿主切换读到旧值」
|
|
194
|
+
* 先例)。 */
|
|
112
195
|
private stateDir(): string {
|
|
113
|
-
return join(getHostServices().dataRoot(), STATE_DIR_NAME);
|
|
196
|
+
return this.stateDirOverride ?? join(getHostServices().dataRoot(), STATE_DIR_NAME);
|
|
114
197
|
}
|
|
115
198
|
|
|
199
|
+
/** 显式状态目录覆盖(构造注入;见 FileRunStoreOptions.stateDir)。 */
|
|
200
|
+
private readonly stateDirOverride: string | undefined;
|
|
201
|
+
|
|
116
202
|
/** save 节流最小间隔(ms),0 = 禁用。 */
|
|
117
203
|
private readonly saveMinIntervalMs: number;
|
|
118
204
|
/**
|
|
@@ -125,6 +211,7 @@ export class FileRunStore implements RunStore {
|
|
|
125
211
|
|
|
126
212
|
constructor(opts?: FileRunStoreOptions) {
|
|
127
213
|
this.saveMinIntervalMs = Math.max(0, opts?.saveMinIntervalMs ?? DEFAULT_SAVE_MIN_INTERVAL_MS);
|
|
214
|
+
this.stateDirOverride = opts?.stateDir;
|
|
128
215
|
}
|
|
129
216
|
|
|
130
217
|
stateFilePath(runId: string): string {
|
|
@@ -181,6 +268,41 @@ export class FileRunStore implements RunStore {
|
|
|
181
268
|
return runs;
|
|
182
269
|
}
|
|
183
270
|
|
|
271
|
+
/**
|
|
272
|
+
* [W4 sweep 判据,F2] 按 runId 同步查 run 状态(注册对账 sweep 的 workflow 收口
|
|
273
|
+
* 判据)。同步形态:sweep 在 session_start 同步链内运行(runReconcileSweep 同步
|
|
274
|
+
* 契约),不能 await loadAll——对单 runId 做同步文件读(对齐 sweep 自身的 sync fs
|
|
275
|
+
* 读先例),逐行解析复用 parseLine(版本衔接 + 形状校验与 loadLatestValidLine
|
|
276
|
+
* 单源,同步只读不触碰 lastSavedAt 节流记账)。
|
|
277
|
+
*
|
|
278
|
+
* 判定(宁挂账不失明——误注销活跃 run 是事故方向,判据保守侧取「不可判定」):
|
|
279
|
+
* - state 文件不存在 → missing(设计判据「已归档/不存在视同终态」——run 从未
|
|
280
|
+
* 落盘或已被清理,注册是死亡窗口残留);
|
|
281
|
+
* - 末条有效快照 status = running → running(活跃,sweep 跳过);
|
|
282
|
+
* - 末条有效快照 status ≠ running(done)→ terminal + reason(I2:done ⟹ reason
|
|
283
|
+
* 有值;reason 作 pending unregister 的 status 语义源);
|
|
284
|
+
* - 文件存在但全部行损坏(无有效快照)→ running(读不出 ≠ 不存在,不补注销)。
|
|
285
|
+
*/
|
|
286
|
+
findStateByIdSync(runId: string): { kind: "running" } | { kind: "terminal"; reason: string | undefined } | { kind: "missing" } {
|
|
287
|
+
let content: string;
|
|
288
|
+
try {
|
|
289
|
+
content = readFileSync(this.stateFilePath(runId), "utf8");
|
|
290
|
+
} catch {
|
|
291
|
+
return { kind: "missing" }; // ENOENT(未落盘/已清理)等不可读形态同视——见头注判定
|
|
292
|
+
}
|
|
293
|
+
const lines = content.split("\n");
|
|
294
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
295
|
+
const line = lines[i].trim();
|
|
296
|
+
if (line === "") continue; // 尾部空行(末行 \n 产物)静默跳过
|
|
297
|
+
const run = this.parseLine(line, `${runId}.jsonl`, i);
|
|
298
|
+
if (run === undefined) continue; // 损坏行继续向前找——最后一条有效行可能早于文件尾部
|
|
299
|
+
if (run.state.status === "running") return { kind: "running" };
|
|
300
|
+
return { kind: "terminal", reason: run.state.reason };
|
|
301
|
+
}
|
|
302
|
+
// 全部行损坏:读不出 ≠ 不存在——保守按活跃处理(宁挂账不误注销)
|
|
303
|
+
return { kind: "running" };
|
|
304
|
+
}
|
|
305
|
+
|
|
184
306
|
/** 单文件从尾向头取第一条有效快照行;整文件无有效行返回 undefined(warn)。 */
|
|
185
307
|
private async loadLatestValidLine(absPath: string, display: string): Promise<WorkflowRun | undefined> {
|
|
186
308
|
let content: string;
|
|
@@ -247,15 +369,12 @@ export class FileRunStore implements RunStore {
|
|
|
247
369
|
|
|
248
370
|
/**
|
|
249
371
|
* 把 workflow-state 目录裁剪到上限个最新 state 文件(mtime 升序删最旧,C1)。
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
* - stat 全集取 mtime,allSettled 部分降级——单文件 stat 失败(并发删除
|
|
257
|
-
* ENOENT 等)静默跳过该文件,不阻断本轮裁剪。
|
|
258
|
-
*
|
|
372
|
+
*
|
|
373
|
+
* 主体委托导出单源 {@link pruneStateFilesBeyondCap}(retention 语义两宿主单源,
|
|
374
|
+
* S4-A7;日志经 deps 注入本模块 logger + `[file-run-store]` tag,行为与收口前
|
|
375
|
+
* 逐字一致)。磁盘裁剪不动内存 runs Map(内存侧淘汰归
|
|
376
|
+
* lifecycle.evictDoneRunsBeyondCap,两域独立)。
|
|
377
|
+
*
|
|
259
378
|
* 上限解析(envName 通道,OR-5 ⑥b 默认开;显式非法值 opt-out 对齐 pi 解析风格):
|
|
260
379
|
* - `envName` 提供 → env 通道:`process.env[envName]` 未设/空 → 按默认上限
|
|
261
380
|
* {@link DEFAULT_STATE_MAX_RUNS} 裁剪(**默认开**——OR-5 修复前的 opt-in
|
|
@@ -265,19 +384,16 @@ export class FileRunStore implements RunStore {
|
|
|
265
384
|
* 宿主如需自管保留可设足够大的正数值);
|
|
266
385
|
* - `envName` 缺省 → 无 env 通道,直接按 `max` 参数裁剪(上限 = max,调用方
|
|
267
386
|
* 自管启用时机)。
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
* @param envName opt-in 开关 + 上限覆盖 env 变量名(可选;pi 先例
|
|
274
|
-
* `XYZ_SUBAGENT_STATE_MAX_RUNS`)
|
|
275
|
-
*/
|
|
387
|
+
*
|
|
388
|
+
* @param max 上限(envName 缺省时生效;env 通道启用时被 env 值覆盖)
|
|
389
|
+
* @param envName opt-in 开关 + 上限覆盖 env 变量名(可选;pi 先例
|
|
390
|
+
* `XYZ_SUBAGENT_STATE_MAX_RUNS`)
|
|
391
|
+
*/
|
|
276
392
|
async pruneStateFilesBeyondCap(max: number, envName?: string): Promise<void> {
|
|
277
393
|
let cap = max;
|
|
278
394
|
if (envName !== undefined) {
|
|
279
|
-
|
|
280
|
-
|
|
395
|
+
// 未设/空 → 默认开(OR-5 ⑥b:DEFAULT_STATE_MAX_RUNS);非法/≤0 → 不清理
|
|
396
|
+
// (显式 opt-out 通道,见方法注释);有效正数 → env 值覆盖
|
|
281
397
|
const raw = process.env[envName];
|
|
282
398
|
if (raw === undefined || raw === "") {
|
|
283
399
|
cap = DEFAULT_STATE_MAX_RUNS;
|
|
@@ -287,41 +403,10 @@ export class FileRunStore implements RunStore {
|
|
|
287
403
|
cap = parsed;
|
|
288
404
|
}
|
|
289
405
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
} catch (err) {
|
|
296
|
-
if (!isEnoentError(err)) {
|
|
297
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
298
|
-
logger.warn(`[file-run-store] state retention: readdir ${stateDir} failed: ${reason}`);
|
|
299
|
-
}
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
const stateFiles = names.filter((n) => STATE_FILE_GLOB.test(n)).sort();
|
|
303
|
-
if (stateFiles.length <= cap) return;
|
|
304
|
-
|
|
305
|
-
// stat 全集取 mtime;allSettled 部分降级(单文件失败静默跳过,不阻断本轮)
|
|
306
|
-
const settled = await Promise.allSettled(
|
|
307
|
-
stateFiles.map(async (name) => {
|
|
308
|
-
const full = join(stateDir, name);
|
|
309
|
-
return { full, mtimeMs: (await stat(full)).mtimeMs };
|
|
310
|
-
}),
|
|
311
|
-
);
|
|
312
|
-
const byMtimeAsc = settled
|
|
313
|
-
.flatMap((r) => (r.status === "fulfilled" ? [r.value] : []))
|
|
314
|
-
.sort((a, b) => a.mtimeMs - b.mtimeMs);
|
|
315
|
-
const victims = byMtimeAsc.slice(0, byMtimeAsc.length - cap);
|
|
316
|
-
for (const victim of victims) {
|
|
317
|
-
try {
|
|
318
|
-
await unlink(victim.full);
|
|
319
|
-
logger.debug(`[file-run-store] state retention: pruned ${victim.full}`);
|
|
320
|
-
} catch (err) {
|
|
321
|
-
if (isEnoentError(err)) continue; // 并发删除已达成目标
|
|
322
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
323
|
-
logger.warn(`[file-run-store] state retention: failed to delete ${victim.full}: ${reason}`);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
406
|
+
await pruneStateFilesBeyondCap(this.stateDir(), cap, {
|
|
407
|
+
warn: (msg) => logger.warn(`[file-run-store] ${msg}`),
|
|
408
|
+
debug: (msg) => logger.debug(`[file-run-store] ${msg}`),
|
|
409
|
+
toMsg: (err) => (err instanceof Error ? err.message : String(err)),
|
|
410
|
+
});
|
|
326
411
|
}
|
|
327
412
|
}
|
|
@@ -7,12 +7,19 @@
|
|
|
7
7
|
* 核心内容:
|
|
8
8
|
* - 状态机:RunStatus = "running" | "done"(2 态,一次性生命周期,FR-3)
|
|
9
9
|
* + DoneReason(completed/failed/aborted/budget_limited/time_limited)
|
|
10
|
-
* - AgentCallOpts / AgentResult
|
|
10
|
+
* - AgentCallOpts / AgentResult(单次 agent 调用的输入/输出,宿主面 SSOT 留守本地)
|
|
11
|
+
* + AgentUsage / ToolCallEntry / AgentFailureKind(自 SDK re-export,S4 簇 3 收编)
|
|
11
12
|
* - ExecutionTraceNode / TracePatch / ToolCallEntry / WorkerLogEntry(trace 数据)
|
|
12
13
|
*
|
|
13
14
|
* 层归属:Engine(数据结构 + 不变式守卫)。
|
|
14
15
|
*/
|
|
15
16
|
|
|
17
|
+
import type {
|
|
18
|
+
AgentFailureKind,
|
|
19
|
+
AgentOutcomeUsage as AgentUsage,
|
|
20
|
+
ToolCallEntry,
|
|
21
|
+
} from "@zhushanwen/subagent-engine-sdk";
|
|
22
|
+
|
|
16
23
|
import type { ExecutionRecord, WorktreeHandle } from "../../execution/types.ts";
|
|
17
24
|
|
|
18
25
|
// ── 状态机 ────────────────────────────────────────────────────
|
|
@@ -188,6 +195,14 @@ export interface AgentCallOpts {
|
|
|
188
195
|
cwd?: string;
|
|
189
196
|
/** Inherit parent session context (fork mode). Independent of worktree (file isolation). */
|
|
190
197
|
fork?: boolean;
|
|
198
|
+
/**
|
|
199
|
+
* fork-from 显式分叉源 session 文件(fork-from 断联恢复通道的唯一 lossless 载体)。
|
|
200
|
+
* 来源 = ExecuteOptions.forkFromSessionFile(host-task-spec 映射时的唯一改名点——
|
|
201
|
+
* 本形状起与 SDK 协议字段、引擎侧 SpawnRunParams.forkSource 三层同名,降低跨层
|
|
202
|
+
* 双名漂移面)。区别于 fork:true(主 session 作分叉源):本字段点名任意已有
|
|
203
|
+
* session 文件。chat 域唯一写入方 = fork-from action。
|
|
204
|
+
*/
|
|
205
|
+
forkSource?: string;
|
|
191
206
|
/**
|
|
192
207
|
* 执行引擎 id(P4 D9 三层优先级的第一层:调用参数级,workflow step 显式指定)。
|
|
193
208
|
* 仅限「必须某引擎独有能力」的场景使用并注释原因(D9③ workflow 脚本不写死
|
|
@@ -227,46 +242,32 @@ export interface AgentCallOpts {
|
|
|
227
242
|
permissionMode?: string;
|
|
228
243
|
}
|
|
229
244
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
* - stale_context:pi session context 被 compact/cancel/替换——重试无意义(同 call
|
|
257
|
-
* 再次失败),不重试。
|
|
258
|
-
* - schema_deterministic:确定性 schema 失败(SO tool 从未调用 / gate 终止 /
|
|
259
|
-
* 不可满足 schema)——同 schema 重试必同结果,不重试。
|
|
260
|
-
* - unknown:其余一切失败(瞬态 provider 错误、spawn 失败等)——**默认可重试**。
|
|
261
|
-
*
|
|
262
|
-
* **语义守恒(最高优先约束)**:unknown(含字段缺省)= 可重试——保持收敛前的
|
|
263
|
-
* 默认重试语义;仅 stale_context 与 schema_deterministic 两态维持不重试特判。
|
|
264
|
-
* 词表归属(产出侧单点识别):stale_context / schema_deterministic 的识别词表
|
|
265
|
-
* (stale 词表与确定性 schema 失败标记前缀)保留在产出侧
|
|
266
|
-
* execution/engine/engines/pi/output-collector.ts 包内——词表漂移的失效模式是
|
|
267
|
-
* failureKind=unknown → 保守重试(安全默认),不再是静默漏诊。
|
|
268
|
-
*/
|
|
269
|
-
export type AgentFailureKind = "stale_context" | "schema_deterministic" | "unknown";
|
|
245
|
+
// [S4 簇 3 收编] 以下三个契约类型本地定义已删除,自 @zhushanwen/subagent-engine-sdk
|
|
246
|
+
// re-export(type-only,import 方路径零改动,结构等价由 protocol-closure.test.ts
|
|
247
|
+
// 断言族守卫):
|
|
248
|
+
// - AgentUsage ← SDK AgentOutcomeUsage(SDK 改名消歧:core 的两个同名 AgentUsage
|
|
249
|
+
// 分属 execution 与 orchestration 域,本处锚定 orchestration 域——AgentResult.usage
|
|
250
|
+
// 字段型,FR-7 跨 turn 累积);
|
|
251
|
+
// - ToolCallEntry(单次 tool 调用记录,FR-7 从 agent JSONL 流采);
|
|
252
|
+
// - AgentFailureKind(失败分诊结构化标签,D5-③)。
|
|
253
|
+
// AgentCallOpts / AgentResult 留守本地(宿主面 SSOT——SDK 版 AgentCallOpts 是引擎面
|
|
254
|
+
// 子集,字段裁决见 SDK contract-types 注释)。
|
|
255
|
+
//
|
|
256
|
+
// AgentFailureKind 语义守恒(最高优先约束,core 侧权威说明——SDK 侧为简版):
|
|
257
|
+
// - stale_context:pi session context 被 compact/cancel/替换——重试无意义(同 call
|
|
258
|
+
// 再次失败),不重试。
|
|
259
|
+
// - schema_deterministic:确定性 schema 失败(SO tool 从未调用 / gate 终止 /
|
|
260
|
+
// 不可满足 schema)——同 schema 重试必同结果,不重试。
|
|
261
|
+
// - unknown:其余一切失败(瞬态 provider 错误、spawn 失败等)——**默认可重试**。
|
|
262
|
+
// unknown(含字段缺省)= 可重试;仅 stale_context 与 schema_deterministic 两态
|
|
263
|
+
// 维持不重试特判。词表归属(产出侧单点识别):识别词表保留在产出侧
|
|
264
|
+
// execution/engine/inproc pi 引擎目录/output-collector.ts 包内——词表漂移的失效模式
|
|
265
|
+
// 是 failureKind=unknown → 保守重试(安全默认),不再是静默漏诊。
|
|
266
|
+
export type {
|
|
267
|
+
AgentFailureKind,
|
|
268
|
+
AgentOutcomeUsage as AgentUsage,
|
|
269
|
+
ToolCallEntry,
|
|
270
|
+
} from "@zhushanwen/subagent-engine-sdk";
|
|
270
271
|
|
|
271
272
|
/**
|
|
272
273
|
* 单次 agent 调用的结果(统一形态)。
|
|
@@ -279,7 +280,7 @@ export interface AgentResult {
|
|
|
279
280
|
content: string;
|
|
280
281
|
/**
|
|
281
282
|
* [D5-③] 失败分诊结构化标签(AgentFailureKind)。产出侧唯一识别点 =
|
|
282
|
-
* execution/engine/
|
|
283
|
+
* execution/engine/inproc pi 引擎目录/output-collector.ts(collectResult 对最终 error
|
|
283
284
|
* 分类后写入,经 agent-result-mapper / AgentOutcome 透传到本形态);消费侧
|
|
284
285
|
* execute-agent-call 读本字段分诊,不再扫 error 文案子串。
|
|
285
286
|
*
|
|
@@ -74,7 +74,7 @@ describe("C2 W2①: async 链 realpath 去重", () => {
|
|
|
74
74
|
ws = tmpWorkspace();
|
|
75
75
|
});
|
|
76
76
|
afterEach(() => {
|
|
77
|
-
fs.rmSync(ws, { recursive: true, force: true });
|
|
77
|
+
fs.rmSync(ws, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
it("多链同文件(a.md 本体 + b.md symlink → a.md)清单只留 1 条", async () => {
|
|
@@ -171,7 +171,7 @@ describe("C2 W2④: hostRoots 同标签多根语义", () => {
|
|
|
171
171
|
agentDir = path.join(ws, ".fake-agent");
|
|
172
172
|
});
|
|
173
173
|
afterEach(() => {
|
|
174
|
-
fs.rmSync(ws, { recursive: true, force: true });
|
|
174
|
+
fs.rmSync(ws, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
175
175
|
});
|
|
176
176
|
|
|
177
177
|
it("同标签两条 user-pi 根都被扫描(非靠后者整体覆盖)", async () => {
|
|
@@ -300,7 +300,7 @@ describe("C2 W2②: project-host 槽位序位", () => {
|
|
|
300
300
|
hostRoot = path.join(ws, ".zcode", "agents");
|
|
301
301
|
});
|
|
302
302
|
afterEach(() => {
|
|
303
|
-
fs.rmSync(ws, { recursive: true, force: true });
|
|
303
|
+
fs.rmSync(ws, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
304
304
|
});
|
|
305
305
|
|
|
306
306
|
it("project-host 同名被 project-agents 遮蔽(project-agents 是项目级最高逃生门)", async () => {
|
|
@@ -364,7 +364,7 @@ describe("C2 红线 3: 单层扫描维持", () => {
|
|
|
364
364
|
agentDir = path.join(ws, ".fake-agent");
|
|
365
365
|
});
|
|
366
366
|
afterEach(() => {
|
|
367
|
-
fs.rmSync(ws, { recursive: true, force: true });
|
|
367
|
+
fs.rmSync(ws, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
368
368
|
});
|
|
369
369
|
|
|
370
370
|
it("子目录不递归(nested/deep.md 不入清单)", async () => {
|
|
@@ -410,7 +410,7 @@ describe("C2 回归红线: pi 单条目形态快照", () => {
|
|
|
410
410
|
agentDir = path.join(ws, ".fake-agent");
|
|
411
411
|
});
|
|
412
412
|
afterEach(() => {
|
|
413
|
-
fs.rmSync(ws, { recursive: true, force: true });
|
|
413
|
+
fs.rmSync(ws, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
414
414
|
});
|
|
415
415
|
|
|
416
416
|
it("与 pi 真实 agentDir 同构 fixture——source 标签与胜出路径逐项稳定", async () => {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/shared/zcode-model-ref.ts
|
|
2
|
+
//
|
|
3
|
+
// zcode 模型引用切分原语(U1 契约面批件)——[W11/H2] 随 engines/zcode 内建目录删除
|
|
4
|
+
// 从 engines/zcode/{preparer,constants}.ts 迁出的宿主侧原语(barrel 原四件导出面
|
|
5
|
+
// 不变:splitZcodeModelRef / hasApiKey / DEFAULT_PROVIDER_ID / ZCODE_FALLBACK_
|
|
6
|
+
// DEFAULT_MODEL)。引擎侧等价物在 @zhushanwen/zcode-subagent-cli(两处单源各自
|
|
7
|
+
// 演进,协议面不共享该常量——宿主只做引用切分,不做凭据校验)。
|
|
8
|
+
|
|
9
|
+
/** provider 条目(v2 config.provider.<id>)的最小消费面(索引签名形态)。 */
|
|
10
|
+
export interface ZcodeProviderEntryLike {
|
|
11
|
+
options?: { apiKey?: unknown };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** 短名(无 provider 前缀)解析的默认 provider(zsub DEFAULT_PROVIDER_ID 同构)。 */
|
|
15
|
+
export const DEFAULT_PROVIDER_ID = "builtin:bigmodel-coding-plan";
|
|
16
|
+
|
|
17
|
+
/** zsub 同构的兜底缺省模型(v2 config 无 model.main 且 task 未指定时)。 */
|
|
18
|
+
export const ZCODE_FALLBACK_DEFAULT_MODEL = "builtin:bigmodel-coding-plan/GLM-5.3";
|
|
19
|
+
|
|
20
|
+
/** [R4] 规范化全名 provider/model → create 参数的 per-session model 拆分。 */
|
|
21
|
+
export function splitZcodeModelRef(
|
|
22
|
+
modelRef: string,
|
|
23
|
+
): { providerId: string; modelId: string } {
|
|
24
|
+
const slash = modelRef.lastIndexOf("/");
|
|
25
|
+
return { providerId: modelRef.slice(0, slash), modelId: modelRef.slice(slash + 1) };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function hasApiKey(entry: ZcodeProviderEntryLike): boolean {
|
|
29
|
+
const key = entry.options?.apiKey;
|
|
30
|
+
return typeof key === "string" && key !== "";
|
|
31
|
+
}
|