@caupulican/pi-adaptative 0.81.39 → 0.81.41
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/CHANGELOG.md +77 -0
- package/README.md +2 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts +2 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +3 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +4 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +9 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +290 -107
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +357 -122
- package/dist/bundled-resources/skills/tool-call-repair/references/repair-catalogue.md +2 -2
- package/dist/cli/args.d.ts +4 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +31 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-directory-layout.d.ts +15 -0
- package/dist/core/agent-directory-layout.d.ts.map +1 -0
- package/dist/core/agent-directory-layout.js +72 -0
- package/dist/core/agent-directory-layout.js.map +1 -0
- package/dist/core/agent-paths.d.ts +25 -2
- package/dist/core/agent-paths.d.ts.map +1 -1
- package/dist/core/agent-paths.js +79 -4
- package/dist/core/agent-paths.js.map +1 -1
- package/dist/core/agent-session-contracts.d.ts +293 -0
- package/dist/core/agent-session-contracts.d.ts.map +1 -0
- package/dist/core/agent-session-contracts.js +26 -0
- package/dist/core/agent-session-contracts.js.map +1 -0
- package/dist/core/agent-session-runtime.d.ts +52 -8
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +400 -79
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -0
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +1 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +74 -518
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +370 -1432
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -1
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/autonomy/approval-gate.d.ts +3 -2
- package/dist/core/autonomy/approval-gate.d.ts.map +1 -1
- package/dist/core/autonomy/approval-gate.js +6 -28
- package/dist/core/autonomy/approval-gate.js.map +1 -1
- package/dist/core/autonomy/bounded-completion.d.ts +1 -1
- package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
- package/dist/core/autonomy/bounded-completion.js +1 -1
- package/dist/core/autonomy/bounded-completion.js.map +1 -1
- package/dist/core/autonomy/contracts.d.ts +20 -12
- package/dist/core/autonomy/contracts.d.ts.map +1 -1
- package/dist/core/autonomy/contracts.js.map +1 -1
- package/dist/core/autonomy/foreground-envelope.d.ts +8 -2
- package/dist/core/autonomy/foreground-envelope.d.ts.map +1 -1
- package/dist/core/autonomy/foreground-envelope.js +8 -25
- package/dist/core/autonomy/foreground-envelope.js.map +1 -1
- package/dist/core/autonomy/gates.d.ts.map +1 -1
- package/dist/core/autonomy/gates.js +8 -10
- package/dist/core/autonomy/gates.js.map +1 -1
- package/dist/core/autonomy/lane-private-paths.d.ts +2 -0
- package/dist/core/autonomy/lane-private-paths.d.ts.map +1 -0
- package/dist/core/autonomy/lane-private-paths.js +16 -0
- package/dist/core/autonomy/lane-private-paths.js.map +1 -0
- package/dist/core/autonomy/lane-tool-surface.d.ts +10 -0
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +48 -9
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/autonomy/lane-tracker.d.ts +14 -0
- package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tracker.js +38 -0
- package/dist/core/autonomy/lane-tracker.js.map +1 -1
- package/dist/core/autonomy/risk-assessment.d.ts +1 -2
- package/dist/core/autonomy/risk-assessment.d.ts.map +1 -1
- package/dist/core/autonomy/risk-assessment.js +1 -123
- package/dist/core/autonomy/risk-assessment.js.map +1 -1
- package/dist/core/autonomy/session-lane-record.d.ts +4 -4
- package/dist/core/autonomy/session-lane-record.d.ts.map +1 -1
- package/dist/core/autonomy/session-lane-record.js +16 -29
- package/dist/core/autonomy/session-lane-record.js.map +1 -1
- package/dist/core/autonomy/telemetry-events.d.ts +1 -1
- package/dist/core/autonomy/telemetry-events.d.ts.map +1 -1
- package/dist/core/autonomy/telemetry-events.js +1 -1
- package/dist/core/autonomy/telemetry-events.js.map +1 -1
- package/dist/core/autonomy-telemetry.d.ts +7 -7
- package/dist/core/autonomy-telemetry.d.ts.map +1 -1
- package/dist/core/autonomy-telemetry.js +9 -9
- package/dist/core/autonomy-telemetry.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +56 -236
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +141 -1273
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/bedrock-sso-login.d.ts +16 -0
- package/dist/core/bedrock-sso-login.d.ts.map +1 -0
- package/dist/core/bedrock-sso-login.js +98 -0
- package/dist/core/bedrock-sso-login.js.map +1 -0
- package/dist/core/capability-contract.d.ts +4 -0
- package/dist/core/capability-contract.d.ts.map +1 -0
- package/dist/core/capability-contract.js +28 -0
- package/dist/core/capability-contract.js.map +1 -0
- package/dist/core/compaction-controller.d.ts +90 -0
- package/dist/core/compaction-controller.d.ts.map +1 -0
- package/dist/core/compaction-controller.js +452 -0
- package/dist/core/compaction-controller.js.map +1 -0
- package/dist/core/compaction-support.d.ts +13 -17
- package/dist/core/compaction-support.d.ts.map +1 -1
- package/dist/core/compaction-support.js +3 -3
- package/dist/core/compaction-support.js.map +1 -1
- package/dist/core/context/context-artifacts.d.ts +6 -2
- package/dist/core/context/context-artifacts.d.ts.map +1 -1
- package/dist/core/context/context-artifacts.js +34 -2
- package/dist/core/context/context-artifacts.js.map +1 -1
- package/dist/core/context/context-store-retention.d.ts +8 -2
- package/dist/core/context/context-store-retention.d.ts.map +1 -1
- package/dist/core/context/context-store-retention.js +158 -35
- package/dist/core/context/context-store-retention.js.map +1 -1
- package/dist/core/context/okf-memory.d.ts.map +1 -1
- package/dist/core/context/okf-memory.js +9 -11
- package/dist/core/context/okf-memory.js.map +1 -1
- package/dist/core/context/sqlite-runtime-index.d.ts.map +1 -1
- package/dist/core/context/sqlite-runtime-index.js +6 -8
- package/dist/core/context/sqlite-runtime-index.js.map +1 -1
- package/dist/core/context-gc.d.ts +3 -0
- package/dist/core/context-gc.d.ts.map +1 -1
- package/dist/core/context-gc.js +10 -5
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +1 -1
- package/dist/core/context-pipeline.d.ts.map +1 -1
- package/dist/core/context-pipeline.js +16 -37
- package/dist/core/context-pipeline.js.map +1 -1
- package/dist/core/cost/cost-summary.d.ts.map +1 -1
- package/dist/core/cost/cost-summary.js +5 -3
- package/dist/core/cost/cost-summary.js.map +1 -1
- package/dist/core/cost/daily-usage.d.ts.map +1 -1
- package/dist/core/cost/daily-usage.js +4 -5
- package/dist/core/cost/daily-usage.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts.map +1 -1
- package/dist/core/default-tool-surface.js +2 -0
- package/dist/core/default-tool-surface.js.map +1 -1
- package/dist/core/delegation/managed-lane-controller.d.ts +34 -0
- package/dist/core/delegation/managed-lane-controller.d.ts.map +1 -0
- package/dist/core/delegation/managed-lane-controller.js +217 -0
- package/dist/core/delegation/managed-lane-controller.js.map +1 -0
- package/dist/core/delegation/session-worker-claim.d.ts +44 -0
- package/dist/core/delegation/session-worker-claim.d.ts.map +1 -0
- package/dist/core/delegation/session-worker-claim.js +98 -0
- package/dist/core/delegation/session-worker-claim.js.map +1 -0
- package/dist/core/delegation/worker-actions.d.ts +7 -5
- package/dist/core/delegation/worker-actions.d.ts.map +1 -1
- package/dist/core/delegation/worker-actions.js +20 -4
- package/dist/core/delegation/worker-actions.js.map +1 -1
- package/dist/core/delegation/{worker-result.d.ts → worker-claim.d.ts} +13 -13
- package/dist/core/delegation/worker-claim.d.ts.map +1 -0
- package/dist/core/delegation/{worker-result.js → worker-claim.js} +61 -51
- package/dist/core/delegation/worker-claim.js.map +1 -0
- package/dist/core/delegation/worker-delegation-controller.d.ts +110 -0
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -0
- package/dist/core/delegation/worker-delegation-controller.js +861 -0
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -0
- package/dist/core/delegation/worker-delegation-request.d.ts +11 -0
- package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -0
- package/dist/core/delegation/worker-delegation-request.js +2 -0
- package/dist/core/delegation/worker-delegation-request.js.map +1 -0
- package/dist/core/delegation/worker-dispatch-scheduler.d.ts +40 -0
- package/dist/core/delegation/worker-dispatch-scheduler.d.ts.map +1 -0
- package/dist/core/delegation/worker-dispatch-scheduler.js +93 -0
- package/dist/core/delegation/worker-dispatch-scheduler.js.map +1 -0
- package/dist/core/delegation/worker-execution-policy.d.ts +62 -0
- package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -0
- package/dist/core/delegation/worker-execution-policy.js +160 -0
- package/dist/core/delegation/worker-execution-policy.js.map +1 -0
- package/dist/core/delegation/worker-lane-projection.d.ts +14 -0
- package/dist/core/delegation/worker-lane-projection.d.ts.map +1 -0
- package/dist/core/delegation/worker-lane-projection.js +100 -0
- package/dist/core/delegation/worker-lane-projection.js.map +1 -0
- package/dist/core/delegation/worker-lifecycle.d.ts +97 -0
- package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -0
- package/dist/core/delegation/worker-lifecycle.js +339 -0
- package/dist/core/delegation/worker-lifecycle.js.map +1 -0
- package/dist/core/delegation/worker-notification-coordinator.d.ts +36 -0
- package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -0
- package/dist/core/delegation/worker-notification-coordinator.js +90 -0
- package/dist/core/delegation/worker-notification-coordinator.js.map +1 -0
- package/dist/core/delegation/worker-profile-resolver.d.ts +55 -0
- package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -0
- package/dist/core/delegation/worker-profile-resolver.js +113 -0
- package/dist/core/delegation/worker-profile-resolver.js.map +1 -0
- package/dist/core/delegation/worker-runner.d.ts +25 -14
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +122 -53
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/delegation/worker-task-label.d.ts +3 -0
- package/dist/core/delegation/worker-task-label.d.ts.map +1 -0
- package/dist/core/delegation/worker-task-label.js +11 -0
- package/dist/core/delegation/worker-task-label.js.map +1 -0
- package/dist/core/doctor.d.ts +8 -0
- package/dist/core/doctor.d.ts.map +1 -1
- package/dist/core/doctor.js +32 -1
- package/dist/core/doctor.js.map +1 -1
- package/dist/core/extension-import-authority.d.ts +6 -0
- package/dist/core/extension-import-authority.d.ts.map +1 -0
- package/dist/core/extension-import-authority.js +10 -0
- package/dist/core/extension-import-authority.js.map +1 -0
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +5 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +52 -18
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +20 -5
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/stale-context.d.ts +2 -0
- package/dist/core/extensions/stale-context.d.ts.map +1 -0
- package/dist/core/extensions/stale-context.js +2 -0
- package/dist/core/extensions/stale-context.js.map +1 -0
- package/dist/core/extensions/storage.d.ts +8 -0
- package/dist/core/extensions/storage.d.ts.map +1 -0
- package/dist/core/extensions/storage.js +28 -0
- package/dist/core/extensions/storage.js.map +1 -0
- package/dist/core/extensions/types.d.ts +78 -21
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/failure-corpus.d.ts +1 -15
- package/dist/core/failure-corpus.d.ts.map +1 -1
- package/dist/core/failure-corpus.js +9 -37
- package/dist/core/failure-corpus.js.map +1 -1
- package/dist/core/foreground-recovery-controller.d.ts +53 -0
- package/dist/core/foreground-recovery-controller.d.ts.map +1 -0
- package/dist/core/foreground-recovery-controller.js +111 -0
- package/dist/core/foreground-recovery-controller.js.map +1 -0
- package/dist/core/gateways/channel-provider.d.ts +3 -0
- package/dist/core/gateways/channel-provider.d.ts.map +1 -1
- package/dist/core/gateways/channel-provider.js +31 -6
- package/dist/core/gateways/channel-provider.js.map +1 -1
- package/dist/core/goal-loop-controller.d.ts +14 -9
- package/dist/core/goal-loop-controller.d.ts.map +1 -1
- package/dist/core/goal-loop-controller.js +47 -75
- package/dist/core/goal-loop-controller.js.map +1 -1
- package/dist/core/goals/compact-goal-context.d.ts +11 -0
- package/dist/core/goals/compact-goal-context.d.ts.map +1 -0
- package/dist/core/goals/compact-goal-context.js +59 -0
- package/dist/core/goals/compact-goal-context.js.map +1 -0
- package/dist/core/goals/goal-acceptance.d.ts +11 -0
- package/dist/core/goals/goal-acceptance.d.ts.map +1 -0
- package/dist/core/goals/goal-acceptance.js +27 -0
- package/dist/core/goals/goal-acceptance.js.map +1 -0
- package/dist/core/goals/goal-auto-continue-controller.d.ts +28 -0
- package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -0
- package/dist/core/goals/goal-auto-continue-controller.js +90 -0
- package/dist/core/goals/goal-auto-continue-controller.js.map +1 -0
- package/dist/core/goals/goal-continuation-controller.d.ts +2 -2
- package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-controller.js +52 -11
- package/dist/core/goals/goal-continuation-controller.js.map +1 -1
- package/dist/core/goals/goal-continuation-defaults.d.ts +4 -29
- package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-defaults.js +4 -32
- package/dist/core/goals/goal-continuation-defaults.js.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.d.ts +8 -18
- package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.js +9 -179
- package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
- package/dist/core/goals/goal-lifecycle.d.ts +43 -0
- package/dist/core/goals/goal-lifecycle.d.ts.map +1 -0
- package/dist/core/goals/goal-lifecycle.js +102 -0
- package/dist/core/goals/goal-lifecycle.js.map +1 -0
- package/dist/core/goals/goal-record.d.ts +17 -0
- package/dist/core/goals/goal-record.d.ts.map +1 -0
- package/dist/core/goals/goal-record.js +31 -0
- package/dist/core/goals/goal-record.js.map +1 -0
- package/dist/core/goals/goal-runtime-snapshot.d.ts +11 -9
- package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
- package/dist/core/goals/goal-runtime-snapshot.js +10 -8
- package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
- package/dist/core/goals/goal-session-controller.d.ts +42 -0
- package/dist/core/goals/goal-session-controller.d.ts.map +1 -0
- package/dist/core/goals/goal-session-controller.js +128 -0
- package/dist/core/goals/goal-session-controller.js.map +1 -0
- package/dist/core/goals/goal-state.d.ts +46 -25
- package/dist/core/goals/goal-state.d.ts.map +1 -1
- package/dist/core/goals/goal-state.js +91 -24
- package/dist/core/goals/goal-state.js.map +1 -1
- package/dist/core/goals/goal-tool-core.d.ts +9 -10
- package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
- package/dist/core/goals/goal-tool-core.js +60 -75
- package/dist/core/goals/goal-tool-core.js.map +1 -1
- package/dist/core/goals/session-goal-state.d.ts +20 -12
- package/dist/core/goals/session-goal-state.d.ts.map +1 -1
- package/dist/core/goals/session-goal-state.js +133 -33
- package/dist/core/goals/session-goal-state.js.map +1 -1
- package/dist/core/human-input-controller.d.ts +47 -0
- package/dist/core/human-input-controller.d.ts.map +1 -0
- package/dist/core/human-input-controller.js +181 -0
- package/dist/core/human-input-controller.js.map +1 -0
- package/dist/core/human-input.d.ts +100 -0
- package/dist/core/human-input.d.ts.map +1 -0
- package/dist/core/human-input.js +362 -0
- package/dist/core/human-input.js.map +1 -0
- package/dist/core/index.d.ts +9 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +9 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/{telemetry.d.ts → install-telemetry.d.ts} +1 -1
- package/dist/core/install-telemetry.d.ts.map +1 -0
- package/dist/core/{telemetry.js → install-telemetry.js} +1 -1
- package/dist/core/install-telemetry.js.map +1 -0
- package/dist/core/keybindings.d.ts +17 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +24 -6
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/learning/learning-audit.d.ts +2 -4
- package/dist/core/learning/learning-audit.d.ts.map +1 -1
- package/dist/core/learning/learning-audit.js +9 -29
- package/dist/core/learning/learning-audit.js.map +1 -1
- package/dist/core/learning/learning-gate.d.ts.map +1 -1
- package/dist/core/learning/learning-gate.js +1 -6
- package/dist/core/learning/learning-gate.js.map +1 -1
- package/dist/core/learning/session-learning-decision.d.ts +2 -4
- package/dist/core/learning/session-learning-decision.d.ts.map +1 -1
- package/dist/core/learning/session-learning-decision.js +9 -29
- package/dist/core/learning/session-learning-decision.js.map +1 -1
- package/dist/core/local-runtime-controller.d.ts +1 -1
- package/dist/core/local-runtime-controller.d.ts.map +1 -1
- package/dist/core/local-runtime-controller.js.map +1 -1
- package/dist/core/memory-controller.d.ts.map +1 -1
- package/dist/core/memory-controller.js +4 -4
- package/dist/core/memory-controller.js.map +1 -1
- package/dist/core/model-capability.d.ts +0 -19
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +1 -19
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-registry.d.ts +6 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +13 -5
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +17 -2
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +38 -25
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-router/intent-classifier.d.ts +1 -4
- package/dist/core/model-router/intent-classifier.d.ts.map +1 -1
- package/dist/core/model-router/intent-classifier.js +1 -156
- package/dist/core/model-router/intent-classifier.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +1 -1
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js +2 -2
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/model-selection-controller.d.ts +5 -5
- package/dist/core/model-selection-controller.d.ts.map +1 -1
- package/dist/core/model-selection-controller.js.map +1 -1
- package/dist/core/model-tool-protocol.d.ts +23 -0
- package/dist/core/model-tool-protocol.d.ts.map +1 -0
- package/dist/core/model-tool-protocol.js +43 -0
- package/dist/core/model-tool-protocol.js.map +1 -0
- package/dist/core/models/adaptation-store.d.ts +4 -6
- package/dist/core/models/adaptation-store.d.ts.map +1 -1
- package/dist/core/models/adaptation-store.js +95 -83
- package/dist/core/models/adaptation-store.js.map +1 -1
- package/dist/core/models/fitness-store.d.ts +2 -12
- package/dist/core/models/fitness-store.d.ts.map +1 -1
- package/dist/core/models/fitness-store.js +84 -57
- package/dist/core/models/fitness-store.js.map +1 -1
- package/dist/core/models/host-state-store.d.ts +34 -0
- package/dist/core/models/host-state-store.d.ts.map +1 -0
- package/dist/core/models/host-state-store.js +86 -0
- package/dist/core/models/host-state-store.js.map +1 -0
- package/dist/core/orchestration/agent-resume.d.ts +24 -0
- package/dist/core/orchestration/agent-resume.d.ts.map +1 -0
- package/dist/core/orchestration/agent-resume.js +90 -0
- package/dist/core/orchestration/agent-resume.js.map +1 -0
- package/dist/core/orchestration/capability-gateway.d.ts +61 -0
- package/dist/core/orchestration/capability-gateway.d.ts.map +1 -0
- package/dist/core/orchestration/capability-gateway.js +152 -0
- package/dist/core/orchestration/capability-gateway.js.map +1 -0
- package/dist/core/orchestration/contracts.d.ts +343 -0
- package/dist/core/orchestration/contracts.d.ts.map +1 -0
- package/dist/core/orchestration/contracts.js +135 -0
- package/dist/core/orchestration/contracts.js.map +1 -0
- package/dist/core/orchestration/delegation-ledger.d.ts +56 -0
- package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -0
- package/dist/core/orchestration/delegation-ledger.js +200 -0
- package/dist/core/orchestration/delegation-ledger.js.map +1 -0
- package/dist/core/orchestration/event-store.d.ts +83 -0
- package/dist/core/orchestration/event-store.d.ts.map +1 -0
- package/dist/core/orchestration/event-store.js +560 -0
- package/dist/core/orchestration/event-store.js.map +1 -0
- package/dist/core/orchestration/lane-tool-manifests.d.ts +9 -0
- package/dist/core/orchestration/lane-tool-manifests.d.ts.map +1 -0
- package/dist/core/orchestration/lane-tool-manifests.js +37 -0
- package/dist/core/orchestration/lane-tool-manifests.js.map +1 -0
- package/dist/core/orchestration/model-binding.d.ts +15 -0
- package/dist/core/orchestration/model-binding.d.ts.map +1 -0
- package/dist/core/orchestration/model-binding.js +29 -0
- package/dist/core/orchestration/model-binding.js.map +1 -0
- package/dist/core/orchestration/policy-compiler.d.ts +49 -0
- package/dist/core/orchestration/policy-compiler.d.ts.map +1 -0
- package/dist/core/orchestration/policy-compiler.js +191 -0
- package/dist/core/orchestration/policy-compiler.js.map +1 -0
- package/dist/core/orchestration/policy-gate.d.ts +18 -0
- package/dist/core/orchestration/policy-gate.d.ts.map +1 -0
- package/dist/core/orchestration/policy-gate.js +24 -0
- package/dist/core/orchestration/policy-gate.js.map +1 -0
- package/dist/core/orchestration/profile-registry.d.ts +51 -0
- package/dist/core/orchestration/profile-registry.d.ts.map +1 -0
- package/dist/core/orchestration/profile-registry.js +393 -0
- package/dist/core/orchestration/profile-registry.js.map +1 -0
- package/dist/core/orchestration/profile-store.d.ts +31 -0
- package/dist/core/orchestration/profile-store.d.ts.map +1 -0
- package/dist/core/orchestration/profile-store.js +136 -0
- package/dist/core/orchestration/profile-store.js.map +1 -0
- package/dist/core/orchestration/risk-budget.d.ts +9 -0
- package/dist/core/orchestration/risk-budget.d.ts.map +1 -0
- package/dist/core/orchestration/risk-budget.js +48 -0
- package/dist/core/orchestration/risk-budget.js.map +1 -0
- package/dist/core/orchestration/task-runtime.d.ts +168 -0
- package/dist/core/orchestration/task-runtime.d.ts.map +1 -0
- package/dist/core/orchestration/task-runtime.js +1600 -0
- package/dist/core/orchestration/task-runtime.js.map +1 -0
- package/dist/core/orchestration/work-state-projection.d.ts +32 -0
- package/dist/core/orchestration/work-state-projection.d.ts.map +1 -0
- package/dist/core/orchestration/work-state-projection.js +116 -0
- package/dist/core/orchestration/work-state-projection.js.map +1 -0
- package/dist/core/orchestration/worker-execution-contract.d.ts +21 -0
- package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -0
- package/dist/core/orchestration/worker-execution-contract.js +179 -0
- package/dist/core/orchestration/worker-execution-contract.js.map +1 -0
- package/dist/core/orchestration/worker-result-adapter.d.ts +21 -0
- package/dist/core/orchestration/worker-result-adapter.d.ts.map +1 -0
- package/dist/core/orchestration/worker-result-adapter.js +109 -0
- package/dist/core/orchestration/worker-result-adapter.js.map +1 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +20 -3
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/process-identity.d.ts +11 -0
- package/dist/core/process-identity.d.ts.map +1 -0
- package/dist/core/process-identity.js +26 -0
- package/dist/core/process-identity.js.map +1 -0
- package/dist/core/process-matrix/codes.d.ts +14 -3
- package/dist/core/process-matrix/codes.d.ts.map +1 -1
- package/dist/core/process-matrix/codes.js.map +1 -1
- package/dist/core/process-matrix/resume-launcher.d.ts +26 -0
- package/dist/core/process-matrix/resume-launcher.d.ts.map +1 -0
- package/dist/core/process-matrix/resume-launcher.js +62 -0
- package/dist/core/process-matrix/resume-launcher.js.map +1 -0
- package/dist/core/process-matrix/runtime.d.ts +37 -22
- package/dist/core/process-matrix/runtime.d.ts.map +1 -1
- package/dist/core/process-matrix/runtime.js +399 -76
- package/dist/core/process-matrix/runtime.js.map +1 -1
- package/dist/core/process-matrix/store.d.ts +5 -2
- package/dist/core/process-matrix/store.d.ts.map +1 -1
- package/dist/core/process-matrix/store.js +123 -14
- package/dist/core/process-matrix/store.js.map +1 -1
- package/dist/core/process-matrix/supervisor.d.ts +10 -7
- package/dist/core/process-matrix/supervisor.d.ts.map +1 -1
- package/dist/core/process-matrix/supervisor.js +45 -14
- package/dist/core/process-matrix/supervisor.js.map +1 -1
- package/dist/core/profile-filter-controller.d.ts +8 -1
- package/dist/core/profile-filter-controller.d.ts.map +1 -1
- package/dist/core/profile-filter-controller.js +23 -5
- package/dist/core/profile-filter-controller.js.map +1 -1
- package/dist/core/profile-registry.d.ts.map +1 -1
- package/dist/core/profile-registry.js +6 -8
- package/dist/core/profile-registry.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +1 -0
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +18 -29
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +5 -5
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +5 -2
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/reload-blockers.d.ts.map +1 -1
- package/dist/core/reload-blockers.js +6 -8
- package/dist/core/reload-blockers.js.map +1 -1
- package/dist/core/request-auth.d.ts +7 -0
- package/dist/core/request-auth.d.ts.map +1 -0
- package/dist/core/request-auth.js +8 -0
- package/dist/core/request-auth.js.map +1 -0
- package/dist/core/research/evidence-bundle.d.ts.map +1 -1
- package/dist/core/research/evidence-bundle.js +1 -6
- package/dist/core/research/evidence-bundle.js.map +1 -1
- package/dist/core/research/lane-model-resolver.d.ts +33 -0
- package/dist/core/research/lane-model-resolver.d.ts.map +1 -0
- package/dist/core/research/lane-model-resolver.js +65 -0
- package/dist/core/research/lane-model-resolver.js.map +1 -0
- package/dist/core/research/model-fitness-controller.d.ts +38 -0
- package/dist/core/research/model-fitness-controller.d.ts.map +1 -0
- package/dist/core/research/model-fitness-controller.js +106 -0
- package/dist/core/research/model-fitness-controller.js.map +1 -0
- package/dist/core/research/model-fitness.d.ts +1 -1
- package/dist/core/research/model-fitness.d.ts.map +1 -1
- package/dist/core/research/model-fitness.js +4 -4
- package/dist/core/research/model-fitness.js.map +1 -1
- package/dist/core/research/research-gate.d.ts.map +1 -1
- package/dist/core/research/research-gate.js +7 -7
- package/dist/core/research/research-gate.js.map +1 -1
- package/dist/core/research/research-lane-controller.d.ts +62 -0
- package/dist/core/research/research-lane-controller.d.ts.map +1 -0
- package/dist/core/research/research-lane-controller.js +292 -0
- package/dist/core/research/research-lane-controller.js.map +1 -0
- package/dist/core/research/session-evidence-bundle.d.ts +2 -4
- package/dist/core/research/session-evidence-bundle.d.ts.map +1 -1
- package/dist/core/research/session-evidence-bundle.js +10 -46
- package/dist/core/research/session-evidence-bundle.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +23 -8
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/risk-classifier.d.ts +6 -0
- package/dist/core/risk-classifier.d.ts.map +1 -0
- package/dist/core/risk-classifier.js +233 -0
- package/dist/core/risk-classifier.js.map +1 -0
- package/dist/core/runtime-builder.d.ts +41 -23
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +365 -253
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/sdk.d.ts +6 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +68 -25
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.d.ts +9 -0
- package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -0
- package/dist/core/secrets/credential-exposure-guard.js +241 -0
- package/dist/core/secrets/credential-exposure-guard.js.map +1 -0
- package/dist/core/secrets/secret-dotenv.d.ts +27 -0
- package/dist/core/secrets/secret-dotenv.d.ts.map +1 -0
- package/dist/core/secrets/secret-dotenv.js +183 -0
- package/dist/core/secrets/secret-dotenv.js.map +1 -0
- package/dist/core/secrets/secret-vault-format.d.ts +112 -0
- package/dist/core/secrets/secret-vault-format.d.ts.map +1 -0
- package/dist/core/secrets/secret-vault-format.js +397 -0
- package/dist/core/secrets/secret-vault-format.js.map +1 -0
- package/dist/core/secrets/secret-vault.d.ts +72 -0
- package/dist/core/secrets/secret-vault.d.ts.map +1 -0
- package/dist/core/secrets/secret-vault.js +671 -0
- package/dist/core/secrets/secret-vault.js.map +1 -0
- package/dist/core/session-analytics.d.ts +4 -23
- package/dist/core/session-analytics.d.ts.map +1 -1
- package/dist/core/session-analytics.js +67 -70
- package/dist/core/session-analytics.js.map +1 -1
- package/dist/core/session-image-store.d.ts +33 -0
- package/dist/core/session-image-store.d.ts.map +1 -0
- package/dist/core/session-image-store.js +283 -0
- package/dist/core/session-image-store.js.map +1 -0
- package/dist/core/session-role.d.ts +11 -4
- package/dist/core/session-role.d.ts.map +1 -1
- package/dist/core/session-role.js +24 -5
- package/dist/core/session-role.js.map +1 -1
- package/dist/core/session-snapshot.d.ts +34 -0
- package/dist/core/session-snapshot.d.ts.map +1 -0
- package/dist/core/session-snapshot.js +68 -0
- package/dist/core/session-snapshot.js.map +1 -0
- package/dist/core/session-supervision-runtime.d.ts +31 -0
- package/dist/core/session-supervision-runtime.d.ts.map +1 -0
- package/dist/core/session-supervision-runtime.js +97 -0
- package/dist/core/session-supervision-runtime.js.map +1 -0
- package/dist/core/session-tree-navigator.d.ts +4 -6
- package/dist/core/session-tree-navigator.d.ts.map +1 -1
- package/dist/core/session-tree-navigator.js +4 -1
- package/dist/core/session-tree-navigator.js.map +1 -1
- package/dist/core/settings-manager.d.ts +10 -5
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +81 -29
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +2 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tasks/session-task-state.d.ts +2 -4
- package/dist/core/tasks/session-task-state.d.ts.map +1 -1
- package/dist/core/tasks/session-task-state.js +10 -28
- package/dist/core/tasks/session-task-state.js.map +1 -1
- package/dist/core/tasks/task-projection.d.ts +20 -0
- package/dist/core/tasks/task-projection.d.ts.map +1 -0
- package/dist/core/tasks/task-projection.js +47 -0
- package/dist/core/tasks/task-projection.js.map +1 -0
- package/dist/core/tasks/task-state.d.ts +4 -0
- package/dist/core/tasks/task-state.d.ts.map +1 -1
- package/dist/core/tasks/task-state.js +28 -11
- package/dist/core/tasks/task-state.js.map +1 -1
- package/dist/core/tool-capability-policy.d.ts +13 -0
- package/dist/core/tool-capability-policy.d.ts.map +1 -0
- package/dist/core/tool-capability-policy.js +86 -0
- package/dist/core/tool-capability-policy.js.map +1 -0
- package/dist/core/tool-gate-controller.d.ts.map +1 -1
- package/dist/core/tool-gate-controller.js +8 -2
- package/dist/core/tool-gate-controller.js.map +1 -1
- package/dist/core/tool-protocol-controller.d.ts +89 -0
- package/dist/core/tool-protocol-controller.d.ts.map +1 -0
- package/dist/core/tool-protocol-controller.js +512 -0
- package/dist/core/tool-protocol-controller.js.map +1 -0
- package/dist/core/tool-recovery-log-records.d.ts +2 -3
- package/dist/core/tool-recovery-log-records.d.ts.map +1 -1
- package/dist/core/tool-recovery-log-records.js +9 -35
- package/dist/core/tool-recovery-log-records.js.map +1 -1
- package/dist/core/tool-recovery-stats.d.ts +21 -1
- package/dist/core/tool-recovery-stats.d.ts.map +1 -1
- package/dist/core/tool-recovery-stats.js.map +1 -1
- package/dist/core/tool-selection/tool-performance-store.d.ts +3 -7
- package/dist/core/tool-selection/tool-performance-store.d.ts.map +1 -1
- package/dist/core/tool-selection/tool-performance-store.js +97 -138
- package/dist/core/tool-selection/tool-performance-store.js.map +1 -1
- package/dist/core/tools/ask-question.d.ts +124 -0
- package/dist/core/tools/ask-question.d.ts.map +1 -0
- package/dist/core/tools/ask-question.js +693 -0
- package/dist/core/tools/ask-question.js.map +1 -0
- package/dist/core/tools/bash.d.ts +5 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +59 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/delegate-status.d.ts +31 -3
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +148 -29
- package/dist/core/tools/delegate-status.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +15 -13
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +106 -23
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/extensionify.d.ts.map +1 -1
- package/dist/core/tools/extensionify.js +1 -0
- package/dist/core/tools/extensionify.js.map +1 -1
- package/dist/core/tools/git-filter.d.ts +1 -8
- package/dist/core/tools/git-filter.d.ts.map +1 -1
- package/dist/core/tools/git-filter.js +2 -63
- package/dist/core/tools/git-filter.js.map +1 -1
- package/dist/core/tools/goal.d.ts +10 -8
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +106 -28
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/model-fitness.d.ts.map +1 -1
- package/dist/core/tools/model-fitness.js +2 -2
- package/dist/core/tools/model-fitness.js.map +1 -1
- package/dist/core/tools/orchestration-panel.d.ts +40 -0
- package/dist/core/tools/orchestration-panel.d.ts.map +1 -0
- package/dist/core/tools/orchestration-panel.js +124 -0
- package/dist/core/tools/orchestration-panel.js.map +1 -0
- package/dist/core/tools/output-accumulator.d.ts +11 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +36 -3
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/python.d.ts +2 -0
- package/dist/core/tools/python.d.ts.map +1 -1
- package/dist/core/tools/python.js +3 -1
- package/dist/core/tools/python.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/run-process.d.ts +26 -0
- package/dist/core/tools/run-process.d.ts.map +1 -0
- package/dist/core/tools/run-process.js +138 -0
- package/dist/core/tools/run-process.js.map +1 -0
- package/dist/core/tools/search-command-guard.d.ts +14 -0
- package/dist/core/tools/search-command-guard.d.ts.map +1 -0
- package/dist/core/tools/search-command-guard.js +333 -0
- package/dist/core/tools/search-command-guard.js.map +1 -0
- package/dist/core/tools/secret-store.d.ts +38 -0
- package/dist/core/tools/secret-store.d.ts.map +1 -0
- package/dist/core/tools/secret-store.js +412 -0
- package/dist/core/tools/secret-store.js.map +1 -0
- package/dist/core/tools/shell-command-parser.d.ts +16 -0
- package/dist/core/tools/shell-command-parser.d.ts.map +1 -0
- package/dist/core/tools/shell-command-parser.js +113 -0
- package/dist/core/tools/shell-command-parser.js.map +1 -0
- package/dist/core/tools/task-steps.d.ts +2 -0
- package/dist/core/tools/task-steps.d.ts.map +1 -1
- package/dist/core/tools/task-steps.js +99 -0
- package/dist/core/tools/task-steps.js.map +1 -1
- package/dist/core/tools/tmux-dispatch.d.ts +3 -5
- package/dist/core/tools/tmux-dispatch.d.ts.map +1 -1
- package/dist/core/tools/tmux-dispatch.js +4 -4
- package/dist/core/tools/tmux-dispatch.js.map +1 -1
- package/dist/core/tools/windows-shell-engine.d.ts.map +1 -1
- package/dist/core/tools/windows-shell-engine.js +4 -6
- package/dist/core/tools/windows-shell-engine.js.map +1 -1
- package/dist/core/util/atomic-file.d.ts +6 -2
- package/dist/core/util/atomic-file.d.ts.map +1 -1
- package/dist/core/util/atomic-file.js +4 -4
- package/dist/core/util/atomic-file.js.map +1 -1
- package/dist/core/util/bounded-jsonl.d.ts +10 -0
- package/dist/core/util/bounded-jsonl.d.ts.map +1 -0
- package/dist/core/util/bounded-jsonl.js +75 -0
- package/dist/core/util/bounded-jsonl.js.map +1 -0
- package/dist/core/util/value-guards.d.ts +5 -0
- package/dist/core/util/value-guards.d.ts.map +1 -0
- package/dist/core/util/value-guards.js +12 -0
- package/dist/core/util/value-guards.js.map +1 -0
- package/dist/core/worktree-sync/store.d.ts +3 -3
- package/dist/core/worktree-sync/store.d.ts.map +1 -1
- package/dist/core/worktree-sync/store.js +10 -5
- package/dist/core/worktree-sync/store.js.map +1 -1
- package/dist/index.d.ts +15 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +149 -51
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +4 -6
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +186 -28
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/auth-dialogs-controller.d.ts +4 -0
- package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
- package/dist/modes/interactive/auth-dialogs-controller.js +60 -1
- package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
- package/dist/modes/interactive/clipboard-input.d.ts +7 -1
- package/dist/modes/interactive/clipboard-input.d.ts.map +1 -1
- package/dist/modes/interactive/clipboard-input.js +44 -6
- package/dist/modes/interactive/clipboard-input.js.map +1 -1
- package/dist/modes/interactive/components/activity-lane.d.ts +55 -0
- package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -0
- package/dist/modes/interactive/components/activity-lane.js +304 -0
- package/dist/modes/interactive/components/activity-lane.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +19 -10
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/expandable-text.d.ts +12 -0
- package/dist/modes/interactive/components/expandable-text.d.ts.map +1 -0
- package/dist/modes/interactive/components/expandable-text.js +17 -0
- package/dist/modes/interactive/components/expandable-text.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +15 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +30 -21
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts +1 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +6 -1
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -2
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +23 -14
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +6 -6
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +19 -11
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +53 -20
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-group.js +3 -0
- package/dist/modes/interactive/components/tool-group.js.map +1 -1
- package/dist/modes/interactive/components/usage-action-selector.d.ts +16 -0
- package/dist/modes/interactive/components/usage-action-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/usage-action-selector.js +46 -0
- package/dist/modes/interactive/components/usage-action-selector.js.map +1 -0
- package/dist/modes/interactive/config-backup.d.ts.map +1 -1
- package/dist/modes/interactive/config-backup.js +5 -4
- package/dist/modes/interactive/config-backup.js.map +1 -1
- package/dist/modes/interactive/extension-ui-host.d.ts +14 -0
- package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
- package/dist/modes/interactive/extension-ui-host.js +77 -15
- package/dist/modes/interactive/extension-ui-host.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts +15 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +27 -19
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/history-reload-math.d.ts +6 -2
- package/dist/modes/interactive/history-reload-math.d.ts.map +1 -1
- package/dist/modes/interactive/history-reload-math.js +10 -5
- package/dist/modes/interactive/history-reload-math.js.map +1 -1
- package/dist/modes/interactive/interactive-event-controller.d.ts +74 -0
- package/dist/modes/interactive/interactive-event-controller.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-event-controller.js +328 -0
- package/dist/modes/interactive/interactive-event-controller.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +22 -24
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +245 -595
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/key-handlers.d.ts.map +1 -1
- package/dist/modes/interactive/key-handlers.js +1 -1
- package/dist/modes/interactive/key-handlers.js.map +1 -1
- package/dist/modes/interactive/loaded-resources-view.d.ts +20 -0
- package/dist/modes/interactive/loaded-resources-view.d.ts.map +1 -0
- package/dist/modes/interactive/loaded-resources-view.js +147 -0
- package/dist/modes/interactive/loaded-resources-view.js.map +1 -0
- package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -1
- package/dist/modes/interactive/profile-menu-controller.js +7 -7
- package/dist/modes/interactive/profile-menu-controller.js.map +1 -1
- package/dist/modes/interactive/report-commands.d.ts.map +1 -1
- package/dist/modes/interactive/report-commands.js +21 -0
- package/dist/modes/interactive/report-commands.js.map +1 -1
- package/dist/modes/interactive/resource-display.d.ts.map +1 -1
- package/dist/modes/interactive/resource-display.js +8 -2
- package/dist/modes/interactive/resource-display.js.map +1 -1
- package/dist/modes/interactive/resource-shell-commands.d.ts +1 -5
- package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -1
- package/dist/modes/interactive/resource-shell-commands.js +0 -5
- package/dist/modes/interactive/resource-shell-commands.js.map +1 -1
- package/dist/modes/interactive/session-flow-commands.d.ts +27 -8
- package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-flow-commands.js +150 -64
- package/dist/modes/interactive/session-flow-commands.js.map +1 -1
- package/dist/modes/interactive/session-io-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-io-commands.js +16 -6
- package/dist/modes/interactive/session-io-commands.js.map +1 -1
- package/dist/modes/interactive/session-replacement-errors.d.ts +7 -0
- package/dist/modes/interactive/session-replacement-errors.d.ts.map +1 -0
- package/dist/modes/interactive/session-replacement-errors.js +15 -0
- package/dist/modes/interactive/session-replacement-errors.js.map +1 -0
- package/dist/modes/interactive/startup-checks.d.ts.map +1 -1
- package/dist/modes/interactive/startup-checks.js +1 -1
- package/dist/modes/interactive/startup-checks.js.map +1 -1
- package/dist/modes/interactive/usage-commands.d.ts +34 -0
- package/dist/modes/interactive/usage-commands.d.ts.map +1 -0
- package/dist/modes/interactive/usage-commands.js +225 -0
- package/dist/modes/interactive/usage-commands.js.map +1 -0
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +82 -23
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +15 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js +138 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +2 -13
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +1 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts +1 -0
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +52 -1
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/platform.d.ts +3 -0
- package/dist/utils/platform.d.ts.map +1 -0
- package/dist/utils/platform.js +8 -0
- package/dist/utils/platform.js.map +1 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +5 -3
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +3 -1
- package/dist/utils/version-check.js.map +1 -1
- package/dist/utils/work-directory.d.ts +11 -0
- package/dist/utils/work-directory.d.ts.map +1 -1
- package/dist/utils/work-directory.js +30 -9
- package/dist/utils/work-directory.js.map +1 -1
- package/docs/UI_POLISH_ORCHESTRATION.md +38 -0
- package/docs/UI_QUALITY_ORCHESTRATION.md +28 -0
- package/docs/docs.json +4 -0
- package/docs/extensions.md +62 -2
- package/docs/harness-architecture.md +156 -0
- package/docs/keybindings.md +11 -1
- package/docs/process-matrix.md +59 -26
- package/docs/providers.md +9 -1
- package/docs/rpc.md +45 -2
- package/docs/sessions.md +15 -0
- package/docs/settings.md +125 -11
- package/docs/task-steps.md +8 -0
- package/docs/telemetry.md +19 -0
- package/docs/tmux-agent-manager.md +10 -3
- package/docs/ui-reference/README.md +9 -0
- package/docs/ui-reference/orchestration-after.txt +14 -0
- package/docs/ui-reference/orchestration-before.txt +13 -0
- package/docs/ui-reference/orchestration-reference.txt +16 -0
- package/docs/usage.md +22 -2
- package/docs/work-directory.md +19 -8
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/question.ts +34 -245
- package/examples/extensions/questionnaire.ts +41 -407
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +13 -13
- package/package.json +4 -4
- package/dist/core/delegation/session-worker-result.d.ts +0 -46
- package/dist/core/delegation/session-worker-result.d.ts.map +0 -1
- package/dist/core/delegation/session-worker-result.js +0 -113
- package/dist/core/delegation/session-worker-result.js.map +0 -1
- package/dist/core/delegation/worker-result.d.ts.map +0 -1
- package/dist/core/delegation/worker-result.js.map +0 -1
- package/dist/core/telemetry.d.ts.map +0 -1
- package/dist/core/telemetry.js.map +0 -1
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { readFileSync
|
|
3
|
-
import { basename, dirname
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { cleanupSessionResources, formatToolRepairStandingRule, formatVariantEnvelope, generateTextToolProtocolPrimer, getSupportedThinkingLevels, isContextOverflow, modelsAreEqual, parseTextToolCalls, streamSimple, } from "@caupulican/pi-ai";
|
|
7
|
-
import { Type } from "typebox";
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { basename, dirname } from "node:path";
|
|
4
|
+
import { compactToolResultDetailsForRetention, createCustomMessage, DEFAULT_STREAM_IDLE, withStreamIdleWatchdog, } from "@caupulican/pi-agent-core";
|
|
5
|
+
import { cleanupSessionResources, getSupportedThinkingLevels, modelsAreEqual, streamSimple } from "@caupulican/pi-ai";
|
|
8
6
|
import { getAgentDir } from "../config.js";
|
|
9
7
|
import { stripFrontmatter } from "../utils/frontmatter.js";
|
|
10
|
-
import { getProcessWorkRun } from "../utils/work-directory.js";
|
|
11
8
|
import { resourceDir, stateFile } from "./agent-paths.js";
|
|
12
9
|
import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
|
|
13
10
|
import { buildForegroundEnvelope, formatForegroundEnvelopeObservation } from "./autonomy/foreground-envelope.js";
|
|
@@ -15,19 +12,20 @@ import { evaluateToolGate } from "./autonomy/gates.js";
|
|
|
15
12
|
import { AutonomyTelemetry } from "./autonomy-telemetry.js";
|
|
16
13
|
import { BackgroundLaneController } from "./background-lane-controller.js";
|
|
17
14
|
import { BashExecutionController } from "./bash-execution-controller.js";
|
|
18
|
-
import {
|
|
15
|
+
import { CompactionController } from "./compaction-controller.js";
|
|
19
16
|
import { CompactionSupport } from "./compaction-support.js";
|
|
20
17
|
import { buildContextCompositionReport, formatContextCompositionDashboard, } from "./context/context-composition.js";
|
|
21
18
|
import { ContextPipeline } from "./context-pipeline.js";
|
|
22
19
|
import { downgradeReasoning, estimateTurnCostUsd, evaluateCostGuard } from "./cost-guard.js";
|
|
23
|
-
import {
|
|
20
|
+
import { appendWorkerClaimSnapshot, getWorkerClaimSnapshots } from "./delegation/session-worker-claim.js";
|
|
24
21
|
import { FailureCorpusRecorder } from "./failure-corpus.js";
|
|
22
|
+
import { ForegroundRecoveryController } from "./foreground-recovery-controller.js";
|
|
25
23
|
import { GatewayRegistry } from "./gateways/channel-provider.js";
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import { applyGoalEvent } from "./goals/goal-state.js";
|
|
29
|
-
import { appendGoalStateSnapshot, getLatestGoalStateSnapshot } from "./goals/session-goal-state.js";
|
|
24
|
+
import { injectCompactGoalContext } from "./goals/compact-goal-context.js";
|
|
25
|
+
import { GoalSessionController } from "./goals/goal-session-controller.js";
|
|
30
26
|
import { constrainStreamIdleToHttpTimeout } from "./http-dispatcher.js";
|
|
27
|
+
import { getWorkerHumanInputsRequiringDelivery } from "./human-input.js";
|
|
28
|
+
import { HumanInputController } from "./human-input-controller.js";
|
|
31
29
|
import { appendLearningDecisionSnapshot, getLearningDecisionSnapshots } from "./learning/session-learning-decision.js";
|
|
32
30
|
import { isPromotedFrontmatter, SkillCurator } from "./learning/skill-curator.js";
|
|
33
31
|
import { LocalRuntimeController } from "./local-runtime-controller.js";
|
|
@@ -36,9 +34,11 @@ import { deriveModelCapabilityProfile, evaluateLaneWorkerRefusal, filterToolName
|
|
|
36
34
|
import { isLocalOrManagedRouterModel } from "./model-router/tool-escalation.js";
|
|
37
35
|
import { formatModelRouterModel, ModelRouterController } from "./model-router-controller.js";
|
|
38
36
|
import { ModelSelectionController } from "./model-selection-controller.js";
|
|
39
|
-
import { ModelAdaptationStore
|
|
37
|
+
import { ModelAdaptationStore } from "./models/adaptation-store.js";
|
|
40
38
|
import { HF_TRANSFORMERS_PROVIDER, OLLAMA_PROVIDER } from "./models/local-registration.js";
|
|
41
39
|
import { DEFAULT_ADAPTIVE_STREAM_IDLE_CEILING_MS, estimateContextPromptTokens, resolveAdaptiveStreamIdleOptions, withModelPerfProfile, } from "./models/perf-profile.js";
|
|
40
|
+
import { resolveConfiguredOrchestrationModel } from "./orchestration/model-binding.js";
|
|
41
|
+
import { validateOrchestrationProfile } from "./orchestration/profile-registry.js";
|
|
42
42
|
import { ProfileFilterController } from "./profile-filter-controller.js";
|
|
43
43
|
import { expandPromptTemplate } from "./prompt-templates.js";
|
|
44
44
|
import { ReflectionController } from "./reflection-controller.js";
|
|
@@ -47,15 +47,16 @@ import { collectWorkspaceSources } from "./research/workspace-collector.js";
|
|
|
47
47
|
import { stripResourceProfileBlocks } from "./resource-profile-blocks.js";
|
|
48
48
|
import { RuntimeBuilder } from "./runtime-builder.js";
|
|
49
49
|
import { SessionAnalytics } from "./session-analytics.js";
|
|
50
|
+
import { SessionImageStore } from "./session-image-store.js";
|
|
51
|
+
import { getActiveSessionBranchEntries } from "./session-snapshot.js";
|
|
50
52
|
import { SessionTreeNavigator } from "./session-tree-navigator.js";
|
|
51
53
|
import { SystemPromptBuilder } from "./system-prompt-builder.js";
|
|
52
54
|
import { appendTaskStepsStateSnapshot, getLatestTaskStepsStateSnapshot } from "./tasks/session-task-state.js";
|
|
53
55
|
import { formatTaskStepsContext } from "./tasks/task-state.js";
|
|
54
56
|
import { ToolGateController } from "./tool-gate-controller.js";
|
|
57
|
+
import { ToolProtocolController } from "./tool-protocol-controller.js";
|
|
55
58
|
import { TOOL_RECOVERY_EVENT_LOG_FILE } from "./tool-recovery-log-records.js";
|
|
56
59
|
import { ToolRecoveryLogger } from "./tool-recovery-logger.js";
|
|
57
|
-
import { formatToolRepairHealthReport } from "./tool-repair-health.js";
|
|
58
|
-
import { resolveCurrentToolRepairSettings } from "./tool-repair-settings.js";
|
|
59
60
|
import { ToolPerformanceStore } from "./tool-selection/tool-performance-store.js";
|
|
60
61
|
import { formatToolSelectionReport, ToolSelectionController } from "./tool-selection/tool-selection-controller.js";
|
|
61
62
|
import { disposePersistentShellSession } from "./tools/shell-session.js";
|
|
@@ -72,39 +73,6 @@ import { disposePersistentShellSession } from "./tools/shell-session.js";
|
|
|
72
73
|
* key stable regardless of how many times this module is evaluated.
|
|
73
74
|
*/
|
|
74
75
|
const RAW_STREAM_MARKER = Symbol.for("pi.rawStreamSimple");
|
|
75
|
-
const MODEL_ADAPTATION_REPAIR_THRESHOLD = 3;
|
|
76
|
-
const TEXT_TOOL_PROTOCOL_VERSION = 1;
|
|
77
|
-
const TEXT_TOOL_PROTOCOL_TRIALS_PER_VARIANT = 2;
|
|
78
|
-
const TEXT_TOOL_PROTOCOL_PARSE_FAILURE_THRESHOLD = 3;
|
|
79
|
-
/** How often the one-line envelope-format corrective steer (see
|
|
80
|
-
* {@link AgentSession._maybeInjectTextProtocolCorrectiveSteer}) re-fires after the first parse
|
|
81
|
-
* failure this session — every Nth failure thereafter, not every single one, so a model that keeps
|
|
82
|
-
* missing the envelope doesn't get the reminder spliced into every turn (the breaker's same-signature
|
|
83
|
-
* counter is what actually demotes it, at {@link TEXT_TOOL_PROTOCOL_PARSE_FAILURE_THRESHOLD}). */
|
|
84
|
-
const TEXT_TOOL_PROTOCOL_STEER_INTERVAL = 5;
|
|
85
|
-
/** Anti-loop cooldown: the evidence-gated auto-probe (see {@link
|
|
86
|
-
* AgentSession._maybeAutoProbeOnValidationEscalation}) skips a model whose persisted `toolProbe`
|
|
87
|
-
* verdict was written within this window, so a burst of validation-escalation events for a still-
|
|
88
|
-
* failing model — or a very recent explicit `/toolprobe` run, or a future circuit-breaker demote — does
|
|
89
|
-
* not re-fire the (multi-completion) probe every time. Independent of, and complementary to, the
|
|
90
|
-
* per-session `_autoProbedModels` latch. */
|
|
91
|
-
const AUTO_TOOL_PROBE_FRESHNESS_MS = 15 * 60 * 1000;
|
|
92
|
-
const TEXT_TOOL_PROTOCOL_VARIANTS = [
|
|
93
|
-
"tool-tag",
|
|
94
|
-
"tool-call",
|
|
95
|
-
"fenced-json",
|
|
96
|
-
"function-xml",
|
|
97
|
-
];
|
|
98
|
-
const TEXT_TOOL_PROTOCOL_ECHO_TOOL = {
|
|
99
|
-
name: "echo",
|
|
100
|
-
description: "Echo calibration data",
|
|
101
|
-
parameters: Type.Object({ data: Type.String() }),
|
|
102
|
-
};
|
|
103
|
-
const NATIVE_TOOL_PROBE_READ_TOOL = {
|
|
104
|
-
name: "read",
|
|
105
|
-
description: "Read file contents",
|
|
106
|
-
parameters: Type.Object({ path: Type.String() }),
|
|
107
|
-
};
|
|
108
76
|
/** Test-only override of the stream-idle bounds. Read per-request by the wiring's resolver. */
|
|
109
77
|
let streamIdleOptionsOverride;
|
|
110
78
|
/**
|
|
@@ -124,63 +92,8 @@ function tagRawness(wrapped, innerIsRawStreamSimple) {
|
|
|
124
92
|
Object.defineProperty(wrapped, RAW_STREAM_MARKER, { value: innerIsRawStreamSimple });
|
|
125
93
|
return wrapped;
|
|
126
94
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
* Returns null if the text doesn't contain a skill block.
|
|
130
|
-
*/
|
|
131
|
-
export function parseSkillBlock(text) {
|
|
132
|
-
const match = text.match(/^<skill name="([^"]+)" location="([^"]+)">\n([\s\S]*?)\n<\/skill>(?:\n\n([\s\S]+))?$/);
|
|
133
|
-
if (!match)
|
|
134
|
-
return null;
|
|
135
|
-
return {
|
|
136
|
-
name: match[1],
|
|
137
|
-
location: match[2],
|
|
138
|
-
content: match[3],
|
|
139
|
-
userMessage: match[4]?.trim() || undefined,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
/** customType for spawned-usage roll-up entries (Cost Aggregation, Model A). */
|
|
143
|
-
export const SPAWNED_USAGE_CUSTOM_TYPE = "spawned_usage";
|
|
144
|
-
/**
|
|
145
|
-
* customType for a persisted runaway-loop-backstop entry: the agent loop stopped a turn stuck
|
|
146
|
-
* repeating one identical tool-call signature. This is the session-log/telemetry sink for
|
|
147
|
-
* {@link Agent.onRunawayStop} — see `_installAgentToolHooks`.
|
|
148
|
-
*/
|
|
149
|
-
export const RUNAWAY_STOP_CUSTOM_TYPE = "runaway_stop";
|
|
150
|
-
/**
|
|
151
|
-
* customType for a persisted tool-validation-escalation entry: the agent loop bounced the same
|
|
152
|
-
* tool-call validation failure enough times to escalate. This is the session-log/telemetry sink for
|
|
153
|
-
* {@link Agent.onToolValidationEscalation} — see `_installAgentToolHooks`.
|
|
154
|
-
*/
|
|
155
|
-
export const TOOL_VALIDATION_ESCALATION_CUSTOM_TYPE = "tool_validation_escalation";
|
|
156
|
-
/** Fallback {@link IsolatedCompletionOptions.laneKind} for callers that do not tag their lane. */
|
|
157
|
-
export const DEFAULT_ISOLATED_LANE_KIND = "isolated";
|
|
158
|
-
/**
|
|
159
|
-
* Derive a STABLE synthetic cache-affinity key for an isolated completion lane. Isolated calls
|
|
160
|
-
* deliberately never carry the real session id (see reflection-controller.ts's isolation invariants —
|
|
161
|
-
* an isolated call must not entangle with the main session), which today also means every isolated
|
|
162
|
-
* call looks like a brand-new, uncorrelated session to providers with session-affinity headers /
|
|
163
|
-
* `prompt_cache_key` (anthropic.ts's `x-session-affinity`, openai-responses.ts /
|
|
164
|
-
* openai-completions.ts's `prompt_cache_key`), defeating their cache routing.
|
|
165
|
-
*
|
|
166
|
-
* This key is deterministic per `(laneKind, model, systemPrompt)` — the SAME lane calling the SAME
|
|
167
|
-
* model with the SAME (static) system prompt always gets the SAME key, so repeat calls route to the
|
|
168
|
-
* same cache-warm backend — while remaining fully synthetic: it is a salted hash, namespaced with a
|
|
169
|
-
* `lane:` prefix, and never derived from or equal to the real session id.
|
|
170
|
-
*/
|
|
171
|
-
export function computeLaneAffinityKey(laneKind, model, systemPrompt) {
|
|
172
|
-
const modelKey = model ? `${model.provider}/${model.id}` : "unknown-model";
|
|
173
|
-
// NUL-separated fields: laneKind/modelKey are drawn from small caller-controlled vocabularies
|
|
174
|
-
// that never contain a raw NUL, so this cannot field-collide the way a plain colon/space join could.
|
|
175
|
-
const digest = createHash("sha256")
|
|
176
|
-
.update(["pi-lane-affinity-v1", laneKind, modelKey, systemPrompt].join("\u0000"))
|
|
177
|
-
.digest("hex")
|
|
178
|
-
.slice(0, 32);
|
|
179
|
-
return `lane:${laneKind}:${digest}`;
|
|
180
|
-
}
|
|
181
|
-
// ============================================================================
|
|
182
|
-
// Constants
|
|
183
|
-
// ============================================================================
|
|
95
|
+
export * from "./agent-session-contracts.js";
|
|
96
|
+
import { RUNAWAY_STOP_CUSTOM_TYPE, TOOL_VALIDATION_ESCALATION_CUSTOM_TYPE } from "./agent-session-contracts.js";
|
|
184
97
|
// ============================================================================
|
|
185
98
|
// AgentSession Class
|
|
186
99
|
// ============================================================================
|
|
@@ -204,12 +117,8 @@ export class AgentSession {
|
|
|
204
117
|
* switching from a small-window model back to a large one restores the full requested set.
|
|
205
118
|
*/
|
|
206
119
|
_requestedActiveToolNames;
|
|
207
|
-
_compactionAbortController = undefined;
|
|
208
|
-
_autoCompactionAbortController = undefined;
|
|
209
|
-
_overflowRecoveryAttempted = false;
|
|
210
120
|
_unboundToolGrantWarnings = [];
|
|
211
121
|
_branchSummaryAbortController = undefined;
|
|
212
|
-
_retryController;
|
|
213
122
|
_modelSelection;
|
|
214
123
|
_bash;
|
|
215
124
|
_profileFilter;
|
|
@@ -226,39 +135,26 @@ export class AgentSession {
|
|
|
226
135
|
_agentDir;
|
|
227
136
|
_collectWorkspaceSources;
|
|
228
137
|
_localRuntimeController;
|
|
229
|
-
|
|
138
|
+
_toolProtocol;
|
|
230
139
|
_prefixWarmer;
|
|
231
140
|
_completedPrefixWarms = new Set();
|
|
232
|
-
_repairModeSessionCounts = new Map();
|
|
233
|
-
_textProtocolParseFailures = new Map();
|
|
234
|
-
_textProtocolParseObservedThisTurn = false;
|
|
235
|
-
/** Total text-protocol parse-failure events observed this session, backing the
|
|
236
|
-
* {@link TEXT_TOOL_PROTOCOL_STEER_INTERVAL} throttle on {@link _maybeInjectTextProtocolCorrectiveSteer}. */
|
|
237
|
-
_textProtocolCorrectiveSteerCount = 0;
|
|
238
|
-
/** Monotonic counter backing tool-probe/text-protocol-calibration spawned-usage reportIds
|
|
239
|
-
* (see {@link _nextProbeUsageReportId}); guarantees each probe/calibration completion in the
|
|
240
|
-
* session lands in the cost ledger exactly once, even across repeated /toolprobe invocations. */
|
|
241
|
-
_toolProbeUsageReportSeq = 0;
|
|
242
|
-
/** Anti-loop: modelKeys the evidence-gated auto-probe has already fired for THIS session (see
|
|
243
|
-
* {@link _maybeAutoProbeOnValidationEscalation}), so a burst of validation-escalation events for
|
|
244
|
-
* the same still-failing model never re-fires the probe more than once per session. */
|
|
245
|
-
_autoProbedModels = new Set();
|
|
246
|
-
_textProtocolValidationOutcomeThisTurn;
|
|
247
141
|
/** Assembles the session's base system prompt from live session state (see
|
|
248
142
|
* system-prompt-builder.ts); owns the paired _baseSystemPromptOptions. */
|
|
249
143
|
_systemPromptBuilder;
|
|
250
144
|
/** Autonomy telemetry sink + status/diagnostic snapshots (see autonomy-telemetry.ts); owns
|
|
251
145
|
* the latest gate outcome and the bounded gate-outcome history. */
|
|
252
146
|
_autonomyTelemetry;
|
|
253
|
-
/** Goal auto-continue + research lane +
|
|
147
|
+
/** Goal auto-continue + research lane + profile-bound worker delegation + model-fitness probe (see
|
|
254
148
|
* background-lane-controller.ts); owns the lane timers/guards, the last research-lane skip
|
|
255
149
|
* reason, the live LaneTracker, and the in-flight research/worker abort controllers. */
|
|
256
150
|
_backgroundLanes;
|
|
151
|
+
_humanInput;
|
|
257
152
|
/** Plug-and-play memory subsystem (see memory-controller.ts); owns the OKF retrieval provider, the
|
|
258
153
|
* latest retrieval/prompt-inclusion reports, the reload-safe MemoryManager, the recall
|
|
259
154
|
* effectiveness tracker, and the extension-contributed pending providers. */
|
|
260
155
|
_memory;
|
|
261
156
|
_compactionSupport;
|
|
157
|
+
_compaction;
|
|
262
158
|
/** Per-turn context-shaping subsystem (see context-pipeline.ts); owns the latest
|
|
263
159
|
* audit/policy/correlation/enforcement/gc reports, the brain-curation sidecar + its skip reasons,
|
|
264
160
|
* and the tool-output artifact store. Invoked stage-by-stage from the context transform. */
|
|
@@ -288,19 +184,19 @@ export class AgentSession {
|
|
|
288
184
|
* used by the status report. Its parallel routed drive path delegates every turn back to
|
|
289
185
|
* {@link _runAgentPrompt} so the drive loop stays host-side. */
|
|
290
186
|
_modelRouter;
|
|
291
|
-
|
|
187
|
+
_foregroundRecovery;
|
|
292
188
|
_failureCorpus;
|
|
293
189
|
_toolRecoveryLogger;
|
|
294
190
|
_toolRecoveryEventLogPath;
|
|
295
191
|
_skillCuratorInstance;
|
|
296
192
|
_disposed = false;
|
|
193
|
+
_disposeCompletion;
|
|
297
194
|
_reflectionAbort = new AbortController();
|
|
298
195
|
/** Native reflection engine + learning-apply/rollback path (see reflection-controller.ts); owns no
|
|
299
196
|
* session state, applies durable writes through the bundled memory tool and the session log. */
|
|
300
197
|
_reflection;
|
|
301
|
-
/**
|
|
302
|
-
|
|
303
|
-
_goalContinuation;
|
|
198
|
+
/** Durable goal lifecycle, accounting, and raw continuation loop. */
|
|
199
|
+
_goals;
|
|
304
200
|
_isChildSession;
|
|
305
201
|
_baseToolsOverride;
|
|
306
202
|
_sessionStartEvent;
|
|
@@ -323,7 +219,7 @@ export class AgentSession {
|
|
|
323
219
|
this.agent = config.agent;
|
|
324
220
|
// Bound every provider stream this session starts against a silently dead connection: a
|
|
325
221
|
// stall aborts the inner request and surfaces as a retryable "stream stalled" error, which
|
|
326
|
-
//
|
|
222
|
+
// ForegroundRecoveryController routes into the existing auto-retry path. Wrapped exactly once, here.
|
|
327
223
|
// The wrapper reports the stall immediately and aborts the inner request; releasing the
|
|
328
224
|
// inner pump relies on the provider ending its stream after abort (real providers do — see
|
|
329
225
|
// withStreamIdleWatchdog's contract), so no extra drain is added at this wiring site.
|
|
@@ -367,31 +263,46 @@ export class AgentSession {
|
|
|
367
263
|
}), baseStreamFn === streamSimple);
|
|
368
264
|
this.sessionManager = config.sessionManager;
|
|
369
265
|
this.settingsManager = config.settingsManager;
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
266
|
+
if (config.orchestrationProfile) {
|
|
267
|
+
validateOrchestrationProfile(config.orchestrationProfile);
|
|
268
|
+
const resolved = resolveConfiguredOrchestrationModel(config.orchestrationProfile, config.modelRegistry);
|
|
269
|
+
if (!resolved) {
|
|
270
|
+
throw new TypeError(`Orchestration profile '${config.orchestrationProfile.profileId}' has no configured, authenticated model that supports its exact thinking level.`);
|
|
271
|
+
}
|
|
272
|
+
if (!this.agent.state.model || !modelsAreEqual(this.agent.state.model, resolved.model)) {
|
|
273
|
+
this.sessionManager.appendModelChange(resolved.model.provider, resolved.model.id);
|
|
274
|
+
}
|
|
275
|
+
if (this.agent.state.thinkingLevel !== resolved.binding.thinkingLevel) {
|
|
276
|
+
this.sessionManager.appendThinkingLevelChange(resolved.binding.thinkingLevel);
|
|
277
|
+
}
|
|
278
|
+
this.agent.state.model = resolved.model;
|
|
279
|
+
this.agent.state.thinkingLevel = resolved.binding.thinkingLevel;
|
|
280
|
+
this.settingsManager.setRuntimeResourceProfiles([...config.orchestrationProfile.resourceProfileNames]);
|
|
281
|
+
}
|
|
282
|
+
this._scopedModels = config.orchestrationProfile
|
|
283
|
+
? [{ model: this.agent.state.model, thinkingLevel: this.agent.state.thinkingLevel }]
|
|
284
|
+
: (config.scopedModels ?? []);
|
|
388
285
|
this._resourceLoader = config.resourceLoader;
|
|
389
286
|
this._customTools = config.customTools ?? [];
|
|
390
287
|
this._cwd = config.cwd;
|
|
391
288
|
this._agentDir = agentDir;
|
|
392
|
-
this.
|
|
393
|
-
|
|
394
|
-
|
|
289
|
+
this._toolProtocol = new ToolProtocolController({
|
|
290
|
+
agent: this.agent,
|
|
291
|
+
agentDir: this._agentDir,
|
|
292
|
+
settingsManager: this.settingsManager,
|
|
293
|
+
getModelRegistry: () => this._modelRegistry,
|
|
294
|
+
adaptationStore: modelAdaptationStore,
|
|
295
|
+
isRawStreamSimple: (fn) => this._isRawStreamSimple(fn),
|
|
296
|
+
getRequiredRequestAuth: (model) => this._getRequiredRequestAuth(model),
|
|
297
|
+
addSpawnedUsage: (usage, opts) => this.addSpawnedUsage(usage, opts),
|
|
298
|
+
emitWarning: (message) => this._emit({ type: "warning", message }),
|
|
299
|
+
sendCorrectiveSteer: (message) => this.sendCustomMessage({ customType: "text-protocol-corrective-steer", content: message, display: false }, { deliverAs: "nextTurn" }),
|
|
300
|
+
findLastAssistantMessage: () => this._findLastAssistantMessage(),
|
|
301
|
+
isDisposed: () => this._disposed,
|
|
302
|
+
probeForAuto: (model) => this._probeToolCallingForModel(model),
|
|
303
|
+
});
|
|
304
|
+
this.agent.onTextToolProtocolParse = (event) => this._toolProtocol.handleTextProtocolParse(event);
|
|
305
|
+
this._toolProtocol.applyRepairLayerSettings();
|
|
395
306
|
this._collectWorkspaceSources = config.collectWorkspaceSources ?? collectWorkspaceSources;
|
|
396
307
|
this._localRuntimeController = new LocalRuntimeController({
|
|
397
308
|
agentDir: this._agentDir,
|
|
@@ -410,7 +321,7 @@ export class AgentSession {
|
|
|
410
321
|
hasTool: (name) => this._runtimeBuilder.hasTool(name),
|
|
411
322
|
getToolPromptSnippet: (name) => this._runtimeBuilder.getToolPromptSnippet(name),
|
|
412
323
|
getToolPromptGuidelines: (name) => this._runtimeBuilder.getToolPromptGuidelines(name),
|
|
413
|
-
getModelAdaptationRules: () => this.
|
|
324
|
+
getModelAdaptationRules: () => this._toolProtocol.getAdaptationRulesForPrompt(),
|
|
414
325
|
getActiveExtensions: () => this._extensionRunner.activeExtensions,
|
|
415
326
|
getContextWindow: () => this.model?.contextWindow,
|
|
416
327
|
getThinkingLevel: () => this.thinkingLevel,
|
|
@@ -425,12 +336,36 @@ export class AgentSession {
|
|
|
425
336
|
getCostSummary: () => this.getCostSummary(),
|
|
426
337
|
getGoalStateSnapshot: () => this.getGoalStateSnapshot(),
|
|
427
338
|
getActiveLaneCount: () => this._backgroundLanes.getActiveLaneCount(),
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
339
|
+
getSessionEvidenceBundleHistory: () => getEvidenceBundleSnapshots(this.sessionManager.getEntries()),
|
|
340
|
+
getSessionWorkerClaimHistory: () => getWorkerClaimSnapshots(this.sessionManager.getEntries()),
|
|
341
|
+
getSessionLearningDecisionHistory: () => getLearningDecisionSnapshots(this.sessionManager.getEntries()),
|
|
431
342
|
getLearningAuditRecords: () => this.getLearningAuditRecords(),
|
|
432
343
|
});
|
|
433
344
|
this._modelRegistry = config.modelRegistry;
|
|
345
|
+
this._humanInput = new HumanInputController({
|
|
346
|
+
getSessionManager: () => this.sessionManager,
|
|
347
|
+
getUIContext: () => this._extensionUIContext,
|
|
348
|
+
getExtensionMode: () => this._extensionMode,
|
|
349
|
+
waitForIdle: () => this.agent.waitForIdle(),
|
|
350
|
+
isDisposed: () => this._disposed,
|
|
351
|
+
isStreaming: () => this.isStreaming,
|
|
352
|
+
getModel: () => this.model,
|
|
353
|
+
getArtifactStore: () => this._getToolArtifactStore(),
|
|
354
|
+
getImageStore: () => this._getSessionImageStore(),
|
|
355
|
+
runAgentPrompt: (messages) => this._runAgentPrompt(messages),
|
|
356
|
+
sendCustomMessage: (message, options) => this.sendCustomMessage(message, options),
|
|
357
|
+
emitWarning: (message) => this._emit({ type: "warning", message }),
|
|
358
|
+
});
|
|
359
|
+
this._goals = new GoalSessionController({
|
|
360
|
+
getSessionManager: () => this.sessionManager,
|
|
361
|
+
getModelProvider: () => this.model?.provider,
|
|
362
|
+
getLaneRecords: () => this._backgroundLanes.getLaneRecords(),
|
|
363
|
+
getTaskRuntimeSnapshot: () => this._backgroundLanes.getTaskRuntimeSnapshot(),
|
|
364
|
+
synchronizeGoalState: (state) => this._backgroundLanes.synchronizeGoalState(state),
|
|
365
|
+
scheduleGoalAutoContinueFromIdle: () => this._backgroundLanes.scheduleGoalAutoContinueFromIdle(),
|
|
366
|
+
prompt: (text, options) => this.prompt(text, options),
|
|
367
|
+
emitWarning: (message) => this._emit({ type: "warning", message }),
|
|
368
|
+
});
|
|
434
369
|
this._backgroundLanes = new BackgroundLaneController({
|
|
435
370
|
isDisposed: () => this._disposed,
|
|
436
371
|
isChildSession: () => this._isChildSession,
|
|
@@ -439,8 +374,9 @@ export class AgentSession {
|
|
|
439
374
|
getAgentDir: () => this._agentDir,
|
|
440
375
|
getSessionManager: () => this.sessionManager,
|
|
441
376
|
getSettingsManager: () => this.settingsManager,
|
|
377
|
+
getActiveOrchestrationProfile: () => config.orchestrationProfile,
|
|
442
378
|
getModelRegistry: () => this._modelRegistry,
|
|
443
|
-
isModelExhausted: (model) => this.
|
|
379
|
+
isModelExhausted: (model) => this._foregroundRecovery.isModelExhausted(`${model.provider}/${model.id}`),
|
|
444
380
|
getModel: () => this.model ?? undefined,
|
|
445
381
|
isDelegateToolActive: () => this.getActiveToolNames().includes("delegate"),
|
|
446
382
|
isGoalToolActive: () => this.getActiveToolNames().includes("goal"),
|
|
@@ -451,16 +387,18 @@ export class AgentSession {
|
|
|
451
387
|
emitAutonomyTelemetry: (event) => this._emitAutonomyTelemetry(event),
|
|
452
388
|
getGoalStateSnapshot: () => this.getGoalStateSnapshot(),
|
|
453
389
|
getGoalRuntimeSnapshot: (settings) => this.getGoalRuntimeSnapshot(settings),
|
|
390
|
+
markGoalToolUnavailable: () => this._goals.markToolUnavailable(),
|
|
454
391
|
getEvidenceBundleSnapshot: () => this.getEvidenceBundleSnapshot(),
|
|
455
392
|
saveEvidenceBundleSnapshot: (bundle) => this.saveEvidenceBundleSnapshot(bundle),
|
|
456
|
-
|
|
393
|
+
saveWorkerClaimSnapshot: (claim, request) => this.saveWorkerClaimSnapshot(claim, request),
|
|
394
|
+
queueWorkerHumanInput: (request) => this._humanInput.queueWorkerInput(request),
|
|
457
395
|
readMemoryForLane: (query) => this._memory.readMemoryForLane(query),
|
|
458
396
|
addSpawnedUsage: (usage, opts) => this.addSpawnedUsage(usage, opts),
|
|
459
397
|
runIsolatedCompletion: (opts) => this.runIsolatedCompletion(opts),
|
|
460
398
|
// RAW loop, deliberately bypassing the public `continueGoalLoop` — that method now delegates
|
|
461
399
|
// to this controller's own `continueGoalLoopExclusive` guard, so routing through it here would
|
|
462
400
|
// recurse into the guard from inside itself instead of driving the actual continuation pass.
|
|
463
|
-
continueGoalLoop: (options) => this.
|
|
401
|
+
continueGoalLoop: (options) => this._goals.continueLoop(options),
|
|
464
402
|
collectWorkspaceSources: (args) => this._collectWorkspaceSources(args),
|
|
465
403
|
});
|
|
466
404
|
this._memory = new MemoryController({
|
|
@@ -480,7 +418,7 @@ export class AgentSession {
|
|
|
480
418
|
getModelRegistry: () => this._modelRegistry,
|
|
481
419
|
isRawStream: () => this._isRawStreamSimple(this.agent.streamFn),
|
|
482
420
|
getRequiredRequestAuth: (model) => this._getRequiredRequestAuth(model),
|
|
483
|
-
isModelExhausted: (ref) => this.
|
|
421
|
+
isModelExhausted: (ref) => this._foregroundRecovery.isModelExhausted(ref),
|
|
484
422
|
getStoredFitnessReport: (ref) => this.getStoredFitnessReports().find((entry) => entry.model === ref)?.report,
|
|
485
423
|
// Live context is an over-estimate of the span to summarize (includes the kept tail) —
|
|
486
424
|
// conservative in the safe direction for the summarizer capacity check.
|
|
@@ -507,23 +445,51 @@ export class AgentSession {
|
|
|
507
445
|
});
|
|
508
446
|
const failureCorpusPath = stateFile(this._agentDir, "failure-corpus.jsonl");
|
|
509
447
|
this._toolRecoveryEventLogPath = stateFile(this._agentDir, TOOL_RECOVERY_EVENT_LOG_FILE);
|
|
510
|
-
const toolRepairSettings = this.
|
|
448
|
+
const toolRepairSettings = this._toolProtocol.getRepairSettings();
|
|
511
449
|
this._failureCorpus = new FailureCorpusRecorder({
|
|
512
450
|
filePath: failureCorpusPath,
|
|
513
451
|
});
|
|
452
|
+
this._compaction = new CompactionController({
|
|
453
|
+
agent: this.agent,
|
|
454
|
+
sessionManager: this.sessionManager,
|
|
455
|
+
settingsManager: this.settingsManager,
|
|
456
|
+
getModel: () => this.model,
|
|
457
|
+
getAdaptedSettings: () => this._getAdaptedCompactionSettings(),
|
|
458
|
+
getRequestAuth: (model) => this._getCompactionRequestAuth(model),
|
|
459
|
+
resolveModelAndAuth: (compactionModel, sessionModel) => this._resolveCompactionModelAndAuth(compactionModel, sessionModel),
|
|
460
|
+
resolveModel: (sessionModel) => this._resolveCompactionModel(sessionModel),
|
|
461
|
+
getSelectionReason: () => this._getLastCompactionSelectionReason(),
|
|
462
|
+
resolveThinkingLevel: (compactionModel, sessionModel) => this._resolveCompactionThinkingLevel(compactionModel, sessionModel),
|
|
463
|
+
describeSummarizer: () => this._describeCompactionSummarizer(),
|
|
464
|
+
getExtensionRunner: () => this._extensionRunner,
|
|
465
|
+
isRawStream: () => this._isRawStreamSimple(this.agent.streamFn),
|
|
466
|
+
disconnectAgent: () => this._disconnectFromAgent(),
|
|
467
|
+
reconnectAgent: () => this._reconnectToAgent(),
|
|
468
|
+
abortForeground: () => this.abort(),
|
|
469
|
+
emit: (event) => this._emit(event),
|
|
470
|
+
estimateCurrentContextTokens: (messages) => this._pipeline.estimateCurrentContextTokens(messages),
|
|
471
|
+
buildPreDigest: () => this._buildCompactionPreDigest(),
|
|
472
|
+
refreshAfterCompaction: () => this._refreshAfterCompaction(),
|
|
473
|
+
getFailureCorpus: () => this._failureCorpus,
|
|
474
|
+
measureLiveContextTokens: () => this._measureLiveContextTokensForCompaction(),
|
|
475
|
+
runAutoCompaction: (reason, willRetry) => this._runAutoCompaction(reason, willRetry),
|
|
476
|
+
compactWithRetry: (run, signal, provider) => this._compactWithRetry(run, signal, provider),
|
|
477
|
+
});
|
|
514
478
|
this._toolRecoveryLogger = new ToolRecoveryLogger({
|
|
515
479
|
enabled: toolRepairSettings.logging,
|
|
516
480
|
sessionId: this.sessionManager.getSessionId(),
|
|
517
481
|
eventLogPath: this._toolRecoveryEventLogPath,
|
|
518
482
|
failureCorpusPath,
|
|
519
483
|
});
|
|
520
|
-
this.
|
|
484
|
+
this._foregroundRecovery = new ForegroundRecoveryController({
|
|
521
485
|
agent: this.agent,
|
|
522
486
|
modelRegistry: this._modelRegistry,
|
|
523
|
-
|
|
524
|
-
|
|
487
|
+
settingsManager: this.settingsManager,
|
|
488
|
+
failureCorpus: this._failureCorpus,
|
|
489
|
+
getContextWindow: () => this.model?.contextWindow ?? 0,
|
|
525
490
|
emit: (event) => this._emit(event),
|
|
526
|
-
|
|
491
|
+
checkCompaction: (message) => this._checkCompaction(message),
|
|
492
|
+
onSuccessfulAssistant: () => this._compaction.resetOverflowRecovery(),
|
|
527
493
|
});
|
|
528
494
|
this._modelRouter = new ModelRouterController({
|
|
529
495
|
getAgent: () => this.agent,
|
|
@@ -531,8 +497,11 @@ export class AgentSession {
|
|
|
531
497
|
getSettingsManager: () => this.settingsManager,
|
|
532
498
|
getSessionManager: () => this.sessionManager,
|
|
533
499
|
getModelRegistry: () => this._modelRegistry,
|
|
534
|
-
isModelExhausted: (model) => this.
|
|
535
|
-
getFailoverStatus: () => ({
|
|
500
|
+
isModelExhausted: (model) => this._foregroundRecovery.isModelExhausted(`${model.provider}/${model.id}`),
|
|
501
|
+
getFailoverStatus: () => ({
|
|
502
|
+
...this._foregroundRecovery.getFailoverStatus(),
|
|
503
|
+
failureStats: this._failureCorpus.stats(),
|
|
504
|
+
}),
|
|
536
505
|
getAgentDir: () => this._agentDir,
|
|
537
506
|
getReflectionSignal: () => this._reflectionAbort.signal,
|
|
538
507
|
getBaseSystemPrompt: () => this._baseSystemPrompt,
|
|
@@ -545,7 +514,7 @@ export class AgentSession {
|
|
|
545
514
|
emitAutonomyTelemetry: (event) => this._emitAutonomyTelemetry(event),
|
|
546
515
|
resolveLaneModel: (pattern) => this._backgroundLanes.resolveLaneModel(pattern),
|
|
547
516
|
resolveCurationModelIfFit: () => this._resolveCurationModelIfFit(),
|
|
548
|
-
getToolProbeVerdict: (model) => this.
|
|
517
|
+
getToolProbeVerdict: (model) => this._toolProtocol.getToolProbeVerdict(model),
|
|
549
518
|
});
|
|
550
519
|
this._reflection = new ReflectionController({
|
|
551
520
|
getModel: () => this.model,
|
|
@@ -559,22 +528,27 @@ export class AgentSession {
|
|
|
559
528
|
isChildSession: () => this._isChildSession,
|
|
560
529
|
isDisposed: () => this._disposed,
|
|
561
530
|
getReflectionSignal: () => this._reflectionAbort.signal,
|
|
562
|
-
resolveTextToolCallProtocol: (model) => this.
|
|
531
|
+
resolveTextToolCallProtocol: (model) => this._resolveModelToolProtocol(model).protocol,
|
|
563
532
|
archivePromotedSkill: (name) => this.archivePromotedSkill(name),
|
|
564
533
|
emitAutonomyTelemetry: (event) => this._emitAutonomyTelemetry(event),
|
|
565
534
|
ensureModelReady: (model) => this._localRuntimeController.ensureIsolatedModelReady(model),
|
|
566
535
|
addSpawnedUsage: (usage, opts) => this.addSpawnedUsage(usage, opts),
|
|
567
536
|
saveLearningDecisionSnapshot: (decision) => this.saveLearningDecisionSnapshot(decision),
|
|
568
537
|
});
|
|
569
|
-
this._goalContinuation = new GoalLoopController({
|
|
570
|
-
getGoalRuntimeSnapshot: (settings) => this.getGoalRuntimeSnapshot(settings),
|
|
571
|
-
prompt: (text, options) => this.prompt(text, options),
|
|
572
|
-
recordGoalContinuationPass: (pass) => this.recordGoalContinuationPass(pass),
|
|
573
|
-
});
|
|
574
538
|
this._extensionRunnerRef = config.extensionRunnerRef;
|
|
575
|
-
this._initialActiveToolNames = config.
|
|
576
|
-
|
|
577
|
-
|
|
539
|
+
this._initialActiveToolNames = config.orchestrationProfile
|
|
540
|
+
? [...config.orchestrationProfile.toolNames]
|
|
541
|
+
: config.initialActiveToolNames;
|
|
542
|
+
this._allowedToolNames = config.orchestrationProfile
|
|
543
|
+
? new Set(config.orchestrationProfile.toolNames)
|
|
544
|
+
: config.allowedToolNames
|
|
545
|
+
? new Set(config.allowedToolNames)
|
|
546
|
+
: undefined;
|
|
547
|
+
this._excludedToolNames = config.orchestrationProfile
|
|
548
|
+
? undefined
|
|
549
|
+
: config.excludedToolNames
|
|
550
|
+
? new Set(config.excludedToolNames)
|
|
551
|
+
: undefined;
|
|
578
552
|
this._toolProfileFilter = config.toolProfileFilter
|
|
579
553
|
? { allow: config.toolProfileFilter.allow ?? [], block: config.toolProfileFilter.block ?? [] }
|
|
580
554
|
: undefined;
|
|
@@ -591,7 +565,7 @@ export class AgentSession {
|
|
|
591
565
|
getSessionManager: () => this.sessionManager,
|
|
592
566
|
getSettingsManager: () => this.settingsManager,
|
|
593
567
|
getModelRegistry: () => this._modelRegistry,
|
|
594
|
-
isModelExhausted: (model) => this.
|
|
568
|
+
isModelExhausted: (model) => this._foregroundRecovery.isModelExhausted(`${model.provider}/${model.id}`),
|
|
595
569
|
getResourceLoader: () => this._resourceLoader,
|
|
596
570
|
getExtensionRunner: () => this._extensionRunner,
|
|
597
571
|
setExtensionRunner: (runner) => {
|
|
@@ -615,10 +589,12 @@ export class AgentSession {
|
|
|
615
589
|
this._toolProfileFilter = filter;
|
|
616
590
|
},
|
|
617
591
|
getAllowedToolNames: () => this._allowedToolNames,
|
|
592
|
+
getOrchestrationProfile: () => config.orchestrationProfile,
|
|
618
593
|
getExcludedToolNames: () => this._excludedToolNames,
|
|
619
594
|
deriveToolProfileFilter: () => this._profileFilter.deriveToolProfileFilter(),
|
|
620
595
|
isToolOrCommandAllowedByProfile: (name) => this._profileFilter.isToolOrCommandAllowedByProfile(name),
|
|
621
|
-
|
|
596
|
+
isExtensionPathAllowed: (path, authority, baseDir) => this._profileFilter.isExtensionPathAllowed(path, authority, baseDir),
|
|
597
|
+
filterExtensionsForRuntime: (extensions, explicitLiveExtensionPaths) => this._profileFilter.filterExtensionsForRuntime(extensions, explicitLiveExtensionPaths),
|
|
622
598
|
setUnboundToolGrantWarnings: (warnings) => {
|
|
623
599
|
this._unboundToolGrantWarnings = warnings;
|
|
624
600
|
},
|
|
@@ -635,6 +611,7 @@ export class AgentSession {
|
|
|
635
611
|
reapplyActiveProfileModelSettings: () => this._profileFilter.reapplyActiveProfileModelSettings(),
|
|
636
612
|
notifyExtensionsChanged: () => this._notifyExtensionsChanged(),
|
|
637
613
|
getToolArtifactStore: () => this._getToolArtifactStore(),
|
|
614
|
+
getSessionImageStore: () => this._getSessionImageStore(),
|
|
638
615
|
getMemoryManager: () => this._memory.getMemoryManager(),
|
|
639
616
|
getMemoryAuditDiagnostics: () => this._memory.getMemoryAuditDiagnostics(),
|
|
640
617
|
clearPendingMemoryProviders: () => this._memory.clearPendingProviders(),
|
|
@@ -647,8 +624,9 @@ export class AgentSession {
|
|
|
647
624
|
saveTaskStepsStateSnapshot: (state) => this.saveTaskStepsStateSnapshot(state),
|
|
648
625
|
getContextGcReport: (messages) => this.getContextGcReport(messages),
|
|
649
626
|
startWorkerDelegation: (request) => this._backgroundLanes.startWorkerDelegation(request),
|
|
627
|
+
getOrchestrationProfileCatalog: () => this._backgroundLanes.getOrchestrationProfileCatalog(),
|
|
650
628
|
getWorkerLaneRecords: () => this._backgroundLanes.getLaneRecords(),
|
|
651
|
-
|
|
629
|
+
getWorkerClaimSnapshots: () => this.getWorkerClaimSnapshots(),
|
|
652
630
|
resolveManagedLaneId: (id) => this._backgroundLanes.resolveManagedLaneId(id),
|
|
653
631
|
runWorkerDelegationOnce: (request) => this.runWorkerDelegationOnce(request),
|
|
654
632
|
runModelFitness: (args) => this.runModelFitness(args),
|
|
@@ -680,7 +658,7 @@ export class AgentSession {
|
|
|
680
658
|
});
|
|
681
659
|
const previousToolArgumentValidation = this.agent.onToolArgumentValidation;
|
|
682
660
|
this.agent.onToolArgumentValidation = (event) => {
|
|
683
|
-
const taggedEvent = this.
|
|
661
|
+
const taggedEvent = this._toolProtocol.tagAdaptationRuleTeaching(event);
|
|
684
662
|
if (taggedEvent.outcome === "repaired" || taggedEvent.outcome === "bounced") {
|
|
685
663
|
this._toolSelection.recordValidation(taggedEvent.tool, taggedEvent.outcome);
|
|
686
664
|
}
|
|
@@ -689,8 +667,8 @@ export class AgentSession {
|
|
|
689
667
|
if (!logRecord)
|
|
690
668
|
return;
|
|
691
669
|
this._analytics.recordToolArgumentValidation(logRecord);
|
|
692
|
-
this.
|
|
693
|
-
this.
|
|
670
|
+
this._toolProtocol.handleValidationOutcome(taggedEvent);
|
|
671
|
+
this._toolProtocol.handleAdaptationTelemetry(taggedEvent);
|
|
694
672
|
};
|
|
695
673
|
this._treeNavigator = new SessionTreeNavigator({
|
|
696
674
|
getSessionManager: () => this.sessionManager,
|
|
@@ -887,7 +865,7 @@ export class AgentSession {
|
|
|
887
865
|
}
|
|
888
866
|
throw new Error(result.error);
|
|
889
867
|
}
|
|
890
|
-
if (result
|
|
868
|
+
if (this._modelRegistry.canUseResolvedRequestAuth(model, result)) {
|
|
891
869
|
return { apiKey: result.apiKey, headers: result.headers };
|
|
892
870
|
}
|
|
893
871
|
const isOAuth = this._modelRegistry.isUsingOAuth(model);
|
|
@@ -940,35 +918,9 @@ export class AgentSession {
|
|
|
940
918
|
const authoritativeMessages = this.agent.state.messages.length > 0 ? this.agent.state.messages : transformed;
|
|
941
919
|
let currentMessages = authoritativeMessages;
|
|
942
920
|
try {
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
const triggerTokens = this.model?.autoCompactionTriggerTokens;
|
|
947
|
-
const contextTokens = this._estimateCurrentContextTokens(authoritativeMessages);
|
|
948
|
-
if (shouldCompact(contextTokens, contextWindow, settings, triggerTokens)) {
|
|
949
|
-
// This pre-check runs BEFORE context-gc (below, same transform pass), so the
|
|
950
|
-
// raw estimate above can't see this turn's own GC packing. Since context-gc later
|
|
951
|
-
// packs the SAME messages before they're ever sent, a raw-over-threshold turn that
|
|
952
|
-
// GC alone would bring back under threshold doesn't actually need compaction.
|
|
953
|
-
// Project this turn's GC pass read-only (writePayloads=false -- no digest/curation
|
|
954
|
-
// enqueue, no disk write, no artifact-reference release; see
|
|
955
|
-
// ContextPipeline.applyContextGc) to get the same packed output the real pass would
|
|
956
|
-
// produce for these messages, then re-check against ITS estimate. Packing only ever
|
|
957
|
-
// shrinks (never grows) a message, so the projected estimate is never higher than
|
|
958
|
-
// the raw one: this can only SUPPRESS an unnecessary compaction, never skip a
|
|
959
|
-
// genuinely needed one -- the hard near-full trigger inside shouldCompact still
|
|
960
|
-
// fires whenever the projected estimate itself remains over threshold.
|
|
961
|
-
const gcProjection = this._applyContextGc(authoritativeMessages, false);
|
|
962
|
-
const projectedContextTokens = this._estimateCurrentContextTokens(gcProjection.messages);
|
|
963
|
-
if (shouldCompact(projectedContextTokens, contextWindow, settings, triggerTokens)) {
|
|
964
|
-
const latestBefore = getLatestCompactionEntry(this.sessionManager.getBranch())?.id;
|
|
965
|
-
await this._runAutoCompaction("threshold", false);
|
|
966
|
-
const latestAfter = getLatestCompactionEntry(this.sessionManager.getBranch())?.id;
|
|
967
|
-
if (latestAfter && latestAfter !== latestBefore) {
|
|
968
|
-
currentMessages = this.agent.state.messages.slice();
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
}
|
|
921
|
+
if (!this.isCompacting &&
|
|
922
|
+
(await this._compaction.maybeCompactBeforeContextTransform(authoritativeMessages, (messages) => this._applyContextGc(messages, false).messages))) {
|
|
923
|
+
currentMessages = this.agent.state.messages.slice();
|
|
972
924
|
}
|
|
973
925
|
}
|
|
974
926
|
catch {
|
|
@@ -993,7 +945,7 @@ export class AgentSession {
|
|
|
993
945
|
// character caps are the only budget protection for this block -- load-bearing,
|
|
994
946
|
// not merely defensive.
|
|
995
947
|
const gcMessages = this._maybeAppendMemoryEvidenceBlock(enforcementResult.messages, memoryReport);
|
|
996
|
-
return gcMessages;
|
|
948
|
+
return injectCompactGoalContext(gcMessages, this.getGoalStateSnapshot());
|
|
997
949
|
};
|
|
998
950
|
}
|
|
999
951
|
/**
|
|
@@ -1005,7 +957,8 @@ export class AgentSession {
|
|
|
1005
957
|
* The ceiling is turn-cumulative: the next foreground call's projection is folded together with
|
|
1006
958
|
* background/research/worker/reflection spend recorded SINCE THIS TURN BEGAN — {@link getSpawnedUsage}'s
|
|
1007
959
|
* already-recorded rollup (the same read-side-deduped total the footer's SUBAGENTS line uses) minus the
|
|
1008
|
-
* baseline snapshotted
|
|
960
|
+
* baseline snapshotted before a new turn enters routing in `_promptUnserialized`
|
|
961
|
+
* ({@link _costGuardTurnBaselineUsd}) — so a
|
|
1009
962
|
* turn that is cheap in the foreground but has spent heavily via background lanes THIS turn still trips
|
|
1010
963
|
* the warning, while a prior turn's background spend does not keep every later turn's guard stuck
|
|
1011
964
|
* "over". A background lane that finishes mid-turn is attributed to whichever turn it completes in.
|
|
@@ -1106,520 +1059,32 @@ export class AgentSession {
|
|
|
1106
1059
|
tools: this.agent.state.tools.slice(),
|
|
1107
1060
|
};
|
|
1108
1061
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
_toolRepairSettings() {
|
|
1113
|
-
return resolveCurrentToolRepairSettings(this.settingsManager.settings);
|
|
1114
|
-
}
|
|
1115
|
-
_applyToolRepairLayerSettings() {
|
|
1116
|
-
const settings = this._toolRepairSettings();
|
|
1117
|
-
this.agent.toolArgumentTeachEnabled = settings.teach;
|
|
1118
|
-
}
|
|
1119
|
-
_getModelAdaptationRulesForPrompt() {
|
|
1120
|
-
if (!this._toolRepairSettings().teach)
|
|
1121
|
-
return [];
|
|
1122
|
-
const modelKey = this._modelAdaptationKeyFor(this.agent.state.model);
|
|
1123
|
-
return modelKey ? this._modelAdaptationStore.get(modelKey).rules : [];
|
|
1124
|
-
}
|
|
1125
|
-
_textProtocolFlag(model) {
|
|
1126
|
-
// Phase 7 gating hierarchy: PI_TEXT_TOOL_CALL_PROTOCOL_DISABLED is resolved
|
|
1127
|
-
// in _toolRepairSettings() as the env kill switch, then settings.toolRepair.textProtocol
|
|
1128
|
-
// force-enables/disables globally, then Model.textToolCallProtocol opts in per model,
|
|
1129
|
-
// then a persisted /toolprobe text-protocol verdict opts in that exact model. The
|
|
1130
|
-
// calibration store is consulted after this flag; native provider tool calls still
|
|
1131
|
-
// win when emitted, and this only enables the text-protocol fallback lane.
|
|
1132
|
-
const override = this._toolRepairSettings().textProtocol;
|
|
1133
|
-
if (override !== undefined)
|
|
1134
|
-
return override;
|
|
1135
|
-
if (model?.textToolCallProtocol === true)
|
|
1136
|
-
return true;
|
|
1137
|
-
const modelKey = this._modelAdaptationKeyFor(model);
|
|
1138
|
-
return !!modelKey && this._modelAdaptationStore.get(modelKey).toolProbe?.status === "text-protocol";
|
|
1139
|
-
}
|
|
1140
|
-
async _streamForToolProbe(model, context, options) {
|
|
1141
|
-
let requestOptions = options;
|
|
1142
|
-
if (this._isRawStreamSimple(this.agent.streamFn)) {
|
|
1143
|
-
const auth = await this._getRequiredRequestAuth(model);
|
|
1144
|
-
requestOptions = {
|
|
1145
|
-
...options,
|
|
1146
|
-
apiKey: auth.apiKey,
|
|
1147
|
-
headers: auth.headers || options.headers ? { ...auth.headers, ...options.headers } : undefined,
|
|
1148
|
-
};
|
|
1149
|
-
}
|
|
1150
|
-
return this.agent.streamFn(model, context, requestOptions);
|
|
1151
|
-
}
|
|
1152
|
-
/** Builds a reportId that uniquely identifies one probe/calibration completion within the
|
|
1153
|
-
* session: the model, a caller-supplied `kind` (e.g. "read-task", "echo", or
|
|
1154
|
-
* "text-protocol:<variant>"), and a monotonic sequence number. The sequence number (not
|
|
1155
|
-
* wall-clock time or randomness) is what guarantees no collision even when the same model+kind
|
|
1156
|
-
* is probed again later in the session (e.g. a repeated /toolprobe run), so genuine repeat spend
|
|
1157
|
-
* is never silently deduped away. */
|
|
1158
|
-
_nextProbeUsageReportId(model, kind) {
|
|
1159
|
-
return `tool-probe:${this._modelRef(model)}:${kind}:${this._toolProbeUsageReportSeq++}`;
|
|
1160
|
-
}
|
|
1161
|
-
/** Awaits a tool-probe/text-protocol-calibration stream's result and, if the resolved message
|
|
1162
|
-
* carries reportable usage, rolls it into spawned usage under `reportId` so the turn-scoped cost
|
|
1163
|
-
* guard and daily usage see it. These trial completions previously spent tokens with no
|
|
1164
|
-
* addSpawnedUsage call, making them invisible to both. `addSpawnedUsage` dedups on `reportId`, so
|
|
1165
|
-
* a re-report of the same id is a no-op. */
|
|
1166
|
-
async _resolveProbeStreamCountingUsage(stream, label, reportId) {
|
|
1167
|
-
const message = await stream.result();
|
|
1168
|
-
const usage = message.usage;
|
|
1169
|
-
if (usage && (usage.cost.total > 0 || usage.totalTokens > 0)) {
|
|
1170
|
-
this.addSpawnedUsage(usage, { label, reportId });
|
|
1171
|
-
}
|
|
1172
|
-
return message;
|
|
1173
|
-
}
|
|
1174
|
-
_textProtocolCalibrationContext(variant, token) {
|
|
1175
|
-
const primer = generateTextToolProtocolPrimer([TEXT_TOOL_PROTOCOL_ECHO_TOOL], { variant });
|
|
1176
|
-
const instruction = `Text tool protocol calibration trial. Using the protocol above, call echo with data exactly "${token}". Output only the tool-call envelope.`;
|
|
1177
|
-
return {
|
|
1178
|
-
systemPrompt: `${primer}\n\n${instruction}`,
|
|
1179
|
-
messages: [{ role: "user", content: [{ type: "text", text: instruction }], timestamp: Date.now() }],
|
|
1180
|
-
};
|
|
1181
|
-
}
|
|
1182
|
-
_messageHasToolCallWithStringArgument(message, toolName, argName, argValue) {
|
|
1183
|
-
return message.content.some((block) => {
|
|
1184
|
-
if (block.type !== "toolCall" || block.name !== toolName)
|
|
1185
|
-
return false;
|
|
1186
|
-
const args = block.arguments;
|
|
1187
|
-
return (typeof args === "object" &&
|
|
1188
|
-
args !== null &&
|
|
1189
|
-
!Array.isArray(args) &&
|
|
1190
|
-
args[argName] === argValue);
|
|
1191
|
-
});
|
|
1192
|
-
}
|
|
1193
|
-
_nativeToolProbeSystemPrompt(instruction) {
|
|
1194
|
-
const base = (this.agent.state.systemPrompt ?? "").trim();
|
|
1195
|
-
return base ? `${base}\n\n${instruction}` : instruction;
|
|
1196
|
-
}
|
|
1197
|
-
async _runNativeReadTaskProbeTrial(model, path) {
|
|
1198
|
-
const instruction = `Native tool-call capability probe: task-scale read. Use provider-native tool calling, not prose. ` +
|
|
1199
|
-
`Call read exactly once with path exactly "${path}".`;
|
|
1200
|
-
const stream = await this._streamForToolProbe(model, {
|
|
1201
|
-
systemPrompt: this._nativeToolProbeSystemPrompt(instruction),
|
|
1202
|
-
messages: [{ role: "user", content: [{ type: "text", text: instruction }], timestamp: Date.now() }],
|
|
1203
|
-
tools: [NATIVE_TOOL_PROBE_READ_TOOL],
|
|
1204
|
-
}, { textToolCallProtocol: false, maxRetries: 0, temperature: 0, maxTokens: 768 });
|
|
1205
|
-
const message = await this._resolveProbeStreamCountingUsage(stream, "tool-probe", this._nextProbeUsageReportId(model, "read-task"));
|
|
1206
|
-
return this._messageHasToolCallWithStringArgument(message, "read", "path", path);
|
|
1207
|
-
}
|
|
1208
|
-
async _runNativeEchoToolProbeTrial(model, token) {
|
|
1209
|
-
const instruction = `Native tool-call capability probe: echo-only. Use provider-native tool calling, not prose. ` +
|
|
1210
|
-
`Call echo with data exactly "${token}".`;
|
|
1211
|
-
const stream = await this._streamForToolProbe(model, {
|
|
1212
|
-
systemPrompt: this._nativeToolProbeSystemPrompt(instruction),
|
|
1213
|
-
messages: [{ role: "user", content: [{ type: "text", text: instruction }], timestamp: Date.now() }],
|
|
1214
|
-
tools: [TEXT_TOOL_PROTOCOL_ECHO_TOOL],
|
|
1215
|
-
}, { textToolCallProtocol: false, maxRetries: 0, temperature: 0, maxTokens: 256 });
|
|
1216
|
-
const message = await this._resolveProbeStreamCountingUsage(stream, "tool-probe", this._nextProbeUsageReportId(model, "echo"));
|
|
1217
|
-
return this._messageHasToolCallWithStringArgument(message, "echo", "data", token);
|
|
1218
|
-
}
|
|
1219
|
-
async _gradeNativeToolCallingForModel(model, token) {
|
|
1220
|
-
const path = join(getProcessWorkRun(this._agentDir, "probes", "native-tools").path, `pi-native-probe-${process.pid}-${Date.now()}.txt`);
|
|
1221
|
-
writeFileSync(path, token, "utf-8");
|
|
1222
|
-
try {
|
|
1223
|
-
const taskPassed = await this._runNativeReadTaskProbeTrial(model, path);
|
|
1224
|
-
if (taskPassed)
|
|
1225
|
-
return "task";
|
|
1226
|
-
const echoPassed = await this._runNativeEchoToolProbeTrial(model, token);
|
|
1227
|
-
if (echoPassed)
|
|
1228
|
-
return "echo-only";
|
|
1229
|
-
return "absent";
|
|
1230
|
-
}
|
|
1231
|
-
finally {
|
|
1232
|
-
rmSync(path, { force: true });
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
async _runTextProtocolTrial(model, variant, token) {
|
|
1236
|
-
const stream = await this._streamForToolProbe(model, this._textProtocolCalibrationContext(variant, token), {
|
|
1237
|
-
textToolCallProtocol: false,
|
|
1238
|
-
maxRetries: 0,
|
|
1239
|
-
temperature: 0,
|
|
1240
|
-
maxTokens: 256,
|
|
1241
|
-
});
|
|
1242
|
-
const message = await this._resolveProbeStreamCountingUsage(stream, "text-protocol-calibration", this._nextProbeUsageReportId(model, `text-protocol:${variant}`));
|
|
1243
|
-
const text = message.content
|
|
1244
|
-
.filter((block) => block.type === "text")
|
|
1245
|
-
.map((block) => block.text)
|
|
1246
|
-
.join("\n")
|
|
1247
|
-
.trim();
|
|
1248
|
-
if (!text)
|
|
1249
|
-
return false;
|
|
1250
|
-
const parsed = parseTextToolCalls(text, [TEXT_TOOL_PROTOCOL_ECHO_TOOL]);
|
|
1251
|
-
return parsed.calls.some((call) => call.name === "echo" && call.arguments.data === token);
|
|
1252
|
-
}
|
|
1253
|
-
async _calibrateTextToolProtocolForModel(model, modelKey, options) {
|
|
1254
|
-
const variantsTried = [];
|
|
1255
|
-
for (const variant of TEXT_TOOL_PROTOCOL_VARIANTS) {
|
|
1256
|
-
variantsTried.push(variant);
|
|
1257
|
-
let passed = true;
|
|
1258
|
-
for (let trial = 0; trial < TEXT_TOOL_PROTOCOL_TRIALS_PER_VARIANT; trial++) {
|
|
1259
|
-
const ok = await this._runTextProtocolTrial(model, variant, `pi-calibration-${trial + 1}`);
|
|
1260
|
-
if (!ok) {
|
|
1261
|
-
passed = false;
|
|
1262
|
-
break;
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
if (passed) {
|
|
1266
|
-
const calibratedAt = new Date().toISOString();
|
|
1267
|
-
if (modelKey) {
|
|
1268
|
-
this._modelAdaptationStore.setProtocol(modelKey, { version: TEXT_TOOL_PROTOCOL_VERSION, status: "calibrated", variant, calibratedAt }, calibratedAt);
|
|
1269
|
-
}
|
|
1270
|
-
return { status: "calibrated", variant, calibratedAt };
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
const attemptedAt = new Date().toISOString();
|
|
1274
|
-
if (modelKey && options.persistFailure) {
|
|
1275
|
-
this._modelAdaptationStore.setProtocol(modelKey, { version: TEXT_TOOL_PROTOCOL_VERSION, status: "failed", attemptedAt, variantsTried }, attemptedAt);
|
|
1276
|
-
}
|
|
1277
|
-
return { status: "failed", attemptedAt, variantsTried };
|
|
1278
|
-
}
|
|
1279
|
-
/**
|
|
1280
|
-
* A PURE READER of the persisted calibration — never calibrates inline and
|
|
1281
|
-
* never throws out of the prompt path. A model whose flag is on but has no valid current-version
|
|
1282
|
-
* protocol on record falls back to native for this turn (with a warning pointing at /toolprobe)
|
|
1283
|
-
* instead of blocking the user's message behind up to 8 inline calibration completions or
|
|
1284
|
-
* aborting the turn entirely. Calibration now only ever happens off the hot path: explicit
|
|
1285
|
-
* /toolprobe, or the capability-gate spine's evidence-gated auto-probe.
|
|
1286
|
-
*/
|
|
1287
|
-
async _ensureTextToolProtocolForActiveModel() {
|
|
1288
|
-
const model = this.agent.state.model;
|
|
1289
|
-
if (!this._textProtocolFlag(model)) {
|
|
1290
|
-
this.agent.textToolCallProtocol = undefined;
|
|
1291
|
-
return;
|
|
1292
|
-
}
|
|
1293
|
-
// Force-enable (a global settings override or Model.textToolCallProtocol) wins regardless of
|
|
1294
|
-
// whether this model has ever been graded-probed — that is the point of an explicit override.
|
|
1295
|
-
// Preserve it exactly as before: default to the tool-tag variant, no inline calibration. Only
|
|
1296
|
-
// the graded-evidence path below (flag on solely because of a persisted toolProbe verdict)
|
|
1297
|
-
// needs a valid persisted protocol to proceed.
|
|
1298
|
-
const forceEnabled = this._toolRepairSettings().textProtocol === true || model?.textToolCallProtocol === true;
|
|
1299
|
-
const modelKey = this._modelAdaptationKeyFor(model);
|
|
1300
|
-
if (!modelKey || forceEnabled) {
|
|
1301
|
-
this.agent.textToolCallProtocol = true;
|
|
1302
|
-
return;
|
|
1303
|
-
}
|
|
1304
|
-
const profile = this._modelAdaptationStore.get(modelKey);
|
|
1305
|
-
if (profile.protocol?.version === TEXT_TOOL_PROTOCOL_VERSION && profile.protocol.status !== "failed") {
|
|
1306
|
-
this.agent.textToolCallProtocol = { variant: profile.protocol.variant };
|
|
1307
|
-
return;
|
|
1308
|
-
}
|
|
1309
|
-
this.agent.textToolCallProtocol = undefined;
|
|
1310
|
-
this._emit({
|
|
1311
|
-
type: "warning",
|
|
1312
|
-
message: profile.protocol?.status === "failed"
|
|
1313
|
-
? `Text tool protocol calibration for ${modelKey} previously failed (variants tried: ${profile.protocol.variantsTried.join(", ")}); falling back to native tool calls this turn. Run /toolprobe ${modelKey} to recalibrate.`
|
|
1314
|
-
: `Text tool protocol for ${modelKey} has no valid calibration on record; falling back to native tool calls this turn. Run /toolprobe ${modelKey} to calibrate.`,
|
|
1315
|
-
});
|
|
1316
|
-
}
|
|
1317
|
-
_modelRef(model) {
|
|
1318
|
-
return `${model.provider}/${model.id}`;
|
|
1319
|
-
}
|
|
1320
|
-
/** The persisted `/toolprobe` verdict on record for this model, if any (undefined = unprobed). */
|
|
1321
|
-
_toolProbeVerdict(model) {
|
|
1322
|
-
return this._modelAdaptationStore.get(this._modelRef(model)).toolProbe?.status;
|
|
1323
|
-
}
|
|
1324
|
-
_formatToolProbeReport(results) {
|
|
1325
|
-
const lines = [
|
|
1326
|
-
"Tool probe results:",
|
|
1327
|
-
"Model | Verdict | Variant | Native grade | Diagnostic",
|
|
1328
|
-
"--- | --- | --- | --- | ---",
|
|
1329
|
-
];
|
|
1330
|
-
for (const result of results) {
|
|
1331
|
-
lines.push([
|
|
1332
|
-
result.model,
|
|
1333
|
-
result.verdict,
|
|
1334
|
-
result.variant ?? "-",
|
|
1335
|
-
result.nativeGrade ?? "-",
|
|
1336
|
-
result.diagnostic ? result.diagnostic.replace(/\s+/g, " ").slice(0, 160) : "-",
|
|
1337
|
-
].join(" | "));
|
|
1338
|
-
}
|
|
1339
|
-
return lines.join("\n");
|
|
1340
|
-
}
|
|
1341
|
-
_storeToolProbe(modelKey, probe) {
|
|
1342
|
-
this._modelAdaptationStore.setToolProbe(modelKey, probe, probe.probedAt);
|
|
1062
|
+
/** Compatibility seam retained for focused auto-probe regressions. */
|
|
1063
|
+
_probeToolCallingForModel(model) {
|
|
1064
|
+
return this._toolProtocol.probeToolCallingForModel(model);
|
|
1343
1065
|
}
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
let nativeGrade = "absent";
|
|
1348
|
-
let diagnostic;
|
|
1349
|
-
try {
|
|
1350
|
-
nativeGrade = await this._gradeNativeToolCallingForModel(model, "pi-native-probe");
|
|
1351
|
-
if (nativeGrade === "task") {
|
|
1352
|
-
this._storeToolProbe(modelKey, {
|
|
1353
|
-
version: TEXT_TOOL_PROTOCOL_VERSION,
|
|
1354
|
-
status: "native",
|
|
1355
|
-
probedAt,
|
|
1356
|
-
nativeGrade,
|
|
1357
|
-
});
|
|
1358
|
-
return { model: modelKey, verdict: "native", nativeGrade };
|
|
1359
|
-
}
|
|
1360
|
-
diagnostic =
|
|
1361
|
-
nativeGrade === "echo-only"
|
|
1362
|
-
? "Native echo probe passed but task-scale read probe failed."
|
|
1363
|
-
: "Native task-scale read and echo probes did not produce provider-native tool calls.";
|
|
1364
|
-
}
|
|
1365
|
-
catch (error) {
|
|
1366
|
-
diagnostic = error instanceof Error ? error.message : String(error);
|
|
1367
|
-
}
|
|
1368
|
-
try {
|
|
1369
|
-
const calibrated = await this._calibrateTextToolProtocolForModel(model, modelKey, { persistFailure: false });
|
|
1370
|
-
if (calibrated.status === "calibrated") {
|
|
1371
|
-
this._storeToolProbe(modelKey, {
|
|
1372
|
-
version: TEXT_TOOL_PROTOCOL_VERSION,
|
|
1373
|
-
status: "text-protocol",
|
|
1374
|
-
probedAt: calibrated.calibratedAt,
|
|
1375
|
-
variant: calibrated.variant,
|
|
1376
|
-
nativeGrade,
|
|
1377
|
-
diagnostic,
|
|
1378
|
-
});
|
|
1379
|
-
return { model: modelKey, verdict: "text-protocol", variant: calibrated.variant, nativeGrade, diagnostic };
|
|
1380
|
-
}
|
|
1381
|
-
diagnostic = `${diagnostic ? `${diagnostic} ` : ""}Text protocol variants failed: ${calibrated.variantsTried.join(", ")}`;
|
|
1382
|
-
}
|
|
1383
|
-
catch (error) {
|
|
1384
|
-
diagnostic = error instanceof Error ? error.message : String(error);
|
|
1385
|
-
}
|
|
1386
|
-
this._storeToolProbe(modelKey, {
|
|
1387
|
-
version: TEXT_TOOL_PROTOCOL_VERSION,
|
|
1388
|
-
status: "none",
|
|
1389
|
-
probedAt,
|
|
1390
|
-
nativeGrade,
|
|
1391
|
-
diagnostic,
|
|
1392
|
-
});
|
|
1393
|
-
return { model: modelKey, verdict: "none", nativeGrade, diagnostic };
|
|
1394
|
-
}
|
|
1395
|
-
async _resolveToolProbeModels(target) {
|
|
1396
|
-
const trimmed = target?.trim();
|
|
1397
|
-
if (!trimmed)
|
|
1398
|
-
return this._modelRegistry.getAvailable();
|
|
1399
|
-
const [provider, ...modelParts] = trimmed.split("/");
|
|
1400
|
-
const modelId = modelParts.join("/");
|
|
1401
|
-
if (!provider || !modelId)
|
|
1402
|
-
throw new Error("Usage: /toolprobe [provider/model]");
|
|
1403
|
-
const exact = this._modelRegistry.find(provider, modelId);
|
|
1404
|
-
if (exact)
|
|
1405
|
-
return [exact];
|
|
1406
|
-
const current = this.agent.state.model;
|
|
1407
|
-
if (current?.provider === provider && current.id === modelId)
|
|
1408
|
-
return [current];
|
|
1409
|
-
throw new Error(`Model not found: ${trimmed}`);
|
|
1066
|
+
/** Compatibility seam retained for focused protocol-selection doctrine regressions. */
|
|
1067
|
+
_resolveModelToolProtocol(model) {
|
|
1068
|
+
return this._toolProtocol.resolveModelToolProtocol(model);
|
|
1410
1069
|
}
|
|
1411
1070
|
async probeToolCalling(target) {
|
|
1412
|
-
|
|
1413
|
-
if (models.length === 0)
|
|
1414
|
-
throw new Error("No available models to probe.");
|
|
1415
|
-
const results = [];
|
|
1416
|
-
for (const model of models) {
|
|
1417
|
-
results.push(await this._probeToolCallingForModel(model));
|
|
1418
|
-
}
|
|
1419
|
-
return { results, table: this._formatToolProbeReport(results) };
|
|
1420
|
-
}
|
|
1421
|
-
/**
|
|
1422
|
-
* The text-protocol circuit breaker. Every parse failure (from either the
|
|
1423
|
-
* live per-completion {@link Agent.onTextToolProtocolParse} callback or the post-hoc detection in
|
|
1424
|
-
* {@link _recordTextToolProtocolParseOutcomeFromLastAssistant}) gets a throttled one-line
|
|
1425
|
-
* corrective steer for the next turn. On the 3rd consecutive SAME-SIGNATURE failure — graded
|
|
1426
|
-
* evidence a model genuinely cannot speak this dialect, not a single bad turn — the breaker also
|
|
1427
|
-
* demotes the persisted tool-probe verdict to "none" so {@link _textProtocolFlag} reads false next
|
|
1428
|
-
* turn and native is attempted instead of thrashing on a protocol this model has proven it can't
|
|
1429
|
-
* follow.
|
|
1430
|
-
*/
|
|
1431
|
-
_handleTextToolProtocolParse(event) {
|
|
1432
|
-
this._textProtocolParseObservedThisTurn = true;
|
|
1433
|
-
const modelKey = `${event.provider}/${event.model}`;
|
|
1434
|
-
if (event.status === "parsed")
|
|
1435
|
-
return;
|
|
1436
|
-
this._maybeInjectTextProtocolCorrectiveSteer(event.variant);
|
|
1437
|
-
const signature = `${event.variant}:${event.reason ?? "failed"}`;
|
|
1438
|
-
const previous = this._textProtocolParseFailures.get(modelKey);
|
|
1439
|
-
const repeats = previous?.signature === signature ? previous.repeats + 1 : 1;
|
|
1440
|
-
this._textProtocolParseFailures.set(modelKey, { signature, repeats });
|
|
1441
|
-
if (repeats < TEXT_TOOL_PROTOCOL_PARSE_FAILURE_THRESHOLD)
|
|
1442
|
-
return;
|
|
1443
|
-
const profile = this._modelAdaptationStore.get(modelKey);
|
|
1444
|
-
if (profile.protocol?.version === TEXT_TOOL_PROTOCOL_VERSION && profile.protocol.status !== "failed") {
|
|
1445
|
-
this._modelAdaptationStore.removeProtocol(modelKey);
|
|
1446
|
-
this.agent.textToolCallProtocol = undefined;
|
|
1447
|
-
}
|
|
1448
|
-
this._textProtocolParseFailures.delete(modelKey);
|
|
1449
|
-
// Demote on graded evidence -- TEXT_TOOL_PROTOCOL_PARSE_FAILURE_THRESHOLD identical-signature
|
|
1450
|
-
// parse failures in a row -- rather than thrashing every turn. The fresh probedAt doubles as
|
|
1451
|
-
// the capability-gate spine's auto-probe freshness gate, so this demotion doesn't immediately
|
|
1452
|
-
// trigger a re-probe/re-phone loop.
|
|
1453
|
-
const probedAt = new Date().toISOString();
|
|
1454
|
-
this._modelAdaptationStore.setToolProbe(modelKey, {
|
|
1455
|
-
version: TEXT_TOOL_PROTOCOL_VERSION,
|
|
1456
|
-
status: "none",
|
|
1457
|
-
probedAt,
|
|
1458
|
-
nativeGrade: profile.toolProbe?.nativeGrade,
|
|
1459
|
-
diagnostic: `Text protocol parsing failed ${TEXT_TOOL_PROTOCOL_PARSE_FAILURE_THRESHOLD}x in a row with signature "${signature}".`,
|
|
1460
|
-
}, probedAt);
|
|
1461
|
-
this._emit({
|
|
1462
|
-
type: "warning",
|
|
1463
|
-
message: `Text tool protocol for ${modelKey} stopped parsing after ${TEXT_TOOL_PROTOCOL_PARSE_FAILURE_THRESHOLD} attempts; demoted to native fallback. Run /toolprobe ${modelKey} to recalibrate.`,
|
|
1464
|
-
});
|
|
1465
|
-
}
|
|
1466
|
-
/**
|
|
1467
|
-
* A phone model whose envelope fails to parse gets no corrective guidance today —
|
|
1468
|
-
* the runaway-loop backstop only trips on repeated PARSED tool-call signatures (agent-loop.ts), so
|
|
1469
|
-
* an every-turn unparseable-prose model never trips it. Inject a one-line reminder of the envelope
|
|
1470
|
-
* shape as a nextTurn message, reusing {@link formatVariantEnvelope} so the reminder can never
|
|
1471
|
-
* drift from the grammar the primer actually teaches. Throttled to the first failure this session
|
|
1472
|
-
* and then every {@link TEXT_TOOL_PROTOCOL_STEER_INTERVAL}th after — the breaker above is what
|
|
1473
|
-
* actually demotes a genuinely-failing model at the 3rd same-signature failure; this is guidance,
|
|
1474
|
-
* not a second counter.
|
|
1475
|
-
*/
|
|
1476
|
-
_maybeInjectTextProtocolCorrectiveSteer(variant) {
|
|
1477
|
-
this._textProtocolCorrectiveSteerCount++;
|
|
1478
|
-
if (this._textProtocolCorrectiveSteerCount !== 1 &&
|
|
1479
|
-
this._textProtocolCorrectiveSteerCount % TEXT_TOOL_PROTOCOL_STEER_INTERVAL !== 0) {
|
|
1480
|
-
return;
|
|
1481
|
-
}
|
|
1482
|
-
const reminder = `Reminder: to call a tool, emit exactly this envelope shape: ${formatVariantEnvelope(variant, "TOOL", '{"arg":"value"}')} — no other format is recognized. Reasoning may appear as prose before the envelope, never inside it.`;
|
|
1483
|
-
this.sendCustomMessage({ customType: "text-protocol-corrective-steer", content: reminder, display: false }, { deliverAs: "nextTurn" }).catch(() => {
|
|
1484
|
-
// Best-effort steer; a failure to queue it must not break parse-failure handling.
|
|
1485
|
-
});
|
|
1486
|
-
}
|
|
1487
|
-
_handleTextToolProtocolValidationOutcome(event) {
|
|
1488
|
-
if (event.source !== "text-protocol")
|
|
1489
|
-
return;
|
|
1490
|
-
const protocol = this.agent.textToolCallProtocol;
|
|
1491
|
-
const variant = protocol === true ? "tool-tag" : protocol ? protocol.variant : undefined;
|
|
1492
|
-
if (!variant)
|
|
1493
|
-
return;
|
|
1494
|
-
const status = event.outcome === "bounced" ? "failed" : "parsed";
|
|
1495
|
-
if (this._textProtocolValidationOutcomeThisTurn?.status === "parsed" && status === "failed")
|
|
1496
|
-
return;
|
|
1497
|
-
this._textProtocolValidationOutcomeThisTurn = {
|
|
1498
|
-
provider: event.provider ?? this.agent.state.model.provider,
|
|
1499
|
-
model: event.model ?? this.agent.state.model.id,
|
|
1500
|
-
variant,
|
|
1501
|
-
status,
|
|
1502
|
-
callCount: 1,
|
|
1503
|
-
textLength: 0,
|
|
1504
|
-
...(status === "failed" && {
|
|
1505
|
-
reason: event.errorKeywords?.includes("unknown_tool") ? "unknown-tool" : "validation-failed",
|
|
1506
|
-
}),
|
|
1507
|
-
};
|
|
1508
|
-
}
|
|
1509
|
-
_recordTextToolProtocolParseOutcomeFromLastAssistant() {
|
|
1510
|
-
const validationOutcome = this._textProtocolValidationOutcomeThisTurn;
|
|
1511
|
-
this._textProtocolValidationOutcomeThisTurn = undefined;
|
|
1512
|
-
if (validationOutcome?.status === "parsed") {
|
|
1513
|
-
this._textProtocolParseObservedThisTurn = true;
|
|
1514
|
-
this._textProtocolParseFailures.delete(`${validationOutcome.provider}/${validationOutcome.model}`);
|
|
1515
|
-
return;
|
|
1516
|
-
}
|
|
1517
|
-
if (validationOutcome) {
|
|
1518
|
-
this._handleTextToolProtocolParse(validationOutcome);
|
|
1519
|
-
return;
|
|
1520
|
-
}
|
|
1521
|
-
if (this._textProtocolParseObservedThisTurn)
|
|
1522
|
-
return;
|
|
1523
|
-
const protocol = this.agent.textToolCallProtocol;
|
|
1524
|
-
if (protocol === false || protocol === true || !protocol?.variant)
|
|
1525
|
-
return;
|
|
1526
|
-
const response = this._findLastAssistantMessage();
|
|
1527
|
-
if (!response)
|
|
1528
|
-
return;
|
|
1529
|
-
const responseText = response.content
|
|
1530
|
-
.filter((content) => content.type === "text")
|
|
1531
|
-
.map((content) => content.text)
|
|
1532
|
-
.join("\n");
|
|
1533
|
-
if (!responseText)
|
|
1534
|
-
return;
|
|
1535
|
-
const parsed = parseTextToolCalls(responseText, this.agent.state.tools);
|
|
1536
|
-
const attempted = parsed.attempted || this._looksLikeTextToolProtocolAttempt(responseText);
|
|
1537
|
-
if (!attempted)
|
|
1538
|
-
return;
|
|
1539
|
-
this._handleTextToolProtocolParse({
|
|
1540
|
-
provider: this.agent.state.model.provider,
|
|
1541
|
-
model: this.agent.state.model.id,
|
|
1542
|
-
variant: protocol.variant,
|
|
1543
|
-
status: parsed.calls.length > 0 ? "parsed" : "failed",
|
|
1544
|
-
reason: parsed.failure,
|
|
1545
|
-
callCount: parsed.calls.length,
|
|
1546
|
-
textLength: responseText.length,
|
|
1547
|
-
});
|
|
1548
|
-
}
|
|
1549
|
-
_looksLikeTextToolProtocolAttempt(text) {
|
|
1550
|
-
return /<pi:call\b|<tool_call\b|```(?:tool|tool_call)[\s\S]*"name"\s*:/i.test(text);
|
|
1551
|
-
}
|
|
1552
|
-
_tagModelAdaptationRuleTeaching(event) {
|
|
1553
|
-
if (!this._toolRepairSettings().teach || event.taught !== "none")
|
|
1554
|
-
return event;
|
|
1555
|
-
const modelKey = event.provider && event.model
|
|
1556
|
-
? `${event.provider}/${event.model}`
|
|
1557
|
-
: this._modelAdaptationKeyFor(this.agent.state.model);
|
|
1558
|
-
if (!modelKey)
|
|
1559
|
-
return event;
|
|
1560
|
-
try {
|
|
1561
|
-
const rules = this._modelAdaptationStore.get(modelKey).rules;
|
|
1562
|
-
const modes = new Set([...event.failureModes, ...event.repairsApplied]);
|
|
1563
|
-
if (rules.some((rule) => modes.has(rule.mode))) {
|
|
1564
|
-
return { ...event, taught: "rule" };
|
|
1565
|
-
}
|
|
1566
|
-
}
|
|
1567
|
-
catch {
|
|
1568
|
-
// Adaptation telemetry tagging is best-effort; leave the original event unchanged.
|
|
1569
|
-
}
|
|
1570
|
-
return event;
|
|
1571
|
-
}
|
|
1572
|
-
_repairSessionCount(modelKey, mode) {
|
|
1573
|
-
const key = `${modelKey}\0${mode}`;
|
|
1574
|
-
const count = (this._repairModeSessionCounts.get(key) ?? 0) + 1;
|
|
1575
|
-
this._repairModeSessionCounts.set(key, count);
|
|
1576
|
-
return count;
|
|
1577
|
-
}
|
|
1578
|
-
_handleModelAdaptationTelemetry(event) {
|
|
1579
|
-
if (!this._toolRepairSettings().teach || event.outcome !== "repaired" || event.repairsApplied.length === 0)
|
|
1580
|
-
return;
|
|
1581
|
-
const modelKey = event.provider && event.model
|
|
1582
|
-
? `${event.provider}/${event.model}`
|
|
1583
|
-
: this._modelAdaptationKeyFor(this.agent.state.model);
|
|
1584
|
-
if (!modelKey)
|
|
1585
|
-
return;
|
|
1586
|
-
try {
|
|
1587
|
-
for (const mode of [...new Set(event.repairsApplied)]) {
|
|
1588
|
-
const profile = this._modelAdaptationStore.get(modelKey);
|
|
1589
|
-
const stats = profile.teachStats[mode] ?? { taught: 0, recurrenceBefore: 0, recurrenceAfter: 0 };
|
|
1590
|
-
if (profile.rules.some((rule) => rule.mode === mode)) {
|
|
1591
|
-
this._modelAdaptationStore.markRuleFired(modelKey, mode);
|
|
1592
|
-
this._modelAdaptationStore.setTeachStats(modelKey, mode, {
|
|
1593
|
-
...stats,
|
|
1594
|
-
recurrenceAfter: stats.recurrenceAfter + 1,
|
|
1595
|
-
});
|
|
1596
|
-
continue;
|
|
1597
|
-
}
|
|
1598
|
-
const recurrenceBefore = stats.recurrenceBefore + 1;
|
|
1599
|
-
this._modelAdaptationStore.setTeachStats(modelKey, mode, { ...stats, recurrenceBefore });
|
|
1600
|
-
const sessionCount = this._repairSessionCount(modelKey, mode);
|
|
1601
|
-
if (sessionCount >= MODEL_ADAPTATION_REPAIR_THRESHOLD ||
|
|
1602
|
-
recurrenceBefore >= MODEL_ADAPTATION_REPAIR_THRESHOLD) {
|
|
1603
|
-
this._modelAdaptationStore.addRule(modelKey, {
|
|
1604
|
-
mode,
|
|
1605
|
-
text: formatToolRepairStandingRule(mode),
|
|
1606
|
-
});
|
|
1607
|
-
this._modelAdaptationStore.setTeachStats(modelKey, mode, {
|
|
1608
|
-
...stats,
|
|
1609
|
-
taught: stats.taught + 1,
|
|
1610
|
-
recurrenceBefore,
|
|
1611
|
-
});
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1614
|
-
}
|
|
1615
|
-
catch {
|
|
1616
|
-
// Model adaptation is best-effort; failed telemetry persistence must not affect the turn.
|
|
1617
|
-
}
|
|
1071
|
+
return this._toolProtocol.probeToolCalling(target);
|
|
1618
1072
|
}
|
|
1619
1073
|
/** Tool-build call-site delegation to {@link ContextPipeline.getToolArtifactStore}. */
|
|
1620
1074
|
_getToolArtifactStore() {
|
|
1621
1075
|
return this._pipeline.getToolArtifactStore();
|
|
1622
1076
|
}
|
|
1077
|
+
_getSessionImageStore() {
|
|
1078
|
+
const directory = this.settingsManager.getClipboardImageDirectory();
|
|
1079
|
+
if (!this.sessionManager.isPersisted() && !directory)
|
|
1080
|
+
return undefined;
|
|
1081
|
+
return new SessionImageStore({
|
|
1082
|
+
agentDir: this._agentDir,
|
|
1083
|
+
cwd: this._cwd,
|
|
1084
|
+
sessionId: this.sessionId,
|
|
1085
|
+
directory,
|
|
1086
|
+
});
|
|
1087
|
+
}
|
|
1623
1088
|
/**
|
|
1624
1089
|
* Context-transform hot-path delegation to {@link ContextPipeline.runContextAudit}. Kept as a
|
|
1625
1090
|
* one-line method (not inlined) so the transform stays the single owner of the pass ordering.
|
|
@@ -1767,7 +1232,7 @@ export class AgentSession {
|
|
|
1767
1232
|
}
|
|
1768
1233
|
formatToolRepairHealthReport() {
|
|
1769
1234
|
return [
|
|
1770
|
-
|
|
1235
|
+
this._toolProtocol.formatRepairHealth(this._toolRecoveryLogger.getStats()),
|
|
1771
1236
|
formatToolSelectionReport(this._toolSelection.getReport()),
|
|
1772
1237
|
].join("\n\n");
|
|
1773
1238
|
}
|
|
@@ -1775,12 +1240,10 @@ export class AgentSession {
|
|
|
1775
1240
|
await this._toolRecoveryLogger.flush(timeoutMs);
|
|
1776
1241
|
}
|
|
1777
1242
|
removeToolRepairRule(model, mode) {
|
|
1778
|
-
return this.
|
|
1243
|
+
return this._toolProtocol.removeRepairRule(model, mode);
|
|
1779
1244
|
}
|
|
1780
1245
|
resetToolProtocolCalibration(model) {
|
|
1781
|
-
|
|
1782
|
-
this._textProtocolParseFailures.delete(model);
|
|
1783
|
-
return removed;
|
|
1246
|
+
return this._toolProtocol.resetProtocolCalibration(model);
|
|
1784
1247
|
}
|
|
1785
1248
|
/** Curation status for diagnostics/dashboard: settings, live telemetry, last refusal reason. */
|
|
1786
1249
|
/** Curation status for diagnostics/dashboard (delegates to {@link ContextPipeline.getContextCurationStatus}). */
|
|
@@ -1825,14 +1288,6 @@ export class AgentSession {
|
|
|
1825
1288
|
getContextGcReport(messages) {
|
|
1826
1289
|
return this._pipeline.getContextGcReport(messages);
|
|
1827
1290
|
}
|
|
1828
|
-
/**
|
|
1829
|
-
* Context-transform hot-path delegation to {@link ContextPipeline.estimateCurrentContextTokens}. Kept
|
|
1830
|
-
* as a one-line method (not inlined) so the transform stays the single owner of the pass ordering;
|
|
1831
|
-
* also feeds the per-turn cost guard.
|
|
1832
|
-
*/
|
|
1833
|
-
_estimateCurrentContextTokens(messages) {
|
|
1834
|
-
return this._pipeline.estimateCurrentContextTokens(messages);
|
|
1835
|
-
}
|
|
1836
1291
|
_installAgentToolHooks() {
|
|
1837
1292
|
this.agent.beforeToolCall = this._toolGate.beforeToolCall;
|
|
1838
1293
|
this.agent.afterToolCall = this._toolGate.afterToolCall;
|
|
@@ -1859,17 +1314,6 @@ export class AgentSession {
|
|
|
1859
1314
|
message: `Stopped: the model repeated the same tool call ${info.repeats} times in a row without making progress. Review the last tool result and steer or retry with a different approach.`,
|
|
1860
1315
|
});
|
|
1861
1316
|
}
|
|
1862
|
-
/** Anti-loop: true when this model's persisted tool-probe verdict was written within the
|
|
1863
|
-
* auto-probe freshness window ({@link AUTO_TOOL_PROBE_FRESHNESS_MS}) — covers a very recent
|
|
1864
|
-
* explicit `/toolprobe` run or a fresh circuit-breaker demote from an EARLIER session, complementing
|
|
1865
|
-
* the in-session {@link _autoProbedModels} latch. */
|
|
1866
|
-
_hasFreshToolProbeVerdict(modelKey) {
|
|
1867
|
-
const probedAt = this._modelAdaptationStore.get(modelKey).toolProbe?.probedAt;
|
|
1868
|
-
if (!probedAt)
|
|
1869
|
-
return false;
|
|
1870
|
-
const age = Date.now() - new Date(probedAt).getTime();
|
|
1871
|
-
return Number.isFinite(age) && age >= 0 && age < AUTO_TOOL_PROBE_FRESHNESS_MS;
|
|
1872
|
-
}
|
|
1873
1317
|
/**
|
|
1874
1318
|
* Evidence-gated native→phone auto-probe for a LOCAL/MANAGED model (never cloud — see
|
|
1875
1319
|
* {@link isLocalOrManagedRouterModel}) that just crossed the tool-argument-validation escalation
|
|
@@ -1880,36 +1324,11 @@ export class AgentSession {
|
|
|
1880
1324
|
* "native" and is never phoned) entirely OFF the hot path — fired here but never awaited by the
|
|
1881
1325
|
* caller, so a slow or failing probe can never block or throw the user's in-flight turn.
|
|
1882
1326
|
* Anti-loop: skipped when this session already auto-probed this model, or a fresh persisted
|
|
1883
|
-
* verdict already exists ({@link
|
|
1327
|
+
* verdict already exists (enforced by {@link ToolProtocolController}) — otherwise a model that keeps
|
|
1884
1328
|
* failing validation every turn would re-fire the (multi-completion) probe every single turn.
|
|
1885
1329
|
*/
|
|
1886
1330
|
_maybeAutoProbeOnValidationEscalation(model) {
|
|
1887
|
-
|
|
1888
|
-
if (this._autoProbedModels.has(modelKey) || this._hasFreshToolProbeVerdict(modelKey))
|
|
1889
|
-
return;
|
|
1890
|
-
this._autoProbedModels.add(modelKey);
|
|
1891
|
-
void this._probeToolCallingForModel(model)
|
|
1892
|
-
.then((result) => {
|
|
1893
|
-
if (this._disposed)
|
|
1894
|
-
return;
|
|
1895
|
-
const detail = result.verdict === "text-protocol"
|
|
1896
|
-
? ` (variant ${result.variant}); it will use the text tool protocol starting next turn`
|
|
1897
|
-
: result.verdict === "none"
|
|
1898
|
-
? " — no working tool-call path was found; run /toolprobe for details"
|
|
1899
|
-
: "; native tool calls stay in use";
|
|
1900
|
-
this._emit({
|
|
1901
|
-
type: "warning",
|
|
1902
|
-
message: `Auto-probed ${modelKey} after repeated native tool-call validation failures: verdict "${result.verdict}"${detail}.`,
|
|
1903
|
-
});
|
|
1904
|
-
})
|
|
1905
|
-
.catch((error) => {
|
|
1906
|
-
if (this._disposed)
|
|
1907
|
-
return;
|
|
1908
|
-
this._emit({
|
|
1909
|
-
type: "warning",
|
|
1910
|
-
message: `Auto-probe for ${modelKey} (triggered by repeated tool-call validation failures) did not complete: ${error instanceof Error ? error.message : String(error)}.`,
|
|
1911
|
-
});
|
|
1912
|
-
});
|
|
1331
|
+
this._toolProtocol.maybeAutoProbe(model);
|
|
1913
1332
|
}
|
|
1914
1333
|
/**
|
|
1915
1334
|
* A repeated identical tool-argument-validation failure crossed the escalation threshold
|
|
@@ -1960,11 +1379,23 @@ export class AgentSession {
|
|
|
1960
1379
|
}
|
|
1961
1380
|
}
|
|
1962
1381
|
async _notifyWorkerTerminalHandoff(records) {
|
|
1963
|
-
if (
|
|
1382
|
+
if (records.length === 0)
|
|
1964
1383
|
return;
|
|
1384
|
+
if (this._disposed)
|
|
1385
|
+
throw new Error("Session disposed before worker terminal handoff was persisted");
|
|
1386
|
+
// sendCustomMessage only queues in process memory while the foreground is streaming. Wait for
|
|
1387
|
+
// the owning run to settle so a successful return proves the handoff reached session storage
|
|
1388
|
+
// before the durable notification outbox marks it delivered.
|
|
1389
|
+
await this.agent.waitForIdle();
|
|
1390
|
+
if (this._disposed)
|
|
1391
|
+
throw new Error("Session disposed before worker terminal handoff was persisted");
|
|
1965
1392
|
const included = records.slice(0, 8);
|
|
1966
1393
|
const sanitize = (value) => value.replace(/[\r\n]+/g, " ").slice(0, 120);
|
|
1967
1394
|
const omitted = records.length - included.length;
|
|
1395
|
+
const workerRequestsAwaitingDelivery = new Set(getWorkerHumanInputsRequiringDelivery(this.sessionManager).flatMap((snapshot) => snapshot.request.workerRequestId ? [snapshot.request.workerRequestId] : []));
|
|
1396
|
+
const ownerQuestionWillWakeParent = this._extensionUIContext !== undefined &&
|
|
1397
|
+
this._extensionMode !== "print" &&
|
|
1398
|
+
records.every((record) => workerRequestsAwaitingDelivery.has(record.laneId));
|
|
1968
1399
|
const content = [
|
|
1969
1400
|
"Background worker terminal handoff:",
|
|
1970
1401
|
...included.map((record) => {
|
|
@@ -1979,7 +1410,7 @@ export class AgentSession {
|
|
|
1979
1410
|
content,
|
|
1980
1411
|
display: true,
|
|
1981
1412
|
details: { records: included },
|
|
1982
|
-
}, { triggerTurn:
|
|
1413
|
+
}, { triggerTurn: !ownerQuestionWillWakeParent, deliverAs: "followUp" });
|
|
1983
1414
|
}
|
|
1984
1415
|
_emitQueueUpdate() {
|
|
1985
1416
|
this._emit({
|
|
@@ -1989,8 +1420,6 @@ export class AgentSession {
|
|
|
1989
1420
|
commands: [...this._queuedExtensionCommands],
|
|
1990
1421
|
});
|
|
1991
1422
|
}
|
|
1992
|
-
// Track last assistant message for auto-compaction check
|
|
1993
|
-
_lastAssistantMessage = undefined;
|
|
1994
1423
|
/**
|
|
1995
1424
|
* User messages already painted to the UI by an early, synthetic `message_start` fired from
|
|
1996
1425
|
* `_promptUnserialized` — before the model-router judge's bounded LLM call — so the prompt
|
|
@@ -2006,7 +1435,7 @@ export class AgentSession {
|
|
|
2006
1435
|
// When a user message starts, check if it's from either queue and remove it BEFORE emitting
|
|
2007
1436
|
// This ensures the UI sees the updated queue state
|
|
2008
1437
|
if (event.type === "message_start" && event.message.role === "user") {
|
|
2009
|
-
this.
|
|
1438
|
+
this._compaction.resetOverflowRecovery();
|
|
2010
1439
|
const messageText = this._getUserMessageText(event.message);
|
|
2011
1440
|
if (messageText) {
|
|
2012
1441
|
// Check steering queue first
|
|
@@ -2065,41 +1494,21 @@ export class AgentSession {
|
|
|
2065
1494
|
messagePersisted = true;
|
|
2066
1495
|
}
|
|
2067
1496
|
// Other message types (bashExecution, compactionSummary, branchSummary) are persisted elsewhere
|
|
2068
|
-
// Track
|
|
1497
|
+
// Track the response for ordered retry/failover/compaction handling after agent_end.
|
|
2069
1498
|
if (event.message.role === "assistant") {
|
|
2070
|
-
this._lastAssistantMessage = event.message;
|
|
2071
1499
|
const assistantMsg = event.message;
|
|
2072
1500
|
if (messagePersisted) {
|
|
2073
1501
|
this._pipeline.observeProviderUsage(this.agent.state.messages, assistantMsg);
|
|
2074
1502
|
}
|
|
2075
|
-
|
|
2076
|
-
this._overflowRecoveryAttempted = false;
|
|
2077
|
-
}
|
|
2078
|
-
// Reset retry counter immediately on successful assistant response
|
|
2079
|
-
// This prevents accumulation across multiple LLM calls within a turn
|
|
2080
|
-
if (assistantMsg.stopReason !== "error" && this._retryController.attempt > 0) {
|
|
2081
|
-
this._emit({
|
|
2082
|
-
type: "auto_retry_end",
|
|
2083
|
-
success: true,
|
|
2084
|
-
attempt: this._retryController.attempt,
|
|
2085
|
-
});
|
|
2086
|
-
this._retryController.reset();
|
|
2087
|
-
}
|
|
1503
|
+
this._foregroundRecovery.observeAssistant(assistantMsg);
|
|
2088
1504
|
}
|
|
2089
1505
|
}
|
|
1506
|
+
if (event.type === "agent_end" && !this._willRetryAfterAgentEnd(event)) {
|
|
1507
|
+
this._humanInput.schedulePendingWorkerInputs();
|
|
1508
|
+
}
|
|
2090
1509
|
};
|
|
2091
1510
|
_willRetryAfterAgentEnd(event) {
|
|
2092
|
-
|
|
2093
|
-
if (!settings.enabled || this._retryController.attempt >= settings.maxRetries) {
|
|
2094
|
-
return false;
|
|
2095
|
-
}
|
|
2096
|
-
for (let i = event.messages.length - 1; i >= 0; i--) {
|
|
2097
|
-
const message = event.messages[i];
|
|
2098
|
-
if (message.role === "assistant") {
|
|
2099
|
-
return this._isRetryableError(message);
|
|
2100
|
-
}
|
|
2101
|
-
}
|
|
2102
|
-
return false;
|
|
1511
|
+
return this._foregroundRecovery.willRetryAfterAgentEnd(event);
|
|
2103
1512
|
}
|
|
2104
1513
|
/** Extract text content from a message */
|
|
2105
1514
|
_getUserMessageText(message) {
|
|
@@ -2287,45 +1696,50 @@ export class AgentSession {
|
|
|
2287
1696
|
* Call this when completely done with the session.
|
|
2288
1697
|
*/
|
|
2289
1698
|
dispose() {
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
1699
|
+
if (this._disposed)
|
|
1700
|
+
return;
|
|
1701
|
+
this._disposed = true;
|
|
1702
|
+
const shutdowns = [];
|
|
1703
|
+
const safely = (action) => {
|
|
1704
|
+
try {
|
|
1705
|
+
action();
|
|
1706
|
+
}
|
|
1707
|
+
catch {
|
|
1708
|
+
// Every independent cleanup remains best-effort; one failure cannot skip the rest.
|
|
1709
|
+
}
|
|
1710
|
+
};
|
|
1711
|
+
const track = (action) => {
|
|
1712
|
+
try {
|
|
1713
|
+
shutdowns.push(action());
|
|
1714
|
+
}
|
|
1715
|
+
catch {
|
|
1716
|
+
// A synchronously throwing async-resource adapter cannot skip the remaining shutdowns.
|
|
1717
|
+
}
|
|
1718
|
+
};
|
|
1719
|
+
safely(() => this._backgroundLanes.clearGoalAutoContinueTimer());
|
|
1720
|
+
safely(() => this._backgroundLanes.clearResearchLaneTimer());
|
|
1721
|
+
safely(() => this.abortRetry());
|
|
1722
|
+
safely(() => this.abortCompaction());
|
|
1723
|
+
safely(() => this.abortBranchSummary());
|
|
1724
|
+
safely(() => this.abortBash());
|
|
1725
|
+
safely(() => disposePersistentShellSession(this._shellSessionKey));
|
|
1726
|
+
safely(() => this._cancelPrefixWarm());
|
|
1727
|
+
safely(() => this.agent.abort());
|
|
1728
|
+
track(() => this._gatewayRegistry.stop());
|
|
1729
|
+
safely(() => this._reflectionAbort.abort());
|
|
1730
|
+
safely(() => this._backgroundLanes.abortInFlightLanes());
|
|
1731
|
+
safely(() => {
|
|
2312
1732
|
this.agent.afterToolCall = undefined;
|
|
2313
1733
|
this.agent.transformContext = undefined;
|
|
2314
|
-
}
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
}
|
|
2318
|
-
this._extensionRunner.invalidate("This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().");
|
|
2319
|
-
this._disconnectFromAgent();
|
|
1734
|
+
});
|
|
1735
|
+
safely(() => this._extensionRunner.invalidate());
|
|
1736
|
+
safely(() => this._disconnectFromAgent());
|
|
2320
1737
|
this._eventListeners = [];
|
|
2321
1738
|
// Best-effort memory cleanup (release locks/handles). Write-side onSessionEnd is wired on a
|
|
2322
1739
|
// true session-end hook; file-store shutdown is a no-op.
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
.catch(() => { });
|
|
2327
|
-
void this._toolRecoveryLogger.shutdown().catch(() => { });
|
|
2328
|
-
cleanupSessionResources(this.sessionId);
|
|
1740
|
+
track(() => this._memory.getMemoryManager().shutdownAll());
|
|
1741
|
+
track(() => this._toolRecoveryLogger.shutdown());
|
|
1742
|
+
safely(() => cleanupSessionResources(this.sessionId));
|
|
2329
1743
|
// Best-effort final sweep for any grep/find artifact already released (reference
|
|
2330
1744
|
// count zero) but not yet reclaimed -- e.g. a release whose cleanup() call failed
|
|
2331
1745
|
// transiently. This is conservative: it never releases a still-referenced
|
|
@@ -2333,12 +1747,13 @@ export class AgentSession {
|
|
|
2333
1747
|
// short to cross preserveRecentMessages) correctly leaves that artifact in place,
|
|
2334
1748
|
// resolvable if the same session is resumed later. It does not sweep OTHER
|
|
2335
1749
|
// sessions' artifact directories.
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
1750
|
+
safely(() => this._pipeline.cleanupToolArtifactStoreOnDispose());
|
|
1751
|
+
this._disposeCompletion = Promise.allSettled(shutdowns).then(() => undefined);
|
|
1752
|
+
}
|
|
1753
|
+
/** Dispose synchronously-visible state, then await all session-owned asynchronous shutdowns. */
|
|
1754
|
+
async disposeAndWait() {
|
|
1755
|
+
this.dispose();
|
|
1756
|
+
await this._disposeCompletion;
|
|
2342
1757
|
}
|
|
2343
1758
|
// =========================================================================
|
|
2344
1759
|
// Read-only State Access
|
|
@@ -2365,7 +1780,7 @@ export class AgentSession {
|
|
|
2365
1780
|
}
|
|
2366
1781
|
/** Current retry attempt (0 if not retrying) */
|
|
2367
1782
|
get retryAttempt() {
|
|
2368
|
-
return this.
|
|
1783
|
+
return this._foregroundRecovery.attempt;
|
|
2369
1784
|
}
|
|
2370
1785
|
/**
|
|
2371
1786
|
* Get the names of currently active tools.
|
|
@@ -2415,7 +1830,7 @@ export class AgentSession {
|
|
|
2415
1830
|
* Changes take effect on the next agent turn.
|
|
2416
1831
|
*
|
|
2417
1832
|
* artifact_retrieve is auto-activated as a companion whenever an artifact-producing tool
|
|
2418
|
-
* (grep, find, or
|
|
1833
|
+
* (grep, find, run_toolkit_script, or ask_question) ends up in the resulting active set and artifact_retrieve
|
|
2419
1834
|
* is registered (i.e. not excluded/
|
|
2420
1835
|
* blocked/outside an allowlist -- the registry itself is built with that same filter,
|
|
2421
1836
|
* so registry presence already tracks "allowed"). This is enforced here, not just in
|
|
@@ -2449,7 +1864,8 @@ export class AgentSession {
|
|
|
2449
1864
|
}
|
|
2450
1865
|
if (validToolNames.includes("grep") ||
|
|
2451
1866
|
validToolNames.includes("find") ||
|
|
2452
|
-
validToolNames.includes("run_toolkit_script")
|
|
1867
|
+
validToolNames.includes("run_toolkit_script") ||
|
|
1868
|
+
validToolNames.includes("ask_question")) {
|
|
2453
1869
|
addIfRegistered("artifact_retrieve");
|
|
2454
1870
|
}
|
|
2455
1871
|
if (validToolNames.includes("delegate")) {
|
|
@@ -2463,9 +1879,7 @@ export class AgentSession {
|
|
|
2463
1879
|
}
|
|
2464
1880
|
/** Whether compaction or branch summarization is currently running */
|
|
2465
1881
|
get isCompacting() {
|
|
2466
|
-
return (this.
|
|
2467
|
-
this._compactionAbortController !== undefined ||
|
|
2468
|
-
this._branchSummaryAbortController !== undefined);
|
|
1882
|
+
return this._compaction.isRunning() || this._branchSummaryAbortController !== undefined;
|
|
2469
1883
|
}
|
|
2470
1884
|
/** All messages including custom types like BashExecutionMessage */
|
|
2471
1885
|
get messages() {
|
|
@@ -2536,7 +1950,7 @@ export class AgentSession {
|
|
|
2536
1950
|
try {
|
|
2537
1951
|
const maxGoalLoopRounds = this.settingsManager.getAutonomySettings().maxStallTurns;
|
|
2538
1952
|
this.agent.maxStallTurns = maxGoalLoopRounds;
|
|
2539
|
-
await this.
|
|
1953
|
+
await this._toolProtocol.ensureActiveModelProtocol();
|
|
2540
1954
|
let goalLoopRounds = 1;
|
|
2541
1955
|
await this.agent.prompt(messages);
|
|
2542
1956
|
while ((maxGoalLoopRounds === 0 || goalLoopRounds < maxGoalLoopRounds) && (await this._handlePostAgentRun())) {
|
|
@@ -2549,6 +1963,14 @@ export class AgentSession {
|
|
|
2549
1963
|
await this._drainQueuedExtensionCommands();
|
|
2550
1964
|
}
|
|
2551
1965
|
}
|
|
1966
|
+
/**
|
|
1967
|
+
* Re-enter an interrupted ask_question call from its durable request snapshot. Pending requests
|
|
1968
|
+
* are presented again; already-checkpointed answers are replayed without asking twice. The
|
|
1969
|
+
* original toolCallId is preserved so provider tool-call ordering remains valid on /resume.
|
|
1970
|
+
*/
|
|
1971
|
+
async resumePendingHumanInput() {
|
|
1972
|
+
return this._humanInput.resumePending();
|
|
1973
|
+
}
|
|
2552
1974
|
/**
|
|
2553
1975
|
* Shared {@link OllamaRuntime} for a given server, lazily created and cached by baseUrl so every
|
|
2554
1976
|
* caller — the router's readiness gate and any host UI's own model-lifecycle commands (e.g.
|
|
@@ -2606,40 +2028,7 @@ export class AgentSession {
|
|
|
2606
2028
|
return this._modelRouter.getStatus(formatLabel);
|
|
2607
2029
|
}
|
|
2608
2030
|
async _handlePostAgentRun() {
|
|
2609
|
-
|
|
2610
|
-
this._lastAssistantMessage = undefined;
|
|
2611
|
-
if (!msg) {
|
|
2612
|
-
return false;
|
|
2613
|
-
}
|
|
2614
|
-
const classified = this._classifyAssistantError(msg);
|
|
2615
|
-
if (classified) {
|
|
2616
|
-
this._failureCorpus.record({
|
|
2617
|
-
provider: msg.provider,
|
|
2618
|
-
modelId: msg.model,
|
|
2619
|
-
message: msg.errorMessage ?? "",
|
|
2620
|
-
classified,
|
|
2621
|
-
});
|
|
2622
|
-
}
|
|
2623
|
-
if (classified?.retryable && (await this._prepareRetry(msg))) {
|
|
2624
|
-
return true;
|
|
2625
|
-
}
|
|
2626
|
-
if (await this._billingFailover.handleAssistantError(msg, classified))
|
|
2627
|
-
return false;
|
|
2628
|
-
if (msg.stopReason === "error" && this._retryController.attempt > 0) {
|
|
2629
|
-
this._emit({
|
|
2630
|
-
type: "auto_retry_end",
|
|
2631
|
-
success: false,
|
|
2632
|
-
attempt: this._retryController.attempt,
|
|
2633
|
-
finalError: msg.errorMessage,
|
|
2634
|
-
});
|
|
2635
|
-
this._retryController.reset();
|
|
2636
|
-
}
|
|
2637
|
-
if (await this._checkCompaction(msg)) {
|
|
2638
|
-
return true;
|
|
2639
|
-
}
|
|
2640
|
-
// The agent loop drains both queues before emitting agent_end. Any messages
|
|
2641
|
-
// here were queued by agent_end extension handlers and need a continuation.
|
|
2642
|
-
return this.agent.hasQueuedMessages();
|
|
2031
|
+
return this._foregroundRecovery.handlePostAgentRun();
|
|
2643
2032
|
}
|
|
2644
2033
|
/**
|
|
2645
2034
|
* Send a prompt to the agent.
|
|
@@ -2662,11 +2051,7 @@ export class AgentSession {
|
|
|
2662
2051
|
return this._promptUnserialized(text, options);
|
|
2663
2052
|
}
|
|
2664
2053
|
async _promptUnserialized(text, options) {
|
|
2665
|
-
|
|
2666
|
-
// window so a PRIOR turn's background/spawned spend doesn't keep this turn's guard permanently
|
|
2667
|
-
// tripped. Every round trip within this same turn (tool-call iterations) shares this baseline.
|
|
2668
|
-
this._costGuardTurnBaselineUsd = this.getSpawnedUsage().cost;
|
|
2669
|
-
this._applyToolRepairLayerSettings();
|
|
2054
|
+
this._toolProtocol.applyRepairLayerSettings();
|
|
2670
2055
|
this._cancelPrefixWarm();
|
|
2671
2056
|
const expandPromptTemplates = options?.expandPromptTemplates ?? true;
|
|
2672
2057
|
const processSlashCommands = options?.processSlashCommands ?? expandPromptTemplates;
|
|
@@ -2678,6 +2063,9 @@ export class AgentSession {
|
|
|
2678
2063
|
// selected/authenticated — can un-register it from _earlyDisplayedUserMessages instead of
|
|
2679
2064
|
// leaking the reference forever.
|
|
2680
2065
|
let userMessage;
|
|
2066
|
+
let promptMessage;
|
|
2067
|
+
let routingStarted = false;
|
|
2068
|
+
let pendingNextTurnCount = 0;
|
|
2681
2069
|
// Effectiveness feedback: remember the recall page + the query so we can score, after the
|
|
2682
2070
|
// response, whether the agent actually used the recalled context.
|
|
2683
2071
|
let injectedRecall = "";
|
|
@@ -2738,6 +2126,9 @@ export class AgentSession {
|
|
|
2738
2126
|
preflightResult?.(true);
|
|
2739
2127
|
return;
|
|
2740
2128
|
}
|
|
2129
|
+
// This submission is starting a new foreground turn. Queued steer/follow-up messages above
|
|
2130
|
+
// remain part of the already-active turn and must not erase its spawned-cost baseline.
|
|
2131
|
+
this._costGuardTurnBaselineUsd = this.getSpawnedUsage().cost;
|
|
2741
2132
|
// Flush any pending bash messages before the new prompt
|
|
2742
2133
|
this._flushPendingBashMessages();
|
|
2743
2134
|
// Build the user message now — before the router judge — and paint it to the UI
|
|
@@ -2745,22 +2136,31 @@ export class AgentSession {
|
|
|
2745
2136
|
// (seconds), not a regex; awaiting it first made the prompt appear to hang. The
|
|
2746
2137
|
// authoritative message_start emitted later for this SAME object is suppressed in
|
|
2747
2138
|
// _handleAgentEvent (see _earlyDisplayedUserMessages) so it is still shown exactly once.
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2139
|
+
if (options?.internalContextType) {
|
|
2140
|
+
if (currentImages && currentImages.length > 0) {
|
|
2141
|
+
throw new Error("Internal context turns do not accept image attachments.");
|
|
2142
|
+
}
|
|
2143
|
+
promptMessage = createCustomMessage(options.internalContextType, expandedText, false, undefined, new Date().toISOString());
|
|
2144
|
+
}
|
|
2145
|
+
else {
|
|
2146
|
+
const userContent = [{ type: "text", text: expandedText }];
|
|
2147
|
+
if (currentImages)
|
|
2148
|
+
userContent.push(...currentImages);
|
|
2149
|
+
userMessage = {
|
|
2150
|
+
role: "user",
|
|
2151
|
+
content: userContent,
|
|
2152
|
+
timestamp: Date.now(),
|
|
2153
|
+
};
|
|
2154
|
+
promptMessage = userMessage;
|
|
2155
|
+
this._earlyDisplayedUserMessages.add(userMessage);
|
|
2156
|
+
this._emit({ type: "message_start", message: userMessage });
|
|
2751
2157
|
}
|
|
2752
|
-
userMessage = {
|
|
2753
|
-
role: "user",
|
|
2754
|
-
content: userContent,
|
|
2755
|
-
timestamp: Date.now(),
|
|
2756
|
-
};
|
|
2757
|
-
this._earlyDisplayedUserMessages.add(userMessage);
|
|
2758
|
-
this._emit({ type: "message_start", message: userMessage });
|
|
2759
2158
|
// Bracket the routing/prep phase (judge, model/auth checks, compaction, ...) so the UI can
|
|
2760
2159
|
// show general "working" feedback for it — otherwise the user stares at their own echoed
|
|
2761
2160
|
// prompt with nothing happening for however long the judge takes. routing_end is emitted
|
|
2762
2161
|
// exactly once below: either in the catch block (this phase failed) or right after the try
|
|
2763
2162
|
// block (this phase succeeded, whether or not it produced a turn to run).
|
|
2163
|
+
routingStarted = true;
|
|
2764
2164
|
this._emit({ type: "routing_start" });
|
|
2765
2165
|
const resolvedRouteInfo = await this._modelRouter.resolveTurnRouteJudged(expandedText, {
|
|
2766
2166
|
// Internally generated turns (goal continuation, lane follow-ups) never consult the judge:
|
|
@@ -2777,6 +2177,9 @@ export class AgentSession {
|
|
|
2777
2177
|
if (!requestModel) {
|
|
2778
2178
|
throw new Error(formatNoModelSelectedMessage());
|
|
2779
2179
|
}
|
|
2180
|
+
if (currentImages && currentImages.length > 0 && !requestModel.input.includes("image")) {
|
|
2181
|
+
throw new Error(`Model "${requestModel.provider}/${requestModel.id}" does not accept image input. Select an image-capable model or route the inspection to a vision worker.`);
|
|
2182
|
+
}
|
|
2780
2183
|
// A manual/default local model has no RouteDecision, so the router readiness gate above is
|
|
2781
2184
|
// intentionally a no-op. It still needs the same managed-runtime boot/residency guarantee.
|
|
2782
2185
|
if (!resolvedRouteInfo) {
|
|
@@ -2805,7 +2208,7 @@ export class AgentSession {
|
|
|
2805
2208
|
// prefetch a relevant <memory_context> page from past sessions and prepend it as data ahead of
|
|
2806
2209
|
// the user message. Best-effort and gated: trivial turns are skipped, and providers return ""
|
|
2807
2210
|
// (no page) when nothing is relevant — so it stays net-negative and the GC packs stale pages.
|
|
2808
|
-
if (this._memory.shouldAttemptRecall(expandedText)) {
|
|
2211
|
+
if (!options?.internalContextType && this._memory.shouldAttemptRecall(expandedText)) {
|
|
2809
2212
|
try {
|
|
2810
2213
|
const recall = await this._memory.prefetchRecall(expandedText);
|
|
2811
2214
|
if (recall) {
|
|
@@ -2824,13 +2227,13 @@ export class AgentSession {
|
|
|
2824
2227
|
}
|
|
2825
2228
|
// Add user message (built earlier, before the router judge, so it could be painted
|
|
2826
2229
|
// immediately — see the early message_start emit above).
|
|
2827
|
-
messages.push(
|
|
2230
|
+
messages.push(promptMessage);
|
|
2828
2231
|
// Inject any pending "nextTurn" messages as context alongside the user message
|
|
2829
|
-
|
|
2232
|
+
pendingNextTurnCount = this._pendingNextTurnMessages.length;
|
|
2233
|
+
for (const msg of this._pendingNextTurnMessages.slice(0, pendingNextTurnCount)) {
|
|
2830
2234
|
messages.push(msg);
|
|
2831
2235
|
}
|
|
2832
|
-
|
|
2833
|
-
const taskStepsState = this.getTaskStepsStateSnapshot();
|
|
2236
|
+
const taskStepsState = options?.internalContextType ? undefined : this.getTaskStepsStateSnapshot();
|
|
2834
2237
|
const taskStepsContext = taskStepsState ? formatTaskStepsContext(taskStepsState) : undefined;
|
|
2835
2238
|
if (taskStepsState && taskStepsContext) {
|
|
2836
2239
|
messages.push(createCustomMessage("task_steps_context", taskStepsContext, false, { revision: taskStepsState.revision }, new Date().toISOString()));
|
|
@@ -2858,6 +2261,9 @@ export class AgentSession {
|
|
|
2858
2261
|
// Ensure we're using the base prompt (in case previous turn had modifications)
|
|
2859
2262
|
this.agent.state.systemPrompt = this._baseSystemPrompt;
|
|
2860
2263
|
}
|
|
2264
|
+
// Commit consumption only after all fallible preflight hooks have succeeded. Messages added
|
|
2265
|
+
// while the hook was running remain queued for the following turn.
|
|
2266
|
+
this._pendingNextTurnMessages.splice(0, pendingNextTurnCount);
|
|
2861
2267
|
}
|
|
2862
2268
|
catch (error) {
|
|
2863
2269
|
// The turn never reached _runAgentPrompt, so the authoritative message_start that would
|
|
@@ -2868,22 +2274,31 @@ export class AgentSession {
|
|
|
2868
2274
|
}
|
|
2869
2275
|
// The routing/prep phase (routing_start above) failed before ever reaching the turn — end
|
|
2870
2276
|
// it here, or the UI's "working" indicator for it spins forever with nothing behind it.
|
|
2871
|
-
|
|
2277
|
+
if (routingStarted)
|
|
2278
|
+
this._emit({ type: "routing_end" });
|
|
2872
2279
|
preflightResult?.(false);
|
|
2873
2280
|
throw error;
|
|
2874
2281
|
}
|
|
2875
2282
|
// The routing/prep phase is over — either we're about to hand off into the turn (which emits
|
|
2876
2283
|
// its own agent_start/streaming events right after), or messages is unexpectedly unset and we
|
|
2877
2284
|
// bail below. Either way nothing is left "routing" past this point.
|
|
2878
|
-
|
|
2285
|
+
if (routingStarted)
|
|
2286
|
+
this._emit({ type: "routing_end" });
|
|
2879
2287
|
if (!messages) {
|
|
2880
2288
|
return;
|
|
2881
2289
|
}
|
|
2882
2290
|
preflightResult?.(true);
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2291
|
+
try {
|
|
2292
|
+
this._toolProtocol.resetTurnState();
|
|
2293
|
+
await this._modelRouter.runRoutedTurn(messages, routedTurnModel, routedTurnRouteDecision);
|
|
2294
|
+
this._toolProtocol.recordParseOutcomeFromLastAssistant();
|
|
2295
|
+
}
|
|
2296
|
+
finally {
|
|
2297
|
+
// Normally consumed by the authoritative message_start. If execution failed before that
|
|
2298
|
+
// event, do not retain the early-painted message identity indefinitely.
|
|
2299
|
+
if (userMessage)
|
|
2300
|
+
this._earlyDisplayedUserMessages.delete(userMessage);
|
|
2301
|
+
}
|
|
2887
2302
|
// Score whether the agent actually used the recalled context, so the recall gate can adapt.
|
|
2888
2303
|
if (injectedRecall) {
|
|
2889
2304
|
const response = this._findLastAssistantMessage();
|
|
@@ -3251,166 +2666,13 @@ export class AgentSession {
|
|
|
3251
2666
|
* @param customInstructions Optional instructions for the compaction summary
|
|
3252
2667
|
*/
|
|
3253
2668
|
async compact(customInstructions) {
|
|
3254
|
-
this.
|
|
3255
|
-
await this.abort();
|
|
3256
|
-
this._compactionAbortController = new AbortController();
|
|
3257
|
-
this._emit({ type: "compaction_start", reason: "manual" });
|
|
3258
|
-
try {
|
|
3259
|
-
if (!this.model) {
|
|
3260
|
-
throw new Error(formatNoModelSelectedMessage());
|
|
3261
|
-
}
|
|
3262
|
-
const sessionModel = this.model;
|
|
3263
|
-
const selectedCompactionModel = this._resolveCompactionModel(sessionModel);
|
|
3264
|
-
if (this._isRawStreamSimple(this.agent.streamFn)) {
|
|
3265
|
-
await this._getCompactionRequestAuth(selectedCompactionModel);
|
|
3266
|
-
}
|
|
3267
|
-
const selectionReason = this._getLastCompactionSelectionReason() ?? "unknown";
|
|
3268
|
-
const settings = this._getAdaptedCompactionSettings();
|
|
3269
|
-
const initialBranch = this.sessionManager.getBranch();
|
|
3270
|
-
const initialPreparation = prepareCompaction(initialBranch, settings);
|
|
3271
|
-
if (!initialPreparation) {
|
|
3272
|
-
const lastEntry = initialBranch[initialBranch.length - 1];
|
|
3273
|
-
if (lastEntry?.type === "compaction") {
|
|
3274
|
-
throw new Error("Already compacted");
|
|
3275
|
-
}
|
|
3276
|
-
throw new Error("Nothing to compact (session too small)");
|
|
3277
|
-
}
|
|
3278
|
-
let extensionCompaction;
|
|
3279
|
-
let fromExtension = false;
|
|
3280
|
-
if (this._extensionRunner.hasHandlers("session_before_compact")) {
|
|
3281
|
-
const result = (await this._extensionRunner.emit({
|
|
3282
|
-
type: "session_before_compact",
|
|
3283
|
-
preparation: initialPreparation,
|
|
3284
|
-
branchEntries: initialBranch,
|
|
3285
|
-
customInstructions,
|
|
3286
|
-
signal: this._compactionAbortController.signal,
|
|
3287
|
-
}));
|
|
3288
|
-
if (result?.cancel)
|
|
3289
|
-
throw new Error("Compaction cancelled");
|
|
3290
|
-
if (result?.compaction) {
|
|
3291
|
-
extensionCompaction = result.compaction;
|
|
3292
|
-
fromExtension = true;
|
|
3293
|
-
}
|
|
3294
|
-
}
|
|
3295
|
-
if (extensionCompaction) {
|
|
3296
|
-
this.sessionManager.appendCompaction(extensionCompaction.summary, extensionCompaction.firstKeptEntryId, extensionCompaction.tokensBefore, extensionCompaction.details, true);
|
|
3297
|
-
this._refreshAfterCompaction();
|
|
3298
|
-
const savedCompactionEntry = this.sessionManager
|
|
3299
|
-
.getEntries()
|
|
3300
|
-
.find((entry) => entry.type === "compaction" && entry.summary === extensionCompaction.summary);
|
|
3301
|
-
if (this._extensionRunner && savedCompactionEntry) {
|
|
3302
|
-
await this._extensionRunner.emit({
|
|
3303
|
-
type: "session_compact",
|
|
3304
|
-
compactionEntry: savedCompactionEntry,
|
|
3305
|
-
fromExtension: true,
|
|
3306
|
-
});
|
|
3307
|
-
}
|
|
3308
|
-
this._emit({
|
|
3309
|
-
type: "compaction_end",
|
|
3310
|
-
reason: "manual",
|
|
3311
|
-
result: extensionCompaction,
|
|
3312
|
-
aborted: false,
|
|
3313
|
-
willRetry: false,
|
|
3314
|
-
});
|
|
3315
|
-
return extensionCompaction;
|
|
3316
|
-
}
|
|
3317
|
-
let appliedResult;
|
|
3318
|
-
const signal = this._compactionAbortController.signal;
|
|
3319
|
-
const outcome = await runCompactionLoop({
|
|
3320
|
-
measureLiveTokens: () => Math.max(this._estimateCurrentContextTokens(this.agent.state.messages), 1),
|
|
3321
|
-
shouldCompact: () => true,
|
|
3322
|
-
getPostApplyMargin: () => 0,
|
|
3323
|
-
getBranch: () => this.sessionManager.getBranch(),
|
|
3324
|
-
getBaseKeepRecentTokens: () => settings.keepRecentTokens,
|
|
3325
|
-
resolveModelAndAuth: async (modelTier) => {
|
|
3326
|
-
const model = modelTier === "cheap" ? selectedCompactionModel : sessionModel;
|
|
3327
|
-
// Return the resolution result AS-IS: it may have fallen back to a different model
|
|
3328
|
-
// (e.g. session model, when the tier's model failed auth or the readiness gate),
|
|
3329
|
-
// and `failure` must reach the retry loop's auth-failed escalation rather than be
|
|
3330
|
-
// dropped — dropping it would pair the wrong model with the fallback's credentials
|
|
3331
|
-
// and silently skip the loop's visible failure/escalation handling.
|
|
3332
|
-
return this._resolveCompactionModelAndAuth(model, sessionModel);
|
|
3333
|
-
},
|
|
3334
|
-
summarizeAndVerify: async (params, model, apiKey, headers, branch) => {
|
|
3335
|
-
const preparation = prepareCompaction(branch, {
|
|
3336
|
-
...settings,
|
|
3337
|
-
keepRecentTokens: params.keepRecentTokens,
|
|
3338
|
-
}, { allowTrailingCompactionAsPrevious: true });
|
|
3339
|
-
if (!preparation)
|
|
3340
|
-
throw new Error("Nothing to compact (session too small)");
|
|
3341
|
-
if (extensionCompaction)
|
|
3342
|
-
return { result: extensionCompaction };
|
|
3343
|
-
const compactionThinkingLevel = this._resolveCompactionThinkingLevel(model, sessionModel);
|
|
3344
|
-
const result = await this._compactWithRetry(() => compact(preparation, model, apiKey, headers, customInstructions, signal, compactionThinkingLevel, this.agent.streamFn, this._buildCompactionPreDigest(), { chunked: params.chunked }), signal, model.provider);
|
|
3345
|
-
return { result };
|
|
3346
|
-
},
|
|
3347
|
-
buildDeterministicCheckpoint: () => ({ result: createDeterministicCompaction(initialPreparation) }),
|
|
3348
|
-
apply: async (result) => {
|
|
3349
|
-
if (signal.aborted)
|
|
3350
|
-
throw new Error("Compaction cancelled");
|
|
3351
|
-
this.sessionManager.appendCompaction(result.summary, result.firstKeptEntryId, result.tokensBefore, result.details, fromExtension);
|
|
3352
|
-
this._refreshAfterCompaction();
|
|
3353
|
-
const savedCompactionEntry = this.sessionManager
|
|
3354
|
-
.getEntries()
|
|
3355
|
-
.find((entry) => entry.type === "compaction" && entry.summary === result.summary);
|
|
3356
|
-
if (this._extensionRunner && savedCompactionEntry) {
|
|
3357
|
-
await this._extensionRunner.emit({
|
|
3358
|
-
type: "session_compact",
|
|
3359
|
-
compactionEntry: savedCompactionEntry,
|
|
3360
|
-
fromExtension,
|
|
3361
|
-
});
|
|
3362
|
-
}
|
|
3363
|
-
appliedResult = result;
|
|
3364
|
-
},
|
|
3365
|
-
verifyPostApplyEffect: () => false,
|
|
3366
|
-
onTransition: ({ cycle, cause, detail }) => {
|
|
3367
|
-
this._emit({
|
|
3368
|
-
type: "warning",
|
|
3369
|
-
message: `manual compaction cycle ${cycle}: ${cause}${detail ? ` (${detail})` : ""} — retrying from step 0 (${this._describeCompactionSummarizer()})`,
|
|
3370
|
-
});
|
|
3371
|
-
},
|
|
3372
|
-
signal,
|
|
3373
|
-
});
|
|
3374
|
-
if (outcome.kind === "failed") {
|
|
3375
|
-
if (outcome.reason === "aborted")
|
|
3376
|
-
throw new Error("Compaction cancelled");
|
|
3377
|
-
throw new Error(`manual compaction failed after retry ladder using ${selectedCompactionModel.provider}/${selectedCompactionModel.id} (${selectionReason}); first failure: ${outcome.reason}`);
|
|
3378
|
-
}
|
|
3379
|
-
if (outcome.kind === "skip" || !appliedResult)
|
|
3380
|
-
throw new Error(outcome.kind === "skip" ? outcome.reason : "Compaction failed");
|
|
3381
|
-
this._emit({
|
|
3382
|
-
type: "compaction_end",
|
|
3383
|
-
reason: "manual",
|
|
3384
|
-
result: appliedResult,
|
|
3385
|
-
aborted: false,
|
|
3386
|
-
willRetry: false,
|
|
3387
|
-
});
|
|
3388
|
-
return appliedResult;
|
|
3389
|
-
}
|
|
3390
|
-
catch (error) {
|
|
3391
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3392
|
-
const aborted = message === "Compaction cancelled" || (error instanceof Error && error.name === "AbortError");
|
|
3393
|
-
this._emit({
|
|
3394
|
-
type: "compaction_end",
|
|
3395
|
-
reason: "manual",
|
|
3396
|
-
result: undefined,
|
|
3397
|
-
aborted,
|
|
3398
|
-
willRetry: false,
|
|
3399
|
-
errorMessage: aborted ? undefined : `Compaction failed: ${message}`,
|
|
3400
|
-
});
|
|
3401
|
-
throw error;
|
|
3402
|
-
}
|
|
3403
|
-
finally {
|
|
3404
|
-
this._compactionAbortController = undefined;
|
|
3405
|
-
this._reconnectToAgent();
|
|
3406
|
-
}
|
|
2669
|
+
return this._compaction.compact(customInstructions);
|
|
3407
2670
|
}
|
|
3408
2671
|
/**
|
|
3409
2672
|
* Cancel in-progress compaction (manual or auto).
|
|
3410
2673
|
*/
|
|
3411
2674
|
abortCompaction() {
|
|
3412
|
-
this.
|
|
3413
|
-
this._autoCompactionAbortController?.abort();
|
|
2675
|
+
this._compaction.abort();
|
|
3414
2676
|
}
|
|
3415
2677
|
/**
|
|
3416
2678
|
* Cancel in-progress branch summarization.
|
|
@@ -3433,280 +2695,19 @@ export class AgentSession {
|
|
|
3433
2695
|
return this._compactionSupport.getAdaptedSettings();
|
|
3434
2696
|
}
|
|
3435
2697
|
_checkContextWindowUsageWarning() {
|
|
3436
|
-
|
|
3437
|
-
return;
|
|
3438
|
-
const contextWindow = this.model.contextWindow ?? 0;
|
|
3439
|
-
if (contextWindow <= 0)
|
|
3440
|
-
return;
|
|
3441
|
-
const systemPromptTokens = Math.ceil((this.agent.state.systemPrompt ?? "").length / 4);
|
|
3442
|
-
let toolsChars = 0;
|
|
3443
|
-
for (const tool of this.agent.state.tools || []) {
|
|
3444
|
-
toolsChars += tool.name.length;
|
|
3445
|
-
toolsChars += tool.description?.length ?? 0;
|
|
3446
|
-
if (tool.parameters) {
|
|
3447
|
-
toolsChars += JSON.stringify(tool.parameters).length;
|
|
3448
|
-
}
|
|
3449
|
-
}
|
|
3450
|
-
const toolsTokens = Math.ceil(toolsChars / 4);
|
|
3451
|
-
const baseTokens = systemPromptTokens + toolsTokens;
|
|
3452
|
-
if (baseTokens >= contextWindow) {
|
|
3453
|
-
this._emit({
|
|
3454
|
-
type: "warning",
|
|
3455
|
-
message: `Base configuration (system prompt and active tools) consumes ${baseTokens} tokens, which exceeds the model's context window of ${contextWindow} tokens. The model cannot process any prompts in this state.`,
|
|
3456
|
-
});
|
|
3457
|
-
}
|
|
3458
|
-
else if (baseTokens >= contextWindow * 0.7) {
|
|
3459
|
-
this._emit({
|
|
3460
|
-
type: "warning",
|
|
3461
|
-
message: `Base configuration (system prompt and active tools) consumes ${baseTokens} tokens (${Math.round((baseTokens / contextWindow) * 100)}% of the ${contextWindow} context window). This leaves very little room for conversation history and may cause immediate compaction or context overflow.`,
|
|
3462
|
-
});
|
|
3463
|
-
}
|
|
2698
|
+
this._compaction.checkContextWindowUsageWarning();
|
|
3464
2699
|
}
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
if (!settings.enabled)
|
|
3468
|
-
return false;
|
|
3469
|
-
// Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
|
|
3470
|
-
if (skipAbortedCheck && assistantMessage.stopReason === "aborted")
|
|
3471
|
-
return false;
|
|
3472
|
-
const contextWindow = this.model?.contextWindow ?? 0;
|
|
3473
|
-
// Skip overflow check if the message came from a different model.
|
|
3474
|
-
// This handles the case where user switched from a smaller-context model (e.g. opus)
|
|
3475
|
-
// to a larger-context model (e.g. codex) - the overflow error from the old model
|
|
3476
|
-
// shouldn't trigger compaction for the new model.
|
|
3477
|
-
const sameModel = this.model && assistantMessage.provider === this.model.provider && assistantMessage.model === this.model.id;
|
|
3478
|
-
// Skip compaction checks if this assistant message is older than the latest
|
|
3479
|
-
// compaction boundary. This prevents a stale pre-compaction usage/error
|
|
3480
|
-
// from retriggering compaction on the first prompt after compaction.
|
|
3481
|
-
const compactionEntry = getLatestCompactionEntry(this.sessionManager.getBranch());
|
|
3482
|
-
const assistantIsFromBeforeCompaction = compactionEntry !== null && assistantMessage.timestamp <= new Date(compactionEntry.timestamp).getTime();
|
|
3483
|
-
if (assistantIsFromBeforeCompaction) {
|
|
3484
|
-
return false;
|
|
3485
|
-
}
|
|
3486
|
-
// Case 1: Overflow - LLM returned context overflow error
|
|
3487
|
-
if (sameModel && isContextOverflow(assistantMessage, contextWindow)) {
|
|
3488
|
-
if (this._overflowRecoveryAttempted) {
|
|
3489
|
-
this._emit({
|
|
3490
|
-
type: "compaction_end",
|
|
3491
|
-
reason: "overflow",
|
|
3492
|
-
result: undefined,
|
|
3493
|
-
aborted: false,
|
|
3494
|
-
willRetry: false,
|
|
3495
|
-
errorMessage: "Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.",
|
|
3496
|
-
});
|
|
3497
|
-
return false;
|
|
3498
|
-
}
|
|
3499
|
-
this._overflowRecoveryAttempted = true;
|
|
3500
|
-
// Remove the error message from agent state (it IS saved to session for history,
|
|
3501
|
-
// but we don't want it in context for the retry)
|
|
3502
|
-
const messages = this.agent.state.messages;
|
|
3503
|
-
if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
|
|
3504
|
-
this.agent.state.messages = messages.slice(0, -1);
|
|
3505
|
-
}
|
|
3506
|
-
return await this._runAutoCompaction("overflow", true);
|
|
3507
|
-
}
|
|
3508
|
-
// Case 2: Threshold - context is getting large
|
|
3509
|
-
// For error messages (no usage data), estimate from last successful response.
|
|
3510
|
-
// This ensures sessions that hit persistent API errors (e.g. 529) can still compact.
|
|
3511
|
-
let contextTokens;
|
|
3512
|
-
if (assistantMessage.stopReason === "error") {
|
|
3513
|
-
const messages = this.agent.state.messages;
|
|
3514
|
-
const estimate = estimateContextTokens(messages);
|
|
3515
|
-
if (estimate.lastUsageIndex === null)
|
|
3516
|
-
return false; // No usage data at all
|
|
3517
|
-
// Verify the usage source is post-compaction. Kept pre-compaction messages
|
|
3518
|
-
// have stale usage reflecting the old (larger) context and would falsely
|
|
3519
|
-
// trigger compaction right after one just finished.
|
|
3520
|
-
const usageMsg = messages[estimate.lastUsageIndex];
|
|
3521
|
-
if (compactionEntry &&
|
|
3522
|
-
usageMsg.role === "assistant" &&
|
|
3523
|
-
usageMsg.timestamp <= new Date(compactionEntry.timestamp).getTime()) {
|
|
3524
|
-
return false;
|
|
3525
|
-
}
|
|
3526
|
-
contextTokens = estimate.tokens;
|
|
3527
|
-
}
|
|
3528
|
-
else {
|
|
3529
|
-
contextTokens = calculateContextTokens(assistantMessage.usage);
|
|
3530
|
-
const estimate = estimateContextTokens(this.agent.state.messages);
|
|
3531
|
-
if (estimate.lastUsageIndex !== null) {
|
|
3532
|
-
const usageMsg = this.agent.state.messages[estimate.lastUsageIndex];
|
|
3533
|
-
const usageIsPostCompaction = !(compactionEntry &&
|
|
3534
|
-
usageMsg.role === "assistant" &&
|
|
3535
|
-
usageMsg.timestamp <= new Date(compactionEntry.timestamp).getTime());
|
|
3536
|
-
if (usageIsPostCompaction) {
|
|
3537
|
-
contextTokens = Math.max(contextTokens, estimate.tokens);
|
|
3538
|
-
}
|
|
3539
|
-
}
|
|
3540
|
-
}
|
|
3541
|
-
if (shouldCompact(contextTokens, contextWindow, settings, this.model?.autoCompactionTriggerTokens)) {
|
|
3542
|
-
return await this._runAutoCompaction("threshold", false);
|
|
3543
|
-
}
|
|
3544
|
-
return false;
|
|
2700
|
+
_checkCompaction(assistantMessage, skipAbortedCheck = true) {
|
|
2701
|
+
return this._compaction.check(assistantMessage, skipAbortedCheck);
|
|
3545
2702
|
}
|
|
3546
2703
|
_measureLiveContextTokensForCompaction() {
|
|
3547
|
-
|
|
3548
|
-
const assistantMessage = findLastAssistantMessage(this.agent.state.messages);
|
|
3549
|
-
if (!assistantMessage || assistantMessage.stopReason === "error" || assistantMessage.stopReason === "aborted") {
|
|
3550
|
-
return estimatedTokens;
|
|
3551
|
-
}
|
|
3552
|
-
const compactionEntry = getLatestCompactionEntry(this.sessionManager.getBranch());
|
|
3553
|
-
if (compactionEntry && assistantMessage.timestamp <= new Date(compactionEntry.timestamp).getTime()) {
|
|
3554
|
-
return estimatedTokens;
|
|
3555
|
-
}
|
|
3556
|
-
return Math.max(calculateContextTokens(assistantMessage.usage), estimatedTokens);
|
|
2704
|
+
return this._compaction.measureLiveContextTokens();
|
|
3557
2705
|
}
|
|
3558
2706
|
/**
|
|
3559
2707
|
* Internal: Run auto-compaction with events.
|
|
3560
2708
|
*/
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
const model = this.model;
|
|
3564
|
-
this._emit({ type: "compaction_start", reason });
|
|
3565
|
-
const hadQueuedMessages = this.agent.hasQueuedMessages();
|
|
3566
|
-
this._autoCompactionAbortController = new AbortController();
|
|
3567
|
-
const signal = this._autoCompactionAbortController.signal;
|
|
3568
|
-
let fromExtension = false;
|
|
3569
|
-
let lastCompaction;
|
|
3570
|
-
let extensionCancelled = false;
|
|
3571
|
-
try {
|
|
3572
|
-
if (!model) {
|
|
3573
|
-
this._emit({
|
|
3574
|
-
type: "compaction_end",
|
|
3575
|
-
reason,
|
|
3576
|
-
result: undefined,
|
|
3577
|
-
aborted: false,
|
|
3578
|
-
willRetry: false,
|
|
3579
|
-
skipReason: "no model selected",
|
|
3580
|
-
});
|
|
3581
|
-
return hadQueuedMessages || this.agent.hasQueuedMessages();
|
|
3582
|
-
}
|
|
3583
|
-
const contextWindow = model.contextWindow;
|
|
3584
|
-
const margin = Math.max(0, Math.floor(0.01 * contextWindow));
|
|
3585
|
-
const outcome = await runCompactionLoop({
|
|
3586
|
-
getBranch: () => this.sessionManager.getBranch(),
|
|
3587
|
-
measureLiveTokens: () => this._measureLiveContextTokensForCompaction(),
|
|
3588
|
-
shouldCompact: reason === "overflow"
|
|
3589
|
-
? () => true
|
|
3590
|
-
: (tokens) => shouldCompact(tokens, contextWindow, settings, model.autoCompactionTriggerTokens),
|
|
3591
|
-
getPostApplyMargin: () => margin,
|
|
3592
|
-
getBaseKeepRecentTokens: () => settings.keepRecentTokens,
|
|
3593
|
-
resolveModelAndAuth: async (modelTier) => this._resolveCompactionModelAndAuth(modelTier === "session" ? model : this._resolveCompactionModel(model), model),
|
|
3594
|
-
summarizeAndVerify: async (params, compactModel, apiKey, headers, branchEntries) => {
|
|
3595
|
-
fromExtension = false;
|
|
3596
|
-
const adaptedSettings = { ...settings, keepRecentTokens: params.keepRecentTokens };
|
|
3597
|
-
const preparation = prepareCompaction(branchEntries, adaptedSettings);
|
|
3598
|
-
if (!preparation) {
|
|
3599
|
-
throw new Error("already compacted");
|
|
3600
|
-
}
|
|
3601
|
-
const compactionThinkingLevel = this._resolveCompactionThinkingLevel(compactModel, model);
|
|
3602
|
-
if (this._extensionRunner.hasHandlers("session_before_compact")) {
|
|
3603
|
-
const extensionResult = (await this._extensionRunner.emit({
|
|
3604
|
-
type: "session_before_compact",
|
|
3605
|
-
preparation,
|
|
3606
|
-
branchEntries,
|
|
3607
|
-
customInstructions: undefined,
|
|
3608
|
-
signal,
|
|
3609
|
-
}));
|
|
3610
|
-
if (extensionResult?.cancel) {
|
|
3611
|
-
extensionCancelled = true;
|
|
3612
|
-
throw new Error("auto-compaction-cancelled");
|
|
3613
|
-
}
|
|
3614
|
-
if (extensionResult?.compaction) {
|
|
3615
|
-
fromExtension = true;
|
|
3616
|
-
return { result: extensionResult.compaction };
|
|
3617
|
-
}
|
|
3618
|
-
}
|
|
3619
|
-
const compactResult = await this._compactWithRetry(() => compact(preparation, compactModel, apiKey, headers, undefined, signal, compactionThinkingLevel, this.agent.streamFn, this._buildCompactionPreDigest(), { chunked: params.chunked }), signal, compactModel.provider);
|
|
3620
|
-
return { result: compactResult };
|
|
3621
|
-
},
|
|
3622
|
-
buildDeterministicCheckpoint: async () => {
|
|
3623
|
-
const branch = this.sessionManager.getBranch();
|
|
3624
|
-
const preparation = prepareCompaction(branch, {
|
|
3625
|
-
...settings,
|
|
3626
|
-
});
|
|
3627
|
-
if (!preparation) {
|
|
3628
|
-
throw new Error("already compacted");
|
|
3629
|
-
}
|
|
3630
|
-
fromExtension = false;
|
|
3631
|
-
return { result: createDeterministicCompaction(preparation) };
|
|
3632
|
-
},
|
|
3633
|
-
apply: async (result) => {
|
|
3634
|
-
lastCompaction = result;
|
|
3635
|
-
this.sessionManager.appendCompaction(result.summary, result.firstKeptEntryId, result.tokensBefore, result.details, fromExtension);
|
|
3636
|
-
this._refreshAfterCompaction();
|
|
3637
|
-
const newEntries = this.sessionManager.getEntries();
|
|
3638
|
-
const savedCompactionEntry = newEntries.find((entry) => entry.type === "compaction" && entry.summary === result.summary);
|
|
3639
|
-
if (this._extensionRunner && savedCompactionEntry) {
|
|
3640
|
-
await this._extensionRunner.emit({
|
|
3641
|
-
type: "session_compact",
|
|
3642
|
-
compactionEntry: savedCompactionEntry,
|
|
3643
|
-
fromExtension,
|
|
3644
|
-
});
|
|
3645
|
-
}
|
|
3646
|
-
},
|
|
3647
|
-
verifyPostApplyEffect: reason === "overflow" ? () => false : undefined,
|
|
3648
|
-
onTransition: ({ cycle, cause, detail }) => {
|
|
3649
|
-
this._emit({
|
|
3650
|
-
type: "warning",
|
|
3651
|
-
message: `auto-compaction cycle ${cycle}: ${cause}${detail ? ` (${detail})` : ""} — retrying from step 0 (${this._describeCompactionSummarizer()})`,
|
|
3652
|
-
});
|
|
3653
|
-
},
|
|
3654
|
-
signal,
|
|
3655
|
-
});
|
|
3656
|
-
if (outcome.kind === "skip") {
|
|
3657
|
-
this._emit({
|
|
3658
|
-
type: "compaction_end",
|
|
3659
|
-
reason,
|
|
3660
|
-
result: undefined,
|
|
3661
|
-
aborted: false,
|
|
3662
|
-
willRetry: false,
|
|
3663
|
-
skipReason: outcome.reason,
|
|
3664
|
-
});
|
|
3665
|
-
return hadQueuedMessages || this.agent.hasQueuedMessages();
|
|
3666
|
-
}
|
|
3667
|
-
if (outcome.kind === "failed") {
|
|
3668
|
-
if (outcome.reason === "aborted") {
|
|
3669
|
-
this._emit({ type: "compaction_end", reason, result: undefined, aborted: true, willRetry: false });
|
|
3670
|
-
return hadQueuedMessages || this.agent.hasQueuedMessages();
|
|
3671
|
-
}
|
|
3672
|
-
throw new Error(outcome.reason);
|
|
3673
|
-
}
|
|
3674
|
-
if (extensionCancelled || signal.aborted) {
|
|
3675
|
-
this._emit({ type: "compaction_end", reason, result: undefined, aborted: true, willRetry: false });
|
|
3676
|
-
return hadQueuedMessages || this.agent.hasQueuedMessages();
|
|
3677
|
-
}
|
|
3678
|
-
const result = outcome.kind === "success" ? outcome.result : lastCompaction;
|
|
3679
|
-
if (!result) {
|
|
3680
|
-
throw new Error("Auto-compaction succeeded without a result");
|
|
3681
|
-
}
|
|
3682
|
-
this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
|
|
3683
|
-
if (willRetry) {
|
|
3684
|
-
const messages = this.agent.state.messages;
|
|
3685
|
-
const lastMsg = messages[messages.length - 1];
|
|
3686
|
-
if (lastMsg?.role === "assistant" && lastMsg.stopReason === "error") {
|
|
3687
|
-
this.agent.state.messages = messages.slice(0, -1);
|
|
3688
|
-
}
|
|
3689
|
-
return true;
|
|
3690
|
-
}
|
|
3691
|
-
return hadQueuedMessages || this.agent.hasQueuedMessages();
|
|
3692
|
-
}
|
|
3693
|
-
catch (error) {
|
|
3694
|
-
const errorMessage = error instanceof Error ? error.message : "compaction failed";
|
|
3695
|
-
this._emit({
|
|
3696
|
-
type: "compaction_end",
|
|
3697
|
-
reason,
|
|
3698
|
-
result: undefined,
|
|
3699
|
-
aborted: false,
|
|
3700
|
-
willRetry: false,
|
|
3701
|
-
errorMessage: reason === "overflow"
|
|
3702
|
-
? `Context overflow recovery failed: ${errorMessage}`
|
|
3703
|
-
: `Auto-compaction failed: ${errorMessage}`,
|
|
3704
|
-
});
|
|
3705
|
-
return hadQueuedMessages || this.agent.hasQueuedMessages();
|
|
3706
|
-
}
|
|
3707
|
-
finally {
|
|
3708
|
-
this._autoCompactionAbortController = undefined;
|
|
3709
|
-
}
|
|
2709
|
+
_runAutoCompaction(reason, willRetry) {
|
|
2710
|
+
return this._compaction.runAuto(reason, willRetry);
|
|
3710
2711
|
}
|
|
3711
2712
|
/**
|
|
3712
2713
|
* Run one compaction attempt, retrying retryable provider failures (stream stalls,
|
|
@@ -3716,30 +2717,8 @@ export class AgentSession {
|
|
|
3716
2717
|
* same failure via auto-retry. Caller aborts are never retried; sleepAbortable rejects
|
|
3717
2718
|
* with the abort reason if the signal fires mid-backoff.
|
|
3718
2719
|
*/
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
const maxAttempts = retrySettings.enabled ? Math.max(1, retrySettings.maxRetries + 1) : 1;
|
|
3722
|
-
const policy = {
|
|
3723
|
-
maxAttempts,
|
|
3724
|
-
baseDelayMs: retrySettings.baseDelayMs,
|
|
3725
|
-
maxDelayMs: DEFAULT_RETRY_POLICY.maxDelayMs,
|
|
3726
|
-
jitterRatio: 0,
|
|
3727
|
-
};
|
|
3728
|
-
for (let attempt = 1;; attempt++) {
|
|
3729
|
-
try {
|
|
3730
|
-
return await run();
|
|
3731
|
-
}
|
|
3732
|
-
catch (error) {
|
|
3733
|
-
if (signal.aborted || attempt >= maxAttempts)
|
|
3734
|
-
throw error;
|
|
3735
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
3736
|
-
const classified = classifyFailure({ message, provider });
|
|
3737
|
-
this._failureCorpus.record({ provider, message, classified });
|
|
3738
|
-
if (!classified.retryable)
|
|
3739
|
-
throw error;
|
|
3740
|
-
await sleepAbortable(computeRetryDelayMs(policy, attempt, { retryAfterMs: classified.retryAfterMs }), signal);
|
|
3741
|
-
}
|
|
3742
|
-
}
|
|
2720
|
+
_compactWithRetry(run, signal, provider) {
|
|
2721
|
+
return this._compaction.compactWithRetry(run, signal, provider);
|
|
3743
2722
|
}
|
|
3744
2723
|
/**
|
|
3745
2724
|
* Toggle auto-compaction setting.
|
|
@@ -4018,40 +2997,15 @@ export class AgentSession {
|
|
|
4018
2997
|
// =========================================================================
|
|
4019
2998
|
// Auto-Retry
|
|
4020
2999
|
// =========================================================================
|
|
4021
|
-
/**
|
|
4022
|
-
* Check if an error is retryable (transient provider/network failures). Billing/quota and auth
|
|
4023
|
-
* are terminal; context overflow is handled by compaction, not retry. The verdict comes from the
|
|
4024
|
-
* reliability kernel's classifier, fed the host-computed context-overflow flag.
|
|
4025
|
-
*/
|
|
4026
|
-
_classifyAssistantError(message) {
|
|
4027
|
-
if (message.stopReason !== "error" || !message.errorMessage)
|
|
4028
|
-
return undefined;
|
|
4029
|
-
const contextWindow = this.model?.contextWindow ?? 0;
|
|
4030
|
-
return classifyFailure({
|
|
4031
|
-
message: message.errorMessage,
|
|
4032
|
-
contextOverflow: isContextOverflow(message, contextWindow),
|
|
4033
|
-
provider: message.provider,
|
|
4034
|
-
});
|
|
4035
|
-
}
|
|
4036
|
-
_isRetryableError(message) {
|
|
4037
|
-
return this._classifyAssistantError(message)?.retryable ?? false;
|
|
4038
|
-
}
|
|
4039
|
-
/**
|
|
4040
|
-
* Prepare a retryable error for continuation with exponential backoff.
|
|
4041
|
-
* @returns true if the caller should continue the agent, false otherwise
|
|
4042
|
-
*/
|
|
4043
|
-
async _prepareRetry(message) {
|
|
4044
|
-
return this._retryController.prepareRetry(message);
|
|
4045
|
-
}
|
|
4046
3000
|
/**
|
|
4047
3001
|
* Cancel in-progress retry.
|
|
4048
3002
|
*/
|
|
4049
3003
|
abortRetry() {
|
|
4050
|
-
this.
|
|
3004
|
+
this._foregroundRecovery.abortRetry();
|
|
4051
3005
|
}
|
|
4052
3006
|
/** Whether auto-retry is currently in progress */
|
|
4053
3007
|
get isRetrying() {
|
|
4054
|
-
return this.
|
|
3008
|
+
return this._foregroundRecovery.isRetrying;
|
|
4055
3009
|
}
|
|
4056
3010
|
/** Whether auto-retry is enabled */
|
|
4057
3011
|
get autoRetryEnabled() {
|
|
@@ -4131,39 +3085,35 @@ export class AgentSession {
|
|
|
4131
3085
|
*
|
|
4132
3086
|
* @returns the id of the appended custom entry
|
|
4133
3087
|
*/
|
|
4134
|
-
saveGoalStateSnapshot(state) {
|
|
4135
|
-
return
|
|
3088
|
+
saveGoalStateSnapshot(state, expected) {
|
|
3089
|
+
return this._goals.saveState(state, expected);
|
|
3090
|
+
}
|
|
3091
|
+
/** Persist a branch-scoped tombstone and stop goal-owned execution without resurrecting old state. */
|
|
3092
|
+
clearGoalStateSnapshot(state, now) {
|
|
3093
|
+
return this._goals.clearState(state, now);
|
|
4136
3094
|
}
|
|
4137
3095
|
/**
|
|
4138
3096
|
* Retrieve the latest valid goal state snapshot from the session log.
|
|
4139
3097
|
*/
|
|
4140
3098
|
getGoalStateSnapshot() {
|
|
4141
|
-
return
|
|
3099
|
+
return this._goals.getState();
|
|
4142
3100
|
}
|
|
4143
3101
|
/**
|
|
4144
|
-
* Persist one submitted continuation pass's turn/wall-clock/spend contribution onto the active
|
|
4145
|
-
* goal's durable cumulative
|
|
3102
|
+
* Persist one submitted continuation pass's exact turn/wall-clock/token/spend contribution onto the active
|
|
3103
|
+
* goal's durable cumulative accounting (see `GoalState.continuationTurnsUsed` et al.). This is the
|
|
4146
3104
|
* "persistence dep" `GoalLoopController` calls once per pass actually submitted — it, not the
|
|
4147
|
-
* loop controller, is where
|
|
4148
|
-
*
|
|
4149
|
-
*
|
|
4150
|
-
* `record_continuation_budget` event; the pure reducer in `goal-state.ts` derives the delta.
|
|
3105
|
+
* loop controller, is where usage gets attributed: it scans only assistant messages appended on
|
|
3106
|
+
* the active branch after the pass's captured cursor. Compaction cannot erase or reattribute that
|
|
3107
|
+
* append-only interval, and unrelated foreground turns outside the interval are excluded.
|
|
4151
3108
|
* A no-op when no goal state exists (defensive — in practice this is only ever called right
|
|
4152
3109
|
* after a pass the loop already confirmed was submitted against an active goal).
|
|
4153
3110
|
*/
|
|
4154
3111
|
recordGoalContinuationPass(pass) {
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
type: "record_continuation_budget",
|
|
4161
|
-
turns: pass.turns,
|
|
4162
|
-
wallClockMs: pass.wallClockMs,
|
|
4163
|
-
sessionCostUsd,
|
|
4164
|
-
now: new Date().toISOString(),
|
|
4165
|
-
});
|
|
4166
|
-
this.saveGoalStateSnapshot(updated);
|
|
3112
|
+
this._goals.recordContinuationPass(pass);
|
|
3113
|
+
}
|
|
3114
|
+
/** Restore runtime intent without mutating persisted goal lifecycle state. */
|
|
3115
|
+
restoreGoalRuntimeAfterResume() {
|
|
3116
|
+
this._goals.restoreAfterResume();
|
|
4167
3117
|
}
|
|
4168
3118
|
/** Save native task-step state to the active session log. */
|
|
4169
3119
|
saveTaskStepsStateSnapshot(state) {
|
|
@@ -4182,13 +3132,14 @@ export class AgentSession {
|
|
|
4182
3132
|
return appendEvidenceBundleSnapshot(this.sessionManager, bundle);
|
|
4183
3133
|
}
|
|
4184
3134
|
/**
|
|
4185
|
-
* Retrieve the latest valid evidence bundle snapshot from the
|
|
3135
|
+
* Retrieve the latest valid evidence bundle snapshot from the active branch.
|
|
4186
3136
|
*/
|
|
4187
3137
|
getEvidenceBundleSnapshot() {
|
|
4188
|
-
return getLatestEvidenceBundleSnapshot(this.sessionManager
|
|
3138
|
+
return getLatestEvidenceBundleSnapshot(getActiveSessionBranchEntries(this.sessionManager));
|
|
4189
3139
|
}
|
|
3140
|
+
/** Retrieve all valid evidence bundle snapshots from the active branch. */
|
|
4190
3141
|
getEvidenceBundleSnapshots() {
|
|
4191
|
-
return getEvidenceBundleSnapshots(this.sessionManager
|
|
3142
|
+
return getEvidenceBundleSnapshots(getActiveSessionBranchEntries(this.sessionManager));
|
|
4192
3143
|
}
|
|
4193
3144
|
/** Live lane records tracked by this process (running and terminal). */
|
|
4194
3145
|
getLaneRecords() {
|
|
@@ -4207,17 +3158,17 @@ export class AgentSession {
|
|
|
4207
3158
|
getGateOutcomeHistory() {
|
|
4208
3159
|
return this._autonomyTelemetry.getGateOutcomeHistory();
|
|
4209
3160
|
}
|
|
4210
|
-
|
|
4211
|
-
return
|
|
3161
|
+
saveWorkerClaimSnapshot(claim, request) {
|
|
3162
|
+
return appendWorkerClaimSnapshot(this.sessionManager, claim, request);
|
|
4212
3163
|
}
|
|
4213
|
-
|
|
4214
|
-
return
|
|
3164
|
+
getWorkerClaimSnapshots() {
|
|
3165
|
+
return getWorkerClaimSnapshots(getActiveSessionBranchEntries(this.sessionManager));
|
|
4215
3166
|
}
|
|
4216
3167
|
saveLearningDecisionSnapshot(decision) {
|
|
4217
3168
|
return appendLearningDecisionSnapshot(this.sessionManager, decision);
|
|
4218
3169
|
}
|
|
4219
3170
|
getLearningDecisionSnapshots() {
|
|
4220
|
-
return getLearningDecisionSnapshots(this.sessionManager
|
|
3171
|
+
return getLearningDecisionSnapshots(getActiveSessionBranchEntries(this.sessionManager));
|
|
4221
3172
|
}
|
|
4222
3173
|
/**
|
|
4223
3174
|
* The single injection point that makes the goal-continuation snapshot lane-aware:
|
|
@@ -4227,11 +3178,7 @@ export class AgentSession {
|
|
|
4227
3178
|
* same live lane state, since both reach this same method.
|
|
4228
3179
|
*/
|
|
4229
3180
|
getGoalRuntimeSnapshot(settings) {
|
|
4230
|
-
return
|
|
4231
|
-
sessionManager: this.sessionManager,
|
|
4232
|
-
settings,
|
|
4233
|
-
laneRecords: this._backgroundLanes.getLaneRecords(),
|
|
4234
|
-
});
|
|
3181
|
+
return this._goals.getRuntimeSnapshot(settings);
|
|
4235
3182
|
}
|
|
4236
3183
|
/**
|
|
4237
3184
|
* Capability profile derived from the CURRENT session model's own metadata (context window),
|
|
@@ -4254,7 +3201,7 @@ export class AgentSession {
|
|
|
4254
3201
|
getLaneWorkerRefusal() {
|
|
4255
3202
|
const profile = this.getModelCapabilityProfile();
|
|
4256
3203
|
const model = this.model;
|
|
4257
|
-
const verdict = model ? this.
|
|
3204
|
+
const verdict = model ? this._toolProtocol.getToolProbeVerdict(model) : undefined;
|
|
4258
3205
|
return evaluateLaneWorkerRefusal({
|
|
4259
3206
|
capabilityClass: profile.class,
|
|
4260
3207
|
contextWindow: profile.contextWindow,
|
|
@@ -4270,7 +3217,7 @@ export class AgentSession {
|
|
|
4270
3217
|
return this._backgroundLanes.runResearchLaneOnce(request);
|
|
4271
3218
|
}
|
|
4272
3219
|
/**
|
|
4273
|
-
* Run one bounded
|
|
3220
|
+
* Run one bounded profile-bound worker delegation. Delegates to {@link BackgroundLaneController};
|
|
4274
3221
|
* consumed by the `delegate` tool.
|
|
4275
3222
|
*/
|
|
4276
3223
|
async runWorkerDelegationOnce(request) {
|
|
@@ -4288,14 +3235,14 @@ export class AgentSession {
|
|
|
4288
3235
|
return this._backgroundLanes.getStoredFitnessReports();
|
|
4289
3236
|
}
|
|
4290
3237
|
async continueGoalOnce(options) {
|
|
4291
|
-
return this.
|
|
3238
|
+
return this._goals.continueOnce(options);
|
|
4292
3239
|
}
|
|
4293
3240
|
/**
|
|
4294
3241
|
* Public entry point for BOTH idle autosteer and manual (`/goal start`, `/goal-continue`)
|
|
4295
3242
|
* continuation. Delegates to {@link BackgroundLaneController.continueGoalLoopExclusive}, the
|
|
4296
3243
|
* single-flight guard that prevents two goal loops from racing to submit prompts through the
|
|
4297
3244
|
* same session (which throws "Agent is already processing" from the second submission). Do not
|
|
4298
|
-
* call `this.
|
|
3245
|
+
* call `this._goals.continueLoop` directly from here — that bypasses the guard.
|
|
4299
3246
|
*/
|
|
4300
3247
|
async continueGoalLoop(options) {
|
|
4301
3248
|
return this._backgroundLanes.continueGoalLoopExclusive(options);
|
|
@@ -4370,13 +3317,4 @@ export class AgentSession {
|
|
|
4370
3317
|
return this._extensionRunner;
|
|
4371
3318
|
}
|
|
4372
3319
|
}
|
|
4373
|
-
function findLastAssistantMessage(messages) {
|
|
4374
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
4375
|
-
const message = messages[i];
|
|
4376
|
-
if (message.role === "assistant") {
|
|
4377
|
-
return message;
|
|
4378
|
-
}
|
|
4379
|
-
}
|
|
4380
|
-
return undefined;
|
|
4381
|
-
}
|
|
4382
3320
|
//# sourceMappingURL=agent-session.js.map
|