@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
|
@@ -274,39 +274,16 @@ interface PendingToolCall {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
// ============================================================
|
|
277
|
-
//
|
|
277
|
+
// 全量重建内部 helper(按处理阶段拆分:读文件 → 扫身份 → 重建 turns → 组装)
|
|
278
278
|
// ============================================================
|
|
279
279
|
|
|
280
280
|
/**
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
* ║ (损坏行静默跳过;失败 → undefined) ║
|
|
286
|
-
* ║ 2. 扫 custom entry(customType:"subagent-identity")→ 身份 ║
|
|
287
|
-
* ║ 缺 identity → undefined(无法构造 record) ║
|
|
288
|
-
* ║ 3. 顺序遍历 message entries: ║
|
|
289
|
-
* ║ - role:"assistant" → 开新 Turn ║
|
|
290
|
-
* ║ text/thinking 累积;usage → usageDelta ║
|
|
291
|
-
* ║ toolCall block → 待匹配队列;stopReason error → lastError ║
|
|
292
|
-
* ║ - role:"toolResult" → 配对 toolCallId ║
|
|
293
|
-
* ║ 产 InternalToolCall(done/failed)推进请求 Turn ║
|
|
294
|
-
* ║ 4. 闭合所有 turn;算 turnCount/totalTokens/result/eventLog ║
|
|
295
|
-
* ╚══════════════════════════════════════════════════════════════════╝
|
|
296
|
-
*
|
|
297
|
-
* 返回 undefined:文件缺失/空/损坏/缺 identity entry/无 assistant message。
|
|
298
|
-
* 不抛——消费方(collectRecords)降级跳过该 record。
|
|
299
|
-
*
|
|
300
|
-
* status 由最后一条 assistant message 的 stopReason 推导(error/aborted → failed,
|
|
301
|
-
* 其余 → done)。cancelled 由 tombstone override(record-store 层),本函数不感知。
|
|
302
|
-
*
|
|
303
|
-
* [perf] 本函数是重路径(全文读 + 全 entry 解析)。列表扫描用 readIdentityHeader
|
|
304
|
-
* (只读头部 identity),详情才走本函数(RecordStore.getFullRecord 懒加载)。
|
|
281
|
+
* 读文件 + 逐行 JSON.parse(session.jsonl = newline-delimited JSON)。
|
|
282
|
+
* 第 1 行是 session header(type:"session",跳过);后续每行一个 entry。
|
|
283
|
+
* 损坏行静默跳过(与 SDK parseSessionEntries 行为一致)。
|
|
284
|
+
* @returns 文件缺失/读失败 → undefined;否则 entry 数组(可能为空)。
|
|
305
285
|
*/
|
|
306
|
-
|
|
307
|
-
// 读文件 + 逐行 JSON.parse(session.jsonl = newline-delimited JSON)。
|
|
308
|
-
// 第 1 行是 session header(跳过);后续每行一个 entry。
|
|
309
|
-
// 损坏行静默跳过(与 SDK parseSessionEntries 行为一致)。
|
|
286
|
+
function readJsonlEntries(sessionFile: string): JsonlEntry[] | undefined {
|
|
310
287
|
let raw: string;
|
|
311
288
|
try {
|
|
312
289
|
raw = fs.readFileSync(sessionFile, "utf-8");
|
|
@@ -338,10 +315,18 @@ export function reconstructFromFile(sessionFile: string): ReconstructedRecord |
|
|
|
338
315
|
void _e; // 损坏行跳过(不阻断后续行)。
|
|
339
316
|
}
|
|
340
317
|
}
|
|
318
|
+
return entries;
|
|
319
|
+
}
|
|
341
320
|
|
|
342
|
-
|
|
321
|
+
/** 身份/模型扫描产出(identity custom entry + 途经的 model/thinking_level change)。 */
|
|
322
|
+
interface IdentityScan {
|
|
323
|
+
identity: SubagentIdentityData | undefined;
|
|
324
|
+
model: string;
|
|
325
|
+
thinkingLevel: string | undefined;
|
|
326
|
+
}
|
|
343
327
|
|
|
344
|
-
|
|
328
|
+
/** 扫 identity custom entry(必须存在,否则无法构造 record)+ 途经 model/thinking_level。 */
|
|
329
|
+
function scanIdentityAndModel(entries: JsonlEntry[]): IdentityScan {
|
|
345
330
|
let identity: SubagentIdentityData | undefined;
|
|
346
331
|
let model = "";
|
|
347
332
|
let thinkingLevel: string | undefined;
|
|
@@ -357,14 +342,95 @@ export function reconstructFromFile(sessionFile: string): ReconstructedRecord |
|
|
|
357
342
|
if (typeof entry.thinkingLevel === "string") thinkingLevel = entry.thinkingLevel;
|
|
358
343
|
}
|
|
359
344
|
}
|
|
360
|
-
|
|
345
|
+
return { identity, model, thinkingLevel };
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/** message entries 重建产出(turns + 跨 entry 累积状态)。 */
|
|
349
|
+
interface RebuiltTurns {
|
|
350
|
+
turns: Turn[];
|
|
351
|
+
lastError: string | undefined;
|
|
352
|
+
totalTokens: number;
|
|
353
|
+
/** 最后一条 entry 的时间戳(ms),推导 endedAt(避免重建 record 耗时随墙钟无限增长)。 */
|
|
354
|
+
lastEntryTsMs: number | undefined;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* assistant message → 填充调用方已创建的空 Turn:text/thinking 累积;toolCall block 进
|
|
359
|
+
* 待匹配队列;usage → usageDelta(token 总量增量返回给调用方累加)。
|
|
360
|
+
*
|
|
361
|
+
* stopReason 语义(与 updateFromEvent 一致):error/aborted → 设 lastError;
|
|
362
|
+
* stop(正常结束)→ 清 lastError(镜像 turn_end 的清除语义,即前序 turn 的瞬态
|
|
363
|
+
* error 在后续成功 turn 后恢复,不误判 success=false);其余 stopReason → 保持
|
|
364
|
+
* prevLastError 原值。 [v4 B-1] status 恒 closed 后 lastStopReason 不再参与推导,死变量已删。
|
|
365
|
+
*
|
|
366
|
+
* content 非数组 → 跳过 usage/stopReason 处理(镜像原实现的 continue):turn 仍存在
|
|
367
|
+
* (由调用方 push),lastError 透传 prevLastError、token 增量为 0。
|
|
368
|
+
*/
|
|
369
|
+
function applyAssistantMessage(
|
|
370
|
+
msg: JsonlAssistantMessage,
|
|
371
|
+
turn: Turn,
|
|
372
|
+
pending: PendingToolCall[],
|
|
373
|
+
prevLastError: string | undefined,
|
|
374
|
+
): { lastError: string | undefined; totalTokensDelta: number } {
|
|
375
|
+
if (!Array.isArray(msg.content)) {
|
|
376
|
+
return { lastError: prevLastError, totalTokensDelta: 0 };
|
|
377
|
+
}
|
|
378
|
+
for (const block of msg.content) {
|
|
379
|
+
if (block.type === "text") {
|
|
380
|
+
turn.text += block.text;
|
|
381
|
+
} else if (block.type === "thinking") {
|
|
382
|
+
turn.thinking += block.thinking;
|
|
383
|
+
} else if (block.type === "toolCall") {
|
|
384
|
+
pending.push({
|
|
385
|
+
toolCallId: block.id,
|
|
386
|
+
toolName: block.name,
|
|
387
|
+
args: block.arguments,
|
|
388
|
+
turn,
|
|
389
|
+
startedTs: msg.timestamp,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
let totalTokensDelta = 0;
|
|
395
|
+
if (msg.usage) {
|
|
396
|
+
const u = toAgentUsage(msg.usage);
|
|
397
|
+
turn.usageDelta = addUsage(turn.usageDelta, u);
|
|
398
|
+
totalTokensDelta = u.input + u.output + u.cacheRead + u.cacheWrite;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
let lastError = prevLastError;
|
|
402
|
+
if (msg.stopReason === "error" || msg.stopReason === "aborted") {
|
|
403
|
+
lastError = msg.errorMessage ?? msg.stopReason;
|
|
404
|
+
} else if (msg.stopReason === "stop") {
|
|
405
|
+
lastError = undefined;
|
|
406
|
+
}
|
|
407
|
+
return { lastError, totalTokensDelta };
|
|
408
|
+
}
|
|
361
409
|
|
|
362
|
-
|
|
410
|
+
/** toolResult message → 按 toolCallId 配对回填 InternalToolCall;未配对(孤儿)→ 丢弃。 */
|
|
411
|
+
function applyToolResultMessage(msg: JsonlToolResultMessage, pending: PendingToolCall[]): void {
|
|
412
|
+
const idx = pending.findIndex((p) => p.toolCallId === msg.toolCallId);
|
|
413
|
+
if (idx >= 0) {
|
|
414
|
+
const p = pending[idx];
|
|
415
|
+
pending.splice(idx, 1);
|
|
416
|
+
const tc: InternalToolCall = {
|
|
417
|
+
toolName: p.toolName,
|
|
418
|
+
args: p.args,
|
|
419
|
+
result: { content: msg.content, details: msg.details },
|
|
420
|
+
isError: msg.isError ?? false,
|
|
421
|
+
_status: msg.isError ? "failed" : "done",
|
|
422
|
+
startedTs: p.startedTs,
|
|
423
|
+
};
|
|
424
|
+
p.turn.toolCalls.push(tc);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/** 顺序遍历 entries 重建 turns[](assistant 开 turn / toolResult 配对回填;user 跳过)。 */
|
|
429
|
+
function rebuildTurns(entries: JsonlEntry[]): RebuiltTurns {
|
|
363
430
|
const turns: Turn[] = [];
|
|
364
431
|
const pending: PendingToolCall[] = [];
|
|
365
432
|
let lastError: string | undefined;
|
|
366
433
|
let totalTokens = 0;
|
|
367
|
-
/** 最后一条 entry 的时间戳(ms),推导 endedAt(避免重建 record 耗时随墙钟无限增长)。 */
|
|
368
434
|
let lastEntryTsMs: number | undefined;
|
|
369
435
|
|
|
370
436
|
for (const entry of entries) {
|
|
@@ -383,81 +449,38 @@ export function reconstructFromFile(sessionFile: string): ReconstructedRecord |
|
|
|
383
449
|
if (msg.role === "assistant") {
|
|
384
450
|
const turn = emptyTurn();
|
|
385
451
|
turns.push(turn);
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
if (block.type === "text") {
|
|
390
|
-
turn.text += block.text;
|
|
391
|
-
} else if (block.type === "thinking") {
|
|
392
|
-
turn.thinking += block.thinking;
|
|
393
|
-
} else if (block.type === "toolCall") {
|
|
394
|
-
pending.push({
|
|
395
|
-
toolCallId: block.id,
|
|
396
|
-
toolName: block.name,
|
|
397
|
-
args: block.arguments,
|
|
398
|
-
turn,
|
|
399
|
-
startedTs: msg.timestamp,
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
if (msg.usage) {
|
|
405
|
-
const u = toAgentUsage(msg.usage);
|
|
406
|
-
turn.usageDelta = addUsage(turn.usageDelta, u);
|
|
407
|
-
totalTokens += u.input + u.output + u.cacheRead + u.cacheWrite;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// stopReason 驱动 lastError(与 updateFromEvent 一致):
|
|
411
|
-
// error/aborted → 设 lastError;stop(正常结束)→ 清 lastError(镜像 turn_end 的清除语义,
|
|
412
|
-
// 即前序 turn 的瞬态 error 在后续成功 turn 后恢复,不误判 success=false)。
|
|
413
|
-
// [v4 B-1] status 恒 closed 后 lastStopReason 不再参与推导,死变量已删。
|
|
414
|
-
if (msg.stopReason === "error" || msg.stopReason === "aborted") {
|
|
415
|
-
lastError = msg.errorMessage ?? msg.stopReason;
|
|
416
|
-
} else if (msg.stopReason === "stop") {
|
|
417
|
-
lastError = undefined;
|
|
418
|
-
}
|
|
452
|
+
const applied = applyAssistantMessage(msg, turn, pending, lastError);
|
|
453
|
+
totalTokens += applied.totalTokensDelta;
|
|
454
|
+
lastError = applied.lastError;
|
|
419
455
|
} else if (msg.role === "toolResult") {
|
|
420
|
-
|
|
421
|
-
if (idx >= 0) {
|
|
422
|
-
const p = pending[idx];
|
|
423
|
-
pending.splice(idx, 1);
|
|
424
|
-
const tc: InternalToolCall = {
|
|
425
|
-
toolName: p.toolName,
|
|
426
|
-
args: p.args,
|
|
427
|
-
result: { content: msg.content, details: msg.details },
|
|
428
|
-
isError: msg.isError ?? false,
|
|
429
|
-
_status: msg.isError ? "failed" : "done",
|
|
430
|
-
startedTs: p.startedTs,
|
|
431
|
-
};
|
|
432
|
-
p.turn.toolCalls.push(tc);
|
|
433
|
-
}
|
|
434
|
-
// 未配对(孤儿 toolResult)→ 丢弃。
|
|
456
|
+
applyToolResultMessage(msg, pending);
|
|
435
457
|
}
|
|
436
458
|
// role:"user" → 跳过(task 来自 identity custom entry)。
|
|
437
459
|
}
|
|
460
|
+
return { turns, lastError, totalTokens, lastEntryTsMs };
|
|
461
|
+
}
|
|
438
462
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
.map((t) => t.text)
|
|
449
|
-
.filter((t) => t.length > 0)
|
|
450
|
-
.join("\n\n");
|
|
451
|
-
|
|
452
|
-
// eventLog 从 turns[] 派生(与活态 record 的 getEventLog 同形,消费方无感知差异)。
|
|
453
|
-
const eventLog = deriveEventLog(turns, lastError, identity.startedAt);
|
|
454
|
-
|
|
463
|
+
/** 组装 ReconstructedRecord(终态投影:status 恒 closed/gc + 身份字段归一化 + 派生数据)。 */
|
|
464
|
+
function buildReconstructedRecord(
|
|
465
|
+
sessionFile: string,
|
|
466
|
+
identity: SubagentIdentityData,
|
|
467
|
+
rebuilt: RebuiltTurns,
|
|
468
|
+
eventLog: AgentEventLogEntry[],
|
|
469
|
+
model: string,
|
|
470
|
+
thinkingLevel: string | undefined,
|
|
471
|
+
): ReconstructedRecord {
|
|
455
472
|
// 终态 status:最后一条 assistant message 的 stopReason 推导(与 finalizeRecord 的判定一致)。
|
|
456
473
|
// SP-1:done/failed 合并为 closed,cancelled 由 tombstone override(record-store 层),本函数不感知。
|
|
457
474
|
const status: ExecutionStatus = "closed";
|
|
458
475
|
// closedReason 统 gc(通用完成/失败)。error/aborted 的区分由 error 字段保留。
|
|
459
476
|
const closedReason: import("./types.ts").ClosedReason = "gc";
|
|
460
477
|
|
|
478
|
+
const turnCount = rebuilt.turns.length;
|
|
479
|
+
const resultText = rebuilt.turns
|
|
480
|
+
.map((t) => t.text)
|
|
481
|
+
.filter((t) => t.length > 0)
|
|
482
|
+
.join("\n\n");
|
|
483
|
+
|
|
461
484
|
// rootSessionId 归一化:新文件读 rootSessionId,旧文件 fallback parentSessionId。
|
|
462
485
|
const rootSessionId = identity.rootSessionId ?? identity.parentSessionId;
|
|
463
486
|
// slug 兜底:旧 identity entry 无 slug 字段 → 空串(与 SubagentRecord.slug: string 契约一致)。
|
|
@@ -472,19 +495,74 @@ export function reconstructFromFile(sessionFile: string): ReconstructedRecord |
|
|
|
472
495
|
sessionFile,
|
|
473
496
|
status,
|
|
474
497
|
closedReason,
|
|
475
|
-
turns,
|
|
498
|
+
turns: rebuilt.turns,
|
|
476
499
|
turnCount,
|
|
477
|
-
totalTokens,
|
|
478
|
-
lastError,
|
|
500
|
+
totalTokens: rebuilt.totalTokens,
|
|
501
|
+
lastError: rebuilt.lastError,
|
|
479
502
|
model,
|
|
480
503
|
thinkingLevel,
|
|
481
|
-
endedAt: lastEntryTsMs,
|
|
504
|
+
endedAt: rebuilt.lastEntryTsMs,
|
|
482
505
|
result: resultText.length > 0 ? resultText : undefined,
|
|
483
|
-
error: lastError,
|
|
506
|
+
error: rebuilt.lastError,
|
|
484
507
|
eventLog,
|
|
485
508
|
};
|
|
486
509
|
}
|
|
487
510
|
|
|
511
|
+
// ============================================================
|
|
512
|
+
// 公开函数
|
|
513
|
+
// ============================================================
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* 从 session.jsonl 重建完整 SubagentRecord 数据。
|
|
517
|
+
*
|
|
518
|
+
* ╔══════════════════════════════════════════════════════════════════╗
|
|
519
|
+
* ║ 1. readFileSync(sessionFile) + 逐行 JSON.parse(跳 header) ║
|
|
520
|
+
* ║ (损坏行静默跳过;失败 → undefined) ║
|
|
521
|
+
* ║ 2. 扫 custom entry(customType:"subagent-identity")→ 身份 ║
|
|
522
|
+
* ║ 缺 identity → undefined(无法构造 record) ║
|
|
523
|
+
* ║ 3. 顺序遍历 message entries: ║
|
|
524
|
+
* ║ - role:"assistant" → 开新 Turn ║
|
|
525
|
+
* ║ text/thinking 累积;usage → usageDelta ║
|
|
526
|
+
* ║ toolCall block → 待匹配队列;stopReason error → lastError ║
|
|
527
|
+
* ║ - role:"toolResult" → 配对 toolCallId ║
|
|
528
|
+
* ║ 产 InternalToolCall(done/failed)推进请求 Turn ║
|
|
529
|
+
* ║ 4. 闭合所有 turn;算 turnCount/totalTokens/result/eventLog ║
|
|
530
|
+
* ╚══════════════════════════════════════════════════════════════════╝
|
|
531
|
+
*
|
|
532
|
+
* 返回 undefined:文件缺失/空/损坏/缺 identity entry/无 assistant message。
|
|
533
|
+
* 不抛——消费方(collectRecords)降级跳过该 record。
|
|
534
|
+
*
|
|
535
|
+
* status 由最后一条 assistant message 的 stopReason 推导(error/aborted → failed,
|
|
536
|
+
* 其余 → done)。cancelled 由 tombstone override(record-store 层),本函数不感知。
|
|
537
|
+
*
|
|
538
|
+
* [perf] 本函数是重路径(全文读 + 全 entry 解析)。列表扫描用 readIdentityHeader
|
|
539
|
+
* (只读头部 identity),详情才走本函数(RecordStore.getFullRecord 懒加载)。
|
|
540
|
+
*/
|
|
541
|
+
export function reconstructFromFile(sessionFile: string): ReconstructedRecord | undefined {
|
|
542
|
+
// 1. 读文件 + 逐行 JSON.parse(readJsonlEntries:损坏行静默跳过;文件缺失 → undefined)。
|
|
543
|
+
const entries = readJsonlEntries(sessionFile);
|
|
544
|
+
if (!entries || entries.length === 0) return undefined;
|
|
545
|
+
|
|
546
|
+
// 2. 扫身份 custom entry(scanIdentityAndModel:identity 缺失 → 无法构造 record)。
|
|
547
|
+
const { identity, model, thinkingLevel } = scanIdentityAndModel(entries);
|
|
548
|
+
if (!identity) return undefined; // 缺身份 → 无法构造 record。
|
|
549
|
+
|
|
550
|
+
// 3. 重建 turns[](rebuildTurns:assistant 开 turn / toolResult 配对回填)。
|
|
551
|
+
const rebuilt = rebuildTurns(entries);
|
|
552
|
+
if (rebuilt.turns.length === 0) return undefined; // 无 assistant message → 空壳,降级。
|
|
553
|
+
|
|
554
|
+
// 4. 闭合所有 turn(重建的是历史,全是已完成 turn)。
|
|
555
|
+
for (const turn of rebuilt.turns) {
|
|
556
|
+
turn.closed = true;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// eventLog 从 turns[] 派生(与活态 record 的 getEventLog 同形,消费方无感知差异)。
|
|
560
|
+
// 必须在闭合 turn 之后派生(deriveEventLog 读 turn.closed)。
|
|
561
|
+
const eventLog = deriveEventLog(rebuilt.turns, rebuilt.lastError, identity.startedAt);
|
|
562
|
+
|
|
563
|
+
return buildReconstructedRecord(sessionFile, identity, rebuilt, eventLog, model, thinkingLevel);
|
|
564
|
+
}
|
|
565
|
+
|
|
488
566
|
// ============================================================
|
|
489
567
|
// 轻量头部读取(列表扫描用)
|
|
490
568
|
// ============================================================
|
|
@@ -615,48 +693,62 @@ export function readIdentityTail(sessionFile: string): IdentityHeaderRecon | und
|
|
|
615
693
|
return undefined;
|
|
616
694
|
}
|
|
617
695
|
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
696
|
+
// ============================================================
|
|
697
|
+
// 轻量 identity 扫描内部 helper(parseIdentityFromText 按阶段分发)
|
|
698
|
+
// ============================================================
|
|
699
|
+
|
|
700
|
+
/**
|
|
701
|
+
* 预筛([S-4] 同款值匹配):只有含三种目标 entry 值串的行才值得 JSON.parse——
|
|
702
|
+
* head 64KB 内大 toolResult 行(数十 KB/行)占多数,全量 parse 是冷扫描 CPU 大头。
|
|
703
|
+
* 值字符串在任意序列化格式下连续出现,不耦合 pi 的空格习惯。
|
|
704
|
+
*/
|
|
705
|
+
function lineMayCarryScannableEntry(s: string): boolean {
|
|
706
|
+
return (
|
|
707
|
+
s.includes(IDENTITY_CUSTOM_TYPE) ||
|
|
708
|
+
s.includes('"model_change"') ||
|
|
709
|
+
s.includes('"thinking_level_change"')
|
|
710
|
+
);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/** 轻量扫描的可变累积态(identity + 途经 model/thinkingLevel)。 */
|
|
714
|
+
interface LightIdentityScan {
|
|
715
|
+
identity: SubagentIdentityData | undefined;
|
|
716
|
+
model: string;
|
|
717
|
+
thinkingLevel: string | undefined;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* 单条 entry 并入扫描态。identity 命中(custom + customType 匹配 + data 合法)返回
|
|
722
|
+
* true 供调用方 break(找到即停,后续行不再解析);其余恒 false。三个目标 type 互斥,
|
|
723
|
+
* 与原 if/else-if 链语义一致;custom 但 data 非法 → 不并入、不中断扫描。
|
|
724
|
+
*/
|
|
725
|
+
function absorbScannedEntry(state: LightIdentityScan, entry: JsonlEntry): boolean {
|
|
726
|
+
if (entry.type === "custom" && entry.customType === IDENTITY_CUSTOM_TYPE) {
|
|
727
|
+
if (isIdentityData(entry.data)) {
|
|
728
|
+
state.identity = entry.data;
|
|
729
|
+
return true;
|
|
643
730
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
if (typeof entry.provider === "string" && typeof entry.modelId === "string") {
|
|
651
|
-
model = `${entry.provider}/${entry.modelId}`;
|
|
652
|
-
}
|
|
653
|
-
} else if (entry.type === "thinking_level_change") {
|
|
654
|
-
if (typeof entry.thinkingLevel === "string") thinkingLevel = entry.thinkingLevel;
|
|
731
|
+
return false;
|
|
732
|
+
}
|
|
733
|
+
if (entry.type === "model_change") {
|
|
734
|
+
// model_change: {provider, modelId} → "provider/modelId"(与 record.model 同形)。
|
|
735
|
+
if (typeof entry.provider === "string" && typeof entry.modelId === "string") {
|
|
736
|
+
state.model = `${entry.provider}/${entry.modelId}`;
|
|
655
737
|
}
|
|
738
|
+
return false;
|
|
739
|
+
}
|
|
740
|
+
if (entry.type === "thinking_level_change") {
|
|
741
|
+
if (typeof entry.thinkingLevel === "string") state.thinkingLevel = entry.thinkingLevel;
|
|
656
742
|
}
|
|
657
|
-
|
|
743
|
+
return false;
|
|
744
|
+
}
|
|
658
745
|
|
|
659
|
-
|
|
746
|
+
/** 扫描态 → IdentityHeaderRecon(归一化与全量 recon 同源:rootSessionId fallback 旧字段、slug 兜底空串)。 */
|
|
747
|
+
function toIdentityRecon(
|
|
748
|
+
state: LightIdentityScan,
|
|
749
|
+
identity: SubagentIdentityData,
|
|
750
|
+
sessionFile: string,
|
|
751
|
+
): IdentityHeaderRecon {
|
|
660
752
|
const rootSessionId = identity.rootSessionId ?? identity.parentSessionId;
|
|
661
753
|
return {
|
|
662
754
|
id: identity.id,
|
|
@@ -671,8 +763,29 @@ function parseIdentityFromText(text: string, sessionFile: string): IdentityHeade
|
|
|
671
763
|
forkDepth: identity.forkDepth,
|
|
672
764
|
chatMode: identity.chatMode,
|
|
673
765
|
worktree: identity.worktree,
|
|
674
|
-
model,
|
|
675
|
-
thinkingLevel,
|
|
766
|
+
model: state.model,
|
|
767
|
+
thinkingLevel: state.thinkingLevel,
|
|
676
768
|
sessionFile,
|
|
677
769
|
};
|
|
678
770
|
}
|
|
771
|
+
|
|
772
|
+
/** 从文本片段解析 identity(头部/全文两入口共享)。解析到 identity 即停(返回);
|
|
773
|
+
* 找不到返回 undefined。model/thinking_level 仅在 identity 之前的途经 entry 中
|
|
774
|
+
* best-effort 提取,详情场景由全量重建补齐。 */
|
|
775
|
+
function parseIdentityFromText(text: string, sessionFile: string): IdentityHeaderRecon | undefined {
|
|
776
|
+
const state: LightIdentityScan = { identity: undefined, model: "", thinkingLevel: undefined };
|
|
777
|
+
for (const line of text.split("\n")) {
|
|
778
|
+
const s = line.trim();
|
|
779
|
+
if (!s) continue;
|
|
780
|
+
if (!lineMayCarryScannableEntry(s)) continue;
|
|
781
|
+
let entry: JsonlEntry;
|
|
782
|
+
try {
|
|
783
|
+
entry = JSON.parse(s) as JsonlEntry;
|
|
784
|
+
} catch {
|
|
785
|
+
continue; // 损坏行/截断行(头部读取边界)跳过
|
|
786
|
+
}
|
|
787
|
+
if (absorbScannedEntry(state, entry)) break; // 找到即停(后续行不再解析)
|
|
788
|
+
}
|
|
789
|
+
if (!state.identity) return undefined;
|
|
790
|
+
return toIdentityRecon(state, state.identity, sessionFile);
|
|
791
|
+
}
|