@zhushanwen/subagent-core 0.2.0 → 0.5.1
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 +45 -2
- package/agents/analyst.md +60 -0
- package/agents/coder.md +69 -0
- package/agents/debugger.md +66 -0
- package/agents/doc-reviewer.md +49 -0
- package/agents/explorer.md +63 -0
- package/agents/general-purpose.md +32 -0
- package/agents/orchestrator.md +61 -0
- package/agents/planner.md +53 -0
- package/agents/researcher.md +67 -0
- package/agents/reviewer.md +73 -0
- package/dist/chunk-43ONBFZX.js +240 -0
- package/dist/chunk-APZY4IME.js +27 -0
- package/dist/chunk-V3VHZ2VX.js +59 -0
- package/dist/execution/engine/engines/zcode/constants.cjs +62 -9
- package/dist/execution/engine/engines/zcode/constants.d.cts +116 -12
- package/dist/execution/engine/engines/zcode/constants.d.ts +116 -12
- package/dist/execution/engine/engines/zcode/constants.js +39 -7
- 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 +4 -234
- package/dist/execution/engine/paths.js +7 -19
- package/dist/index.cjs +18234 -1277
- package/dist/index.d.cts +5646 -673
- package/dist/index.d.ts +5646 -673
- package/dist/index.js +17828 -1277
- package/dist/{types-BxyAidGf.d.cts → types-Dv4QhSJ_.d.cts} +678 -112
- package/dist/{types-BxyAidGf.d.ts → types-Dv4QhSJ_.d.ts} +678 -112
- package/package.json +7 -4
- 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 +93 -3
- package/src/__tests__/review-fix-loop-utils.test.ts +31 -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/__tests__/smoke.test.ts +9 -2
- 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 +232 -0
- 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 +219 -0
- package/src/execution/__tests__/ask-user-transit-e2e.test.ts +6 -6
- package/src/execution/__tests__/chat-engine-routing.test.ts +136 -30
- package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +5 -4
- package/src/execution/__tests__/cold-resurrect.test.ts +283 -0
- package/src/execution/__tests__/create-concurrency-pool.test.ts +194 -0
- package/src/execution/__tests__/delivery-methods.test.ts +77 -62
- package/src/execution/__tests__/descendant-sweep-guards.test.ts +220 -0
- package/src/execution/__tests__/descendant-sweep.test.ts +269 -0
- package/src/execution/__tests__/dialog-queue.test.ts +199 -1
- package/src/execution/__tests__/engine-model-validation.test.ts +741 -0
- package/src/execution/__tests__/epipe-fallback.test.ts +31 -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 +272 -0
- package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +3 -3
- package/src/execution/__tests__/finalize-record.test.ts +278 -16
- package/src/execution/__tests__/gc-timer.test.ts +57 -2
- package/src/execution/__tests__/get-record-for-action-restart.test.ts +14 -12
- package/src/execution/__tests__/get-state-handshake.test.ts +127 -0
- 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 +280 -0
- package/src/execution/__tests__/kill-all-escalation.test.ts +196 -0
- package/src/execution/__tests__/lifecycle-manager-idle-timer-identity.test.ts +117 -0
- package/src/execution/__tests__/lifecycle-manager.test.ts +39 -0
- 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 +99 -0
- package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +113 -0
- 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-ledger.test.ts +1249 -0
- package/src/execution/__tests__/output-collector.test.ts +117 -6
- package/src/execution/__tests__/pi-invocation.test.ts +1 -1
- package/src/execution/__tests__/record-store-orphan-revive.test.ts +159 -0
- package/src/execution/__tests__/record-store.test.ts +89 -5
- 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__/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 +19 -9
- package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +5 -4
- package/src/execution/__tests__/run-spawn-edges.test.ts +418 -26
- package/src/execution/__tests__/run-spawn-integration.test.ts +3 -3
- 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 +16 -8
- package/src/execution/__tests__/service-kill-escalation.test.ts +91 -0
- package/src/execution/__tests__/session-context-resolver.test.ts +0 -2
- package/src/execution/__tests__/session-file-gc.test.ts +35 -0
- package/src/execution/__tests__/session-pending.test.ts +471 -0
- package/src/execution/__tests__/session-reconstructor.test.ts +366 -15
- package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +110 -0
- package/src/execution/__tests__/session-runner-close-prune.test.ts +181 -0
- package/src/execution/__tests__/session-runner-dispatch.test.ts +489 -0
- package/src/execution/__tests__/session-runner-epipe.test.ts +4 -3
- package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +227 -0
- 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 +524 -0
- 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 +1 -1
- package/src/execution/__tests__/spawn-worktree-guidance.test.ts +5 -4
- package/src/execution/__tests__/spawned-children.test.ts +155 -11
- package/src/execution/__tests__/start-sync-model-guard.test.ts +4 -4
- 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 +1017 -0
- package/src/execution/__tests__/subagent-service-message-close.test.ts +99 -35
- package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +174 -0
- package/src/execution/__tests__/subagent-service-notify-gate.test.ts +271 -0
- package/src/execution/__tests__/subagent-service-parent-guard.test.ts +33 -29
- package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +341 -0
- 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__/temp-prompt.test.ts +1 -1
- package/src/execution/__tests__/timeout-integration.test.ts +13 -12
- 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 +107 -7
- package/src/execution/__tests__/ui-request-handler.test.ts +4 -3
- package/src/execution/__tests__/ui-request-queue.test.ts +167 -2
- package/src/execution/__tests__/worktree-git-ops.test.ts +571 -0
- 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 +204 -0
- package/src/execution/agent-registry.ts +298 -30
- package/src/execution/agent-result-mapper.ts +3 -0
- package/src/execution/agents-assembly.ts +88 -0
- package/src/execution/cold-resurrect.ts +199 -0
- package/src/execution/concurrency-pool.ts +71 -9
- package/src/execution/dialog-queue.ts +101 -3
- 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/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 +211 -51
- 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 +56 -99
- package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +88 -15
- package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +33 -7
- package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +1 -1
- package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +75 -54
- package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +128 -0
- 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 +94 -3
- 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/engine-discovery.ts +12 -16
- 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} +86 -11
- 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/engine/engines/pi/session-runner.ts +2840 -0
- 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 +301 -0
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +36 -0
- package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +321 -0
- package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +473 -0
- 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 +792 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +782 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +168 -0
- 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 +65 -47
- package/src/execution/engine/engines/zcode/appserver-launcher.ts +167 -0
- package/src/execution/engine/engines/zcode/connection.ts +598 -0
- package/src/execution/engine/engines/zcode/constants.ts +147 -14
- package/src/execution/engine/engines/zcode/golden-sample.ts +42 -34
- package/src/execution/engine/engines/zcode/parser.ts +12 -346
- package/src/execution/engine/engines/zcode/preparer.ts +22 -150
- package/src/execution/engine/engines/zcode/session-channel.ts +968 -0
- package/src/execution/engine/engines/zcode/zcode-engine.ts +1023 -250
- 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 +65 -7
- package/src/execution/engine/registry.ts +53 -0
- package/src/execution/engine/routing.ts +75 -1
- package/src/execution/engine/types.ts +30 -103
- package/src/execution/execution-record.ts +222 -144
- package/src/execution/finalize-record.ts +181 -85
- package/src/execution/idle-gc.ts +28 -0
- package/src/execution/lifecycle-manager.ts +27 -3
- package/src/execution/lifecycle-predicates.ts +1 -1
- package/src/execution/manifest-store.ts +53 -62
- package/src/execution/notifier.ts +10 -10
- package/src/execution/notify-host.ts +212 -0
- package/src/execution/notify-ledger.ts +117 -16
- package/src/execution/record-entry.ts +8 -2
- package/src/execution/record-store.ts +148 -88
- package/src/execution/round-settlement.ts +93 -0
- package/src/execution/session-file-gc.ts +96 -62
- package/src/execution/session-pending.ts +213 -62
- package/src/execution/session-reconstructor.ts +256 -143
- package/src/execution/sessions-index.ts +127 -102
- package/src/execution/settled-watchdog.ts +311 -0
- package/src/execution/subagent-actions-core.ts +686 -0
- package/src/execution/subagent-service.ts +1106 -907
- package/src/execution/subprocess-agent-runner.ts +144 -97
- package/src/execution/types.ts +9 -0
- package/src/execution/ui-request-handler-factory.ts +126 -75
- package/src/execution/ui-request-queue.ts +50 -19
- package/src/execution/worktree-git-ops.ts +397 -0
- package/src/execution/worktree-manager.ts +72 -10
- package/src/execution/worktree-registry.ts +6 -12
- package/src/index.ts +542 -9
- package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +42 -3
- package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +3 -5
- package/src/orchestration/__tests__/agent-call-stream.test.ts +2 -2
- package/src/orchestration/__tests__/args-meta.test.ts +358 -0
- package/src/orchestration/__tests__/args-validator.test.ts +14 -0
- package/src/orchestration/__tests__/error-recovery-rebuild-failure.test.ts +312 -0
- package/src/orchestration/__tests__/error-recovery-terminal-hardening.test.ts +384 -0
- package/src/orchestration/__tests__/execute-agent-call.test.ts +151 -11
- package/src/orchestration/__tests__/file-run-store-prune.test.ts +168 -0
- package/src/orchestration/__tests__/file-run-store-throttle.test.ts +168 -0
- package/src/orchestration/__tests__/file-run-store.test.ts +390 -0
- package/src/orchestration/__tests__/helpers/flush-microtasks.ts +13 -0
- package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +34 -0
- package/src/orchestration/__tests__/lifecycle-abort-broadcast-signal.test.ts +357 -0
- package/src/orchestration/__tests__/lifecycle-recover-crashed.test.ts +289 -0
- package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +3 -3
- package/src/orchestration/__tests__/lifecycle.test.ts +84 -5
- package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +1 -1
- package/src/orchestration/__tests__/run-snapshot.test.ts +356 -0
- package/src/orchestration/__tests__/script-generate.test.ts +314 -0
- package/src/orchestration/__tests__/script-lint.test.ts +17 -0
- 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} +28 -27
- 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 +275 -0
- package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +78 -1
- package/src/orchestration/__tests__/worker-script-builder.test.ts +1 -1
- package/src/orchestration/__tests__/workflow-files.test.ts +186 -0
- package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +1 -1
- package/src/orchestration/__tests__/workflow-run-summary.test.ts +119 -0
- package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +124 -0
- package/src/orchestration/agent-opts-resolver.ts +8 -8
- package/src/orchestration/args-meta.ts +198 -0
- package/src/orchestration/args-validator.ts +53 -31
- package/src/orchestration/execute-agent-call.ts +25 -79
- package/src/orchestration/file-run-store.ts +327 -0
- package/src/orchestration/launcher.ts +160 -104
- package/src/orchestration/lifecycle.ts +371 -97
- package/src/orchestration/models/agent-call.ts +7 -7
- package/src/orchestration/models/budget.ts +5 -5
- package/src/orchestration/models/ports.ts +4 -4
- package/src/orchestration/models/run-runtime.ts +15 -15
- package/src/orchestration/models/trace.ts +9 -9
- package/src/orchestration/models/types.ts +111 -22
- package/src/orchestration/models/workflow-run.ts +28 -28
- package/src/orchestration/models/workflow-script.ts +4 -4
- package/src/orchestration/run-snapshot.ts +266 -0
- package/src/orchestration/script-generate.ts +154 -0
- package/src/orchestration/script-lint.ts +123 -90
- package/src/orchestration/worker-handle.ts +10 -10
- package/src/orchestration/worker-host.ts +10 -10
- package/src/orchestration/{error-recovery.ts → worker-message-pump.ts} +498 -221
- package/src/orchestration/worker-script-builder.ts +401 -346
- package/src/orchestration/workflow-files.ts +37 -11
- package/src/orchestration/workflow-run-summary.ts +69 -0
- package/src/orchestration/workflow-script-registry-impl.ts +31 -9
- package/src/shared/__tests__/agent-ref.test.ts +209 -2
- package/src/shared/__tests__/atomic-write.test.ts +267 -0
- package/src/shared/__tests__/bounded-serialize.test.ts +236 -0
- package/src/shared/__tests__/injection-render.test.ts +518 -0
- package/src/shared/__tests__/meta-parser.test.ts +151 -0
- package/src/shared/__tests__/resource-discovery-host-roots.test.ts +474 -0
- package/src/shared/__tests__/resource-discovery.test.ts +261 -217
- package/src/shared/agent-ref.ts +143 -2
- package/src/shared/atomic-write.ts +323 -0
- package/src/shared/bounded-serialize.ts +154 -0
- package/src/shared/injection-render.ts +279 -0
- package/src/shared/meta-parser.ts +182 -68
- package/src/shared/model-ref.ts +15 -2
- package/src/shared/resource-discovery.ts +97 -204
- package/src/shared/resource-meta.ts +14 -0
- package/src/shared/schema-jsonify.ts +1 -1
- package/src/shared/xml-injection.ts +9 -9
- package/workflows/README.md +9 -9
- package/workflows/chain.js +4 -2
- package/workflows/map-reduce.js +5 -3
- package/workflows/parallel.js +5 -3
- package/workflows/review-fix-loop-utils.cjs +165 -92
- package/workflows/review-fix-loop-utils.d.cts +287 -0
- package/workflows/review-fix-loop.js +18 -7
- package/workflows/scatter-gather.js +4 -2
- package/dist/chunk-3VOERJPJ.js +0 -22
- 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__/zcode-engine.test.ts +0 -580
- package/src/execution/engine/engines/zcode/launcher.ts +0 -161
- package/src/execution/execute-options-mapper.ts +0 -115
- package/src/execution/session-runner.ts +0 -1789
- package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -288
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// W1 红灯测试:spawn-event-adapter.ts 协议层重写 — Pi 原生格式 + method 平铺。
|
|
4
4
|
//
|
|
5
|
-
// 测试对象:
|
|
5
|
+
// 测试对象:packages/subagent-core/src/execution/engine/engines/pi/spawn-event-adapter.ts(改造)
|
|
6
6
|
// 契约来源:.fix-plans/00-master-summary.md §二(统一接口契约)+ §一冲突 2/判定顺序
|
|
7
7
|
//
|
|
8
8
|
// 核心改动:
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
import { describe, expect, it } from "vitest";
|
|
20
20
|
|
|
21
|
-
import { parseSpawnLine } from "../spawn-event-adapter.ts";
|
|
21
|
+
import { parseSpawnLine } from "../engine/engines/pi/spawn-event-adapter.ts";
|
|
22
22
|
|
|
23
23
|
// ── Pi 原生协议样本构造(来源:rpc-types.ts L230-265 真实类型) ──────────
|
|
24
24
|
// 10 种 method,全部 {type:"extension_ui_request", id, method, ...平铺字段}。
|
|
@@ -28,6 +28,17 @@ function piLine(methodFields: Record<string, unknown>): string {
|
|
|
28
28
|
return JSON.stringify({ type: "extension_ui_request", id: "req-001", ...methodFields });
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
|
|
32
|
+
/** 判别收窄辅助:string-fallback 变体(method: string)使 !== 收窄失效,
|
|
33
|
+
* 用 Extract 条件类型(可赋值方向)精确取变体。 */
|
|
34
|
+
function asVariant<M extends string>(
|
|
35
|
+
req: import("../engine/engines/pi/spawn-event-adapter.ts").ExtensionUiRequest,
|
|
36
|
+
method: M,
|
|
37
|
+
): Extract<import("../engine/engines/pi/spawn-event-adapter.ts").ExtensionUiRequest, { method: M }> {
|
|
38
|
+
if (req.method !== method) throw new Error(`request.method 应为 ${method}`);
|
|
39
|
+
return req as Extract<import("../engine/engines/pi/spawn-event-adapter.ts").ExtensionUiRequest, { method: M }>;
|
|
40
|
+
}
|
|
41
|
+
|
|
31
42
|
describe("parseSpawnLine — 10 种 method 真实样本分类(Pi 原生格式)", () => {
|
|
32
43
|
describe("dialog 类(select/confirm/input/editor)", () => {
|
|
33
44
|
it("select → kind=extension_ui_request + request.method=select + title/options 平铺", () => {
|
|
@@ -37,9 +48,7 @@ describe("parseSpawnLine — 10 种 method 真实样本分类(Pi 原生格式
|
|
|
37
48
|
expect(result?.kind).toBe("extension_ui_request");
|
|
38
49
|
if (result?.kind !== "extension_ui_request") return;
|
|
39
50
|
expect(result.id).toBe("req-001");
|
|
40
|
-
|
|
41
|
-
expect(result.request.title).toBe("Pick one");
|
|
42
|
-
expect(result.request.options).toEqual(["a", "b"]);
|
|
51
|
+
const req = asVariant(result.request, "select");
|
|
43
52
|
});
|
|
44
53
|
|
|
45
54
|
it("confirm → request.method=confirm + title/message 平铺", () => {
|
|
@@ -48,9 +57,7 @@ describe("parseSpawnLine — 10 种 method 真实样本分类(Pi 原生格式
|
|
|
48
57
|
}));
|
|
49
58
|
expect(result?.kind).toBe("extension_ui_request");
|
|
50
59
|
if (result?.kind !== "extension_ui_request") return;
|
|
51
|
-
|
|
52
|
-
expect(result.request.title).toBe("Sure?");
|
|
53
|
-
expect(result.request.message).toBe("Proceed?");
|
|
60
|
+
const req = asVariant(result.request, "confirm");
|
|
54
61
|
});
|
|
55
62
|
|
|
56
63
|
it("input → request.method=input + title + placeholder", () => {
|
|
@@ -59,8 +66,7 @@ describe("parseSpawnLine — 10 种 method 真实样本分类(Pi 原生格式
|
|
|
59
66
|
}));
|
|
60
67
|
expect(result?.kind).toBe("extension_ui_request");
|
|
61
68
|
if (result?.kind !== "extension_ui_request") return;
|
|
62
|
-
|
|
63
|
-
expect(result.request.placeholder).toBe("type here");
|
|
69
|
+
const req = asVariant(result.request, "input");
|
|
64
70
|
});
|
|
65
71
|
|
|
66
72
|
it("editor → request.method=editor + title + prefill", () => {
|
|
@@ -69,8 +75,7 @@ describe("parseSpawnLine — 10 种 method 真实样本分类(Pi 原生格式
|
|
|
69
75
|
}));
|
|
70
76
|
expect(result?.kind).toBe("extension_ui_request");
|
|
71
77
|
if (result?.kind !== "extension_ui_request") return;
|
|
72
|
-
|
|
73
|
-
expect(result.request.prefill).toBe("initial text");
|
|
78
|
+
const req = asVariant(result.request, "editor");
|
|
74
79
|
});
|
|
75
80
|
});
|
|
76
81
|
|
|
@@ -81,8 +86,7 @@ describe("parseSpawnLine — 10 种 method 真实样本分类(Pi 原生格式
|
|
|
81
86
|
}));
|
|
82
87
|
expect(result?.kind).toBe("extension_ui_request");
|
|
83
88
|
if (result?.kind !== "extension_ui_request") return;
|
|
84
|
-
|
|
85
|
-
expect(result.request.message).toBe("hi");
|
|
89
|
+
const req = asVariant(result.request, "notify");
|
|
86
90
|
});
|
|
87
91
|
|
|
88
92
|
it("setStatus → request.method=setStatus + statusKey/statusText", () => {
|
|
@@ -91,8 +95,8 @@ describe("parseSpawnLine — 10 种 method 真实样本分类(Pi 原生格式
|
|
|
91
95
|
}));
|
|
92
96
|
expect(result?.kind).toBe("extension_ui_request");
|
|
93
97
|
if (result?.kind !== "extension_ui_request") return;
|
|
94
|
-
|
|
95
|
-
expect(
|
|
98
|
+
const req = asVariant(result.request, "setStatus");
|
|
99
|
+
expect(req.statusKey).toBe("k");
|
|
96
100
|
});
|
|
97
101
|
|
|
98
102
|
it("setWidget → request.method=setWidget + widgetKey/widgetLines/widgetPlacement", () => {
|
|
@@ -102,25 +106,24 @@ describe("parseSpawnLine — 10 种 method 真实样本分类(Pi 原生格式
|
|
|
102
106
|
}));
|
|
103
107
|
expect(result?.kind).toBe("extension_ui_request");
|
|
104
108
|
if (result?.kind !== "extension_ui_request") return;
|
|
105
|
-
|
|
106
|
-
expect(
|
|
107
|
-
expect(
|
|
109
|
+
const req = asVariant(result.request, "setWidget");
|
|
110
|
+
expect(req.widgetKey).toBe("w1");
|
|
111
|
+
expect(req.widgetPlacement).toBe("aboveEditor");
|
|
108
112
|
});
|
|
109
113
|
|
|
110
114
|
it("setTitle → request.method=setTitle + title", () => {
|
|
111
115
|
const result = parseSpawnLine(piLine({ method: "setTitle", title: "My Title" }));
|
|
112
116
|
expect(result?.kind).toBe("extension_ui_request");
|
|
113
117
|
if (result?.kind !== "extension_ui_request") return;
|
|
114
|
-
|
|
115
|
-
expect(
|
|
118
|
+
const req = asVariant(result.request, "setTitle");
|
|
119
|
+
expect(req.title).toBe("My Title");
|
|
116
120
|
});
|
|
117
121
|
|
|
118
122
|
it("set_editor_text → request.method=set_editor_text + text", () => {
|
|
119
123
|
const result = parseSpawnLine(piLine({ method: "set_editor_text", text: "body" }));
|
|
120
124
|
expect(result?.kind).toBe("extension_ui_request");
|
|
121
125
|
if (result?.kind !== "extension_ui_request") return;
|
|
122
|
-
|
|
123
|
-
expect(result.request.text).toBe("body");
|
|
126
|
+
const req = asVariant(result.request, "set_editor_text");
|
|
124
127
|
});
|
|
125
128
|
});
|
|
126
129
|
});
|
|
@@ -71,7 +71,7 @@ vi.mock("../alive-store.ts", () => ({
|
|
|
71
71
|
writeAliveMarker: vi.fn(),
|
|
72
72
|
}));
|
|
73
73
|
|
|
74
|
-
vi.mock("../temp-prompt.ts", () => ({
|
|
74
|
+
vi.mock("../engine/engines/pi/temp-prompt.ts", () => ({
|
|
75
75
|
writePromptToTempFile: vi.fn(async (agent: string, content: string) => {
|
|
76
76
|
captured.content = content;
|
|
77
77
|
const safeName = agent.replace(/[^\w.-]+/g, "_");
|
|
@@ -83,7 +83,7 @@ vi.mock("../temp-prompt.ts", () => ({
|
|
|
83
83
|
import { spawn } from "node:child_process";
|
|
84
84
|
|
|
85
85
|
import { createRecord } from "../execution-record.ts";
|
|
86
|
-
import { runSpawn, type RunOptions, type SessionRunnerContext } from "../session-runner.ts";
|
|
86
|
+
import { runSpawn, type RunOptions, type SessionRunnerContext } from "../engine/engines/pi/session-runner.ts";
|
|
87
87
|
|
|
88
88
|
const mockSpawn = vi.mocked(spawn);
|
|
89
89
|
|
|
@@ -117,8 +117,9 @@ function makeRecord() {
|
|
|
117
117
|
return createRecord("wt-guidance-1", {
|
|
118
118
|
agent: "general-purpose",
|
|
119
119
|
model: "test/model",
|
|
120
|
-
mode: "
|
|
120
|
+
mode: "background",
|
|
121
121
|
task: "test task",
|
|
122
|
+
slug: "test",
|
|
122
123
|
startedAt: Date.now(),
|
|
123
124
|
rootSessionId: "s1",
|
|
124
125
|
parentRecordId: undefined,
|
|
@@ -128,7 +129,7 @@ function makeRecord() {
|
|
|
128
129
|
|
|
129
130
|
function makeRunOpts(overrides: Partial<RunOptions> = {}): RunOptions {
|
|
130
131
|
return {
|
|
131
|
-
resolved: { model: { provider: "test", id: "model" }, thinkingLevel: undefined },
|
|
132
|
+
resolved: { model: { provider: "test", id: "model", name: "Model", reasoning: false }, thinkingLevel: undefined },
|
|
132
133
|
agentConfig: undefined,
|
|
133
134
|
appendSystemPrompt: undefined,
|
|
134
135
|
skillPath: undefined,
|
|
@@ -5,7 +5,14 @@
|
|
|
5
5
|
// M2-B1 把 spawnedChildren 从 Set<ChildProcess> 改为 Map<recordId, ChildProcess>,
|
|
6
6
|
// 建立 record→child 映射(busy 投递定位活进程用,设计决策 6)。本文件测 Map API 核心行为:
|
|
7
7
|
// - getChildByRecord:set 后能查到;delete 后查不到;未注册返回 undefined
|
|
8
|
-
// - killAllSpawnedChildren:遍历 .values() kill + clear
|
|
8
|
+
// - killAllSpawnedChildren:遍历 .values() kill + clear;单 child kill 抛错不阻断
|
|
9
|
+
// - [R1 D6③] killAllSpawnedChildren 编排扩容:先触发 engine registry dispose(触发不等待),
|
|
10
|
+
// 后杀 per-record children——dispose 全部先于任何 kill(D6① 时序)
|
|
11
|
+
//
|
|
12
|
+
// [T2-⑤ / LC-2] 跳过条件变更(原「跳过 child.killed=true」契约已废止):killed=发过
|
|
13
|
+
// kill 请求 ≠ 已死,只有 exitCode/signalCode 非 null(已确认死亡)才跳过;killed 但
|
|
14
|
+
// 未确认死亡的 child 补 SIGKILL 升级(SIGTERM 可能被无视)。新契约的完整行为矩阵见
|
|
15
|
+
// kill-all-escalation.test.ts(runSpawn 集成面),本文件保留纯 Map 遍历面的正/反例。
|
|
9
16
|
//
|
|
10
17
|
// 直接操作模块级 spawnedChildren(afterEach clear 防泄漏),不依赖 runSpawn/spawn/fs。
|
|
11
18
|
|
|
@@ -16,13 +23,58 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
|
|
16
23
|
const { loggerMock } = vi.hoisted(() => ({
|
|
17
24
|
loggerMock: { debug: vi.fn(), warn: vi.fn(), error: vi.fn() },
|
|
18
25
|
}));
|
|
26
|
+
// mock core logger:session-runner 与 engine/registry 共用同一 facade 模块(两处
|
|
27
|
+
// `../../core/logger.ts` 解析到同一文件),本 mock 对二者同时生效。
|
|
19
28
|
vi.mock("../../core/logger.ts", () => ({ getLogger: () => loggerMock }));
|
|
20
29
|
|
|
21
|
-
import {
|
|
30
|
+
import type { EnginePort } from "../engine/port.ts";
|
|
31
|
+
import { clearEngines, getEngine, registerEngine } from "../engine/registry.ts";
|
|
32
|
+
import { getChildByRecord, killAllSpawnedChildren, spawnedChildren } from "../engine/engines/pi/session-runner.ts";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 假 child:只关心 killed 标记 + kill 调用(killAllSpawnedChildren 遍历用)。
|
|
36
|
+
* extra 可注入 exitCode/signalCode(模拟已确认死亡的形态)。
|
|
37
|
+
*/
|
|
38
|
+
function makeFakeChild(
|
|
39
|
+
killed = false,
|
|
40
|
+
extra: Partial<Pick<ChildProcess, "exitCode" | "signalCode">> = {},
|
|
41
|
+
): ChildProcess & { kill: ReturnType<typeof vi.fn> } {
|
|
42
|
+
return { killed, kill: vi.fn(), ...extra } as unknown as ChildProcess & {
|
|
43
|
+
kill: ReturnType<typeof vi.fn>;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
22
46
|
|
|
23
|
-
/**
|
|
24
|
-
function
|
|
25
|
-
|
|
47
|
+
/** 带 dispose 的假引擎(编排测试用——dispose 触发顺序记进 events,与 child kill 事件共序)。 */
|
|
48
|
+
function makeDisposingEngine(
|
|
49
|
+
id: string,
|
|
50
|
+
events: string[],
|
|
51
|
+
disposeImpl?: () => Promise<void>,
|
|
52
|
+
): EnginePort {
|
|
53
|
+
return {
|
|
54
|
+
id,
|
|
55
|
+
capabilities: () => ({
|
|
56
|
+
schemaEnforcement: "native",
|
|
57
|
+
steer: "unsupported",
|
|
58
|
+
conversation: "unsupported",
|
|
59
|
+
personaInjection: "prompt",
|
|
60
|
+
eventGranularity: "coarse",
|
|
61
|
+
sandbox: "none",
|
|
62
|
+
sessionRead: "outcome-only",
|
|
63
|
+
resume: "unsupported",
|
|
64
|
+
interrupt: "kill-only",
|
|
65
|
+
permissionMode: "fixed",
|
|
66
|
+
maxTurns: false,
|
|
67
|
+
}),
|
|
68
|
+
probe: () =>
|
|
69
|
+
Promise.resolve({ ok: true, engineVersion: "0.0.0-test", checks: [{ name: "stub", ok: true }] }),
|
|
70
|
+
run: () => Promise.reject(new Error("fake engine: run not implemented")),
|
|
71
|
+
interact: () => Promise.resolve({ ok: false, code: "engine_capability_unsupported", message: "stub" }),
|
|
72
|
+
read: () => Promise.resolve({ engineId: id, turns: [], source: "outcome-only" }),
|
|
73
|
+
dispose: disposeImpl ?? (() => {
|
|
74
|
+
events.push(`dispose:${id}`);
|
|
75
|
+
return Promise.resolve();
|
|
76
|
+
}),
|
|
77
|
+
};
|
|
26
78
|
}
|
|
27
79
|
|
|
28
80
|
describe("spawnedChildren Map + getChildByRecord (M2-B1)", () => {
|
|
@@ -58,17 +110,29 @@ describe("spawnedChildren Map + getChildByRecord (M2-B1)", () => {
|
|
|
58
110
|
expect(spawnedChildren.size).toBe(0);
|
|
59
111
|
});
|
|
60
112
|
|
|
61
|
-
it("
|
|
113
|
+
it("[T2-⑤] killed 但未确认死亡 → 不跳过,补 SIGKILL 升级(killed=发过请求≠已死)", () => {
|
|
62
114
|
const alive = makeFakeChild(false);
|
|
63
|
-
const
|
|
115
|
+
const killedNotClosed = makeFakeChild(true); // SIGTERM 已发、exit/signal 仍 null
|
|
64
116
|
spawnedChildren.set("rec-1", alive);
|
|
65
|
-
spawnedChildren.set("rec-2",
|
|
117
|
+
spawnedChildren.set("rec-2", killedNotClosed);
|
|
66
118
|
|
|
67
119
|
const n = killAllSpawnedChildren();
|
|
68
120
|
|
|
69
|
-
expect(n).toBe(
|
|
70
|
-
expect(alive.kill).
|
|
71
|
-
|
|
121
|
+
expect(n).toBe(2);
|
|
122
|
+
expect(alive.kill).toHaveBeenCalledWith("SIGTERM");
|
|
123
|
+
// dispose 是最后兜底,对 killed-not-closed 直接升级 SIGKILL(不再赌 SIGTERM 生效)
|
|
124
|
+
expect(killedNotClosed.kill).toHaveBeenCalledWith("SIGKILL");
|
|
125
|
+
expect(spawnedChildren.size).toBe(0);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("[T2-⑤] killed 且已确认死亡(signalCode 非 null)→ 跳过,不重复发信号", () => {
|
|
129
|
+
const dead = makeFakeChild(true, { signalCode: "SIGTERM" });
|
|
130
|
+
spawnedChildren.set("rec-1", dead);
|
|
131
|
+
|
|
132
|
+
const n = killAllSpawnedChildren();
|
|
133
|
+
|
|
134
|
+
expect(n).toBe(0);
|
|
135
|
+
expect(dead.kill).not.toHaveBeenCalled();
|
|
72
136
|
expect(spawnedChildren.size).toBe(0);
|
|
73
137
|
});
|
|
74
138
|
|
|
@@ -90,3 +154,83 @@ describe("spawnedChildren Map + getChildByRecord (M2-B1)", () => {
|
|
|
90
154
|
expect(spawnedChildren.size).toBe(0);
|
|
91
155
|
});
|
|
92
156
|
});
|
|
157
|
+
|
|
158
|
+
describe("killAllSpawnedChildren 编排扩容(R1 D6③:先引擎 dispose 后 per-record children)", () => {
|
|
159
|
+
afterEach(() => {
|
|
160
|
+
spawnedChildren.clear();
|
|
161
|
+
// registry 是进程级全局状态(Symbol.for 槽),防用例间 fake 引擎泄漏串扰
|
|
162
|
+
clearEngines();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("先全部触发已实例化引擎 dispose,后遍历杀 children(D6① 时序:dispose 先于 SIGTERM)", () => {
|
|
166
|
+
const events: string[] = [];
|
|
167
|
+
registerEngine("e-alpha", () => makeDisposingEngine("e-alpha", events));
|
|
168
|
+
registerEngine("e-beta", () => makeDisposingEngine("e-beta", events));
|
|
169
|
+
getEngine("e-alpha"); // disposeEngines 只遍历已实例化单例,须先实例化
|
|
170
|
+
getEngine("e-beta");
|
|
171
|
+
|
|
172
|
+
const c1 = makeFakeChild();
|
|
173
|
+
const c2 = makeFakeChild();
|
|
174
|
+
c1.kill.mockImplementation(() => {
|
|
175
|
+
events.push("kill:rec-a");
|
|
176
|
+
});
|
|
177
|
+
c2.kill.mockImplementation(() => {
|
|
178
|
+
events.push("kill:rec-b");
|
|
179
|
+
});
|
|
180
|
+
spawnedChildren.set("rec-a", c1);
|
|
181
|
+
spawnedChildren.set("rec-b", c2);
|
|
182
|
+
|
|
183
|
+
const n = killAllSpawnedChildren();
|
|
184
|
+
|
|
185
|
+
expect(n).toBe(2);
|
|
186
|
+
// 时序断言(不依赖穿插序):最后一个 dispose 的索引 < 第一个 kill 的索引
|
|
187
|
+
const disposeIdx = events
|
|
188
|
+
.map((e, i) => (e.startsWith("dispose:") ? i : -1))
|
|
189
|
+
.filter((i) => i >= 0);
|
|
190
|
+
const firstKill = events.findIndex((e) => e.startsWith("kill:"));
|
|
191
|
+
expect(disposeIdx.length).toBe(2);
|
|
192
|
+
expect(firstKill).toBeGreaterThan(Math.max(...disposeIdx));
|
|
193
|
+
expect(spawnedChildren.size).toBe(0);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it("引擎 dispose 同步 throw 不阻断 children 清理(best-effort 编排,catch 记日志继续)", () => {
|
|
197
|
+
const events: string[] = [];
|
|
198
|
+
registerEngine(
|
|
199
|
+
"throwy",
|
|
200
|
+
() =>
|
|
201
|
+
makeDisposingEngine("throwy", events, () => {
|
|
202
|
+
throw new Error("dispose boom");
|
|
203
|
+
}),
|
|
204
|
+
);
|
|
205
|
+
getEngine("throwy");
|
|
206
|
+
const child = makeFakeChild();
|
|
207
|
+
child.kill.mockImplementation(() => {
|
|
208
|
+
events.push("kill:rec-1");
|
|
209
|
+
});
|
|
210
|
+
spawnedChildren.set("rec-1", child);
|
|
211
|
+
|
|
212
|
+
expect(() => killAllSpawnedChildren()).not.toThrow();
|
|
213
|
+
expect(child.kill).toHaveBeenCalledTimes(1);
|
|
214
|
+
expect(spawnedChildren.size).toBe(0);
|
|
215
|
+
expect(loggerMock.warn).toHaveBeenCalledWith(
|
|
216
|
+
expect.stringContaining("[engine-registry] engine 'throwy' dispose threw synchronously"),
|
|
217
|
+
);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it("引擎仅注册工厂未实例化 → 不触发 dispose 也不实例化(停机路径不反向创建资源)", () => {
|
|
221
|
+
const events: string[] = [];
|
|
222
|
+
const engine = makeDisposingEngine("unused", events);
|
|
223
|
+
registerEngine("unused", () => engine);
|
|
224
|
+
const child = makeFakeChild();
|
|
225
|
+
child.kill.mockImplementation(() => {
|
|
226
|
+
events.push("kill:rec-1");
|
|
227
|
+
});
|
|
228
|
+
spawnedChildren.set("rec-1", child);
|
|
229
|
+
|
|
230
|
+
const n = killAllSpawnedChildren();
|
|
231
|
+
|
|
232
|
+
expect(n).toBe(1);
|
|
233
|
+
expect(events).toEqual(["kill:rec-1"]); // 无 dispose 事件混入
|
|
234
|
+
expect(child.kill).toHaveBeenCalledTimes(1);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
@@ -30,14 +30,14 @@ vi.mock("node:child_process", async () => {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
// buildSpawnArgs 包装为 spy(保留真实实现)——「非全等拒单不触达 spawn 参数组装」的承重断言。
|
|
33
|
-
vi.mock("../session-runner.ts", async (importOriginal) => {
|
|
34
|
-
const actual = await importOriginal<typeof import("../session-runner.ts")>();
|
|
33
|
+
vi.mock("../engine/engines/pi/session-runner.ts", async (importOriginal) => {
|
|
34
|
+
const actual = await importOriginal<typeof import("../engine/engines/pi/session-runner.ts")>();
|
|
35
35
|
return { ...actual, buildSpawnArgs: vi.fn(actual.buildSpawnArgs) };
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
import { ModelConfigService } from "../model-config-service.ts";
|
|
39
39
|
import type { ModelInfo, ModelRegistryLike } from "../model-resolver.ts";
|
|
40
|
-
import { buildSpawnArgs } from "../session-runner.ts";
|
|
40
|
+
import { buildSpawnArgs } from "../engine/engines/pi/session-runner.ts";
|
|
41
41
|
import type { PiLike } from "../subagent-service.ts";
|
|
42
42
|
import { SubagentService } from "../subagent-service.ts";
|
|
43
43
|
|
|
@@ -128,7 +128,7 @@ describe("start 同步期裁决(U1 验收 3:非全等 → isError 且无 spa
|
|
|
128
128
|
});
|
|
129
129
|
|
|
130
130
|
it("全等入参通过裁决(reject 不发生,放行链路触达 spawn 参数组装)——守卫零误伤对照", async () => {
|
|
131
|
-
//
|
|
131
|
+
// 放行路径会进入轮次 kick-off(detached);execute resolve 即视为裁决放行。
|
|
132
132
|
// spawn 本身由 FakeChild 缺失抛错收口——本断言只关心「越过了同步裁决」:
|
|
133
133
|
// execute 不 reject,且 buildSpawnArgs 已被调(或即将被调的 record 已创建)。
|
|
134
134
|
const promise = service.execute({
|
|
@@ -33,7 +33,7 @@ vi.mock("../../core/logger.ts", () => ({
|
|
|
33
33
|
getLogger: () => loggerMock,
|
|
34
34
|
}));
|
|
35
35
|
|
|
36
|
-
import { respond, sendGetStateCommand, sendPromptCommand } from "../stdin-writer.ts";
|
|
36
|
+
import { respond, sendGetStateCommand, sendPromptCommand } from "../engine/engines/pi/stdin-writer.ts";
|
|
37
37
|
|
|
38
38
|
// ── helpers ──
|
|
39
39
|
|
|
@@ -362,8 +362,10 @@ describe("sendGetStateCommand", () => {
|
|
|
362
362
|
describe("writeStdinLine 背压 — write 返回 false 时 warn 不 throw", () => {
|
|
363
363
|
it("child.stdin.write 返回 false → warn 一次,函数正常返回(不 throw)", () => {
|
|
364
364
|
// 构造 write 永远返回 false 的假 stream(模拟内核缓冲满/HWM 到达)
|
|
365
|
+
// 保留 vi.fn 引用(经 PassThrough 视图后 write 的 mock 面不可达)
|
|
366
|
+
const fakeWrite = vi.fn((_chunk: unknown) => false);
|
|
365
367
|
const fakeStdin = {
|
|
366
|
-
write:
|
|
368
|
+
write: fakeWrite,
|
|
367
369
|
destroyed: false,
|
|
368
370
|
} as unknown as PassThrough;
|
|
369
371
|
const child = { stdin: fakeStdin } as unknown as ChildProcess;
|
|
@@ -371,8 +373,8 @@ describe("writeStdinLine 背压 — write 返回 false 时 warn 不 throw", () =
|
|
|
371
373
|
expect(() => respond(child, "req-backpressure", { value: "x" })).not.toThrow();
|
|
372
374
|
|
|
373
375
|
// write 被调一次(写入 command 行)
|
|
374
|
-
expect(
|
|
375
|
-
const writtenArg =
|
|
376
|
+
expect(fakeWrite).toHaveBeenCalledTimes(1);
|
|
377
|
+
const writtenArg = fakeWrite.mock.calls[0]![0] as string;
|
|
376
378
|
expect(writtenArg).toContain("extension_ui_response");
|
|
377
379
|
expect(writtenArg).toContain("req-backpressure");
|
|
378
380
|
expect(writtenArg.endsWith("\n")).toBe(true);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// widget 私货通道退役步骤 2(E 方案 §6.3)测试,两层:
|
|
4
4
|
// 判定层:createBackgroundStream 真实函数(vi.importActual 绕过文件级 mock)——
|
|
5
5
|
// gui+relay 激活不创建;tui / relay 未激活 / headless 原样创建;sink=null 恒降级。
|
|
6
|
-
// 接线层:SubagentService.execute(background →
|
|
6
|
+
// 接线层:SubagentService.execute(background → kickOffChatRound 同步段)透传
|
|
7
7
|
// mode/streamSink 给工厂——mode 传错 = 判定失效,故接线面必须锁定。
|
|
8
8
|
//
|
|
9
9
|
// spawn 层 mock(FakeChild),与 nested-visibility-env-propagation.test.ts 同模式。
|
|
@@ -103,7 +103,7 @@ vi.mock("../manifest-store.ts", () => {
|
|
|
103
103
|
return { ManifestStore: vi.fn(function (_recordsDir: string) { return new FakeManifestStore(); }) };
|
|
104
104
|
});
|
|
105
105
|
|
|
106
|
-
vi.mock("../temp-prompt.ts", () => ({
|
|
106
|
+
vi.mock("../engine/engines/pi/temp-prompt.ts", () => ({
|
|
107
107
|
writePromptToTempFile: vi.fn(async (agent: string) => {
|
|
108
108
|
const safeName = agent.replace(/[^\w.-]+/g, "_");
|
|
109
109
|
return { dir: `/tmp/fake-${safeName}`, filePath: `/tmp/fake-${safeName}/prompt-${safeName}.md` };
|
|
@@ -156,7 +156,7 @@ const ctxModel: ModelInfo = { id: "m", name: "M", provider: "p", reasoning: fals
|
|
|
156
156
|
|
|
157
157
|
function setupService(mode: ExtensionMode | undefined, sessionId = "retire-it"): SubagentService {
|
|
158
158
|
const agentDir = "/tmp/stream-retire-it";
|
|
159
|
-
const modelService = new ModelConfigService({ agentDir });
|
|
159
|
+
const modelService = new ModelConfigService({ agentDir, cwd: agentDir });
|
|
160
160
|
modelService.initModel({
|
|
161
161
|
modelRegistry: makeEmptyRegistry(),
|
|
162
162
|
sessionId,
|
|
@@ -176,7 +176,7 @@ function setupService(mode: ExtensionMode | undefined, sessionId = "retire-it"):
|
|
|
176
176
|
return service;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
/** 等
|
|
179
|
+
/** 等 kickOffChatRound 的 detached 轮次执行走到 spawn(stream 创建先于此)。 */
|
|
180
180
|
async function waitForSpawnCall(): Promise<void> {
|
|
181
181
|
const baseline = mockSpawn.mock.calls.length;
|
|
182
182
|
const deadline = Date.now() + 2000;
|
|
@@ -187,7 +187,7 @@ async function waitForSpawnCall(): Promise<void> {
|
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
async function executeBackground(service: SubagentService): Promise<void> {
|
|
190
|
-
await service.execute({ task: "retire test", ctxModel });
|
|
190
|
+
await service.execute({ task: "retire test", slug: "test", ctxModel });
|
|
191
191
|
await waitForSpawnCall();
|
|
192
192
|
// 推进 detached runSpawn 收尾(FakeChild close),防句柄悬挂干扰后续用例
|
|
193
193
|
lastSpawnedChild().emit("close", 0);
|
|
@@ -234,7 +234,7 @@ describe("退役步骤 2 判定层:createBackgroundStream", () => {
|
|
|
234
234
|
|
|
235
235
|
// ── 接线层:service → 工厂的参数透传(mode 传错 = 判定失效)──
|
|
236
236
|
|
|
237
|
-
describe("退役步骤 2 接线层:
|
|
237
|
+
describe("退役步骤 2 接线层:kickOffChatRound 透传 mode/sink 给工厂", () => {
|
|
238
238
|
beforeEach(() => {
|
|
239
239
|
vi.clearAllMocks();
|
|
240
240
|
for (const key of RELAY_ENV_KEYS) delete process.env[key];
|