@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
|
@@ -84,79 +84,12 @@ function dialogTimeoutLogMessage(req: UiRequest, waitedMs: number): string {
|
|
|
84
84
|
);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
// ──
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
* (string & {}) 兜底:Pi 未来新增 method 或未知 method 走字符串字面量类型。 */
|
|
94
|
-
export type UiMethod =
|
|
95
|
-
| "select"
|
|
96
|
-
| "confirm"
|
|
97
|
-
| "input"
|
|
98
|
-
| "editor"
|
|
99
|
-
| "notify"
|
|
100
|
-
| "setStatus"
|
|
101
|
-
| "setWidget"
|
|
102
|
-
| "setTitle"
|
|
103
|
-
| "set_editor_text"
|
|
104
|
-
| (string & {});
|
|
105
|
-
|
|
106
|
-
/** UI 请求(session-runner 构造后传给 handler)。
|
|
107
|
-
*
|
|
108
|
-
* method 是判别字段,决定排队策略(dialog 排队)和业务路由(channel 分发)。
|
|
109
|
-
* method 特定字段按 method 可选出现(与 ExtensionUiRequest 1:1,由 session-runner 从
|
|
110
|
-
* ExtensionUiRequest 平铺构造)。channel/channelPayload 由 parseChannel 填充。
|
|
111
|
-
*
|
|
112
|
-
* 契约来源:.fix-plans/00-master-summary.md §二 2.2。 */
|
|
113
|
-
export interface UiRequest {
|
|
114
|
-
/** Pi rpc-types.ts 的 method(select/confirm/input/editor 为 dialog 类)。 */
|
|
115
|
-
method: UiMethod;
|
|
116
|
-
/** 请求 id(从 extension_ui_request envelope 顶层提取,用于 response 关联)。 */
|
|
117
|
-
id: string;
|
|
118
|
-
// method 特定字段(按 method 可选,与 ExtensionUiRequest 1:1)
|
|
119
|
-
title?: string;
|
|
120
|
-
options?: string[];
|
|
121
|
-
message?: string;
|
|
122
|
-
placeholder?: string;
|
|
123
|
-
prefill?: string;
|
|
124
|
-
notifyType?: string;
|
|
125
|
-
statusKey?: string;
|
|
126
|
-
statusText?: string | undefined;
|
|
127
|
-
widgetKey?: string;
|
|
128
|
-
widgetLines?: string[] | undefined;
|
|
129
|
-
widgetPlacement?: "aboveEditor" | "belowEditor";
|
|
130
|
-
text?: string;
|
|
131
|
-
timeout?: number;
|
|
132
|
-
/** channel 名(从 method 对应字段的 NUL 前缀解析)。
|
|
133
|
-
* select → 从 title 解析;setWidget → 从 widgetLines[0] 解析;其他 → undefined。
|
|
134
|
-
* 已知值:"ask_user"(select)、"gui_widget"(setWidget)。handler 按 channel 分发。 */
|
|
135
|
-
channel?: string;
|
|
136
|
-
/** channel 解析后的结构化 payload(已 JSON.parse)。
|
|
137
|
-
* ask_user: {questions, allowCancel};gui_widget: {component};无 channel: undefined。 */
|
|
138
|
-
channelPayload?: unknown;
|
|
139
|
-
/** 内部元数据字段:发起该 UI 请求的子进程 pid(由 session-runner.handleUiRequest 从
|
|
140
|
-
* child.pid 填入)。L2 队列据此关联 rejectChildDialogs(child close 时批量 reject)。
|
|
141
|
-
* 下划线前缀表示内部字段,非 Pi 协议字段,不参与 stdin 回写。 */
|
|
142
|
-
_childPid?: number;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/** UI 响应(handler 返回,session-runner 按 shape 回写 stdin)。
|
|
146
|
-
* - {value}: select/input/editor 的答案
|
|
147
|
-
* - {confirmed}: confirm 的答案
|
|
148
|
-
* - {cancelled}: 取消(child close / handler 抛错 / 用户取消)
|
|
149
|
-
* - {ack}: fire-and-forget(当前不透传到 TUI,留作协议完整) */
|
|
150
|
-
export type UiResponse =
|
|
151
|
-
| { value: string }
|
|
152
|
-
| { confirmed: boolean }
|
|
153
|
-
| { cancelled: true }
|
|
154
|
-
| { ack: true };
|
|
155
|
-
|
|
156
|
-
/** UI 请求 handler 签名(单函数,按 req.method 内部路由)。
|
|
157
|
-
* 实现方负责:channel 业务路由(ask_user → AskUserComponent)+ 默认转发(ctx.ui.*)。
|
|
158
|
-
* 抛错由调用方(DialogGlobalQueue / session-runner)兜底为 {cancelled:true}。 */
|
|
159
|
-
export type UiRequestHandler = (req: UiRequest) => Promise<UiResponse>;
|
|
87
|
+
// ── 类型再导出(W7 / R3 S-A + R4-S③:SSOT 迁 @zhushanwen/subagent-engine-sdk
|
|
88
|
+
// src/ui-types.ts,结构等价;队列实现本体留 core——壳侧 host/askUser 消费端与
|
|
89
|
+
// inproc 过渡链路同样消费该类型面。双向可赋值断言挂本包 typecheck 断言族
|
|
90
|
+
// (contract-closure),漂移编译期可抓。 ──
|
|
91
|
+
export type { UiMethod, UiRequest, UiRequestHandler, UiResponse } from "@zhushanwen/subagent-engine-sdk";
|
|
92
|
+
import type { UiRequest, UiRequestHandler, UiResponse } from "@zhushanwen/subagent-engine-sdk";
|
|
160
93
|
|
|
161
94
|
// ── DialogGlobalQueue 实现 ──
|
|
162
95
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// capability-gate.test.ts —— [D3-④ 预检 capabilities 化] 拦截矩阵单测。
|
|
2
|
-
// 设计权威源:docs/design/subagent-
|
|
2
|
+
// 设计权威源:docs/design/subagent-engine-protocolization.md §3.3「能力位」段(manifest
|
|
3
|
+
// 权威双向处置)+ 历史源 subagent-dual-track-convergence.md §3.3 D3-④(r3 裁定:
|
|
3
4
|
// EngineCapabilities +maxTurns 位 pi=true/zcode=false,不保留硬编码 shape 检查)+
|
|
4
5
|
// §3.4 错误规格第 1 行 + §4 V4④⑤(正反向验收)。
|
|
5
6
|
//
|
|
@@ -7,21 +8,41 @@
|
|
|
7
8
|
// 1. per-engine 拦截矩阵:pi 全放行(含 maxTurns/fork/conversation/worktree——V4⑤
|
|
8
9
|
// 反向守护,pi 既有合法能力零拦截);zcode 四参数全拦(fork/conversation/
|
|
9
10
|
// maxTurns/worktree)
|
|
10
|
-
// 2. 错误族:engine_capability_unsupported + recovery
|
|
11
|
-
//
|
|
12
|
-
//
|
|
11
|
+
// 2. 错误族:engine_capability_unsupported + recovery 含可操作指引(调参数 / 修
|
|
12
|
+
// manifest / 升级引擎包——W3 协议化口径,不再指向「engine: pi」内置兜底)
|
|
13
|
+
// 3. fork 判据(借位裁定):session 分叉通道族任一可用即放行(OR 语义,A6⑦)——
|
|
14
|
+
// pi conversation=native 放行(steer 虽 unsupported 不参与否决);通道族全缺才拦
|
|
15
|
+
// 4. [W3] 方向判定②:manifest 多声明 → assertGateCapabilitiesMatched 抛
|
|
16
|
+
// engine_capability_mismatch(gate 位逐位正反例 + 非 gate 位不判定)
|
|
13
17
|
|
|
14
18
|
import { describe, expect, it } from "vitest";
|
|
15
19
|
|
|
16
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
assertGateCapabilitiesMatched,
|
|
22
|
+
assertTaskShapeSupported,
|
|
23
|
+
type TaskShapeForGate,
|
|
24
|
+
} from "../../common/capability-gate.ts";
|
|
17
25
|
import { EngineError } from "../../common/errors.ts";
|
|
26
|
+
import { readFileSync } from "node:fs";
|
|
27
|
+
import { dirname, join } from "node:path";
|
|
28
|
+
import { fileURLToPath } from "node:url";
|
|
29
|
+
|
|
18
30
|
import type { EngineCapabilities } from "../../types.ts";
|
|
19
|
-
import { PiEngine } from "../../engines/pi/pi-engine.ts";
|
|
20
|
-
import { ZcodeEngine } from "../../engines/zcode/zcode-engine.ts";
|
|
21
31
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
// W10(§2.10 ②):gate 判据源改读引擎包 manifest(package.json xyz-agent.capabilities
|
|
33
|
+
// ——协议化后同步成员唯一源),不再深路径构造内建引擎实例(W11 删除)。
|
|
34
|
+
function manifestCaps(relPkg: string): EngineCapabilities {
|
|
35
|
+
const pkg = JSON.parse(
|
|
36
|
+
readFileSync(
|
|
37
|
+
join(dirname(fileURLToPath(import.meta.url)), "../../../../../../", relPkg, "package.json"),
|
|
38
|
+
"utf8",
|
|
39
|
+
),
|
|
40
|
+
) as { "xyz-agent": { subagentEngine: { capabilities: EngineCapabilities } } };
|
|
41
|
+
return pkg["xyz-agent"].subagentEngine.capabilities;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const PI_CAPS = manifestCaps("pi-subagent-cli");
|
|
45
|
+
const ZCODE_CAPS = manifestCaps("zcode-subagent-cli");
|
|
25
46
|
|
|
26
47
|
/** 会话分叉通道族可用的 zcode 形态变体(fork 判据用)。 */
|
|
27
48
|
const ZCODE_CAPS_WITH_CONVERSATION: EngineCapabilities = { ...ZCODE_CAPS, conversation: "native" };
|
|
@@ -34,12 +55,24 @@ function gate(
|
|
|
34
55
|
assertTaskShapeSupported(engineId, caps, task);
|
|
35
56
|
}
|
|
36
57
|
|
|
37
|
-
|
|
58
|
+
/** 断言载体(结构化面):EngineError(core)与 EngineSdkError(SDK 构造器)共用
|
|
59
|
+
* code/message/recovery 契约,测试按结构断言不绑类。 */
|
|
60
|
+
interface GateErrorShape {
|
|
61
|
+
code: string;
|
|
62
|
+
message: string;
|
|
63
|
+
recovery: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function gateError(caps: EngineCapabilities, task: TaskShapeForGate, engineId = "zcode"): GateErrorShape {
|
|
38
67
|
try {
|
|
39
68
|
gate(caps, task, engineId);
|
|
40
69
|
} catch (err) {
|
|
41
|
-
|
|
42
|
-
|
|
70
|
+
// [W1 交接防漂移项落地] conversation 分支抛 SDK EngineSdkError
|
|
71
|
+
//(engineConversationUnsupportedError——core 与引擎侧判据单源,W3 接线);其余
|
|
72
|
+
// 分支仍为 core EngineError。code/recovery/message 前缀契约两侧一致。
|
|
73
|
+
expect(err).toHaveProperty("code");
|
|
74
|
+
expect(err).toHaveProperty("recovery");
|
|
75
|
+
return err as unknown as GateErrorShape;
|
|
43
76
|
}
|
|
44
77
|
throw new Error("expected assertTaskShapeSupported to throw");
|
|
45
78
|
}
|
|
@@ -71,8 +104,10 @@ describe("capability-gate(D3-④ 拦截矩阵)", () => {
|
|
|
71
104
|
expect(err.code).toBe("engine_capability_unsupported");
|
|
72
105
|
expect(err.message).toMatch(pattern);
|
|
73
106
|
expect(err.message).toContain("capabilities");
|
|
74
|
-
// 错误信息可操作(§3.4
|
|
75
|
-
|
|
107
|
+
// 错误信息可操作(§3.4 + W3 协议化口径):恢复指引 = 调整参数 / 修 manifest /
|
|
108
|
+
// 升级引擎包(能力声明的载体),不再指向「engine: pi」内置兜底
|
|
109
|
+
expect(err.recovery).toMatch(/去掉|不传/);
|
|
110
|
+
expect(err.recovery).toMatch(/修 manifest|升级引擎包/);
|
|
76
111
|
}
|
|
77
112
|
});
|
|
78
113
|
|
|
@@ -89,3 +124,68 @@ describe("capability-gate(D3-④ 拦截矩阵)", () => {
|
|
|
89
124
|
expect(() => gate({ ...ZCODE_CAPS, steer: "native" }, { fork: true })).not.toThrow();
|
|
90
125
|
});
|
|
91
126
|
});
|
|
127
|
+
|
|
128
|
+
// ============================================================
|
|
129
|
+
// [W3] 方向判定②:manifest 多声明 → engine_capability_mismatch(impl-plan §2.3)
|
|
130
|
+
// ============================================================
|
|
131
|
+
|
|
132
|
+
describe("assertGateCapabilitiesMatched(manifest vs initialize 应答,gate 位方向判定)", () => {
|
|
133
|
+
function mismatchError(
|
|
134
|
+
manifestCaps: EngineCapabilities,
|
|
135
|
+
answeredCaps: EngineCapabilities,
|
|
136
|
+
): EngineError {
|
|
137
|
+
try {
|
|
138
|
+
assertGateCapabilitiesMatched("fake", manifestCaps, answeredCaps);
|
|
139
|
+
} catch (err) {
|
|
140
|
+
expect(err).toBeInstanceOf(EngineError);
|
|
141
|
+
return err as EngineError;
|
|
142
|
+
}
|
|
143
|
+
throw new Error("expected assertGateCapabilitiesMatched to throw");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
it("conversation:manifest 非 unsupported、应答 unsupported → engine_capability_mismatch", () => {
|
|
147
|
+
const err = mismatchError(
|
|
148
|
+
{ ...ZCODE_CAPS, conversation: "native" },
|
|
149
|
+
{ ...ZCODE_CAPS, conversation: "unsupported" },
|
|
150
|
+
);
|
|
151
|
+
expect(err.code).toBe("engine_capability_mismatch");
|
|
152
|
+
expect(err.message).toContain("conversation");
|
|
153
|
+
expect(err.recovery).toMatch(/manifest|升级引擎包/);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("fork 通道族(OR 对偶):manifest 任一可用、应答双 unsupported → mismatch", () => {
|
|
157
|
+
const err = mismatchError(
|
|
158
|
+
{ ...ZCODE_CAPS, steer: "native" },
|
|
159
|
+
{ ...ZCODE_CAPS, steer: "unsupported", conversation: "unsupported" },
|
|
160
|
+
);
|
|
161
|
+
expect(err.code).toBe("engine_capability_mismatch");
|
|
162
|
+
expect(err.message).toContain("fork");
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("maxTurns:manifest true、应答 false → mismatch", () => {
|
|
166
|
+
const err = mismatchError({ ...ZCODE_CAPS, maxTurns: true }, { ...ZCODE_CAPS, maxTurns: false });
|
|
167
|
+
expect(err.code).toBe("engine_capability_mismatch");
|
|
168
|
+
expect(err.message).toContain("maxTurns");
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("sandbox:manifest 非 none、应答 none → mismatch", () => {
|
|
172
|
+
const err = mismatchError({ ...ZCODE_CAPS, sandbox: "emulated" }, { ...ZCODE_CAPS, sandbox: "none" });
|
|
173
|
+
expect(err.code).toBe("engine_capability_mismatch");
|
|
174
|
+
expect(err.message).toContain("sandbox");
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("应答强于 manifest(引擎兑现更多)→ 不抛;同值对齐 → 不抛(无多声明)", () => {
|
|
178
|
+
const weak = { ...ZCODE_CAPS, conversation: "unsupported" as const, maxTurns: false, sandbox: "none" as const };
|
|
179
|
+
const strong = { ...ZCODE_CAPS, conversation: "native" as const, maxTurns: true, sandbox: "emulated" as const };
|
|
180
|
+
// 应答强于 manifest:引擎兑现 manifest 全部声明,无多声明
|
|
181
|
+
expect(() => assertGateCapabilitiesMatched("fake", weak, strong)).not.toThrow();
|
|
182
|
+
// 同值对齐:无差异
|
|
183
|
+
expect(() => assertGateCapabilitiesMatched("fake", strong, strong)).not.toThrow();
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("非 gate 位不一致 → 不判定不抛(无论强弱一律 warn 留痕,归 EngineClient 诊断面)", () => {
|
|
187
|
+
const manifest = { ...ZCODE_CAPS, personaInjection: "file" as const, eventGranularity: "stream" as const, sessionRead: "full" as const, resume: "native" as const, interrupt: "native" as const, permissionMode: "native" as const, schemaEnforcement: "native" as const };
|
|
188
|
+
const weaker = { ...ZCODE_CAPS, personaInjection: "prompt" as const, eventGranularity: "coarse" as const, sessionRead: "outcome-only" as const, resume: "unsupported" as const, interrupt: "kill-only" as const, permissionMode: "fixed" as const, schemaEnforcement: "emulated" as const };
|
|
189
|
+
expect(() => assertGateCapabilitiesMatched("fake", manifest, weaker)).not.toThrow();
|
|
190
|
+
});
|
|
191
|
+
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// errors.test.ts —— 引擎层错误 SSOT 的结构锁定。
|
|
2
2
|
//
|
|
3
|
-
// 三视角:①构建者——
|
|
4
|
-
//
|
|
3
|
+
// 三视角:①构建者——12 条 code 与设计错误规格全表一致([W3] 协议化增
|
|
4
|
+
// engine_capability_mismatch——manifest 多声明的 run 期握手阻断面,与 SDK 协议错误码
|
|
5
|
+
// 词表同源);②使用者——错误消息 code 前缀格式可被字符串匹配分流;③观察者——每条
|
|
6
|
+
// 错误必有非空恢复指引(可操作)。
|
|
5
7
|
|
|
6
8
|
import { describe, expect, it } from "vitest";
|
|
7
9
|
|
|
@@ -12,14 +14,12 @@ import {
|
|
|
12
14
|
engineRunFailedDetail,
|
|
13
15
|
engineTimeoutDetail,
|
|
14
16
|
isEngineErrorCode,
|
|
15
|
-
nestedSpawnRejectedError,
|
|
16
17
|
promptTooLargeError,
|
|
17
|
-
schemaEmulationFailedDetail,
|
|
18
18
|
STDOUT_TAIL_ECHO_CHARS,
|
|
19
19
|
} from "../../common/errors.ts";
|
|
20
20
|
|
|
21
21
|
describe("ENGINE_ERROR_CODES(§3.3.3 全表)", () => {
|
|
22
|
-
it("
|
|
22
|
+
it("12 条错误码与设计文档错误规格表逐条一致([W3] 协议化增 engine_capability_mismatch)", () => {
|
|
23
23
|
expect([...ENGINE_ERROR_CODES]).toEqual([
|
|
24
24
|
"engine_not_found",
|
|
25
25
|
"engine_probe_failed",
|
|
@@ -28,6 +28,7 @@ describe("ENGINE_ERROR_CODES(§3.3.3 全表)", () => {
|
|
|
28
28
|
"schema_emulation_failed",
|
|
29
29
|
"engine_timeout",
|
|
30
30
|
"engine_capability_unsupported",
|
|
31
|
+
"engine_capability_mismatch",
|
|
31
32
|
"engine_session_not_resumable",
|
|
32
33
|
"model_not_available",
|
|
33
34
|
"prompt_too_large",
|
|
@@ -90,13 +91,6 @@ describe("具名构造器", () => {
|
|
|
90
91
|
expect(err.recovery).toMatch(/stdin/);
|
|
91
92
|
});
|
|
92
93
|
|
|
93
|
-
it("nestedSpawnRejectedError:说明防护规则 + 指向 task 内自行完成", () => {
|
|
94
|
-
const err = nestedSpawnRejectedError();
|
|
95
|
-
expect(err.code).toBe("nested_spawn_rejected");
|
|
96
|
-
expect(err.message).toContain("XYZ_AGENT_SUBAGENT");
|
|
97
|
-
expect(err.recovery).toMatch(/inside the current task/);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
94
|
it("engineTimeoutDetail:含 stdout 尾部 + engine: pi 重跑建议", () => {
|
|
101
95
|
const detail = engineTimeoutDetail("partial stdout output");
|
|
102
96
|
expect(detail).toContain("partial stdout output");
|
|
@@ -123,10 +117,9 @@ describe("具名构造器", () => {
|
|
|
123
117
|
expect(engineRunFailedDetail("crash", null, "t")).toContain("killed by signal");
|
|
124
118
|
});
|
|
125
119
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
});
|
|
120
|
+
// nestedSpawnRejectedError 用例已随构造器删除(nesting-guard 收编 SDK 后死导出,
|
|
121
|
+
// 活体单源 SDK nesting-guard.ts NestedSpawnRejectedError,其行为由 SDK
|
|
122
|
+
// __tests__/primitives.test.ts + 本目录 nesting-guard.test.ts 覆盖)。
|
|
123
|
+
// schemaEmulationFailedDetail 用例已随函数删除(test-only 死镜像收口,活体单源
|
|
124
|
+
// SDK error-codes.ts,其行为由 SDK __tests__/primitives.test.ts 覆盖)。
|
|
132
125
|
});
|
|
@@ -25,7 +25,7 @@ function tmpPath(name: string): string {
|
|
|
25
25
|
|
|
26
26
|
afterEach(() => {
|
|
27
27
|
if (tmpRoot !== undefined) {
|
|
28
|
-
rmSync(tmpRoot, { recursive: true, force: true });
|
|
28
|
+
rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
29
29
|
tmpRoot = undefined;
|
|
30
30
|
}
|
|
31
31
|
});
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
// kill-chain.test.ts —— 杀链两分支 + 超时终态合成 + abort 两级编排(fake timers)。
|
|
2
2
|
//
|
|
3
|
+
// 实现体已收编 @zhushanwen/subagent-engine-sdk(common/kill-chain.ts 为 re-export
|
|
4
|
+
// shim,s4-reuse 簇 1):SDK 侧 __tests__/kill-chain.test.ts 是超集演进版(+
|
|
5
|
+
// LoggerSink 捕获 + kill 抛错幂等用例),本文件保留 core 侧独有断言——engine: pi
|
|
6
|
+
// 重跑建议文案、stdout 尾部 2000 字截断、signalCode 形态退出、grace 贴边不升级。
|
|
7
|
+
// SDK 版 synthesizeTimeoutOutcome 的 engineId 必填(core 原缺省 "pi" 已删),用例显式传。
|
|
8
|
+
//
|
|
3
9
|
// 三视角:①构建者——SIGTERM 优雅 / 超时 SIGKILL 两分支的信号序列正确;②使用者——
|
|
4
10
|
// abortWithFallback 对 CLI-only 与 native-interrupt 引擎都收敛不悬挂;③观察者——
|
|
5
11
|
// 合成终态的 error 含 stdout 尾部与 exitCode=null(被信号杀死判据)。
|
|
@@ -120,6 +126,7 @@ describe("synthesizeTimeoutOutcome", () => {
|
|
|
120
126
|
const outcome = synthesizeTimeoutOutcome(
|
|
121
127
|
{ prompt: "review files", description: "review-files" },
|
|
122
128
|
"last stdout lines...",
|
|
129
|
+
"pi",
|
|
123
130
|
);
|
|
124
131
|
expect(outcome.error!).toContain("engine_timeout");
|
|
125
132
|
expect(outcome.error).toContain("review-files");
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
// nesting-guard.test.ts —— 嵌套标记注入与原生标记剥离(D8 双层防护)。
|
|
2
2
|
//
|
|
3
|
+
// 实现体已收编 @zhushanwen/subagent-engine-sdk(common/nesting-guard.ts 为
|
|
4
|
+
// re-export shim,s4-reuse 簇 2):SDK 侧 __tests__/primitives.test.ts 已有同语义
|
|
5
|
+
// 断言,本文件保留 core 侧独有细粒度断言——精确名 vs 前缀剥离边界(CLAUDE_UNRELATED)、
|
|
6
|
+
// 非 '1' 值不抛、空白 env 最小产出。错误形态随收编改 NestedSpawnRejectedError
|
|
7
|
+
//(code/recovery 文案与 core 词表逐字一致)。
|
|
8
|
+
//
|
|
3
9
|
// 三视角:①构建者——三引擎原生标记(PI_SUBAGENT_* / CLAUDECODE / ZSW_NESTED)全部
|
|
4
10
|
// 剥离且其余 env 保留;②使用者——子代理进程内 assertNotNestedSpawn 同步拒绝且文案
|
|
5
11
|
// 可操作;③观察者——产出的 env 是新对象(不污染入参)。
|
|
@@ -9,9 +15,9 @@ import { describe, expect, it } from "vitest";
|
|
|
9
15
|
import {
|
|
10
16
|
assertNotNestedSpawn,
|
|
11
17
|
buildNestedSpawnEnv,
|
|
18
|
+
NestedSpawnRejectedError,
|
|
12
19
|
NESTED_SPAWN_ENV,
|
|
13
20
|
} from "../../common/nesting-guard.ts";
|
|
14
|
-
import { EngineError } from "../../common/errors.ts";
|
|
15
21
|
|
|
16
22
|
describe("buildNestedSpawnEnv", () => {
|
|
17
23
|
it("注入统一标记 XYZ_AGENT_SUBAGENT=1", () => {
|
|
@@ -60,12 +66,12 @@ describe("buildNestedSpawnEnv", () => {
|
|
|
60
66
|
|
|
61
67
|
describe("assertNotNestedSpawn", () => {
|
|
62
68
|
it("检测到统一标记(本进程已是 subagent)→ 抛 nested_spawn_rejected", () => {
|
|
63
|
-
expect(() => assertNotNestedSpawn({ [NESTED_SPAWN_ENV]: "1" })).toThrowError(
|
|
69
|
+
expect(() => assertNotNestedSpawn({ [NESTED_SPAWN_ENV]: "1" })).toThrowError(NestedSpawnRejectedError);
|
|
64
70
|
try {
|
|
65
71
|
assertNotNestedSpawn({ [NESTED_SPAWN_ENV]: "1" });
|
|
66
72
|
expect.unreachable("should throw");
|
|
67
73
|
} catch (err) {
|
|
68
|
-
const e = err as
|
|
74
|
+
const e = err as NestedSpawnRejectedError;
|
|
69
75
|
expect(e.code).toBe("nested_spawn_rejected");
|
|
70
76
|
// 文案说明防护规则(标记名)+ 指向 task 内自行完成
|
|
71
77
|
expect(e.message).toContain("XYZ_AGENT_SUBAGENT");
|
|
@@ -29,7 +29,7 @@ beforeEach(() => {
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
afterEach(() => {
|
|
32
|
-
rmSync(tmpRoot, { recursive: true, force: true });
|
|
32
|
+
rmSync(tmpRoot, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
/** 读池 refs.json 的解析形态。 */
|
|
@@ -142,7 +142,7 @@ describe("releasePoolRef 引用计数与整池删除", () => {
|
|
|
142
142
|
it("池目录不存在时 release → 无原生状态可清,视为成功不抛", () => {
|
|
143
143
|
acquirePool(tmpRoot, "zcode", "ghost", "bg-1");
|
|
144
144
|
// 归零但目录已被外部删除
|
|
145
|
-
rmSync(resolvePoolDir(tmpRoot, "zcode", "ghost"), { recursive: true, force: true });
|
|
145
|
+
rmSync(resolvePoolDir(tmpRoot, "zcode", "ghost"), { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
146
146
|
expect(() => releasePoolRef(tmpRoot, "zcode", "ghost", "bg-1")).not.toThrow();
|
|
147
147
|
});
|
|
148
148
|
|
|
@@ -34,7 +34,7 @@ beforeEach(() => {
|
|
|
34
34
|
});
|
|
35
35
|
|
|
36
36
|
afterEach(() => {
|
|
37
|
-
rmSync(dataDir, { recursive: true, force: true });
|
|
37
|
+
rmSync(dataDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
|
|
38
38
|
// reader registry 是进程级状态——重置回内置集,防 fake 注入跨用例泄漏
|
|
39
39
|
resetNativeSessionReaders();
|
|
40
40
|
});
|
|
@@ -163,7 +163,13 @@ describe("降级链编排", () => {
|
|
|
163
163
|
});
|
|
164
164
|
});
|
|
165
165
|
|
|
166
|
-
it("①级
|
|
166
|
+
it("[W11/H1] ①级 reader 不可达(协议 read 失败降级形态)→ ②级 journal 命中", async () => {
|
|
167
|
+
// W11 后①级 reader 全经注入(生产 = runtime 协议 read,失败在其内部 catch 后
|
|
168
|
+
// 返回 undefined):注入一个恒 undefined 的 reader 复现「协议失败降②级」语义
|
|
169
|
+
// (原「真 zcode reader 对不存在 db 内部 catch 降级」分支随 H1 内建 reader
|
|
170
|
+
// 删除,sqlite 侧行为由 zcode 包 e2e 接替;NativeSessionReader 契约 = 不抛,
|
|
171
|
+
// 失败以 undefined 表达)。
|
|
172
|
+
registerNativeSessionReader("zcode", async () => undefined);
|
|
167
173
|
const journalPath = join(dataDir, "engines", "zcode", "shared", "journal-sub-1.jsonl");
|
|
168
174
|
await writeJournal(journalPath, [
|
|
169
175
|
{ type: "text_delta", delta: "part one. " },
|
|
@@ -190,7 +196,7 @@ describe("降级链编排", () => {
|
|
|
190
196
|
});
|
|
191
197
|
|
|
192
198
|
it("②级也不可达(无 journalPath)→ ③级 outcome-only,永不返回空数组", async () => {
|
|
193
|
-
//
|
|
199
|
+
// ①级无注册 reader(W11 后注册表初始为空)→ 直落②级;handle 无 journalPath → ③级
|
|
194
200
|
const messages = await readSubagentHistoryMessages(
|
|
195
201
|
makeRecord({ result: "final answer", endedAt: 2_000 }),
|
|
196
202
|
dataDir,
|
|
@@ -228,6 +234,87 @@ describe("降级链编排", () => {
|
|
|
228
234
|
expect(messages).toHaveLength(2);
|
|
229
235
|
expect(messages[1]).toMatchObject({ content: "r" });
|
|
230
236
|
});
|
|
237
|
+
|
|
238
|
+
// ============================================================
|
|
239
|
+
// ①级判空降级矩阵(设计 D3:turns 无实质内容 = 本级不可用,与②级同语义)
|
|
240
|
+
// ============================================================
|
|
241
|
+
|
|
242
|
+
it("①级 defined 空 turns({turns:[], source:'native'})→ 降②级,journal 内容命中(不返回 [task] 空壳)", async () => {
|
|
243
|
+
const journalPath = join(dataDir, "engines", "zcode", "shared", "journal-sub-1.jsonl");
|
|
244
|
+
await writeJournal(journalPath, [
|
|
245
|
+
{ type: "text_delta", delta: "journal answer" },
|
|
246
|
+
{ type: "turn_end" },
|
|
247
|
+
]);
|
|
248
|
+
registerNativeSessionReader("zcode", async () => ({
|
|
249
|
+
engineId: "zcode",
|
|
250
|
+
sessionId: "sess-1",
|
|
251
|
+
turns: [],
|
|
252
|
+
source: "native",
|
|
253
|
+
}));
|
|
254
|
+
const record = makeRecord({
|
|
255
|
+
engineHandle: {
|
|
256
|
+
sessionRef: { sessionId: "sess-1", dbPath: ".zcode/cli/db/db.sqlite" },
|
|
257
|
+
poolKey: "shared",
|
|
258
|
+
journalPath,
|
|
259
|
+
},
|
|
260
|
+
});
|
|
261
|
+
const messages = await readSubagentHistoryMessages(record, dataDir);
|
|
262
|
+
expect(messages).toHaveLength(2);
|
|
263
|
+
expect(messages[0]).toMatchObject({ role: "user", content: "do the thing" });
|
|
264
|
+
expect(messages[1]).toMatchObject({ role: "assistant", content: "journal answer" });
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("①级非空数组但全空 turn(截断/被杀残留形态)→ 同样降级:无 journalPath 落③级 outcome-only", async () => {
|
|
268
|
+
registerNativeSessionReader("zcode", async () => ({
|
|
269
|
+
engineId: "zcode",
|
|
270
|
+
sessionId: "sess-1",
|
|
271
|
+
// closeTurn 对 step-finish 无条件 push + applyPartToTurn 空 acc 创建——形态代码级可达
|
|
272
|
+
turns: [{ text: "", thinking: "", toolCalls: [], closed: true }],
|
|
273
|
+
source: "native",
|
|
274
|
+
}));
|
|
275
|
+
const messages = await readSubagentHistoryMessages(
|
|
276
|
+
makeRecord({ result: "outcome text" }),
|
|
277
|
+
dataDir,
|
|
278
|
+
);
|
|
279
|
+
// 不是「仅 task」空壳:①级空 turn 被判不可用 → ③级占位投影
|
|
280
|
+
expect(messages).toHaveLength(2);
|
|
281
|
+
expect(messages[1]).toMatchObject({ role: "assistant", content: "outcome text" });
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it("①级混合 turn(含空 turn 但任一有实质内容)→ 不降级,真实内容原样投影", async () => {
|
|
285
|
+
registerNativeSessionReader("zcode", async () => ({
|
|
286
|
+
engineId: "zcode",
|
|
287
|
+
sessionId: "sess-1",
|
|
288
|
+
turns: [
|
|
289
|
+
{ text: "", thinking: "", toolCalls: [], closed: true },
|
|
290
|
+
{ text: "real answer", thinking: "", toolCalls: [], closed: true },
|
|
291
|
+
],
|
|
292
|
+
source: "native",
|
|
293
|
+
}));
|
|
294
|
+
const messages = await readSubagentHistoryMessages(makeRecord(), dataDir);
|
|
295
|
+
// task + 两个 turn(空 turn 也随①级放行原样投影)
|
|
296
|
+
expect(messages).toHaveLength(3);
|
|
297
|
+
expect(messages[2]).toMatchObject({ role: "assistant", content: "real answer" });
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it("①空(defined 空 turns)②亦不可达(无 journalPath)→ 落③级 outcome-only 占位", async () => {
|
|
301
|
+
registerNativeSessionReader("zcode", async () => ({
|
|
302
|
+
engineId: "zcode",
|
|
303
|
+
sessionId: "sess-1",
|
|
304
|
+
turns: [],
|
|
305
|
+
source: "native",
|
|
306
|
+
}));
|
|
307
|
+
const messages = await readSubagentHistoryMessages(
|
|
308
|
+
makeRecord({ result: undefined, error: undefined }),
|
|
309
|
+
dataDir,
|
|
310
|
+
);
|
|
311
|
+
expect(messages).toHaveLength(2);
|
|
312
|
+
expect(messages[1]).toMatchObject({
|
|
313
|
+
role: "assistant",
|
|
314
|
+
content: "(no outcome recorded)",
|
|
315
|
+
status: "complete",
|
|
316
|
+
});
|
|
317
|
+
});
|
|
231
318
|
});
|
|
232
319
|
|
|
233
320
|
// ============================================================
|