@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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-controller.d.ts","sourceRoot":"","sources":["../../src/core/memory-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Memory controller: the session's plug-and-play memory subsystem — the read-only OKF retrieval\n * provider, the bounded prompt-evidence surfacing pilot, cross-session recall effectiveness, and the\n * live {@link MemoryManager} (bundled file-store + transcript-recall providers plus any extension\n * contributions).\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Owns the lazily-built OKF\n * provider, the latest retrieval/prompt-inclusion reports, the recreated-on-reload MemoryManager, the\n * recall {@link EffectivenessTracker}, and the extension-contributed pending providers. Everything\n * else it needs — settings, the current turn index, agent/workspace dirs, the session id, the\n * child-session flag, and the tool-registry refresh — is reached through narrow deps accessors rather\n * than the whole AgentSession.\n *\n * Context-transform boundary (deliberate): {@link runMemoryRetrieval} and\n * {@link maybeAppendMemoryEvidenceBlock} are invoked from the session's context transform as one-line\n * delegations. This controller deliberately imports no compaction/context-pipeline internals — it only\n * ever reads settings and builds the retrieval report + the bounded evidence block, so the transform\n * stays the single owner of the pass ordering.\n */\n\nimport { join } from \"node:path\";\nimport type { AgentMessage, CustomMessage } from \"@caupulican/pi-agent-core\";\nimport { collectCurrentWorkMemory } from \"./context/current-work-memory.ts\";\nimport { createFileStoreMemoryProvider } from \"./context/file-store-memory-provider.ts\";\nimport { shouldQueryLongTermMemory } from \"./context/long-term-memory-trigger.ts\";\nimport {\n\tdefaultMemoryPromptInclusionReport,\n\ttype MemoryPromptInclusionReport,\n\ttype MemoryRetrievalDiagnostics,\n\tsanitizeMemoryRetrievalReportForDiagnostics,\n} from \"./context/memory-diagnostics.ts\";\nimport { type MemoryPromptBudget, resolveMemoryPromptBudget } from \"./context/memory-prompt-budget.ts\";\nimport {\n\ttype MemoryProvider as ContextMemoryProvider,\n\tDEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\tDEFAULT_LOCAL_MEMORY_EGRESS_POLICY,\n} from \"./context/memory-provider-contract.ts\";\nimport { type MemoryRetrievalReport, retrieveMemoryForContext } from \"./context/memory-retrieval.ts\";\nimport { composeTieredMemoryPromptBlock, type MemoryTierCandidate } from \"./context/memory-tier-composer.ts\";\nimport { createOkfMemoryProvider } from \"./context/okf-memory-provider.ts\";\nimport type { GoalState } from \"./goals/goal-state.ts\";\nimport { EffectivenessTracker } from \"./memory/effectiveness-tracker.ts\";\nimport { MemoryManager } from \"./memory/memory-manager.ts\";\nimport type { MemoryProvider } from \"./memory/memory-provider.ts\";\nimport { FileStoreProvider } from \"./memory/providers/file-store.ts\";\nimport { TranscriptRecallProvider } from \"./memory/providers/transcript-recall.ts\";\nimport { wrapUntrustedText } from \"./security/untrusted-boundary.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/**\n * Text of the most recent user message, or \"\" if there is none (e.g. goal-continuation\n * turns with no new user input). An empty query is still valid: standing user preferences may\n * surface from the file-store retrieval fallback when the static memory prompt cannot fit,\n * while long-term providers remain gated by shouldQueryLongTermMemory().\n */\nfunction latestUserMessageText(messages: AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message.role !== \"user\") continue;\n\t\tif (typeof message.content === \"string\") return message.content;\n\t\tconst parts: string[] = [];\n\t\tfor (const part of message.content) {\n\t\t\tif (part.type === \"text\") parts.push(part.text);\n\t\t}\n\t\treturn parts.join(\"\\n\");\n\t}\n\treturn \"\";\n}\n\nfunction emptyMemoryRetrievalReport(maxResults: number): MemoryRetrievalReport {\n\treturn { request: { query: \"\", maxResults }, providerReports: [], results: [], contextItems: [] };\n}\n\nconst ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY = {\n\t...DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\tenabled: true,\n\tallowedScopes: DEFAULT_LOCAL_MEMORY_EGRESS_POLICY.allowedScopes,\n\tallowExternalEgress: true,\n} as const;\n\nexport interface MemoryControllerDeps {\n\t/** Memory-retrieval + prompt-inclusion settings (default-on gates for retrieval and surfacing). */\n\tgetSettingsManager(): SettingsManager;\n\t/** Current turn index, stamped into a retrieval request's `createdAtTurn`. */\n\tgetTurnIndex(): number;\n\t/** Agent root — the durable OKF memory docs live under `<agentDir>/okf-memory`. */\n\tgetAgentDir(): string;\n\t/** Workspace root, passed to provider initialization. */\n\tgetCwd(): string;\n\t/** This session's id, passed to provider initialization. */\n\tgetSessionId(): string;\n\t/** Child sessions gate durable memory writes; passed to provider initialization. */\n\tisChildSession(): boolean;\n\t/** Re-derive the tool registry after (re)init so the newly-surfaced memory tools take effect. */\n\trefreshToolRegistry(): void;\n\t/** Active model context window, used to cap prompt-visible memory. */\n\tgetContextWindow(): number | undefined;\n\t/** Latest active goal state, used for short-term current-work memory. */\n\tgetGoalState(): GoalState | undefined;\n}\n\n/** Extension-contributed memory state staged across an atomic runtime reload. */\nexport interface MemoryControllerReloadSnapshot {\n\tpendingMemoryProviders: MemoryProvider[];\n\tpendingContextMemoryProviders: ContextMemoryProvider[];\n\tmemoryOkfProvider: ContextMemoryProvider | undefined;\n\tfileStoreMemoryProvider: ContextMemoryProvider | undefined;\n}\n\nexport class MemoryController {\n\tprivate _memoryOkfProvider: ContextMemoryProvider | undefined = undefined;\n\tprivate _fileStoreMemoryProvider: ContextMemoryProvider | undefined = undefined;\n\tprivate _latestMemoryRetrievalReport: MemoryRetrievalReport | undefined = undefined;\n\tprivate _latestMemoryPromptInclusionReport: MemoryPromptInclusionReport | undefined = undefined;\n\t/** Plug-and-play memory subsystem. Recreated on each (re)initialize so reload is safe. */\n\tprivate _memoryManager: MemoryManager = new MemoryManager();\n\t/** R4: tracks whether injected recall is actually used, to adapt the recall gate. */\n\tprivate readonly _effectivenessTracker = new EffectivenessTracker();\n\t/** Memory providers registered by extensions via pi.registerMemoryProvider, applied on (re)init. */\n\tprivate _pendingMemoryProviders: MemoryProvider[] = [];\n\t/** Context-memory providers registered by extensions via pi.registerContextMemoryProvider. */\n\tprivate _pendingContextMemoryProviders: ContextMemoryProvider[] = [];\n\n\tprivate readonly deps: MemoryControllerDeps;\n\n\tconstructor(deps: MemoryControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\t/** The live memory manager. Callers reach prefetch / tool-definitions / markers / shutdown through it. */\n\tgetMemoryManager(): MemoryManager {\n\t\treturn this._memoryManager;\n\t}\n\n\t/**\n\t * Fixed path for this slice's local Pi OKF memory documents, shared across sessions\n\t * under this agentDir (not session-scoped, unlike tool-artifacts/context-gc, since OKF\n\t * memory represents durable cross-session knowledge, not a per-session capture). Not\n\t * yet user-configurable -- see the memory-retrieval settings doc comment.\n\t */\n\tprivate _memoryOkfDir(): string {\n\t\treturn join(this.deps.getAgentDir(), \"okf-memory\");\n\t}\n\n\t/**\n\t * Session-scoped, read-only local OKF memory provider. Lazily created ONLY when memory\n\t * retrieval is enabled (see `runMemoryRetrieval`) -- never force-created, so a session\n\t * with the setting off never touches `_memoryOkfDir()` at all (no directory access, no\n\t * creation; `createOkfMemoryProvider` itself never writes/mkdirs either way).\n\t */\n\tprivate _getMemoryOkfProvider(): ContextMemoryProvider {\n\t\tthis._memoryOkfProvider ??= createOkfMemoryProvider({ rootDir: this._memoryOkfDir() });\n\t\treturn this._memoryOkfProvider;\n\t}\n\n\tprivate _getFileStoreMemoryProvider(): ContextMemoryProvider {\n\t\tthis._fileStoreMemoryProvider ??= createFileStoreMemoryProvider({\n\t\t\tmemoryFilePath: join(this.deps.getAgentDir(), \"MEMORY.md\"),\n\t\t\tuserFilePath: join(this.deps.getAgentDir(), \"USER.md\"),\n\t\t});\n\t\treturn this._fileStoreMemoryProvider;\n\t}\n\n\tprivate _memoryBudget(configuredMaxResults: number) {\n\t\treturn resolveMemoryPromptBudget({\n\t\t\tcontextWindow: this.deps.getContextWindow(),\n\t\t\tconfiguredMaxResults,\n\t\t});\n\t}\n\n\tprivate _shouldQueryFileStoreFallback(budget: MemoryPromptBudget): boolean {\n\t\t// MEMORY.md/USER.md are already injected through the static file-store prompt on\n\t\t// normal windows, so querying them again would duplicate provider-visible memory.\n\t\t// In compact windows the static block can be omitted because it does not fit; only\n\t\t// then use the retrieval view to surface a few budget-pruned lines.\n\t\tif (!budget.enabled || !budget.compact) return false;\n\t\treturn this._memoryManager.buildSystemPromptBlock(budget).trim().length === 0;\n\t}\n\n\t/**\n\t * Observe-only local memory retrieval (see context/memory-retrieval.ts and\n\t * context/okf-memory-provider.ts): default-on, but settings-gated. When disabled,\n\t * never constructs built-in context-memory providers (no directory access under\n\t * `_memoryOkfDir()` at all) and returns an empty report -- fully fail-closed. When enabled,\n\t * queries local, read-only providers with the latest user message text (empty if there is\n\t * none, e.g. a goal-continuation turn) under `DEFAULT_LOCAL_MEMORY_EGRESS_POLICY`.\n\t * Retrieved items are only ever stored in the report; nothing here touches `messages`,\n\t * the transcript, or the provider-visible prompt. Never throws into a live turn: any\n\t * failure (including a provider search error) degrades to an empty report.\n\t */\n\tasync runMemoryRetrieval(messages: AgentMessage[]): Promise<MemoryRetrievalReport> {\n\t\ttry {\n\t\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\t\tif (!settings.enabled) {\n\t\t\t\tconst report = emptyMemoryRetrievalReport(settings.maxResults);\n\t\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\t\treturn report;\n\t\t\t}\n\t\t\tconst query = latestUserMessageText(messages);\n\t\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\t\tconst currentWork = collectCurrentWorkMemory({ goalState: this.deps.getGoalState() });\n\t\t\tconst longTermDecision = shouldQueryLongTermMemory({\n\t\t\t\tlatestUserText: query,\n\t\t\t\tgoalState: this.deps.getGoalState(),\n\t\t\t\tbudget,\n\t\t\t\tcurrentWorkCandidateCount: currentWork.length,\n\t\t\t});\n\t\t\tconst providers = this._shouldQueryFileStoreFallback(budget) ? [this._getFileStoreMemoryProvider()] : [];\n\t\t\tif (longTermDecision.shouldQuery) {\n\t\t\t\tproviders.push(this._getMemoryOkfProvider(), ...this._pendingContextMemoryProviders);\n\t\t\t}\n\t\t\tconst maxResults = budget.enabled ? Math.min(settings.maxResults, budget.maxResults) : settings.maxResults;\n\t\t\tconst report = await retrieveMemoryForContext(\n\t\t\t\tproviders,\n\t\t\t\t{ query, maxResults },\n\t\t\t\t{\n\t\t\t\t\tcreatedAtTurn: this.deps.getTurnIndex(),\n\t\t\t\t\tmaxResults,\n\t\t\t\t\tdefaultLocalPolicy: DEFAULT_LOCAL_MEMORY_EGRESS_POLICY,\n\t\t\t\t\tdefaultExternalPolicy: settings.allowExternalEgress\n\t\t\t\t\t\t? ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY\n\t\t\t\t\t\t: DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\treturn report;\n\t\t} catch {\n\t\t\tconst report = emptyMemoryRetrievalReport(0);\n\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\treturn report;\n\t\t}\n\t}\n\n\t/** Read-only inspection of the latest memory-retrieval report, for tests/debugging. */\n\tgetMemoryRetrievalReport(): MemoryRetrievalReport {\n\t\treturn this._latestMemoryRetrievalReport ?? emptyMemoryRetrievalReport(0);\n\t}\n\n\tprivate _candidateForContextItem(\n\t\titem: MemoryRetrievalReport[\"contextItems\"][number],\n\t): MemoryTierCandidate | undefined {\n\t\tconst summary = item.summary?.trim();\n\t\tif (!summary) return undefined;\n\t\tconst ref = item.primaryRef?.type === \"memory\" ? item.primaryRef.ref : undefined;\n\t\tconst sourceLabel =\n\t\t\tref?.providerId === \"pi-file-store\" && ref.kind === \"user_preference\"\n\t\t\t\t? \"rule:user\"\n\t\t\t\t: `memory:${ref?.providerId ?? item.source}`;\n\t\tconst tier = ref?.kind === \"user_preference\" ? \"standing\" : \"long_term\";\n\t\treturn {\n\t\t\tid: item.id,\n\t\t\ttier,\n\t\t\tsourceLabel,\n\t\t\tsummary,\n\t\t\tscore: 0.5,\n\t\t\tevidenceRefs: item.evidenceRefs,\n\t\t};\n\t}\n\n\tprivate _memoryCandidates(report: MemoryRetrievalReport): MemoryTierCandidate[] {\n\t\treturn [\n\t\t\t...collectCurrentWorkMemory({ goalState: this.deps.getGoalState() }),\n\t\t\t...report.contextItems.flatMap((item) => {\n\t\t\t\tconst candidate = this._candidateForContextItem(item);\n\t\t\t\treturn candidate === undefined ? [] : [candidate];\n\t\t\t}),\n\t\t];\n\t}\n\n\t/**\n\t * Bounded prompt-surfacing for local memory evidence (see context/memory-tier-composer.ts):\n\t * default-on, but gated on TWO settings (`enabled` AND `includeInPrompt`) plus at least one\n\t * current-work, standing, or retrieved memory candidate -- the first\n\t * two are belt-and-suspenders on top of the fact that `runMemoryRetrieval` already\n\t * leaves `contextItems` empty whenever `enabled` is false, regardless of\n\t * `includeInPrompt`. Reuses the `report` this pass's `runMemoryRetrieval` call already\n\t * computed -- never re-queries the provider here.\n\t *\n\t * Appends exactly one ephemeral `custom`/\"memory_evidence\" message wrapped by\n\t * `wrapUntrustedText` (the same nonce-fenced boundary + always-on system-prompt rule\n\t * used for other untrusted content) to the END of `messages`. This is purely additive\n\t * (never mutates an existing message) and purely transient: `messages` here is the\n\t * array about to be sent to the provider, not `this.agent.state.messages` or anything\n\t * persisted via `sessionManager` -- so the injected message can never reach the\n\t * transcript, regardless of how many times this pass runs.\n\t *\n\t * Also records a `MemoryPromptInclusionReport` (context/memory-diagnostics.ts) at each\n\t * branch below, for context_audit's diagnostic surface only -- this is pure bookkeeping\n\t * alongside the existing branches, not a new branch/condition: the messages returned\n\t * are unchanged by this recording.\n\t */\n\tmaybeAppendMemoryEvidenceBlock(messages: AgentMessage[], report: MemoryRetrievalReport): AgentMessage[] {\n\t\ttry {\n\t\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\t\tconst candidates = this._memoryCandidates(report);\n\t\t\tconst base = {\n\t\t\t\tenabled: settings.enabled,\n\t\t\t\tincludeInPrompt: settings.includeInPrompt,\n\t\t\t\tselectedItemCount: candidates.length,\n\t\t\t};\n\t\t\tif (!settings.enabled) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"disabled\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tif (!settings.includeInPrompt) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"include_disabled\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tif (candidates.length === 0) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"no_results\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\n\t\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\t\tconst block = composeTieredMemoryPromptBlock(candidates, budget);\n\t\t\tif (!block.text) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"empty_block\",\n\t\t\t\t\tincludedCount: block.includedCount,\n\t\t\t\t\tomittedCount: block.omittedCount,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\n\t\t\tconst wrapped = wrapUntrustedText(block.text, \"memory:tiered\");\n\t\t\tconst evidenceMessage: CustomMessage = {\n\t\t\t\trole: \"custom\",\n\t\t\t\tcustomType: \"memory_evidence\",\n\t\t\t\tcontent: [{ type: \"text\", text: wrapped }],\n\t\t\t\tdisplay: false,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t...base,\n\t\t\t\tstatus: \"included\",\n\t\t\t\tincludedCount: block.includedCount,\n\t\t\t\tomittedCount: block.omittedCount,\n\t\t\t\tblockChars: wrapped.length,\n\t\t\t\tsourceLabel: \"memory:tiered\",\n\t\t\t};\n\t\t\treturn [...messages, evidenceMessage];\n\t\t} catch {\n\t\t\t// `base` may not exist yet if the throw happened before it was computed (e.g.\n\t\t\t// settings access or `report.contextItems` itself threw), so this branch cannot\n\t\t\t// rely on it -- fall back to safe, fixed defaults rather than risk referencing\n\t\t\t// a partially-evaluated value.\n\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\tenabled: false,\n\t\t\t\tincludeInPrompt: false,\n\t\t\t\tselectedItemCount: 0,\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tincludedCount: 0,\n\t\t\t\tomittedCount: 0,\n\t\t\t\tblockChars: 0,\n\t\t\t};\n\t\t\treturn messages;\n\t\t}\n\t}\n\n\t/** Read-only inspection of the latest memory-prompt-inclusion decision, for tests/debugging and context_audit. */\n\tgetMemoryPromptInclusionReport(): MemoryPromptInclusionReport {\n\t\treturn this._latestMemoryPromptInclusionReport ?? defaultMemoryPromptInclusionReport();\n\t}\n\n\t/**\n\t * Combines the already-stored, no-arg latest reports (never re-queries the provider or\n\t * touches the OKF directory) into the safe, allow-list-projected shape context_audit\n\t * exposes. See context/memory-diagnostics.ts for why this projection is allow-list\n\t * based rather than a spread-then-delete of the raw report.\n\t */\n\tgetMemoryAuditDiagnostics(): {\n\t\tretrieval: MemoryRetrievalDiagnostics;\n\t\tpromptInclusion: MemoryPromptInclusionReport;\n\t} {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\treturn {\n\t\t\tretrieval: sanitizeMemoryRetrievalReportForDiagnostics(this.getMemoryRetrievalReport(), settings),\n\t\t\tpromptInclusion: this.getMemoryPromptInclusionReport(),\n\t\t};\n\t}\n\n\t/**\n\t * Zero-I/O gate for cross-session recall (R3): skip trivial turns (short acks, slash commands) so\n\t * recall only runs when it could plausibly help. The provider's similarity cutoff is the real\n\t * filter — this just avoids the index query on turns that obviously don't warrant it.\n\t */\n\tshouldAttemptRecall(text: string): boolean {\n\t\tif (!this.deps.getSettingsManager().getMemoryRetrievalSettings().enabled) return false;\n\t\tconst t = text.trim();\n\t\tif (t.length < 12 || t.startsWith(\"/\")) return false;\n\t\tconst words = t.split(/\\s+/).filter((w) => w.length >= 3);\n\t\t// R4 adaptive gate: if recall has rarely been used lately (enough samples to trust the signal),\n\t\t// raise the bar so we only recall on clearly substantial turns — and relax it again once recall\n\t\t// starts paying off. Never fully disabled, so the loop can recover.\n\t\tconst recallRarelyUseful =\n\t\t\tthis._effectivenessTracker.sampleCount >= 5 && this._effectivenessTracker.usefulLately() < 0.15;\n\t\treturn words.length >= (recallRarelyUseful ? 6 : 3);\n\t}\n\n\t/** Legacy recall prefetch with the same hard-off and explicit external-egress policy as context retrieval. */\n\tasync prefetchRecall(query: string): Promise<string> {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\tif (!settings.enabled) return \"\";\n\t\treturn this._memoryManager.prefetch(query, {\n\t\t\texternalEgressPolicy: settings.allowExternalEgress\n\t\t\t\t? ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY\n\t\t\t\t: DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\t\t});\n\t}\n\n\t/** Bounded, read-only memory view for an explicitly authorized delegated worker. */\n\tasync readMemoryForLane(query: string): Promise<string> {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\tif (!settings.enabled) return \"Memory retrieval is disabled by policy.\";\n\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\tconst staticBlock = this._memoryManager\n\t\t\t.buildSystemPromptBlockFresh(budget)\n\t\t\t.replace(\n\t\t\t\t\"[System Note: Below is a snapshot of your persistent memory. You can update these using the 'memory' tool.]\",\n\t\t\t\t\"[Read-only snapshot for a delegated worker.]\",\n\t\t\t);\n\t\tconst recalled = await this.prefetchRecall(query);\n\t\tconst combined = [staticBlock, recalled]\n\t\t\t.filter((part) => part.trim().length > 0)\n\t\t\t.join(\"\\n\\n\")\n\t\t\t.slice(0, 8000);\n\t\treturn combined.length > 0\n\t\t\t? wrapUntrustedText(combined, \"worker-memory\")\n\t\t\t: \"No relevant standing memory was found.\";\n\t}\n\n\t/** R4: score whether the agent actually used an injected recall page, so the recall gate can adapt. */\n\trecordRecallOutcome(recallText: string, queryText: string, responseText: string): void {\n\t\tthis._effectivenessTracker.recordRecallOutcome(recallText, queryText, responseText);\n\t}\n\n\t/**\n\t * (Re)build the memory subsystem: a fresh MemoryManager (reload-safe), register the bundled\n\t * file-store + any extension-contributed providers, initialize, then surface the memory tools and\n\t * the frozen system-prompt block. Best-effort: never throws into the session lifecycle.\n\t */\n\tasync initialize(): Promise<void> {\n\t\ttry {\n\t\t\t// Release the previous generation's providers (locks/handles) before recreating, so a\n\t\t\t// reload does not orphan the old MemoryManager. No-op on first init / for file-store.\n\t\t\tawait this._memoryManager.shutdownAll().catch(() => {});\n\t\t\tconst manager = new MemoryManager();\n\t\t\tmanager.registerProvider(new FileStoreProvider());\n\t\t\t// Bundled read-only cross-session recall (R3): indexes past-session transcripts and answers\n\t\t\t// prefetch() with a <memory_context> page. Never writes.\n\t\t\tmanager.registerProvider(new TranscriptRecallProvider());\n\t\t\tfor (const provider of this._pendingMemoryProviders) {\n\t\t\t\ttry {\n\t\t\t\t\tmanager.registerProvider(provider);\n\t\t\t\t} catch {\n\t\t\t\t\t// Duplicate name or reserved-tool collision — skip this provider, keep the rest.\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._memoryManager = manager;\n\t\t\tawait manager.initializeAll(this.deps.getSessionId(), {\n\t\t\t\tagentDir: this.deps.getAgentDir(),\n\t\t\t\tcwd: this.deps.getCwd(),\n\t\t\t\tisChildSession: this.deps.isChildSession(),\n\t\t\t});\n\t\t\t// Surface memory tools + the frozen memory block now that providers are initialized.\n\t\t\t// refreshToolRegistry() ends in setActiveToolsByName(), which rebuilds AND assigns the\n\t\t\t// system prompt (including the memory block), so no explicit _rebuildSystemPrompt is needed.\n\t\t\tthis.deps.refreshToolRegistry();\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Memory subsystem init failed:\", error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n\n\t/** Register a memory provider contributed by an extension; applied on the next memory (re)init. */\n\tregisterMemoryProvider(provider: MemoryProvider): void {\n\t\tif (!this._pendingMemoryProviders.some((p) => p.name === provider.name)) {\n\t\t\tthis._pendingMemoryProviders.push(provider);\n\t\t}\n\t}\n\n\t/** Register a retrieval-style context memory provider contributed by an extension. */\n\tregisterContextMemoryProvider(provider: ContextMemoryProvider): void {\n\t\tif (!this._pendingContextMemoryProviders.some((p) => p.id === provider.id)) {\n\t\t\tthis._pendingContextMemoryProviders.push(provider);\n\t\t}\n\t}\n\n\tcreateReloadSnapshot(): MemoryControllerReloadSnapshot {\n\t\treturn {\n\t\t\tpendingMemoryProviders: [...this._pendingMemoryProviders],\n\t\t\tpendingContextMemoryProviders: [...this._pendingContextMemoryProviders],\n\t\t\tmemoryOkfProvider: this._memoryOkfProvider,\n\t\t\tfileStoreMemoryProvider: this._fileStoreMemoryProvider,\n\t\t};\n\t}\n\n\trestoreReloadSnapshot(snapshot: MemoryControllerReloadSnapshot): void {\n\t\tthis._pendingMemoryProviders = [...snapshot.pendingMemoryProviders];\n\t\tthis._pendingContextMemoryProviders = [...snapshot.pendingContextMemoryProviders];\n\t\tthis._memoryOkfProvider = snapshot.memoryOkfProvider;\n\t\tthis._fileStoreMemoryProvider = snapshot.fileStoreMemoryProvider;\n\t}\n\n\t/** Reload starts memory providers fresh; loaded extensions re-register before the next `initialize()`. */\n\tclearPendingProviders(): void {\n\t\tthis._pendingMemoryProviders = [];\n\t\tthis._pendingContextMemoryProviders = [];\n\t\tthis._memoryOkfProvider = undefined;\n\t\tthis._fileStoreMemoryProvider = undefined;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"memory-controller.d.ts","sourceRoot":"","sources":["../../src/core/memory-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Memory controller: the session's plug-and-play memory subsystem — the read-only OKF retrieval\n * provider, the bounded prompt-evidence surfacing pilot, cross-session recall effectiveness, and the\n * live {@link MemoryManager} (bundled file-store + transcript-recall providers plus any extension\n * contributions).\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Owns the lazily-built OKF\n * provider, the latest retrieval/prompt-inclusion reports, the recreated-on-reload MemoryManager, the\n * recall {@link EffectivenessTracker}, and the extension-contributed pending providers. Everything\n * else it needs — settings, the current turn index, agent/workspace dirs, the session id, the\n * child-session flag, and the tool-registry refresh — is reached through narrow deps accessors rather\n * than the whole AgentSession.\n *\n * Context-transform boundary (deliberate): {@link runMemoryRetrieval} and\n * {@link maybeAppendMemoryEvidenceBlock} are invoked from the session's context transform as one-line\n * delegations. This controller deliberately imports no compaction/context-pipeline internals — it only\n * ever reads settings and builds the retrieval report + the bounded evidence block, so the transform\n * stays the single owner of the pass ordering.\n */\n\nimport type { AgentMessage, CustomMessage } from \"@caupulican/pi-agent-core\";\nimport { configFile, okfMemoryDir } from \"./agent-paths.ts\";\nimport { collectCurrentWorkMemory } from \"./context/current-work-memory.ts\";\nimport { createFileStoreMemoryProvider } from \"./context/file-store-memory-provider.ts\";\nimport { shouldQueryLongTermMemory } from \"./context/long-term-memory-trigger.ts\";\nimport {\n\tdefaultMemoryPromptInclusionReport,\n\ttype MemoryPromptInclusionReport,\n\ttype MemoryRetrievalDiagnostics,\n\tsanitizeMemoryRetrievalReportForDiagnostics,\n} from \"./context/memory-diagnostics.ts\";\nimport { type MemoryPromptBudget, resolveMemoryPromptBudget } from \"./context/memory-prompt-budget.ts\";\nimport {\n\ttype MemoryProvider as ContextMemoryProvider,\n\tDEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\tDEFAULT_LOCAL_MEMORY_EGRESS_POLICY,\n} from \"./context/memory-provider-contract.ts\";\nimport { type MemoryRetrievalReport, retrieveMemoryForContext } from \"./context/memory-retrieval.ts\";\nimport { composeTieredMemoryPromptBlock, type MemoryTierCandidate } from \"./context/memory-tier-composer.ts\";\nimport { createOkfMemoryProvider } from \"./context/okf-memory-provider.ts\";\nimport type { GoalState } from \"./goals/goal-state.ts\";\nimport { EffectivenessTracker } from \"./memory/effectiveness-tracker.ts\";\nimport { MemoryManager } from \"./memory/memory-manager.ts\";\nimport type { MemoryProvider } from \"./memory/memory-provider.ts\";\nimport { FileStoreProvider } from \"./memory/providers/file-store.ts\";\nimport { TranscriptRecallProvider } from \"./memory/providers/transcript-recall.ts\";\nimport { wrapUntrustedText } from \"./security/untrusted-boundary.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/**\n * Text of the most recent user message, or \"\" if there is none (e.g. goal-continuation\n * turns with no new user input). An empty query is still valid: standing user preferences may\n * surface from the file-store retrieval fallback when the static memory prompt cannot fit,\n * while long-term providers remain gated by shouldQueryLongTermMemory().\n */\nfunction latestUserMessageText(messages: AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message.role !== \"user\") continue;\n\t\tif (typeof message.content === \"string\") return message.content;\n\t\tconst parts: string[] = [];\n\t\tfor (const part of message.content) {\n\t\t\tif (part.type === \"text\") parts.push(part.text);\n\t\t}\n\t\treturn parts.join(\"\\n\");\n\t}\n\treturn \"\";\n}\n\nfunction emptyMemoryRetrievalReport(maxResults: number): MemoryRetrievalReport {\n\treturn { request: { query: \"\", maxResults }, providerReports: [], results: [], contextItems: [] };\n}\n\nconst ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY = {\n\t...DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\tenabled: true,\n\tallowedScopes: DEFAULT_LOCAL_MEMORY_EGRESS_POLICY.allowedScopes,\n\tallowExternalEgress: true,\n} as const;\n\nexport interface MemoryControllerDeps {\n\t/** Memory-retrieval + prompt-inclusion settings (default-on gates for retrieval and surfacing). */\n\tgetSettingsManager(): SettingsManager;\n\t/** Current turn index, stamped into a retrieval request's `createdAtTurn`. */\n\tgetTurnIndex(): number;\n\t/** Agent root — the durable OKF memory docs live under `<agentDir>/okf-memory`. */\n\tgetAgentDir(): string;\n\t/** Workspace root, passed to provider initialization. */\n\tgetCwd(): string;\n\t/** This session's id, passed to provider initialization. */\n\tgetSessionId(): string;\n\t/** Child sessions gate durable memory writes; passed to provider initialization. */\n\tisChildSession(): boolean;\n\t/** Re-derive the tool registry after (re)init so the newly-surfaced memory tools take effect. */\n\trefreshToolRegistry(): void;\n\t/** Active model context window, used to cap prompt-visible memory. */\n\tgetContextWindow(): number | undefined;\n\t/** Latest active goal state, used for short-term current-work memory. */\n\tgetGoalState(): GoalState | undefined;\n}\n\n/** Extension-contributed memory state staged across an atomic runtime reload. */\nexport interface MemoryControllerReloadSnapshot {\n\tpendingMemoryProviders: MemoryProvider[];\n\tpendingContextMemoryProviders: ContextMemoryProvider[];\n\tmemoryOkfProvider: ContextMemoryProvider | undefined;\n\tfileStoreMemoryProvider: ContextMemoryProvider | undefined;\n}\n\nexport class MemoryController {\n\tprivate _memoryOkfProvider: ContextMemoryProvider | undefined = undefined;\n\tprivate _fileStoreMemoryProvider: ContextMemoryProvider | undefined = undefined;\n\tprivate _latestMemoryRetrievalReport: MemoryRetrievalReport | undefined = undefined;\n\tprivate _latestMemoryPromptInclusionReport: MemoryPromptInclusionReport | undefined = undefined;\n\t/** Plug-and-play memory subsystem. Recreated on each (re)initialize so reload is safe. */\n\tprivate _memoryManager: MemoryManager = new MemoryManager();\n\t/** R4: tracks whether injected recall is actually used, to adapt the recall gate. */\n\tprivate readonly _effectivenessTracker = new EffectivenessTracker();\n\t/** Memory providers registered by extensions via pi.registerMemoryProvider, applied on (re)init. */\n\tprivate _pendingMemoryProviders: MemoryProvider[] = [];\n\t/** Context-memory providers registered by extensions via pi.registerContextMemoryProvider. */\n\tprivate _pendingContextMemoryProviders: ContextMemoryProvider[] = [];\n\n\tprivate readonly deps: MemoryControllerDeps;\n\n\tconstructor(deps: MemoryControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\t/** The live memory manager. Callers reach prefetch / tool-definitions / markers / shutdown through it. */\n\tgetMemoryManager(): MemoryManager {\n\t\treturn this._memoryManager;\n\t}\n\n\t/**\n\t * Fixed path for this slice's local Pi OKF memory documents, shared across sessions\n\t * under this agentDir (not session-scoped, unlike tool-artifacts/context-gc, since OKF\n\t * memory represents durable cross-session knowledge, not a per-session capture). Not\n\t * yet user-configurable -- see the memory-retrieval settings doc comment.\n\t */\n\tprivate _memoryOkfDir(): string {\n\t\treturn okfMemoryDir(this.deps.getAgentDir());\n\t}\n\n\t/**\n\t * Session-scoped, read-only local OKF memory provider. Lazily created ONLY when memory\n\t * retrieval is enabled (see `runMemoryRetrieval`) -- never force-created, so a session\n\t * with the setting off never touches `_memoryOkfDir()` at all (no directory access, no\n\t * creation; `createOkfMemoryProvider` itself never writes/mkdirs either way).\n\t */\n\tprivate _getMemoryOkfProvider(): ContextMemoryProvider {\n\t\tthis._memoryOkfProvider ??= createOkfMemoryProvider({ rootDir: this._memoryOkfDir() });\n\t\treturn this._memoryOkfProvider;\n\t}\n\n\tprivate _getFileStoreMemoryProvider(): ContextMemoryProvider {\n\t\tthis._fileStoreMemoryProvider ??= createFileStoreMemoryProvider({\n\t\t\tmemoryFilePath: configFile(this.deps.getAgentDir(), \"MEMORY.md\"),\n\t\t\tuserFilePath: configFile(this.deps.getAgentDir(), \"USER.md\"),\n\t\t});\n\t\treturn this._fileStoreMemoryProvider;\n\t}\n\n\tprivate _memoryBudget(configuredMaxResults: number) {\n\t\treturn resolveMemoryPromptBudget({\n\t\t\tcontextWindow: this.deps.getContextWindow(),\n\t\t\tconfiguredMaxResults,\n\t\t});\n\t}\n\n\tprivate _shouldQueryFileStoreFallback(budget: MemoryPromptBudget): boolean {\n\t\t// MEMORY.md/USER.md are already injected through the static file-store prompt on\n\t\t// normal windows, so querying them again would duplicate provider-visible memory.\n\t\t// In compact windows the static block can be omitted because it does not fit; only\n\t\t// then use the retrieval view to surface a few budget-pruned lines.\n\t\tif (!budget.enabled || !budget.compact) return false;\n\t\treturn this._memoryManager.buildSystemPromptBlock(budget).trim().length === 0;\n\t}\n\n\t/**\n\t * Observe-only local memory retrieval (see context/memory-retrieval.ts and\n\t * context/okf-memory-provider.ts): default-on, but settings-gated. When disabled,\n\t * never constructs built-in context-memory providers (no directory access under\n\t * `_memoryOkfDir()` at all) and returns an empty report -- fully fail-closed. When enabled,\n\t * queries local, read-only providers with the latest user message text (empty if there is\n\t * none, e.g. a goal-continuation turn) under `DEFAULT_LOCAL_MEMORY_EGRESS_POLICY`.\n\t * Retrieved items are only ever stored in the report; nothing here touches `messages`,\n\t * the transcript, or the provider-visible prompt. Never throws into a live turn: any\n\t * failure (including a provider search error) degrades to an empty report.\n\t */\n\tasync runMemoryRetrieval(messages: AgentMessage[]): Promise<MemoryRetrievalReport> {\n\t\ttry {\n\t\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\t\tif (!settings.enabled) {\n\t\t\t\tconst report = emptyMemoryRetrievalReport(settings.maxResults);\n\t\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\t\treturn report;\n\t\t\t}\n\t\t\tconst query = latestUserMessageText(messages);\n\t\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\t\tconst currentWork = collectCurrentWorkMemory({ goalState: this.deps.getGoalState() });\n\t\t\tconst longTermDecision = shouldQueryLongTermMemory({\n\t\t\t\tlatestUserText: query,\n\t\t\t\tgoalState: this.deps.getGoalState(),\n\t\t\t\tbudget,\n\t\t\t\tcurrentWorkCandidateCount: currentWork.length,\n\t\t\t});\n\t\t\tconst providers = this._shouldQueryFileStoreFallback(budget) ? [this._getFileStoreMemoryProvider()] : [];\n\t\t\tif (longTermDecision.shouldQuery) {\n\t\t\t\tproviders.push(this._getMemoryOkfProvider(), ...this._pendingContextMemoryProviders);\n\t\t\t}\n\t\t\tconst maxResults = budget.enabled ? Math.min(settings.maxResults, budget.maxResults) : settings.maxResults;\n\t\t\tconst report = await retrieveMemoryForContext(\n\t\t\t\tproviders,\n\t\t\t\t{ query, maxResults },\n\t\t\t\t{\n\t\t\t\t\tcreatedAtTurn: this.deps.getTurnIndex(),\n\t\t\t\t\tmaxResults,\n\t\t\t\t\tdefaultLocalPolicy: DEFAULT_LOCAL_MEMORY_EGRESS_POLICY,\n\t\t\t\t\tdefaultExternalPolicy: settings.allowExternalEgress\n\t\t\t\t\t\t? ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY\n\t\t\t\t\t\t: DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\treturn report;\n\t\t} catch {\n\t\t\tconst report = emptyMemoryRetrievalReport(0);\n\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\treturn report;\n\t\t}\n\t}\n\n\t/** Read-only inspection of the latest memory-retrieval report, for tests/debugging. */\n\tgetMemoryRetrievalReport(): MemoryRetrievalReport {\n\t\treturn this._latestMemoryRetrievalReport ?? emptyMemoryRetrievalReport(0);\n\t}\n\n\tprivate _candidateForContextItem(\n\t\titem: MemoryRetrievalReport[\"contextItems\"][number],\n\t): MemoryTierCandidate | undefined {\n\t\tconst summary = item.summary?.trim();\n\t\tif (!summary) return undefined;\n\t\tconst ref = item.primaryRef?.type === \"memory\" ? item.primaryRef.ref : undefined;\n\t\tconst sourceLabel =\n\t\t\tref?.providerId === \"pi-file-store\" && ref.kind === \"user_preference\"\n\t\t\t\t? \"rule:user\"\n\t\t\t\t: `memory:${ref?.providerId ?? item.source}`;\n\t\tconst tier = ref?.kind === \"user_preference\" ? \"standing\" : \"long_term\";\n\t\treturn {\n\t\t\tid: item.id,\n\t\t\ttier,\n\t\t\tsourceLabel,\n\t\t\tsummary,\n\t\t\tscore: 0.5,\n\t\t\tevidenceRefs: item.evidenceRefs,\n\t\t};\n\t}\n\n\tprivate _memoryCandidates(report: MemoryRetrievalReport): MemoryTierCandidate[] {\n\t\treturn [\n\t\t\t...collectCurrentWorkMemory({ goalState: this.deps.getGoalState() }),\n\t\t\t...report.contextItems.flatMap((item) => {\n\t\t\t\tconst candidate = this._candidateForContextItem(item);\n\t\t\t\treturn candidate === undefined ? [] : [candidate];\n\t\t\t}),\n\t\t];\n\t}\n\n\t/**\n\t * Bounded prompt-surfacing for local memory evidence (see context/memory-tier-composer.ts):\n\t * default-on, but gated on TWO settings (`enabled` AND `includeInPrompt`) plus at least one\n\t * current-work, standing, or retrieved memory candidate -- the first\n\t * two are belt-and-suspenders on top of the fact that `runMemoryRetrieval` already\n\t * leaves `contextItems` empty whenever `enabled` is false, regardless of\n\t * `includeInPrompt`. Reuses the `report` this pass's `runMemoryRetrieval` call already\n\t * computed -- never re-queries the provider here.\n\t *\n\t * Appends exactly one ephemeral `custom`/\"memory_evidence\" message wrapped by\n\t * `wrapUntrustedText` (the same nonce-fenced boundary + always-on system-prompt rule\n\t * used for other untrusted content) to the END of `messages`. This is purely additive\n\t * (never mutates an existing message) and purely transient: `messages` here is the\n\t * array about to be sent to the provider, not `this.agent.state.messages` or anything\n\t * persisted via `sessionManager` -- so the injected message can never reach the\n\t * transcript, regardless of how many times this pass runs.\n\t *\n\t * Also records a `MemoryPromptInclusionReport` (context/memory-diagnostics.ts) at each\n\t * branch below, for context_audit's diagnostic surface only -- this is pure bookkeeping\n\t * alongside the existing branches, not a new branch/condition: the messages returned\n\t * are unchanged by this recording.\n\t */\n\tmaybeAppendMemoryEvidenceBlock(messages: AgentMessage[], report: MemoryRetrievalReport): AgentMessage[] {\n\t\ttry {\n\t\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\t\tconst candidates = this._memoryCandidates(report);\n\t\t\tconst base = {\n\t\t\t\tenabled: settings.enabled,\n\t\t\t\tincludeInPrompt: settings.includeInPrompt,\n\t\t\t\tselectedItemCount: candidates.length,\n\t\t\t};\n\t\t\tif (!settings.enabled) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"disabled\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tif (!settings.includeInPrompt) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"include_disabled\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tif (candidates.length === 0) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"no_results\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\n\t\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\t\tconst block = composeTieredMemoryPromptBlock(candidates, budget);\n\t\t\tif (!block.text) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"empty_block\",\n\t\t\t\t\tincludedCount: block.includedCount,\n\t\t\t\t\tomittedCount: block.omittedCount,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\n\t\t\tconst wrapped = wrapUntrustedText(block.text, \"memory:tiered\");\n\t\t\tconst evidenceMessage: CustomMessage = {\n\t\t\t\trole: \"custom\",\n\t\t\t\tcustomType: \"memory_evidence\",\n\t\t\t\tcontent: [{ type: \"text\", text: wrapped }],\n\t\t\t\tdisplay: false,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t...base,\n\t\t\t\tstatus: \"included\",\n\t\t\t\tincludedCount: block.includedCount,\n\t\t\t\tomittedCount: block.omittedCount,\n\t\t\t\tblockChars: wrapped.length,\n\t\t\t\tsourceLabel: \"memory:tiered\",\n\t\t\t};\n\t\t\treturn [...messages, evidenceMessage];\n\t\t} catch {\n\t\t\t// `base` may not exist yet if the throw happened before it was computed (e.g.\n\t\t\t// settings access or `report.contextItems` itself threw), so this branch cannot\n\t\t\t// rely on it -- fall back to safe, fixed defaults rather than risk referencing\n\t\t\t// a partially-evaluated value.\n\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\tenabled: false,\n\t\t\t\tincludeInPrompt: false,\n\t\t\t\tselectedItemCount: 0,\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tincludedCount: 0,\n\t\t\t\tomittedCount: 0,\n\t\t\t\tblockChars: 0,\n\t\t\t};\n\t\t\treturn messages;\n\t\t}\n\t}\n\n\t/** Read-only inspection of the latest memory-prompt-inclusion decision, for tests/debugging and context_audit. */\n\tgetMemoryPromptInclusionReport(): MemoryPromptInclusionReport {\n\t\treturn this._latestMemoryPromptInclusionReport ?? defaultMemoryPromptInclusionReport();\n\t}\n\n\t/**\n\t * Combines the already-stored, no-arg latest reports (never re-queries the provider or\n\t * touches the OKF directory) into the safe, allow-list-projected shape context_audit\n\t * exposes. See context/memory-diagnostics.ts for why this projection is allow-list\n\t * based rather than a spread-then-delete of the raw report.\n\t */\n\tgetMemoryAuditDiagnostics(): {\n\t\tretrieval: MemoryRetrievalDiagnostics;\n\t\tpromptInclusion: MemoryPromptInclusionReport;\n\t} {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\treturn {\n\t\t\tretrieval: sanitizeMemoryRetrievalReportForDiagnostics(this.getMemoryRetrievalReport(), settings),\n\t\t\tpromptInclusion: this.getMemoryPromptInclusionReport(),\n\t\t};\n\t}\n\n\t/**\n\t * Zero-I/O gate for cross-session recall (R3): skip trivial turns (short acks, slash commands) so\n\t * recall only runs when it could plausibly help. The provider's similarity cutoff is the real\n\t * filter — this just avoids the index query on turns that obviously don't warrant it.\n\t */\n\tshouldAttemptRecall(text: string): boolean {\n\t\tif (!this.deps.getSettingsManager().getMemoryRetrievalSettings().enabled) return false;\n\t\tconst t = text.trim();\n\t\tif (t.length < 12 || t.startsWith(\"/\")) return false;\n\t\tconst words = t.split(/\\s+/).filter((w) => w.length >= 3);\n\t\t// R4 adaptive gate: if recall has rarely been used lately (enough samples to trust the signal),\n\t\t// raise the bar so we only recall on clearly substantial turns — and relax it again once recall\n\t\t// starts paying off. Never fully disabled, so the loop can recover.\n\t\tconst recallRarelyUseful =\n\t\t\tthis._effectivenessTracker.sampleCount >= 5 && this._effectivenessTracker.usefulLately() < 0.15;\n\t\treturn words.length >= (recallRarelyUseful ? 6 : 3);\n\t}\n\n\t/** Legacy recall prefetch with the same hard-off and explicit external-egress policy as context retrieval. */\n\tasync prefetchRecall(query: string): Promise<string> {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\tif (!settings.enabled) return \"\";\n\t\treturn this._memoryManager.prefetch(query, {\n\t\t\texternalEgressPolicy: settings.allowExternalEgress\n\t\t\t\t? ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY\n\t\t\t\t: DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\t\t});\n\t}\n\n\t/** Bounded, read-only memory view for an explicitly authorized delegated worker. */\n\tasync readMemoryForLane(query: string): Promise<string> {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\tif (!settings.enabled) return \"Memory retrieval is disabled by policy.\";\n\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\tconst staticBlock = this._memoryManager\n\t\t\t.buildSystemPromptBlockFresh(budget)\n\t\t\t.replace(\n\t\t\t\t\"[System Note: Below is a snapshot of your persistent memory. You can update these using the 'memory' tool.]\",\n\t\t\t\t\"[Read-only snapshot for a delegated worker.]\",\n\t\t\t);\n\t\tconst recalled = await this.prefetchRecall(query);\n\t\tconst combined = [staticBlock, recalled]\n\t\t\t.filter((part) => part.trim().length > 0)\n\t\t\t.join(\"\\n\\n\")\n\t\t\t.slice(0, 8000);\n\t\treturn combined.length > 0\n\t\t\t? wrapUntrustedText(combined, \"worker-memory\")\n\t\t\t: \"No relevant standing memory was found.\";\n\t}\n\n\t/** R4: score whether the agent actually used an injected recall page, so the recall gate can adapt. */\n\trecordRecallOutcome(recallText: string, queryText: string, responseText: string): void {\n\t\tthis._effectivenessTracker.recordRecallOutcome(recallText, queryText, responseText);\n\t}\n\n\t/**\n\t * (Re)build the memory subsystem: a fresh MemoryManager (reload-safe), register the bundled\n\t * file-store + any extension-contributed providers, initialize, then surface the memory tools and\n\t * the frozen system-prompt block. Best-effort: never throws into the session lifecycle.\n\t */\n\tasync initialize(): Promise<void> {\n\t\ttry {\n\t\t\t// Release the previous generation's providers (locks/handles) before recreating, so a\n\t\t\t// reload does not orphan the old MemoryManager. No-op on first init / for file-store.\n\t\t\tawait this._memoryManager.shutdownAll().catch(() => {});\n\t\t\tconst manager = new MemoryManager();\n\t\t\tmanager.registerProvider(new FileStoreProvider());\n\t\t\t// Bundled read-only cross-session recall (R3): indexes past-session transcripts and answers\n\t\t\t// prefetch() with a <memory_context> page. Never writes.\n\t\t\tmanager.registerProvider(new TranscriptRecallProvider());\n\t\t\tfor (const provider of this._pendingMemoryProviders) {\n\t\t\t\ttry {\n\t\t\t\t\tmanager.registerProvider(provider);\n\t\t\t\t} catch {\n\t\t\t\t\t// Duplicate name or reserved-tool collision — skip this provider, keep the rest.\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._memoryManager = manager;\n\t\t\tawait manager.initializeAll(this.deps.getSessionId(), {\n\t\t\t\tagentDir: this.deps.getAgentDir(),\n\t\t\t\tcwd: this.deps.getCwd(),\n\t\t\t\tisChildSession: this.deps.isChildSession(),\n\t\t\t});\n\t\t\t// Surface memory tools + the frozen memory block now that providers are initialized.\n\t\t\t// refreshToolRegistry() ends in setActiveToolsByName(), which rebuilds AND assigns the\n\t\t\t// system prompt (including the memory block), so no explicit _rebuildSystemPrompt is needed.\n\t\t\tthis.deps.refreshToolRegistry();\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Memory subsystem init failed:\", error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n\n\t/** Register a memory provider contributed by an extension; applied on the next memory (re)init. */\n\tregisterMemoryProvider(provider: MemoryProvider): void {\n\t\tif (!this._pendingMemoryProviders.some((p) => p.name === provider.name)) {\n\t\t\tthis._pendingMemoryProviders.push(provider);\n\t\t}\n\t}\n\n\t/** Register a retrieval-style context memory provider contributed by an extension. */\n\tregisterContextMemoryProvider(provider: ContextMemoryProvider): void {\n\t\tif (!this._pendingContextMemoryProviders.some((p) => p.id === provider.id)) {\n\t\t\tthis._pendingContextMemoryProviders.push(provider);\n\t\t}\n\t}\n\n\tcreateReloadSnapshot(): MemoryControllerReloadSnapshot {\n\t\treturn {\n\t\t\tpendingMemoryProviders: [...this._pendingMemoryProviders],\n\t\t\tpendingContextMemoryProviders: [...this._pendingContextMemoryProviders],\n\t\t\tmemoryOkfProvider: this._memoryOkfProvider,\n\t\t\tfileStoreMemoryProvider: this._fileStoreMemoryProvider,\n\t\t};\n\t}\n\n\trestoreReloadSnapshot(snapshot: MemoryControllerReloadSnapshot): void {\n\t\tthis._pendingMemoryProviders = [...snapshot.pendingMemoryProviders];\n\t\tthis._pendingContextMemoryProviders = [...snapshot.pendingContextMemoryProviders];\n\t\tthis._memoryOkfProvider = snapshot.memoryOkfProvider;\n\t\tthis._fileStoreMemoryProvider = snapshot.fileStoreMemoryProvider;\n\t}\n\n\t/** Reload starts memory providers fresh; loaded extensions re-register before the next `initialize()`. */\n\tclearPendingProviders(): void {\n\t\tthis._pendingMemoryProviders = [];\n\t\tthis._pendingContextMemoryProviders = [];\n\t\tthis._memoryOkfProvider = undefined;\n\t\tthis._fileStoreMemoryProvider = undefined;\n\t}\n}\n"]}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* ever reads settings and builds the retrieval report + the bounded evidence block, so the transform
|
|
18
18
|
* stays the single owner of the pass ordering.
|
|
19
19
|
*/
|
|
20
|
-
import {
|
|
20
|
+
import { configFile, okfMemoryDir } from "./agent-paths.js";
|
|
21
21
|
import { collectCurrentWorkMemory } from "./context/current-work-memory.js";
|
|
22
22
|
import { createFileStoreMemoryProvider } from "./context/file-store-memory-provider.js";
|
|
23
23
|
import { shouldQueryLongTermMemory } from "./context/long-term-memory-trigger.js";
|
|
@@ -91,7 +91,7 @@ export class MemoryController {
|
|
|
91
91
|
* yet user-configurable -- see the memory-retrieval settings doc comment.
|
|
92
92
|
*/
|
|
93
93
|
_memoryOkfDir() {
|
|
94
|
-
return
|
|
94
|
+
return okfMemoryDir(this.deps.getAgentDir());
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
97
97
|
* Session-scoped, read-only local OKF memory provider. Lazily created ONLY when memory
|
|
@@ -105,8 +105,8 @@ export class MemoryController {
|
|
|
105
105
|
}
|
|
106
106
|
_getFileStoreMemoryProvider() {
|
|
107
107
|
this._fileStoreMemoryProvider ??= createFileStoreMemoryProvider({
|
|
108
|
-
memoryFilePath:
|
|
109
|
-
userFilePath:
|
|
108
|
+
memoryFilePath: configFile(this.deps.getAgentDir(), "MEMORY.md"),
|
|
109
|
+
userFilePath: configFile(this.deps.getAgentDir(), "USER.md"),
|
|
110
110
|
});
|
|
111
111
|
return this._fileStoreMemoryProvider;
|
|
112
112
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-controller.js","sourceRoot":"","sources":["../../src/core/memory-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Memory controller: the session's plug-and-play memory subsystem — the read-only OKF retrieval\n * provider, the bounded prompt-evidence surfacing pilot, cross-session recall effectiveness, and the\n * live {@link MemoryManager} (bundled file-store + transcript-recall providers plus any extension\n * contributions).\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Owns the lazily-built OKF\n * provider, the latest retrieval/prompt-inclusion reports, the recreated-on-reload MemoryManager, the\n * recall {@link EffectivenessTracker}, and the extension-contributed pending providers. Everything\n * else it needs — settings, the current turn index, agent/workspace dirs, the session id, the\n * child-session flag, and the tool-registry refresh — is reached through narrow deps accessors rather\n * than the whole AgentSession.\n *\n * Context-transform boundary (deliberate): {@link runMemoryRetrieval} and\n * {@link maybeAppendMemoryEvidenceBlock} are invoked from the session's context transform as one-line\n * delegations. This controller deliberately imports no compaction/context-pipeline internals — it only\n * ever reads settings and builds the retrieval report + the bounded evidence block, so the transform\n * stays the single owner of the pass ordering.\n */\n\nimport { join } from \"node:path\";\nimport type { AgentMessage, CustomMessage } from \"@caupulican/pi-agent-core\";\nimport { collectCurrentWorkMemory } from \"./context/current-work-memory.ts\";\nimport { createFileStoreMemoryProvider } from \"./context/file-store-memory-provider.ts\";\nimport { shouldQueryLongTermMemory } from \"./context/long-term-memory-trigger.ts\";\nimport {\n\tdefaultMemoryPromptInclusionReport,\n\ttype MemoryPromptInclusionReport,\n\ttype MemoryRetrievalDiagnostics,\n\tsanitizeMemoryRetrievalReportForDiagnostics,\n} from \"./context/memory-diagnostics.ts\";\nimport { type MemoryPromptBudget, resolveMemoryPromptBudget } from \"./context/memory-prompt-budget.ts\";\nimport {\n\ttype MemoryProvider as ContextMemoryProvider,\n\tDEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\tDEFAULT_LOCAL_MEMORY_EGRESS_POLICY,\n} from \"./context/memory-provider-contract.ts\";\nimport { type MemoryRetrievalReport, retrieveMemoryForContext } from \"./context/memory-retrieval.ts\";\nimport { composeTieredMemoryPromptBlock, type MemoryTierCandidate } from \"./context/memory-tier-composer.ts\";\nimport { createOkfMemoryProvider } from \"./context/okf-memory-provider.ts\";\nimport type { GoalState } from \"./goals/goal-state.ts\";\nimport { EffectivenessTracker } from \"./memory/effectiveness-tracker.ts\";\nimport { MemoryManager } from \"./memory/memory-manager.ts\";\nimport type { MemoryProvider } from \"./memory/memory-provider.ts\";\nimport { FileStoreProvider } from \"./memory/providers/file-store.ts\";\nimport { TranscriptRecallProvider } from \"./memory/providers/transcript-recall.ts\";\nimport { wrapUntrustedText } from \"./security/untrusted-boundary.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/**\n * Text of the most recent user message, or \"\" if there is none (e.g. goal-continuation\n * turns with no new user input). An empty query is still valid: standing user preferences may\n * surface from the file-store retrieval fallback when the static memory prompt cannot fit,\n * while long-term providers remain gated by shouldQueryLongTermMemory().\n */\nfunction latestUserMessageText(messages: AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message.role !== \"user\") continue;\n\t\tif (typeof message.content === \"string\") return message.content;\n\t\tconst parts: string[] = [];\n\t\tfor (const part of message.content) {\n\t\t\tif (part.type === \"text\") parts.push(part.text);\n\t\t}\n\t\treturn parts.join(\"\\n\");\n\t}\n\treturn \"\";\n}\n\nfunction emptyMemoryRetrievalReport(maxResults: number): MemoryRetrievalReport {\n\treturn { request: { query: \"\", maxResults }, providerReports: [], results: [], contextItems: [] };\n}\n\nconst ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY = {\n\t...DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\tenabled: true,\n\tallowedScopes: DEFAULT_LOCAL_MEMORY_EGRESS_POLICY.allowedScopes,\n\tallowExternalEgress: true,\n} as const;\n\nexport interface MemoryControllerDeps {\n\t/** Memory-retrieval + prompt-inclusion settings (default-on gates for retrieval and surfacing). */\n\tgetSettingsManager(): SettingsManager;\n\t/** Current turn index, stamped into a retrieval request's `createdAtTurn`. */\n\tgetTurnIndex(): number;\n\t/** Agent root — the durable OKF memory docs live under `<agentDir>/okf-memory`. */\n\tgetAgentDir(): string;\n\t/** Workspace root, passed to provider initialization. */\n\tgetCwd(): string;\n\t/** This session's id, passed to provider initialization. */\n\tgetSessionId(): string;\n\t/** Child sessions gate durable memory writes; passed to provider initialization. */\n\tisChildSession(): boolean;\n\t/** Re-derive the tool registry after (re)init so the newly-surfaced memory tools take effect. */\n\trefreshToolRegistry(): void;\n\t/** Active model context window, used to cap prompt-visible memory. */\n\tgetContextWindow(): number | undefined;\n\t/** Latest active goal state, used for short-term current-work memory. */\n\tgetGoalState(): GoalState | undefined;\n}\n\n/** Extension-contributed memory state staged across an atomic runtime reload. */\nexport interface MemoryControllerReloadSnapshot {\n\tpendingMemoryProviders: MemoryProvider[];\n\tpendingContextMemoryProviders: ContextMemoryProvider[];\n\tmemoryOkfProvider: ContextMemoryProvider | undefined;\n\tfileStoreMemoryProvider: ContextMemoryProvider | undefined;\n}\n\nexport class MemoryController {\n\tprivate _memoryOkfProvider: ContextMemoryProvider | undefined = undefined;\n\tprivate _fileStoreMemoryProvider: ContextMemoryProvider | undefined = undefined;\n\tprivate _latestMemoryRetrievalReport: MemoryRetrievalReport | undefined = undefined;\n\tprivate _latestMemoryPromptInclusionReport: MemoryPromptInclusionReport | undefined = undefined;\n\t/** Plug-and-play memory subsystem. Recreated on each (re)initialize so reload is safe. */\n\tprivate _memoryManager: MemoryManager = new MemoryManager();\n\t/** R4: tracks whether injected recall is actually used, to adapt the recall gate. */\n\tprivate readonly _effectivenessTracker = new EffectivenessTracker();\n\t/** Memory providers registered by extensions via pi.registerMemoryProvider, applied on (re)init. */\n\tprivate _pendingMemoryProviders: MemoryProvider[] = [];\n\t/** Context-memory providers registered by extensions via pi.registerContextMemoryProvider. */\n\tprivate _pendingContextMemoryProviders: ContextMemoryProvider[] = [];\n\n\tprivate readonly deps: MemoryControllerDeps;\n\n\tconstructor(deps: MemoryControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\t/** The live memory manager. Callers reach prefetch / tool-definitions / markers / shutdown through it. */\n\tgetMemoryManager(): MemoryManager {\n\t\treturn this._memoryManager;\n\t}\n\n\t/**\n\t * Fixed path for this slice's local Pi OKF memory documents, shared across sessions\n\t * under this agentDir (not session-scoped, unlike tool-artifacts/context-gc, since OKF\n\t * memory represents durable cross-session knowledge, not a per-session capture). Not\n\t * yet user-configurable -- see the memory-retrieval settings doc comment.\n\t */\n\tprivate _memoryOkfDir(): string {\n\t\treturn join(this.deps.getAgentDir(), \"okf-memory\");\n\t}\n\n\t/**\n\t * Session-scoped, read-only local OKF memory provider. Lazily created ONLY when memory\n\t * retrieval is enabled (see `runMemoryRetrieval`) -- never force-created, so a session\n\t * with the setting off never touches `_memoryOkfDir()` at all (no directory access, no\n\t * creation; `createOkfMemoryProvider` itself never writes/mkdirs either way).\n\t */\n\tprivate _getMemoryOkfProvider(): ContextMemoryProvider {\n\t\tthis._memoryOkfProvider ??= createOkfMemoryProvider({ rootDir: this._memoryOkfDir() });\n\t\treturn this._memoryOkfProvider;\n\t}\n\n\tprivate _getFileStoreMemoryProvider(): ContextMemoryProvider {\n\t\tthis._fileStoreMemoryProvider ??= createFileStoreMemoryProvider({\n\t\t\tmemoryFilePath: join(this.deps.getAgentDir(), \"MEMORY.md\"),\n\t\t\tuserFilePath: join(this.deps.getAgentDir(), \"USER.md\"),\n\t\t});\n\t\treturn this._fileStoreMemoryProvider;\n\t}\n\n\tprivate _memoryBudget(configuredMaxResults: number) {\n\t\treturn resolveMemoryPromptBudget({\n\t\t\tcontextWindow: this.deps.getContextWindow(),\n\t\t\tconfiguredMaxResults,\n\t\t});\n\t}\n\n\tprivate _shouldQueryFileStoreFallback(budget: MemoryPromptBudget): boolean {\n\t\t// MEMORY.md/USER.md are already injected through the static file-store prompt on\n\t\t// normal windows, so querying them again would duplicate provider-visible memory.\n\t\t// In compact windows the static block can be omitted because it does not fit; only\n\t\t// then use the retrieval view to surface a few budget-pruned lines.\n\t\tif (!budget.enabled || !budget.compact) return false;\n\t\treturn this._memoryManager.buildSystemPromptBlock(budget).trim().length === 0;\n\t}\n\n\t/**\n\t * Observe-only local memory retrieval (see context/memory-retrieval.ts and\n\t * context/okf-memory-provider.ts): default-on, but settings-gated. When disabled,\n\t * never constructs built-in context-memory providers (no directory access under\n\t * `_memoryOkfDir()` at all) and returns an empty report -- fully fail-closed. When enabled,\n\t * queries local, read-only providers with the latest user message text (empty if there is\n\t * none, e.g. a goal-continuation turn) under `DEFAULT_LOCAL_MEMORY_EGRESS_POLICY`.\n\t * Retrieved items are only ever stored in the report; nothing here touches `messages`,\n\t * the transcript, or the provider-visible prompt. Never throws into a live turn: any\n\t * failure (including a provider search error) degrades to an empty report.\n\t */\n\tasync runMemoryRetrieval(messages: AgentMessage[]): Promise<MemoryRetrievalReport> {\n\t\ttry {\n\t\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\t\tif (!settings.enabled) {\n\t\t\t\tconst report = emptyMemoryRetrievalReport(settings.maxResults);\n\t\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\t\treturn report;\n\t\t\t}\n\t\t\tconst query = latestUserMessageText(messages);\n\t\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\t\tconst currentWork = collectCurrentWorkMemory({ goalState: this.deps.getGoalState() });\n\t\t\tconst longTermDecision = shouldQueryLongTermMemory({\n\t\t\t\tlatestUserText: query,\n\t\t\t\tgoalState: this.deps.getGoalState(),\n\t\t\t\tbudget,\n\t\t\t\tcurrentWorkCandidateCount: currentWork.length,\n\t\t\t});\n\t\t\tconst providers = this._shouldQueryFileStoreFallback(budget) ? [this._getFileStoreMemoryProvider()] : [];\n\t\t\tif (longTermDecision.shouldQuery) {\n\t\t\t\tproviders.push(this._getMemoryOkfProvider(), ...this._pendingContextMemoryProviders);\n\t\t\t}\n\t\t\tconst maxResults = budget.enabled ? Math.min(settings.maxResults, budget.maxResults) : settings.maxResults;\n\t\t\tconst report = await retrieveMemoryForContext(\n\t\t\t\tproviders,\n\t\t\t\t{ query, maxResults },\n\t\t\t\t{\n\t\t\t\t\tcreatedAtTurn: this.deps.getTurnIndex(),\n\t\t\t\t\tmaxResults,\n\t\t\t\t\tdefaultLocalPolicy: DEFAULT_LOCAL_MEMORY_EGRESS_POLICY,\n\t\t\t\t\tdefaultExternalPolicy: settings.allowExternalEgress\n\t\t\t\t\t\t? ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY\n\t\t\t\t\t\t: DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\treturn report;\n\t\t} catch {\n\t\t\tconst report = emptyMemoryRetrievalReport(0);\n\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\treturn report;\n\t\t}\n\t}\n\n\t/** Read-only inspection of the latest memory-retrieval report, for tests/debugging. */\n\tgetMemoryRetrievalReport(): MemoryRetrievalReport {\n\t\treturn this._latestMemoryRetrievalReport ?? emptyMemoryRetrievalReport(0);\n\t}\n\n\tprivate _candidateForContextItem(\n\t\titem: MemoryRetrievalReport[\"contextItems\"][number],\n\t): MemoryTierCandidate | undefined {\n\t\tconst summary = item.summary?.trim();\n\t\tif (!summary) return undefined;\n\t\tconst ref = item.primaryRef?.type === \"memory\" ? item.primaryRef.ref : undefined;\n\t\tconst sourceLabel =\n\t\t\tref?.providerId === \"pi-file-store\" && ref.kind === \"user_preference\"\n\t\t\t\t? \"rule:user\"\n\t\t\t\t: `memory:${ref?.providerId ?? item.source}`;\n\t\tconst tier = ref?.kind === \"user_preference\" ? \"standing\" : \"long_term\";\n\t\treturn {\n\t\t\tid: item.id,\n\t\t\ttier,\n\t\t\tsourceLabel,\n\t\t\tsummary,\n\t\t\tscore: 0.5,\n\t\t\tevidenceRefs: item.evidenceRefs,\n\t\t};\n\t}\n\n\tprivate _memoryCandidates(report: MemoryRetrievalReport): MemoryTierCandidate[] {\n\t\treturn [\n\t\t\t...collectCurrentWorkMemory({ goalState: this.deps.getGoalState() }),\n\t\t\t...report.contextItems.flatMap((item) => {\n\t\t\t\tconst candidate = this._candidateForContextItem(item);\n\t\t\t\treturn candidate === undefined ? [] : [candidate];\n\t\t\t}),\n\t\t];\n\t}\n\n\t/**\n\t * Bounded prompt-surfacing for local memory evidence (see context/memory-tier-composer.ts):\n\t * default-on, but gated on TWO settings (`enabled` AND `includeInPrompt`) plus at least one\n\t * current-work, standing, or retrieved memory candidate -- the first\n\t * two are belt-and-suspenders on top of the fact that `runMemoryRetrieval` already\n\t * leaves `contextItems` empty whenever `enabled` is false, regardless of\n\t * `includeInPrompt`. Reuses the `report` this pass's `runMemoryRetrieval` call already\n\t * computed -- never re-queries the provider here.\n\t *\n\t * Appends exactly one ephemeral `custom`/\"memory_evidence\" message wrapped by\n\t * `wrapUntrustedText` (the same nonce-fenced boundary + always-on system-prompt rule\n\t * used for other untrusted content) to the END of `messages`. This is purely additive\n\t * (never mutates an existing message) and purely transient: `messages` here is the\n\t * array about to be sent to the provider, not `this.agent.state.messages` or anything\n\t * persisted via `sessionManager` -- so the injected message can never reach the\n\t * transcript, regardless of how many times this pass runs.\n\t *\n\t * Also records a `MemoryPromptInclusionReport` (context/memory-diagnostics.ts) at each\n\t * branch below, for context_audit's diagnostic surface only -- this is pure bookkeeping\n\t * alongside the existing branches, not a new branch/condition: the messages returned\n\t * are unchanged by this recording.\n\t */\n\tmaybeAppendMemoryEvidenceBlock(messages: AgentMessage[], report: MemoryRetrievalReport): AgentMessage[] {\n\t\ttry {\n\t\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\t\tconst candidates = this._memoryCandidates(report);\n\t\t\tconst base = {\n\t\t\t\tenabled: settings.enabled,\n\t\t\t\tincludeInPrompt: settings.includeInPrompt,\n\t\t\t\tselectedItemCount: candidates.length,\n\t\t\t};\n\t\t\tif (!settings.enabled) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"disabled\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tif (!settings.includeInPrompt) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"include_disabled\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tif (candidates.length === 0) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"no_results\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\n\t\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\t\tconst block = composeTieredMemoryPromptBlock(candidates, budget);\n\t\t\tif (!block.text) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"empty_block\",\n\t\t\t\t\tincludedCount: block.includedCount,\n\t\t\t\t\tomittedCount: block.omittedCount,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\n\t\t\tconst wrapped = wrapUntrustedText(block.text, \"memory:tiered\");\n\t\t\tconst evidenceMessage: CustomMessage = {\n\t\t\t\trole: \"custom\",\n\t\t\t\tcustomType: \"memory_evidence\",\n\t\t\t\tcontent: [{ type: \"text\", text: wrapped }],\n\t\t\t\tdisplay: false,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t...base,\n\t\t\t\tstatus: \"included\",\n\t\t\t\tincludedCount: block.includedCount,\n\t\t\t\tomittedCount: block.omittedCount,\n\t\t\t\tblockChars: wrapped.length,\n\t\t\t\tsourceLabel: \"memory:tiered\",\n\t\t\t};\n\t\t\treturn [...messages, evidenceMessage];\n\t\t} catch {\n\t\t\t// `base` may not exist yet if the throw happened before it was computed (e.g.\n\t\t\t// settings access or `report.contextItems` itself threw), so this branch cannot\n\t\t\t// rely on it -- fall back to safe, fixed defaults rather than risk referencing\n\t\t\t// a partially-evaluated value.\n\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\tenabled: false,\n\t\t\t\tincludeInPrompt: false,\n\t\t\t\tselectedItemCount: 0,\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tincludedCount: 0,\n\t\t\t\tomittedCount: 0,\n\t\t\t\tblockChars: 0,\n\t\t\t};\n\t\t\treturn messages;\n\t\t}\n\t}\n\n\t/** Read-only inspection of the latest memory-prompt-inclusion decision, for tests/debugging and context_audit. */\n\tgetMemoryPromptInclusionReport(): MemoryPromptInclusionReport {\n\t\treturn this._latestMemoryPromptInclusionReport ?? defaultMemoryPromptInclusionReport();\n\t}\n\n\t/**\n\t * Combines the already-stored, no-arg latest reports (never re-queries the provider or\n\t * touches the OKF directory) into the safe, allow-list-projected shape context_audit\n\t * exposes. See context/memory-diagnostics.ts for why this projection is allow-list\n\t * based rather than a spread-then-delete of the raw report.\n\t */\n\tgetMemoryAuditDiagnostics(): {\n\t\tretrieval: MemoryRetrievalDiagnostics;\n\t\tpromptInclusion: MemoryPromptInclusionReport;\n\t} {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\treturn {\n\t\t\tretrieval: sanitizeMemoryRetrievalReportForDiagnostics(this.getMemoryRetrievalReport(), settings),\n\t\t\tpromptInclusion: this.getMemoryPromptInclusionReport(),\n\t\t};\n\t}\n\n\t/**\n\t * Zero-I/O gate for cross-session recall (R3): skip trivial turns (short acks, slash commands) so\n\t * recall only runs when it could plausibly help. The provider's similarity cutoff is the real\n\t * filter — this just avoids the index query on turns that obviously don't warrant it.\n\t */\n\tshouldAttemptRecall(text: string): boolean {\n\t\tif (!this.deps.getSettingsManager().getMemoryRetrievalSettings().enabled) return false;\n\t\tconst t = text.trim();\n\t\tif (t.length < 12 || t.startsWith(\"/\")) return false;\n\t\tconst words = t.split(/\\s+/).filter((w) => w.length >= 3);\n\t\t// R4 adaptive gate: if recall has rarely been used lately (enough samples to trust the signal),\n\t\t// raise the bar so we only recall on clearly substantial turns — and relax it again once recall\n\t\t// starts paying off. Never fully disabled, so the loop can recover.\n\t\tconst recallRarelyUseful =\n\t\t\tthis._effectivenessTracker.sampleCount >= 5 && this._effectivenessTracker.usefulLately() < 0.15;\n\t\treturn words.length >= (recallRarelyUseful ? 6 : 3);\n\t}\n\n\t/** Legacy recall prefetch with the same hard-off and explicit external-egress policy as context retrieval. */\n\tasync prefetchRecall(query: string): Promise<string> {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\tif (!settings.enabled) return \"\";\n\t\treturn this._memoryManager.prefetch(query, {\n\t\t\texternalEgressPolicy: settings.allowExternalEgress\n\t\t\t\t? ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY\n\t\t\t\t: DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\t\t});\n\t}\n\n\t/** Bounded, read-only memory view for an explicitly authorized delegated worker. */\n\tasync readMemoryForLane(query: string): Promise<string> {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\tif (!settings.enabled) return \"Memory retrieval is disabled by policy.\";\n\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\tconst staticBlock = this._memoryManager\n\t\t\t.buildSystemPromptBlockFresh(budget)\n\t\t\t.replace(\n\t\t\t\t\"[System Note: Below is a snapshot of your persistent memory. You can update these using the 'memory' tool.]\",\n\t\t\t\t\"[Read-only snapshot for a delegated worker.]\",\n\t\t\t);\n\t\tconst recalled = await this.prefetchRecall(query);\n\t\tconst combined = [staticBlock, recalled]\n\t\t\t.filter((part) => part.trim().length > 0)\n\t\t\t.join(\"\\n\\n\")\n\t\t\t.slice(0, 8000);\n\t\treturn combined.length > 0\n\t\t\t? wrapUntrustedText(combined, \"worker-memory\")\n\t\t\t: \"No relevant standing memory was found.\";\n\t}\n\n\t/** R4: score whether the agent actually used an injected recall page, so the recall gate can adapt. */\n\trecordRecallOutcome(recallText: string, queryText: string, responseText: string): void {\n\t\tthis._effectivenessTracker.recordRecallOutcome(recallText, queryText, responseText);\n\t}\n\n\t/**\n\t * (Re)build the memory subsystem: a fresh MemoryManager (reload-safe), register the bundled\n\t * file-store + any extension-contributed providers, initialize, then surface the memory tools and\n\t * the frozen system-prompt block. Best-effort: never throws into the session lifecycle.\n\t */\n\tasync initialize(): Promise<void> {\n\t\ttry {\n\t\t\t// Release the previous generation's providers (locks/handles) before recreating, so a\n\t\t\t// reload does not orphan the old MemoryManager. No-op on first init / for file-store.\n\t\t\tawait this._memoryManager.shutdownAll().catch(() => {});\n\t\t\tconst manager = new MemoryManager();\n\t\t\tmanager.registerProvider(new FileStoreProvider());\n\t\t\t// Bundled read-only cross-session recall (R3): indexes past-session transcripts and answers\n\t\t\t// prefetch() with a <memory_context> page. Never writes.\n\t\t\tmanager.registerProvider(new TranscriptRecallProvider());\n\t\t\tfor (const provider of this._pendingMemoryProviders) {\n\t\t\t\ttry {\n\t\t\t\t\tmanager.registerProvider(provider);\n\t\t\t\t} catch {\n\t\t\t\t\t// Duplicate name or reserved-tool collision — skip this provider, keep the rest.\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._memoryManager = manager;\n\t\t\tawait manager.initializeAll(this.deps.getSessionId(), {\n\t\t\t\tagentDir: this.deps.getAgentDir(),\n\t\t\t\tcwd: this.deps.getCwd(),\n\t\t\t\tisChildSession: this.deps.isChildSession(),\n\t\t\t});\n\t\t\t// Surface memory tools + the frozen memory block now that providers are initialized.\n\t\t\t// refreshToolRegistry() ends in setActiveToolsByName(), which rebuilds AND assigns the\n\t\t\t// system prompt (including the memory block), so no explicit _rebuildSystemPrompt is needed.\n\t\t\tthis.deps.refreshToolRegistry();\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Memory subsystem init failed:\", error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n\n\t/** Register a memory provider contributed by an extension; applied on the next memory (re)init. */\n\tregisterMemoryProvider(provider: MemoryProvider): void {\n\t\tif (!this._pendingMemoryProviders.some((p) => p.name === provider.name)) {\n\t\t\tthis._pendingMemoryProviders.push(provider);\n\t\t}\n\t}\n\n\t/** Register a retrieval-style context memory provider contributed by an extension. */\n\tregisterContextMemoryProvider(provider: ContextMemoryProvider): void {\n\t\tif (!this._pendingContextMemoryProviders.some((p) => p.id === provider.id)) {\n\t\t\tthis._pendingContextMemoryProviders.push(provider);\n\t\t}\n\t}\n\n\tcreateReloadSnapshot(): MemoryControllerReloadSnapshot {\n\t\treturn {\n\t\t\tpendingMemoryProviders: [...this._pendingMemoryProviders],\n\t\t\tpendingContextMemoryProviders: [...this._pendingContextMemoryProviders],\n\t\t\tmemoryOkfProvider: this._memoryOkfProvider,\n\t\t\tfileStoreMemoryProvider: this._fileStoreMemoryProvider,\n\t\t};\n\t}\n\n\trestoreReloadSnapshot(snapshot: MemoryControllerReloadSnapshot): void {\n\t\tthis._pendingMemoryProviders = [...snapshot.pendingMemoryProviders];\n\t\tthis._pendingContextMemoryProviders = [...snapshot.pendingContextMemoryProviders];\n\t\tthis._memoryOkfProvider = snapshot.memoryOkfProvider;\n\t\tthis._fileStoreMemoryProvider = snapshot.fileStoreMemoryProvider;\n\t}\n\n\t/** Reload starts memory providers fresh; loaded extensions re-register before the next `initialize()`. */\n\tclearPendingProviders(): void {\n\t\tthis._pendingMemoryProviders = [];\n\t\tthis._pendingContextMemoryProviders = [];\n\t\tthis._memoryOkfProvider = undefined;\n\t\tthis._fileStoreMemoryProvider = undefined;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"memory-controller.js","sourceRoot":"","sources":["../../src/core/memory-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Memory controller: the session's plug-and-play memory subsystem — the read-only OKF retrieval\n * provider, the bounded prompt-evidence surfacing pilot, cross-session recall effectiveness, and the\n * live {@link MemoryManager} (bundled file-store + transcript-recall providers plus any extension\n * contributions).\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Owns the lazily-built OKF\n * provider, the latest retrieval/prompt-inclusion reports, the recreated-on-reload MemoryManager, the\n * recall {@link EffectivenessTracker}, and the extension-contributed pending providers. Everything\n * else it needs — settings, the current turn index, agent/workspace dirs, the session id, the\n * child-session flag, and the tool-registry refresh — is reached through narrow deps accessors rather\n * than the whole AgentSession.\n *\n * Context-transform boundary (deliberate): {@link runMemoryRetrieval} and\n * {@link maybeAppendMemoryEvidenceBlock} are invoked from the session's context transform as one-line\n * delegations. This controller deliberately imports no compaction/context-pipeline internals — it only\n * ever reads settings and builds the retrieval report + the bounded evidence block, so the transform\n * stays the single owner of the pass ordering.\n */\n\nimport type { AgentMessage, CustomMessage } from \"@caupulican/pi-agent-core\";\nimport { configFile, okfMemoryDir } from \"./agent-paths.ts\";\nimport { collectCurrentWorkMemory } from \"./context/current-work-memory.ts\";\nimport { createFileStoreMemoryProvider } from \"./context/file-store-memory-provider.ts\";\nimport { shouldQueryLongTermMemory } from \"./context/long-term-memory-trigger.ts\";\nimport {\n\tdefaultMemoryPromptInclusionReport,\n\ttype MemoryPromptInclusionReport,\n\ttype MemoryRetrievalDiagnostics,\n\tsanitizeMemoryRetrievalReportForDiagnostics,\n} from \"./context/memory-diagnostics.ts\";\nimport { type MemoryPromptBudget, resolveMemoryPromptBudget } from \"./context/memory-prompt-budget.ts\";\nimport {\n\ttype MemoryProvider as ContextMemoryProvider,\n\tDEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\tDEFAULT_LOCAL_MEMORY_EGRESS_POLICY,\n} from \"./context/memory-provider-contract.ts\";\nimport { type MemoryRetrievalReport, retrieveMemoryForContext } from \"./context/memory-retrieval.ts\";\nimport { composeTieredMemoryPromptBlock, type MemoryTierCandidate } from \"./context/memory-tier-composer.ts\";\nimport { createOkfMemoryProvider } from \"./context/okf-memory-provider.ts\";\nimport type { GoalState } from \"./goals/goal-state.ts\";\nimport { EffectivenessTracker } from \"./memory/effectiveness-tracker.ts\";\nimport { MemoryManager } from \"./memory/memory-manager.ts\";\nimport type { MemoryProvider } from \"./memory/memory-provider.ts\";\nimport { FileStoreProvider } from \"./memory/providers/file-store.ts\";\nimport { TranscriptRecallProvider } from \"./memory/providers/transcript-recall.ts\";\nimport { wrapUntrustedText } from \"./security/untrusted-boundary.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\n/**\n * Text of the most recent user message, or \"\" if there is none (e.g. goal-continuation\n * turns with no new user input). An empty query is still valid: standing user preferences may\n * surface from the file-store retrieval fallback when the static memory prompt cannot fit,\n * while long-term providers remain gated by shouldQueryLongTermMemory().\n */\nfunction latestUserMessageText(messages: AgentMessage[]): string {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message.role !== \"user\") continue;\n\t\tif (typeof message.content === \"string\") return message.content;\n\t\tconst parts: string[] = [];\n\t\tfor (const part of message.content) {\n\t\t\tif (part.type === \"text\") parts.push(part.text);\n\t\t}\n\t\treturn parts.join(\"\\n\");\n\t}\n\treturn \"\";\n}\n\nfunction emptyMemoryRetrievalReport(maxResults: number): MemoryRetrievalReport {\n\treturn { request: { query: \"\", maxResults }, providerReports: [], results: [], contextItems: [] };\n}\n\nconst ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY = {\n\t...DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\tenabled: true,\n\tallowedScopes: DEFAULT_LOCAL_MEMORY_EGRESS_POLICY.allowedScopes,\n\tallowExternalEgress: true,\n} as const;\n\nexport interface MemoryControllerDeps {\n\t/** Memory-retrieval + prompt-inclusion settings (default-on gates for retrieval and surfacing). */\n\tgetSettingsManager(): SettingsManager;\n\t/** Current turn index, stamped into a retrieval request's `createdAtTurn`. */\n\tgetTurnIndex(): number;\n\t/** Agent root — the durable OKF memory docs live under `<agentDir>/okf-memory`. */\n\tgetAgentDir(): string;\n\t/** Workspace root, passed to provider initialization. */\n\tgetCwd(): string;\n\t/** This session's id, passed to provider initialization. */\n\tgetSessionId(): string;\n\t/** Child sessions gate durable memory writes; passed to provider initialization. */\n\tisChildSession(): boolean;\n\t/** Re-derive the tool registry after (re)init so the newly-surfaced memory tools take effect. */\n\trefreshToolRegistry(): void;\n\t/** Active model context window, used to cap prompt-visible memory. */\n\tgetContextWindow(): number | undefined;\n\t/** Latest active goal state, used for short-term current-work memory. */\n\tgetGoalState(): GoalState | undefined;\n}\n\n/** Extension-contributed memory state staged across an atomic runtime reload. */\nexport interface MemoryControllerReloadSnapshot {\n\tpendingMemoryProviders: MemoryProvider[];\n\tpendingContextMemoryProviders: ContextMemoryProvider[];\n\tmemoryOkfProvider: ContextMemoryProvider | undefined;\n\tfileStoreMemoryProvider: ContextMemoryProvider | undefined;\n}\n\nexport class MemoryController {\n\tprivate _memoryOkfProvider: ContextMemoryProvider | undefined = undefined;\n\tprivate _fileStoreMemoryProvider: ContextMemoryProvider | undefined = undefined;\n\tprivate _latestMemoryRetrievalReport: MemoryRetrievalReport | undefined = undefined;\n\tprivate _latestMemoryPromptInclusionReport: MemoryPromptInclusionReport | undefined = undefined;\n\t/** Plug-and-play memory subsystem. Recreated on each (re)initialize so reload is safe. */\n\tprivate _memoryManager: MemoryManager = new MemoryManager();\n\t/** R4: tracks whether injected recall is actually used, to adapt the recall gate. */\n\tprivate readonly _effectivenessTracker = new EffectivenessTracker();\n\t/** Memory providers registered by extensions via pi.registerMemoryProvider, applied on (re)init. */\n\tprivate _pendingMemoryProviders: MemoryProvider[] = [];\n\t/** Context-memory providers registered by extensions via pi.registerContextMemoryProvider. */\n\tprivate _pendingContextMemoryProviders: ContextMemoryProvider[] = [];\n\n\tprivate readonly deps: MemoryControllerDeps;\n\n\tconstructor(deps: MemoryControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\t/** The live memory manager. Callers reach prefetch / tool-definitions / markers / shutdown through it. */\n\tgetMemoryManager(): MemoryManager {\n\t\treturn this._memoryManager;\n\t}\n\n\t/**\n\t * Fixed path for this slice's local Pi OKF memory documents, shared across sessions\n\t * under this agentDir (not session-scoped, unlike tool-artifacts/context-gc, since OKF\n\t * memory represents durable cross-session knowledge, not a per-session capture). Not\n\t * yet user-configurable -- see the memory-retrieval settings doc comment.\n\t */\n\tprivate _memoryOkfDir(): string {\n\t\treturn okfMemoryDir(this.deps.getAgentDir());\n\t}\n\n\t/**\n\t * Session-scoped, read-only local OKF memory provider. Lazily created ONLY when memory\n\t * retrieval is enabled (see `runMemoryRetrieval`) -- never force-created, so a session\n\t * with the setting off never touches `_memoryOkfDir()` at all (no directory access, no\n\t * creation; `createOkfMemoryProvider` itself never writes/mkdirs either way).\n\t */\n\tprivate _getMemoryOkfProvider(): ContextMemoryProvider {\n\t\tthis._memoryOkfProvider ??= createOkfMemoryProvider({ rootDir: this._memoryOkfDir() });\n\t\treturn this._memoryOkfProvider;\n\t}\n\n\tprivate _getFileStoreMemoryProvider(): ContextMemoryProvider {\n\t\tthis._fileStoreMemoryProvider ??= createFileStoreMemoryProvider({\n\t\t\tmemoryFilePath: configFile(this.deps.getAgentDir(), \"MEMORY.md\"),\n\t\t\tuserFilePath: configFile(this.deps.getAgentDir(), \"USER.md\"),\n\t\t});\n\t\treturn this._fileStoreMemoryProvider;\n\t}\n\n\tprivate _memoryBudget(configuredMaxResults: number) {\n\t\treturn resolveMemoryPromptBudget({\n\t\t\tcontextWindow: this.deps.getContextWindow(),\n\t\t\tconfiguredMaxResults,\n\t\t});\n\t}\n\n\tprivate _shouldQueryFileStoreFallback(budget: MemoryPromptBudget): boolean {\n\t\t// MEMORY.md/USER.md are already injected through the static file-store prompt on\n\t\t// normal windows, so querying them again would duplicate provider-visible memory.\n\t\t// In compact windows the static block can be omitted because it does not fit; only\n\t\t// then use the retrieval view to surface a few budget-pruned lines.\n\t\tif (!budget.enabled || !budget.compact) return false;\n\t\treturn this._memoryManager.buildSystemPromptBlock(budget).trim().length === 0;\n\t}\n\n\t/**\n\t * Observe-only local memory retrieval (see context/memory-retrieval.ts and\n\t * context/okf-memory-provider.ts): default-on, but settings-gated. When disabled,\n\t * never constructs built-in context-memory providers (no directory access under\n\t * `_memoryOkfDir()` at all) and returns an empty report -- fully fail-closed. When enabled,\n\t * queries local, read-only providers with the latest user message text (empty if there is\n\t * none, e.g. a goal-continuation turn) under `DEFAULT_LOCAL_MEMORY_EGRESS_POLICY`.\n\t * Retrieved items are only ever stored in the report; nothing here touches `messages`,\n\t * the transcript, or the provider-visible prompt. Never throws into a live turn: any\n\t * failure (including a provider search error) degrades to an empty report.\n\t */\n\tasync runMemoryRetrieval(messages: AgentMessage[]): Promise<MemoryRetrievalReport> {\n\t\ttry {\n\t\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\t\tif (!settings.enabled) {\n\t\t\t\tconst report = emptyMemoryRetrievalReport(settings.maxResults);\n\t\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\t\treturn report;\n\t\t\t}\n\t\t\tconst query = latestUserMessageText(messages);\n\t\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\t\tconst currentWork = collectCurrentWorkMemory({ goalState: this.deps.getGoalState() });\n\t\t\tconst longTermDecision = shouldQueryLongTermMemory({\n\t\t\t\tlatestUserText: query,\n\t\t\t\tgoalState: this.deps.getGoalState(),\n\t\t\t\tbudget,\n\t\t\t\tcurrentWorkCandidateCount: currentWork.length,\n\t\t\t});\n\t\t\tconst providers = this._shouldQueryFileStoreFallback(budget) ? [this._getFileStoreMemoryProvider()] : [];\n\t\t\tif (longTermDecision.shouldQuery) {\n\t\t\t\tproviders.push(this._getMemoryOkfProvider(), ...this._pendingContextMemoryProviders);\n\t\t\t}\n\t\t\tconst maxResults = budget.enabled ? Math.min(settings.maxResults, budget.maxResults) : settings.maxResults;\n\t\t\tconst report = await retrieveMemoryForContext(\n\t\t\t\tproviders,\n\t\t\t\t{ query, maxResults },\n\t\t\t\t{\n\t\t\t\t\tcreatedAtTurn: this.deps.getTurnIndex(),\n\t\t\t\t\tmaxResults,\n\t\t\t\t\tdefaultLocalPolicy: DEFAULT_LOCAL_MEMORY_EGRESS_POLICY,\n\t\t\t\t\tdefaultExternalPolicy: settings.allowExternalEgress\n\t\t\t\t\t\t? ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY\n\t\t\t\t\t\t: DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\treturn report;\n\t\t} catch {\n\t\t\tconst report = emptyMemoryRetrievalReport(0);\n\t\t\tthis._latestMemoryRetrievalReport = report;\n\t\t\treturn report;\n\t\t}\n\t}\n\n\t/** Read-only inspection of the latest memory-retrieval report, for tests/debugging. */\n\tgetMemoryRetrievalReport(): MemoryRetrievalReport {\n\t\treturn this._latestMemoryRetrievalReport ?? emptyMemoryRetrievalReport(0);\n\t}\n\n\tprivate _candidateForContextItem(\n\t\titem: MemoryRetrievalReport[\"contextItems\"][number],\n\t): MemoryTierCandidate | undefined {\n\t\tconst summary = item.summary?.trim();\n\t\tif (!summary) return undefined;\n\t\tconst ref = item.primaryRef?.type === \"memory\" ? item.primaryRef.ref : undefined;\n\t\tconst sourceLabel =\n\t\t\tref?.providerId === \"pi-file-store\" && ref.kind === \"user_preference\"\n\t\t\t\t? \"rule:user\"\n\t\t\t\t: `memory:${ref?.providerId ?? item.source}`;\n\t\tconst tier = ref?.kind === \"user_preference\" ? \"standing\" : \"long_term\";\n\t\treturn {\n\t\t\tid: item.id,\n\t\t\ttier,\n\t\t\tsourceLabel,\n\t\t\tsummary,\n\t\t\tscore: 0.5,\n\t\t\tevidenceRefs: item.evidenceRefs,\n\t\t};\n\t}\n\n\tprivate _memoryCandidates(report: MemoryRetrievalReport): MemoryTierCandidate[] {\n\t\treturn [\n\t\t\t...collectCurrentWorkMemory({ goalState: this.deps.getGoalState() }),\n\t\t\t...report.contextItems.flatMap((item) => {\n\t\t\t\tconst candidate = this._candidateForContextItem(item);\n\t\t\t\treturn candidate === undefined ? [] : [candidate];\n\t\t\t}),\n\t\t];\n\t}\n\n\t/**\n\t * Bounded prompt-surfacing for local memory evidence (see context/memory-tier-composer.ts):\n\t * default-on, but gated on TWO settings (`enabled` AND `includeInPrompt`) plus at least one\n\t * current-work, standing, or retrieved memory candidate -- the first\n\t * two are belt-and-suspenders on top of the fact that `runMemoryRetrieval` already\n\t * leaves `contextItems` empty whenever `enabled` is false, regardless of\n\t * `includeInPrompt`. Reuses the `report` this pass's `runMemoryRetrieval` call already\n\t * computed -- never re-queries the provider here.\n\t *\n\t * Appends exactly one ephemeral `custom`/\"memory_evidence\" message wrapped by\n\t * `wrapUntrustedText` (the same nonce-fenced boundary + always-on system-prompt rule\n\t * used for other untrusted content) to the END of `messages`. This is purely additive\n\t * (never mutates an existing message) and purely transient: `messages` here is the\n\t * array about to be sent to the provider, not `this.agent.state.messages` or anything\n\t * persisted via `sessionManager` -- so the injected message can never reach the\n\t * transcript, regardless of how many times this pass runs.\n\t *\n\t * Also records a `MemoryPromptInclusionReport` (context/memory-diagnostics.ts) at each\n\t * branch below, for context_audit's diagnostic surface only -- this is pure bookkeeping\n\t * alongside the existing branches, not a new branch/condition: the messages returned\n\t * are unchanged by this recording.\n\t */\n\tmaybeAppendMemoryEvidenceBlock(messages: AgentMessage[], report: MemoryRetrievalReport): AgentMessage[] {\n\t\ttry {\n\t\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\t\tconst candidates = this._memoryCandidates(report);\n\t\t\tconst base = {\n\t\t\t\tenabled: settings.enabled,\n\t\t\t\tincludeInPrompt: settings.includeInPrompt,\n\t\t\t\tselectedItemCount: candidates.length,\n\t\t\t};\n\t\t\tif (!settings.enabled) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"disabled\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tif (!settings.includeInPrompt) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"include_disabled\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\t\t\tif (candidates.length === 0) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"no_results\",\n\t\t\t\t\tincludedCount: 0,\n\t\t\t\t\tomittedCount: 0,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\n\t\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\t\tconst block = composeTieredMemoryPromptBlock(candidates, budget);\n\t\t\tif (!block.text) {\n\t\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t\t...base,\n\t\t\t\t\tstatus: \"empty_block\",\n\t\t\t\t\tincludedCount: block.includedCount,\n\t\t\t\t\tomittedCount: block.omittedCount,\n\t\t\t\t\tblockChars: 0,\n\t\t\t\t};\n\t\t\t\treturn messages;\n\t\t\t}\n\n\t\t\tconst wrapped = wrapUntrustedText(block.text, \"memory:tiered\");\n\t\t\tconst evidenceMessage: CustomMessage = {\n\t\t\t\trole: \"custom\",\n\t\t\t\tcustomType: \"memory_evidence\",\n\t\t\t\tcontent: [{ type: \"text\", text: wrapped }],\n\t\t\t\tdisplay: false,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\t...base,\n\t\t\t\tstatus: \"included\",\n\t\t\t\tincludedCount: block.includedCount,\n\t\t\t\tomittedCount: block.omittedCount,\n\t\t\t\tblockChars: wrapped.length,\n\t\t\t\tsourceLabel: \"memory:tiered\",\n\t\t\t};\n\t\t\treturn [...messages, evidenceMessage];\n\t\t} catch {\n\t\t\t// `base` may not exist yet if the throw happened before it was computed (e.g.\n\t\t\t// settings access or `report.contextItems` itself threw), so this branch cannot\n\t\t\t// rely on it -- fall back to safe, fixed defaults rather than risk referencing\n\t\t\t// a partially-evaluated value.\n\t\t\tthis._latestMemoryPromptInclusionReport = {\n\t\t\t\tenabled: false,\n\t\t\t\tincludeInPrompt: false,\n\t\t\t\tselectedItemCount: 0,\n\t\t\t\tstatus: \"failed\",\n\t\t\t\tincludedCount: 0,\n\t\t\t\tomittedCount: 0,\n\t\t\t\tblockChars: 0,\n\t\t\t};\n\t\t\treturn messages;\n\t\t}\n\t}\n\n\t/** Read-only inspection of the latest memory-prompt-inclusion decision, for tests/debugging and context_audit. */\n\tgetMemoryPromptInclusionReport(): MemoryPromptInclusionReport {\n\t\treturn this._latestMemoryPromptInclusionReport ?? defaultMemoryPromptInclusionReport();\n\t}\n\n\t/**\n\t * Combines the already-stored, no-arg latest reports (never re-queries the provider or\n\t * touches the OKF directory) into the safe, allow-list-projected shape context_audit\n\t * exposes. See context/memory-diagnostics.ts for why this projection is allow-list\n\t * based rather than a spread-then-delete of the raw report.\n\t */\n\tgetMemoryAuditDiagnostics(): {\n\t\tretrieval: MemoryRetrievalDiagnostics;\n\t\tpromptInclusion: MemoryPromptInclusionReport;\n\t} {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\treturn {\n\t\t\tretrieval: sanitizeMemoryRetrievalReportForDiagnostics(this.getMemoryRetrievalReport(), settings),\n\t\t\tpromptInclusion: this.getMemoryPromptInclusionReport(),\n\t\t};\n\t}\n\n\t/**\n\t * Zero-I/O gate for cross-session recall (R3): skip trivial turns (short acks, slash commands) so\n\t * recall only runs when it could plausibly help. The provider's similarity cutoff is the real\n\t * filter — this just avoids the index query on turns that obviously don't warrant it.\n\t */\n\tshouldAttemptRecall(text: string): boolean {\n\t\tif (!this.deps.getSettingsManager().getMemoryRetrievalSettings().enabled) return false;\n\t\tconst t = text.trim();\n\t\tif (t.length < 12 || t.startsWith(\"/\")) return false;\n\t\tconst words = t.split(/\\s+/).filter((w) => w.length >= 3);\n\t\t// R4 adaptive gate: if recall has rarely been used lately (enough samples to trust the signal),\n\t\t// raise the bar so we only recall on clearly substantial turns — and relax it again once recall\n\t\t// starts paying off. Never fully disabled, so the loop can recover.\n\t\tconst recallRarelyUseful =\n\t\t\tthis._effectivenessTracker.sampleCount >= 5 && this._effectivenessTracker.usefulLately() < 0.15;\n\t\treturn words.length >= (recallRarelyUseful ? 6 : 3);\n\t}\n\n\t/** Legacy recall prefetch with the same hard-off and explicit external-egress policy as context retrieval. */\n\tasync prefetchRecall(query: string): Promise<string> {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\tif (!settings.enabled) return \"\";\n\t\treturn this._memoryManager.prefetch(query, {\n\t\t\texternalEgressPolicy: settings.allowExternalEgress\n\t\t\t\t? ENABLED_EXTERNAL_MEMORY_EGRESS_POLICY\n\t\t\t\t: DEFAULT_EXTERNAL_MEMORY_EGRESS_POLICY,\n\t\t});\n\t}\n\n\t/** Bounded, read-only memory view for an explicitly authorized delegated worker. */\n\tasync readMemoryForLane(query: string): Promise<string> {\n\t\tconst settings = this.deps.getSettingsManager().getMemoryRetrievalSettings();\n\t\tif (!settings.enabled) return \"Memory retrieval is disabled by policy.\";\n\t\tconst budget = this._memoryBudget(settings.maxResults);\n\t\tconst staticBlock = this._memoryManager\n\t\t\t.buildSystemPromptBlockFresh(budget)\n\t\t\t.replace(\n\t\t\t\t\"[System Note: Below is a snapshot of your persistent memory. You can update these using the 'memory' tool.]\",\n\t\t\t\t\"[Read-only snapshot for a delegated worker.]\",\n\t\t\t);\n\t\tconst recalled = await this.prefetchRecall(query);\n\t\tconst combined = [staticBlock, recalled]\n\t\t\t.filter((part) => part.trim().length > 0)\n\t\t\t.join(\"\\n\\n\")\n\t\t\t.slice(0, 8000);\n\t\treturn combined.length > 0\n\t\t\t? wrapUntrustedText(combined, \"worker-memory\")\n\t\t\t: \"No relevant standing memory was found.\";\n\t}\n\n\t/** R4: score whether the agent actually used an injected recall page, so the recall gate can adapt. */\n\trecordRecallOutcome(recallText: string, queryText: string, responseText: string): void {\n\t\tthis._effectivenessTracker.recordRecallOutcome(recallText, queryText, responseText);\n\t}\n\n\t/**\n\t * (Re)build the memory subsystem: a fresh MemoryManager (reload-safe), register the bundled\n\t * file-store + any extension-contributed providers, initialize, then surface the memory tools and\n\t * the frozen system-prompt block. Best-effort: never throws into the session lifecycle.\n\t */\n\tasync initialize(): Promise<void> {\n\t\ttry {\n\t\t\t// Release the previous generation's providers (locks/handles) before recreating, so a\n\t\t\t// reload does not orphan the old MemoryManager. No-op on first init / for file-store.\n\t\t\tawait this._memoryManager.shutdownAll().catch(() => {});\n\t\t\tconst manager = new MemoryManager();\n\t\t\tmanager.registerProvider(new FileStoreProvider());\n\t\t\t// Bundled read-only cross-session recall (R3): indexes past-session transcripts and answers\n\t\t\t// prefetch() with a <memory_context> page. Never writes.\n\t\t\tmanager.registerProvider(new TranscriptRecallProvider());\n\t\t\tfor (const provider of this._pendingMemoryProviders) {\n\t\t\t\ttry {\n\t\t\t\t\tmanager.registerProvider(provider);\n\t\t\t\t} catch {\n\t\t\t\t\t// Duplicate name or reserved-tool collision — skip this provider, keep the rest.\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis._memoryManager = manager;\n\t\t\tawait manager.initializeAll(this.deps.getSessionId(), {\n\t\t\t\tagentDir: this.deps.getAgentDir(),\n\t\t\t\tcwd: this.deps.getCwd(),\n\t\t\t\tisChildSession: this.deps.isChildSession(),\n\t\t\t});\n\t\t\t// Surface memory tools + the frozen memory block now that providers are initialized.\n\t\t\t// refreshToolRegistry() ends in setActiveToolsByName(), which rebuilds AND assigns the\n\t\t\t// system prompt (including the memory block), so no explicit _rebuildSystemPrompt is needed.\n\t\t\tthis.deps.refreshToolRegistry();\n\t\t} catch (error) {\n\t\t\tconsole.error(\"Memory subsystem init failed:\", error instanceof Error ? error.message : String(error));\n\t\t}\n\t}\n\n\t/** Register a memory provider contributed by an extension; applied on the next memory (re)init. */\n\tregisterMemoryProvider(provider: MemoryProvider): void {\n\t\tif (!this._pendingMemoryProviders.some((p) => p.name === provider.name)) {\n\t\t\tthis._pendingMemoryProviders.push(provider);\n\t\t}\n\t}\n\n\t/** Register a retrieval-style context memory provider contributed by an extension. */\n\tregisterContextMemoryProvider(provider: ContextMemoryProvider): void {\n\t\tif (!this._pendingContextMemoryProviders.some((p) => p.id === provider.id)) {\n\t\t\tthis._pendingContextMemoryProviders.push(provider);\n\t\t}\n\t}\n\n\tcreateReloadSnapshot(): MemoryControllerReloadSnapshot {\n\t\treturn {\n\t\t\tpendingMemoryProviders: [...this._pendingMemoryProviders],\n\t\t\tpendingContextMemoryProviders: [...this._pendingContextMemoryProviders],\n\t\t\tmemoryOkfProvider: this._memoryOkfProvider,\n\t\t\tfileStoreMemoryProvider: this._fileStoreMemoryProvider,\n\t\t};\n\t}\n\n\trestoreReloadSnapshot(snapshot: MemoryControllerReloadSnapshot): void {\n\t\tthis._pendingMemoryProviders = [...snapshot.pendingMemoryProviders];\n\t\tthis._pendingContextMemoryProviders = [...snapshot.pendingContextMemoryProviders];\n\t\tthis._memoryOkfProvider = snapshot.memoryOkfProvider;\n\t\tthis._fileStoreMemoryProvider = snapshot.fileStoreMemoryProvider;\n\t}\n\n\t/** Reload starts memory providers fresh; loaded extensions re-register before the next `initialize()`. */\n\tclearPendingProviders(): void {\n\t\tthis._pendingMemoryProviders = [];\n\t\tthis._pendingContextMemoryProviders = [];\n\t\tthis._memoryOkfProvider = undefined;\n\t\tthis._fileStoreMemoryProvider = undefined;\n\t}\n}\n"]}
|
|
@@ -36,25 +36,6 @@ export declare function deriveModelCapabilityProfile(args: {
|
|
|
36
36
|
contextWindow?: number;
|
|
37
37
|
mode?: ModelCapabilityMode;
|
|
38
38
|
}): ModelCapabilityProfile;
|
|
39
|
-
/** Goal-continuation (autosteer) budgets, scaled to the session's capability class. */
|
|
40
|
-
export interface ContinuationBudgets {
|
|
41
|
-
/** Maximum continuation prompts per idle goal loop. */
|
|
42
|
-
maxTurns: number;
|
|
43
|
-
/** Wall-clock budget in minutes; 0 means "disabled" (upstream convention). */
|
|
44
|
-
maxWallClockMinutes: number;
|
|
45
|
-
}
|
|
46
|
-
/** Lean-class continuation caps: a 16-32k window cannot afford the full autosteer budget. */
|
|
47
|
-
export declare const MODEL_CAPABILITY_LEAN_MAX_CONTINUE_TURNS = 2;
|
|
48
|
-
export declare const MODEL_CAPABILITY_LEAN_MAX_CONTINUE_WALL_CLOCK_MINUTES = 5;
|
|
49
|
-
/**
|
|
50
|
-
* Scale goal-continuation budgets to the model's capability class. Lean-window models (16-32k) keep
|
|
51
|
-
* autonomy but at a reduced budget; every other class passes the configured budget through unchanged
|
|
52
|
-
* (full stays full; minimal/chat never reach here — their background lanes are disabled upstream).
|
|
53
|
-
*
|
|
54
|
-
* Both dimensions are a straight `min(configured, cap)`: a disabled wall-clock budget (0) stays
|
|
55
|
-
* disabled because `min(0, cap) === 0`, so the cap only ever tightens an already-positive budget.
|
|
56
|
-
*/
|
|
57
|
-
export declare function scaleContinuationBudgetsForCapability(profile: ModelCapabilityProfile, budgets: ContinuationBudgets): ContinuationBudgets;
|
|
58
39
|
/** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */
|
|
59
40
|
export declare function filterToolNamesForCapability(toolNames: readonly string[], profile: ModelCapabilityProfile): string[];
|
|
60
41
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-capability.d.ts","sourceRoot":"","sources":["../../src/core/model-capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAExE,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,KAAK,GAAG,oBAAoB,CAAC;AAExE,MAAM,WAAW,sBAAsB;IACtC,KAAK,EAAE,oBAAoB,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,0FAA0F;IAC1F,sBAAsB,EAAE,OAAO,CAAC;IAChC,4EAA4E;IAC5E,mBAAmB,EAAE,MAAM,CAAC;CAC5B;AAED,8DAA8D;AAC9D,eAAO,MAAM,iCAAiC,QAAS,CAAC;AACxD,oFAAoF;AACpF,eAAO,MAAM,iCAAiC,QAAS,CAAC;AACxD,+EAA+E;AAC/E,eAAO,MAAM,oCAAoC,OAAQ,CAAC;AAE1D,eAAO,MAAM,mCAAmC,EAAE,SAAS,MAAM,EAWhE,CAAC;AACF,eAAO,MAAM,sCAAsC,EAAE,SAAS,MAAM,EASnE,CAAC;AACF,eAAO,MAAM,mCAAmC,EAAE,SAAS,MAAM,EAAO,CAAC;AAEzE,eAAO,MAAM,8BAA8B,OAAO,CAAC;AA0CnD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC3B,GAAG,sBAAsB,CA2BzB;AAED,uFAAuF;AACvF,MAAM,WAAW,mBAAmB;IACnC,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,mBAAmB,EAAE,MAAM,CAAC;CAC5B;AAED,6FAA6F;AAC7F,eAAO,MAAM,wCAAwC,IAAI,CAAC;AAC1D,eAAO,MAAM,qDAAqD,IAAI,CAAC;AAEvE;;;;;;;GAOG;AACH,wBAAgB,qCAAqC,CACpD,OAAO,EAAE,sBAAsB,EAC/B,OAAO,EAAE,mBAAmB,GAC1B,mBAAmB,CAMrB;AAED,6FAA6F;AAC7F,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,sBAAsB,GAAG,MAAM,EAAE,CAWpH;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,uBAAuB,GAChC,6BAA6B,GAC7B,wBAAwB,GACxB,2BAA2B,GAC3B,sBAAsB,CAAC;AAE1B,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,uBAAuB,CAAC;IAChC,eAAe,EAAE,oBAAoB,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC/C,eAAe,EAAE,oBAAoB,CAAC;IACtC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,kBAAkB,EAAE,OAAO,CAAC;CAC5B,GAAG,iBAAiB,GAAG,SAAS,CAOhC;AAED,6EAA6E;AAC7E,eAAO,MAAM,0BAA0B,uCAAuC,CAAC;AAE/E,0GAA0G;AAC1G,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAI5F","sourcesContent":["/**\n * Model capability auto-detection: derive what the harness may load onto a model FROM the model's\n * own metadata (`Model.contextWindow`), so small open models (4k/8k/16k windows, sub-1B params)\n * can still hold a usable chat instead of drowning in tool schemas and background-lane prompts.\n *\n * Derivation is metadata-first; defaults apply only when the metadata is missing (unknown/zero\n * window keeps today's full behavior rather than guessing). Detection can be disabled or forced\n * per class via the `modelCapability.mode` setting.\n */\n\nexport type ModelCapabilityClass = \"full\" | \"lean\" | \"minimal\" | \"chat\";\n\nexport type ModelCapabilityMode = \"auto\" | \"off\" | ModelCapabilityClass;\n\nexport interface ModelCapabilityProfile {\n\tclass: ModelCapabilityClass;\n\tcontextWindow?: number;\n\treasonCode: string;\n\t/** Allow-list; undefined = no allow-list restriction. */\n\tallowedToolNames?: readonly string[];\n\t/** Block-list applied after the allow-list; undefined = nothing blocked. */\n\tblockedToolNames?: readonly string[];\n\t/** Whether idle background lanes (goal auto-continue, research) may run on this model. */\n\tbackgroundLanesEnabled: boolean;\n\t/** Output-token cap for lane isolated completions, scaled to the window. */\n\tlaneMaxOutputTokens: number;\n}\n\n/** Windows at or above this keep the full harness surface. */\nexport const MODEL_CAPABILITY_FULL_MIN_CONTEXT = 32_768;\n/** Windows at or above this keep core tools but shed background-autonomy extras. */\nexport const MODEL_CAPABILITY_LEAN_MIN_CONTEXT = 16_384;\n/** Windows at or above this get the minimal coding set; below is chat-only. */\nexport const MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT = 8_192;\n\nexport const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS: readonly string[] = [\n\t\"delegate\",\n\t\"context_audit\",\n\t\"goal\",\n\t\"worktree_sync\",\n\t\"improvement_loop\",\n\t\"extensionify\",\n\t\"skillify\",\n\t\"model_fitness\",\n\t\"context_scout\",\n\t\"tmux_agent_manager\",\n];\nexport const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS: readonly string[] = [\n\t\"read\",\n\t\"bash\",\n\t\"python\",\n\t\"powershell\",\n\t\"edit\",\n\t\"write\",\n\t// The executor tool: minimal-class models ARE the daily-ops executors, and its schema is tiny.\n\t\"run_toolkit_script\",\n];\nexport const MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS: readonly string[] = [];\n\nexport const DEFAULT_LANE_MAX_OUTPUT_TOKENS = 2048;\nconst MIN_LANE_MAX_OUTPUT_TOKENS = 256;\n\nfunction laneOutputTokensForWindow(contextWindow: number | undefined): number {\n\tif (contextWindow === undefined || contextWindow <= 0) return DEFAULT_LANE_MAX_OUTPUT_TOKENS;\n\t// A lane completion may use at most an eighth of the window for output, floored so tiny\n\t// windows still produce something parseable.\n\treturn Math.min(DEFAULT_LANE_MAX_OUTPUT_TOKENS, Math.max(MIN_LANE_MAX_OUTPUT_TOKENS, Math.floor(contextWindow / 8)));\n}\n\nfunction profileForClass(\n\tcapabilityClass: ModelCapabilityClass,\n\treasonCode: string,\n\tcontextWindow: number | undefined,\n): ModelCapabilityProfile {\n\tconst base = {\n\t\tclass: capabilityClass,\n\t\treasonCode,\n\t\tbackgroundLanesEnabled: true,\n\t\tlaneMaxOutputTokens: laneOutputTokensForWindow(contextWindow),\n\t\t...(contextWindow !== undefined && contextWindow > 0 ? { contextWindow } : {}),\n\t};\n\tswitch (capabilityClass) {\n\t\tcase \"full\":\n\t\t\treturn base;\n\t\tcase \"lean\":\n\t\t\treturn { ...base, blockedToolNames: MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS };\n\t\tcase \"minimal\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t\tcase \"chat\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t}\n}\n\nexport function deriveModelCapabilityProfile(args: {\n\tcontextWindow?: number;\n\tmode?: ModelCapabilityMode;\n}): ModelCapabilityProfile {\n\tconst mode = args.mode ?? \"auto\";\n\tconst contextWindow =\n\t\targs.contextWindow !== undefined && Number.isFinite(args.contextWindow) && args.contextWindow > 0\n\t\t\t? args.contextWindow\n\t\t\t: undefined;\n\tif (mode === \"off\") {\n\t\treturn profileForClass(\"full\", \"detection_disabled\", contextWindow);\n\t}\n\tif (mode !== \"auto\") {\n\t\treturn profileForClass(mode, \"forced_by_setting\", contextWindow);\n\t}\n\n\tif (contextWindow === undefined) {\n\t\t// Metadata missing: defaults, never guesses.\n\t\treturn profileForClass(\"full\", \"unknown_context_window_defaults\", undefined);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_FULL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"full\", \"large_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_LEAN_MIN_CONTEXT) {\n\t\treturn profileForClass(\"lean\", \"lean_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"minimal\", \"minimal_context_window\", contextWindow);\n\t}\n\treturn profileForClass(\"chat\", \"chat_only_context_window\", contextWindow);\n}\n\n/** Goal-continuation (autosteer) budgets, scaled to the session's capability class. */\nexport interface ContinuationBudgets {\n\t/** Maximum continuation prompts per idle goal loop. */\n\tmaxTurns: number;\n\t/** Wall-clock budget in minutes; 0 means \"disabled\" (upstream convention). */\n\tmaxWallClockMinutes: number;\n}\n\n/** Lean-class continuation caps: a 16-32k window cannot afford the full autosteer budget. */\nexport const MODEL_CAPABILITY_LEAN_MAX_CONTINUE_TURNS = 2;\nexport const MODEL_CAPABILITY_LEAN_MAX_CONTINUE_WALL_CLOCK_MINUTES = 5;\n\n/**\n * Scale goal-continuation budgets to the model's capability class. Lean-window models (16-32k) keep\n * autonomy but at a reduced budget; every other class passes the configured budget through unchanged\n * (full stays full; minimal/chat never reach here — their background lanes are disabled upstream).\n *\n * Both dimensions are a straight `min(configured, cap)`: a disabled wall-clock budget (0) stays\n * disabled because `min(0, cap) === 0`, so the cap only ever tightens an already-positive budget.\n */\nexport function scaleContinuationBudgetsForCapability(\n\tprofile: ModelCapabilityProfile,\n\tbudgets: ContinuationBudgets,\n): ContinuationBudgets {\n\tif (profile.class !== \"lean\") return budgets;\n\treturn {\n\t\tmaxTurns: Math.min(budgets.maxTurns, MODEL_CAPABILITY_LEAN_MAX_CONTINUE_TURNS),\n\t\tmaxWallClockMinutes: Math.min(budgets.maxWallClockMinutes, MODEL_CAPABILITY_LEAN_MAX_CONTINUE_WALL_CLOCK_MINUTES),\n\t};\n}\n\n/** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */\nexport function filterToolNamesForCapability(toolNames: readonly string[], profile: ModelCapabilityProfile): string[] {\n\tlet filtered = [...toolNames];\n\tif (profile.allowedToolNames !== undefined) {\n\t\tconst allowed = new Set(profile.allowedToolNames);\n\t\tfiltered = filtered.filter((name) => allowed.has(name));\n\t}\n\tif (profile.blockedToolNames !== undefined) {\n\t\tconst blocked = new Set(profile.blockedToolNames);\n\t\tfiltered = filtered.filter((name) => !blocked.has(name));\n\t}\n\treturn filtered;\n}\n\n/**\n * Lane-worker eligibility: a session bound to a worktree-sync lane (`--worktree-lane` /\n * `PI_WORKTREE_LANE`, see worktree-sync/runtime.ts) is expected to drive the FULL multi-step\n * lane-gate/recovery surface -- sync, conflict recovery, land -- unattended. A sub-full capability\n * class or a model with no working native tool-call path cannot reliably drive that surface. This\n * rides the SAME capability system every other adaptation in this file rides (class + context\n * window + the `/toolprobe` verdict) -- no parallel mechanism, no new env var, no new registry field.\n */\nexport type LaneWorkerRefusalReason =\n\t| \"capability_class_below_full\"\n\t| \"context_window_unknown\"\n\t| \"tool_calling_unadvertised\"\n\t| \"tool_calling_demoted\";\n\nexport interface LaneWorkerRefusal {\n\treason: LaneWorkerRefusalReason;\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow?: number;\n}\n\n/**\n * Decide whether the model described by `args` may drive a worktree-sync lane worker. First\n * failure wins, in order: capability class below full; an unknown/undeclared context window (the\n * classifier's own registry-derived SSOT -- see `deriveModelCapabilityProfile`; a full class can\n * still carry an undefined window via the `unknown_context_window_defaults` fallback); no\n * ADVERTISED native tool-call path (`Model.textToolCallProtocol` unset/false -- set true means\n * phone-only); or a GRADED `/toolprobe` demotion to \"text-protocol\"/\"none\". An UNPROBED model (no\n * verdict on record yet) is eligible on its advertised support alone -- unprobed is never treated\n * as demoted. `undefined` means eligible.\n */\nexport function evaluateLaneWorkerRefusal(args: {\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow: number | undefined;\n\ttoolCallingAdvertised: boolean;\n\ttoolCallingDemoted: boolean;\n}): LaneWorkerRefusal | undefined {\n\tconst { capabilityClass, contextWindow, toolCallingAdvertised, toolCallingDemoted } = args;\n\tif (capabilityClass !== \"full\") return { reason: \"capability_class_below_full\", capabilityClass, contextWindow };\n\tif (contextWindow === undefined) return { reason: \"context_window_unknown\", capabilityClass, contextWindow };\n\tif (!toolCallingAdvertised) return { reason: \"tool_calling_unadvertised\", capabilityClass, contextWindow };\n\tif (toolCallingDemoted) return { reason: \"tool_calling_demoted\", capabilityClass, contextWindow };\n\treturn undefined;\n}\n\n/** Stable, greppable prefix for {@link formatLaneWorkerRefusal}'s output. */\nexport const LANE_WORKER_REFUSAL_PREFIX = \"worktree-sync lane-worker refusal:\";\n\n/** Format a refusal into one deterministic, greppable line naming the lane, class, window, and reason. */\nexport function formatLaneWorkerRefusal(refusal: LaneWorkerRefusal, laneKey?: string): string {\n\tconst laneSuffix = laneKey !== undefined ? ` lane=${laneKey}` : \"\";\n\tconst windowText = refusal.contextWindow !== undefined ? String(refusal.contextWindow) : \"unknown\";\n\treturn `${LANE_WORKER_REFUSAL_PREFIX}${laneSuffix} class=${refusal.capabilityClass} contextWindow=${windowText} reason=${refusal.reason}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"model-capability.d.ts","sourceRoot":"","sources":["../../src/core/model-capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAExE,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,KAAK,GAAG,oBAAoB,CAAC;AAExE,MAAM,WAAW,sBAAsB;IACtC,KAAK,EAAE,oBAAoB,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,0FAA0F;IAC1F,sBAAsB,EAAE,OAAO,CAAC;IAChC,4EAA4E;IAC5E,mBAAmB,EAAE,MAAM,CAAC;CAC5B;AAED,8DAA8D;AAC9D,eAAO,MAAM,iCAAiC,QAAS,CAAC;AACxD,oFAAoF;AACpF,eAAO,MAAM,iCAAiC,QAAS,CAAC;AACxD,+EAA+E;AAC/E,eAAO,MAAM,oCAAoC,OAAQ,CAAC;AAE1D,eAAO,MAAM,mCAAmC,EAAE,SAAS,MAAM,EAWhE,CAAC;AACF,eAAO,MAAM,sCAAsC,EAAE,SAAS,MAAM,EAUnE,CAAC;AACF,eAAO,MAAM,mCAAmC,EAAE,SAAS,MAAM,EAAO,CAAC;AAEzE,eAAO,MAAM,8BAA8B,OAAO,CAAC;AA0CnD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC3B,GAAG,sBAAsB,CA2BzB;AAED,6FAA6F;AAC7F,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,sBAAsB,GAAG,MAAM,EAAE,CAWpH;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,uBAAuB,GAChC,6BAA6B,GAC7B,wBAAwB,GACxB,2BAA2B,GAC3B,sBAAsB,CAAC;AAE1B,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,uBAAuB,CAAC;IAChC,eAAe,EAAE,oBAAoB,CAAC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE;IAC/C,eAAe,EAAE,oBAAoB,CAAC;IACtC,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,kBAAkB,EAAE,OAAO,CAAC;CAC5B,GAAG,iBAAiB,GAAG,SAAS,CAOhC;AAED,6EAA6E;AAC7E,eAAO,MAAM,0BAA0B,uCAAuC,CAAC;AAE/E,0GAA0G;AAC1G,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAI5F","sourcesContent":["/**\n * Model capability auto-detection: derive what the harness may load onto a model FROM the model's\n * own metadata (`Model.contextWindow`), so small open models (4k/8k/16k windows, sub-1B params)\n * can still hold a usable chat instead of drowning in tool schemas and background-lane prompts.\n *\n * Derivation is metadata-first; defaults apply only when the metadata is missing (unknown/zero\n * window keeps today's full behavior rather than guessing). Detection can be disabled or forced\n * per class via the `modelCapability.mode` setting.\n */\n\nexport type ModelCapabilityClass = \"full\" | \"lean\" | \"minimal\" | \"chat\";\n\nexport type ModelCapabilityMode = \"auto\" | \"off\" | ModelCapabilityClass;\n\nexport interface ModelCapabilityProfile {\n\tclass: ModelCapabilityClass;\n\tcontextWindow?: number;\n\treasonCode: string;\n\t/** Allow-list; undefined = no allow-list restriction. */\n\tallowedToolNames?: readonly string[];\n\t/** Block-list applied after the allow-list; undefined = nothing blocked. */\n\tblockedToolNames?: readonly string[];\n\t/** Whether idle background lanes (goal auto-continue, research) may run on this model. */\n\tbackgroundLanesEnabled: boolean;\n\t/** Output-token cap for lane isolated completions, scaled to the window. */\n\tlaneMaxOutputTokens: number;\n}\n\n/** Windows at or above this keep the full harness surface. */\nexport const MODEL_CAPABILITY_FULL_MIN_CONTEXT = 32_768;\n/** Windows at or above this keep core tools but shed background-autonomy extras. */\nexport const MODEL_CAPABILITY_LEAN_MIN_CONTEXT = 16_384;\n/** Windows at or above this get the minimal coding set; below is chat-only. */\nexport const MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT = 8_192;\n\nexport const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS: readonly string[] = [\n\t\"delegate\",\n\t\"context_audit\",\n\t\"goal\",\n\t\"worktree_sync\",\n\t\"improvement_loop\",\n\t\"extensionify\",\n\t\"skillify\",\n\t\"model_fitness\",\n\t\"context_scout\",\n\t\"tmux_agent_manager\",\n];\nexport const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS: readonly string[] = [\n\t\"read\",\n\t\"bash\",\n\t\"python\",\n\t\"powershell\",\n\t\"edit\",\n\t\"write\",\n\t\"ask_question\",\n\t// The executor tool: minimal-class models ARE the daily-ops executors, and its schema is tiny.\n\t\"run_toolkit_script\",\n];\nexport const MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS: readonly string[] = [];\n\nexport const DEFAULT_LANE_MAX_OUTPUT_TOKENS = 2048;\nconst MIN_LANE_MAX_OUTPUT_TOKENS = 256;\n\nfunction laneOutputTokensForWindow(contextWindow: number | undefined): number {\n\tif (contextWindow === undefined || contextWindow <= 0) return DEFAULT_LANE_MAX_OUTPUT_TOKENS;\n\t// A lane completion may use at most an eighth of the window for output, floored so tiny\n\t// windows still produce something parseable.\n\treturn Math.min(DEFAULT_LANE_MAX_OUTPUT_TOKENS, Math.max(MIN_LANE_MAX_OUTPUT_TOKENS, Math.floor(contextWindow / 8)));\n}\n\nfunction profileForClass(\n\tcapabilityClass: ModelCapabilityClass,\n\treasonCode: string,\n\tcontextWindow: number | undefined,\n): ModelCapabilityProfile {\n\tconst base = {\n\t\tclass: capabilityClass,\n\t\treasonCode,\n\t\tbackgroundLanesEnabled: true,\n\t\tlaneMaxOutputTokens: laneOutputTokensForWindow(contextWindow),\n\t\t...(contextWindow !== undefined && contextWindow > 0 ? { contextWindow } : {}),\n\t};\n\tswitch (capabilityClass) {\n\t\tcase \"full\":\n\t\t\treturn base;\n\t\tcase \"lean\":\n\t\t\treturn { ...base, blockedToolNames: MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS };\n\t\tcase \"minimal\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t\tcase \"chat\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t}\n}\n\nexport function deriveModelCapabilityProfile(args: {\n\tcontextWindow?: number;\n\tmode?: ModelCapabilityMode;\n}): ModelCapabilityProfile {\n\tconst mode = args.mode ?? \"auto\";\n\tconst contextWindow =\n\t\targs.contextWindow !== undefined && Number.isFinite(args.contextWindow) && args.contextWindow > 0\n\t\t\t? args.contextWindow\n\t\t\t: undefined;\n\tif (mode === \"off\") {\n\t\treturn profileForClass(\"full\", \"detection_disabled\", contextWindow);\n\t}\n\tif (mode !== \"auto\") {\n\t\treturn profileForClass(mode, \"forced_by_setting\", contextWindow);\n\t}\n\n\tif (contextWindow === undefined) {\n\t\t// Metadata missing: defaults, never guesses.\n\t\treturn profileForClass(\"full\", \"unknown_context_window_defaults\", undefined);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_FULL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"full\", \"large_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_LEAN_MIN_CONTEXT) {\n\t\treturn profileForClass(\"lean\", \"lean_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"minimal\", \"minimal_context_window\", contextWindow);\n\t}\n\treturn profileForClass(\"chat\", \"chat_only_context_window\", contextWindow);\n}\n\n/** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */\nexport function filterToolNamesForCapability(toolNames: readonly string[], profile: ModelCapabilityProfile): string[] {\n\tlet filtered = [...toolNames];\n\tif (profile.allowedToolNames !== undefined) {\n\t\tconst allowed = new Set(profile.allowedToolNames);\n\t\tfiltered = filtered.filter((name) => allowed.has(name));\n\t}\n\tif (profile.blockedToolNames !== undefined) {\n\t\tconst blocked = new Set(profile.blockedToolNames);\n\t\tfiltered = filtered.filter((name) => !blocked.has(name));\n\t}\n\treturn filtered;\n}\n\n/**\n * Lane-worker eligibility: a session bound to a worktree-sync lane (`--worktree-lane` /\n * `PI_WORKTREE_LANE`, see worktree-sync/runtime.ts) is expected to drive the FULL multi-step\n * lane-gate/recovery surface -- sync, conflict recovery, land -- unattended. A sub-full capability\n * class or a model with no working native tool-call path cannot reliably drive that surface. This\n * rides the SAME capability system every other adaptation in this file rides (class + context\n * window + the `/toolprobe` verdict) -- no parallel mechanism, no new env var, no new registry field.\n */\nexport type LaneWorkerRefusalReason =\n\t| \"capability_class_below_full\"\n\t| \"context_window_unknown\"\n\t| \"tool_calling_unadvertised\"\n\t| \"tool_calling_demoted\";\n\nexport interface LaneWorkerRefusal {\n\treason: LaneWorkerRefusalReason;\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow?: number;\n}\n\n/**\n * Decide whether the model described by `args` may drive a worktree-sync lane worker. First\n * failure wins, in order: capability class below full; an unknown/undeclared context window (the\n * classifier's own registry-derived SSOT -- see `deriveModelCapabilityProfile`; a full class can\n * still carry an undefined window via the `unknown_context_window_defaults` fallback); no\n * ADVERTISED native tool-call path (`Model.textToolCallProtocol` unset/false -- set true means\n * phone-only); or a GRADED `/toolprobe` demotion to \"text-protocol\"/\"none\". An UNPROBED model (no\n * verdict on record yet) is eligible on its advertised support alone -- unprobed is never treated\n * as demoted. `undefined` means eligible.\n */\nexport function evaluateLaneWorkerRefusal(args: {\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow: number | undefined;\n\ttoolCallingAdvertised: boolean;\n\ttoolCallingDemoted: boolean;\n}): LaneWorkerRefusal | undefined {\n\tconst { capabilityClass, contextWindow, toolCallingAdvertised, toolCallingDemoted } = args;\n\tif (capabilityClass !== \"full\") return { reason: \"capability_class_below_full\", capabilityClass, contextWindow };\n\tif (contextWindow === undefined) return { reason: \"context_window_unknown\", capabilityClass, contextWindow };\n\tif (!toolCallingAdvertised) return { reason: \"tool_calling_unadvertised\", capabilityClass, contextWindow };\n\tif (toolCallingDemoted) return { reason: \"tool_calling_demoted\", capabilityClass, contextWindow };\n\treturn undefined;\n}\n\n/** Stable, greppable prefix for {@link formatLaneWorkerRefusal}'s output. */\nexport const LANE_WORKER_REFUSAL_PREFIX = \"worktree-sync lane-worker refusal:\";\n\n/** Format a refusal into one deterministic, greppable line naming the lane, class, window, and reason. */\nexport function formatLaneWorkerRefusal(refusal: LaneWorkerRefusal, laneKey?: string): string {\n\tconst laneSuffix = laneKey !== undefined ? ` lane=${laneKey}` : \"\";\n\tconst windowText = refusal.contextWindow !== undefined ? String(refusal.contextWindow) : \"unknown\";\n\treturn `${LANE_WORKER_REFUSAL_PREFIX}${laneSuffix} class=${refusal.capabilityClass} contextWindow=${windowText} reason=${refusal.reason}`;\n}\n"]}
|
|
@@ -32,6 +32,7 @@ export const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS = [
|
|
|
32
32
|
"powershell",
|
|
33
33
|
"edit",
|
|
34
34
|
"write",
|
|
35
|
+
"ask_question",
|
|
35
36
|
// The executor tool: minimal-class models ARE the daily-ops executors, and its schema is tiny.
|
|
36
37
|
"run_toolkit_script",
|
|
37
38
|
];
|
|
@@ -98,25 +99,6 @@ export function deriveModelCapabilityProfile(args) {
|
|
|
98
99
|
}
|
|
99
100
|
return profileForClass("chat", "chat_only_context_window", contextWindow);
|
|
100
101
|
}
|
|
101
|
-
/** Lean-class continuation caps: a 16-32k window cannot afford the full autosteer budget. */
|
|
102
|
-
export const MODEL_CAPABILITY_LEAN_MAX_CONTINUE_TURNS = 2;
|
|
103
|
-
export const MODEL_CAPABILITY_LEAN_MAX_CONTINUE_WALL_CLOCK_MINUTES = 5;
|
|
104
|
-
/**
|
|
105
|
-
* Scale goal-continuation budgets to the model's capability class. Lean-window models (16-32k) keep
|
|
106
|
-
* autonomy but at a reduced budget; every other class passes the configured budget through unchanged
|
|
107
|
-
* (full stays full; minimal/chat never reach here — their background lanes are disabled upstream).
|
|
108
|
-
*
|
|
109
|
-
* Both dimensions are a straight `min(configured, cap)`: a disabled wall-clock budget (0) stays
|
|
110
|
-
* disabled because `min(0, cap) === 0`, so the cap only ever tightens an already-positive budget.
|
|
111
|
-
*/
|
|
112
|
-
export function scaleContinuationBudgetsForCapability(profile, budgets) {
|
|
113
|
-
if (profile.class !== "lean")
|
|
114
|
-
return budgets;
|
|
115
|
-
return {
|
|
116
|
-
maxTurns: Math.min(budgets.maxTurns, MODEL_CAPABILITY_LEAN_MAX_CONTINUE_TURNS),
|
|
117
|
-
maxWallClockMinutes: Math.min(budgets.maxWallClockMinutes, MODEL_CAPABILITY_LEAN_MAX_CONTINUE_WALL_CLOCK_MINUTES),
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
102
|
/** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */
|
|
121
103
|
export function filterToolNamesForCapability(toolNames, profile) {
|
|
122
104
|
let filtered = [...toolNames];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-capability.js","sourceRoot":"","sources":["../../src/core/model-capability.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model capability auto-detection: derive what the harness may load onto a model FROM the model's\n * own metadata (`Model.contextWindow`), so small open models (4k/8k/16k windows, sub-1B params)\n * can still hold a usable chat instead of drowning in tool schemas and background-lane prompts.\n *\n * Derivation is metadata-first; defaults apply only when the metadata is missing (unknown/zero\n * window keeps today's full behavior rather than guessing). Detection can be disabled or forced\n * per class via the `modelCapability.mode` setting.\n */\n\nexport type ModelCapabilityClass = \"full\" | \"lean\" | \"minimal\" | \"chat\";\n\nexport type ModelCapabilityMode = \"auto\" | \"off\" | ModelCapabilityClass;\n\nexport interface ModelCapabilityProfile {\n\tclass: ModelCapabilityClass;\n\tcontextWindow?: number;\n\treasonCode: string;\n\t/** Allow-list; undefined = no allow-list restriction. */\n\tallowedToolNames?: readonly string[];\n\t/** Block-list applied after the allow-list; undefined = nothing blocked. */\n\tblockedToolNames?: readonly string[];\n\t/** Whether idle background lanes (goal auto-continue, research) may run on this model. */\n\tbackgroundLanesEnabled: boolean;\n\t/** Output-token cap for lane isolated completions, scaled to the window. */\n\tlaneMaxOutputTokens: number;\n}\n\n/** Windows at or above this keep the full harness surface. */\nexport const MODEL_CAPABILITY_FULL_MIN_CONTEXT = 32_768;\n/** Windows at or above this keep core tools but shed background-autonomy extras. */\nexport const MODEL_CAPABILITY_LEAN_MIN_CONTEXT = 16_384;\n/** Windows at or above this get the minimal coding set; below is chat-only. */\nexport const MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT = 8_192;\n\nexport const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS: readonly string[] = [\n\t\"delegate\",\n\t\"context_audit\",\n\t\"goal\",\n\t\"worktree_sync\",\n\t\"improvement_loop\",\n\t\"extensionify\",\n\t\"skillify\",\n\t\"model_fitness\",\n\t\"context_scout\",\n\t\"tmux_agent_manager\",\n];\nexport const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS: readonly string[] = [\n\t\"read\",\n\t\"bash\",\n\t\"python\",\n\t\"powershell\",\n\t\"edit\",\n\t\"write\",\n\t// The executor tool: minimal-class models ARE the daily-ops executors, and its schema is tiny.\n\t\"run_toolkit_script\",\n];\nexport const MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS: readonly string[] = [];\n\nexport const DEFAULT_LANE_MAX_OUTPUT_TOKENS = 2048;\nconst MIN_LANE_MAX_OUTPUT_TOKENS = 256;\n\nfunction laneOutputTokensForWindow(contextWindow: number | undefined): number {\n\tif (contextWindow === undefined || contextWindow <= 0) return DEFAULT_LANE_MAX_OUTPUT_TOKENS;\n\t// A lane completion may use at most an eighth of the window for output, floored so tiny\n\t// windows still produce something parseable.\n\treturn Math.min(DEFAULT_LANE_MAX_OUTPUT_TOKENS, Math.max(MIN_LANE_MAX_OUTPUT_TOKENS, Math.floor(contextWindow / 8)));\n}\n\nfunction profileForClass(\n\tcapabilityClass: ModelCapabilityClass,\n\treasonCode: string,\n\tcontextWindow: number | undefined,\n): ModelCapabilityProfile {\n\tconst base = {\n\t\tclass: capabilityClass,\n\t\treasonCode,\n\t\tbackgroundLanesEnabled: true,\n\t\tlaneMaxOutputTokens: laneOutputTokensForWindow(contextWindow),\n\t\t...(contextWindow !== undefined && contextWindow > 0 ? { contextWindow } : {}),\n\t};\n\tswitch (capabilityClass) {\n\t\tcase \"full\":\n\t\t\treturn base;\n\t\tcase \"lean\":\n\t\t\treturn { ...base, blockedToolNames: MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS };\n\t\tcase \"minimal\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t\tcase \"chat\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t}\n}\n\nexport function deriveModelCapabilityProfile(args: {\n\tcontextWindow?: number;\n\tmode?: ModelCapabilityMode;\n}): ModelCapabilityProfile {\n\tconst mode = args.mode ?? \"auto\";\n\tconst contextWindow =\n\t\targs.contextWindow !== undefined && Number.isFinite(args.contextWindow) && args.contextWindow > 0\n\t\t\t? args.contextWindow\n\t\t\t: undefined;\n\tif (mode === \"off\") {\n\t\treturn profileForClass(\"full\", \"detection_disabled\", contextWindow);\n\t}\n\tif (mode !== \"auto\") {\n\t\treturn profileForClass(mode, \"forced_by_setting\", contextWindow);\n\t}\n\n\tif (contextWindow === undefined) {\n\t\t// Metadata missing: defaults, never guesses.\n\t\treturn profileForClass(\"full\", \"unknown_context_window_defaults\", undefined);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_FULL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"full\", \"large_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_LEAN_MIN_CONTEXT) {\n\t\treturn profileForClass(\"lean\", \"lean_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"minimal\", \"minimal_context_window\", contextWindow);\n\t}\n\treturn profileForClass(\"chat\", \"chat_only_context_window\", contextWindow);\n}\n\n/** Goal-continuation (autosteer) budgets, scaled to the session's capability class. */\nexport interface ContinuationBudgets {\n\t/** Maximum continuation prompts per idle goal loop. */\n\tmaxTurns: number;\n\t/** Wall-clock budget in minutes; 0 means \"disabled\" (upstream convention). */\n\tmaxWallClockMinutes: number;\n}\n\n/** Lean-class continuation caps: a 16-32k window cannot afford the full autosteer budget. */\nexport const MODEL_CAPABILITY_LEAN_MAX_CONTINUE_TURNS = 2;\nexport const MODEL_CAPABILITY_LEAN_MAX_CONTINUE_WALL_CLOCK_MINUTES = 5;\n\n/**\n * Scale goal-continuation budgets to the model's capability class. Lean-window models (16-32k) keep\n * autonomy but at a reduced budget; every other class passes the configured budget through unchanged\n * (full stays full; minimal/chat never reach here — their background lanes are disabled upstream).\n *\n * Both dimensions are a straight `min(configured, cap)`: a disabled wall-clock budget (0) stays\n * disabled because `min(0, cap) === 0`, so the cap only ever tightens an already-positive budget.\n */\nexport function scaleContinuationBudgetsForCapability(\n\tprofile: ModelCapabilityProfile,\n\tbudgets: ContinuationBudgets,\n): ContinuationBudgets {\n\tif (profile.class !== \"lean\") return budgets;\n\treturn {\n\t\tmaxTurns: Math.min(budgets.maxTurns, MODEL_CAPABILITY_LEAN_MAX_CONTINUE_TURNS),\n\t\tmaxWallClockMinutes: Math.min(budgets.maxWallClockMinutes, MODEL_CAPABILITY_LEAN_MAX_CONTINUE_WALL_CLOCK_MINUTES),\n\t};\n}\n\n/** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */\nexport function filterToolNamesForCapability(toolNames: readonly string[], profile: ModelCapabilityProfile): string[] {\n\tlet filtered = [...toolNames];\n\tif (profile.allowedToolNames !== undefined) {\n\t\tconst allowed = new Set(profile.allowedToolNames);\n\t\tfiltered = filtered.filter((name) => allowed.has(name));\n\t}\n\tif (profile.blockedToolNames !== undefined) {\n\t\tconst blocked = new Set(profile.blockedToolNames);\n\t\tfiltered = filtered.filter((name) => !blocked.has(name));\n\t}\n\treturn filtered;\n}\n\n/**\n * Lane-worker eligibility: a session bound to a worktree-sync lane (`--worktree-lane` /\n * `PI_WORKTREE_LANE`, see worktree-sync/runtime.ts) is expected to drive the FULL multi-step\n * lane-gate/recovery surface -- sync, conflict recovery, land -- unattended. A sub-full capability\n * class or a model with no working native tool-call path cannot reliably drive that surface. This\n * rides the SAME capability system every other adaptation in this file rides (class + context\n * window + the `/toolprobe` verdict) -- no parallel mechanism, no new env var, no new registry field.\n */\nexport type LaneWorkerRefusalReason =\n\t| \"capability_class_below_full\"\n\t| \"context_window_unknown\"\n\t| \"tool_calling_unadvertised\"\n\t| \"tool_calling_demoted\";\n\nexport interface LaneWorkerRefusal {\n\treason: LaneWorkerRefusalReason;\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow?: number;\n}\n\n/**\n * Decide whether the model described by `args` may drive a worktree-sync lane worker. First\n * failure wins, in order: capability class below full; an unknown/undeclared context window (the\n * classifier's own registry-derived SSOT -- see `deriveModelCapabilityProfile`; a full class can\n * still carry an undefined window via the `unknown_context_window_defaults` fallback); no\n * ADVERTISED native tool-call path (`Model.textToolCallProtocol` unset/false -- set true means\n * phone-only); or a GRADED `/toolprobe` demotion to \"text-protocol\"/\"none\". An UNPROBED model (no\n * verdict on record yet) is eligible on its advertised support alone -- unprobed is never treated\n * as demoted. `undefined` means eligible.\n */\nexport function evaluateLaneWorkerRefusal(args: {\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow: number | undefined;\n\ttoolCallingAdvertised: boolean;\n\ttoolCallingDemoted: boolean;\n}): LaneWorkerRefusal | undefined {\n\tconst { capabilityClass, contextWindow, toolCallingAdvertised, toolCallingDemoted } = args;\n\tif (capabilityClass !== \"full\") return { reason: \"capability_class_below_full\", capabilityClass, contextWindow };\n\tif (contextWindow === undefined) return { reason: \"context_window_unknown\", capabilityClass, contextWindow };\n\tif (!toolCallingAdvertised) return { reason: \"tool_calling_unadvertised\", capabilityClass, contextWindow };\n\tif (toolCallingDemoted) return { reason: \"tool_calling_demoted\", capabilityClass, contextWindow };\n\treturn undefined;\n}\n\n/** Stable, greppable prefix for {@link formatLaneWorkerRefusal}'s output. */\nexport const LANE_WORKER_REFUSAL_PREFIX = \"worktree-sync lane-worker refusal:\";\n\n/** Format a refusal into one deterministic, greppable line naming the lane, class, window, and reason. */\nexport function formatLaneWorkerRefusal(refusal: LaneWorkerRefusal, laneKey?: string): string {\n\tconst laneSuffix = laneKey !== undefined ? ` lane=${laneKey}` : \"\";\n\tconst windowText = refusal.contextWindow !== undefined ? String(refusal.contextWindow) : \"unknown\";\n\treturn `${LANE_WORKER_REFUSAL_PREFIX}${laneSuffix} class=${refusal.capabilityClass} contextWindow=${windowText} reason=${refusal.reason}`;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"model-capability.js","sourceRoot":"","sources":["../../src/core/model-capability.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model capability auto-detection: derive what the harness may load onto a model FROM the model's\n * own metadata (`Model.contextWindow`), so small open models (4k/8k/16k windows, sub-1B params)\n * can still hold a usable chat instead of drowning in tool schemas and background-lane prompts.\n *\n * Derivation is metadata-first; defaults apply only when the metadata is missing (unknown/zero\n * window keeps today's full behavior rather than guessing). Detection can be disabled or forced\n * per class via the `modelCapability.mode` setting.\n */\n\nexport type ModelCapabilityClass = \"full\" | \"lean\" | \"minimal\" | \"chat\";\n\nexport type ModelCapabilityMode = \"auto\" | \"off\" | ModelCapabilityClass;\n\nexport interface ModelCapabilityProfile {\n\tclass: ModelCapabilityClass;\n\tcontextWindow?: number;\n\treasonCode: string;\n\t/** Allow-list; undefined = no allow-list restriction. */\n\tallowedToolNames?: readonly string[];\n\t/** Block-list applied after the allow-list; undefined = nothing blocked. */\n\tblockedToolNames?: readonly string[];\n\t/** Whether idle background lanes (goal auto-continue, research) may run on this model. */\n\tbackgroundLanesEnabled: boolean;\n\t/** Output-token cap for lane isolated completions, scaled to the window. */\n\tlaneMaxOutputTokens: number;\n}\n\n/** Windows at or above this keep the full harness surface. */\nexport const MODEL_CAPABILITY_FULL_MIN_CONTEXT = 32_768;\n/** Windows at or above this keep core tools but shed background-autonomy extras. */\nexport const MODEL_CAPABILITY_LEAN_MIN_CONTEXT = 16_384;\n/** Windows at or above this get the minimal coding set; below is chat-only. */\nexport const MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT = 8_192;\n\nexport const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS: readonly string[] = [\n\t\"delegate\",\n\t\"context_audit\",\n\t\"goal\",\n\t\"worktree_sync\",\n\t\"improvement_loop\",\n\t\"extensionify\",\n\t\"skillify\",\n\t\"model_fitness\",\n\t\"context_scout\",\n\t\"tmux_agent_manager\",\n];\nexport const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS: readonly string[] = [\n\t\"read\",\n\t\"bash\",\n\t\"python\",\n\t\"powershell\",\n\t\"edit\",\n\t\"write\",\n\t\"ask_question\",\n\t// The executor tool: minimal-class models ARE the daily-ops executors, and its schema is tiny.\n\t\"run_toolkit_script\",\n];\nexport const MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS: readonly string[] = [];\n\nexport const DEFAULT_LANE_MAX_OUTPUT_TOKENS = 2048;\nconst MIN_LANE_MAX_OUTPUT_TOKENS = 256;\n\nfunction laneOutputTokensForWindow(contextWindow: number | undefined): number {\n\tif (contextWindow === undefined || contextWindow <= 0) return DEFAULT_LANE_MAX_OUTPUT_TOKENS;\n\t// A lane completion may use at most an eighth of the window for output, floored so tiny\n\t// windows still produce something parseable.\n\treturn Math.min(DEFAULT_LANE_MAX_OUTPUT_TOKENS, Math.max(MIN_LANE_MAX_OUTPUT_TOKENS, Math.floor(contextWindow / 8)));\n}\n\nfunction profileForClass(\n\tcapabilityClass: ModelCapabilityClass,\n\treasonCode: string,\n\tcontextWindow: number | undefined,\n): ModelCapabilityProfile {\n\tconst base = {\n\t\tclass: capabilityClass,\n\t\treasonCode,\n\t\tbackgroundLanesEnabled: true,\n\t\tlaneMaxOutputTokens: laneOutputTokensForWindow(contextWindow),\n\t\t...(contextWindow !== undefined && contextWindow > 0 ? { contextWindow } : {}),\n\t};\n\tswitch (capabilityClass) {\n\t\tcase \"full\":\n\t\t\treturn base;\n\t\tcase \"lean\":\n\t\t\treturn { ...base, blockedToolNames: MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS };\n\t\tcase \"minimal\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t\tcase \"chat\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t}\n}\n\nexport function deriveModelCapabilityProfile(args: {\n\tcontextWindow?: number;\n\tmode?: ModelCapabilityMode;\n}): ModelCapabilityProfile {\n\tconst mode = args.mode ?? \"auto\";\n\tconst contextWindow =\n\t\targs.contextWindow !== undefined && Number.isFinite(args.contextWindow) && args.contextWindow > 0\n\t\t\t? args.contextWindow\n\t\t\t: undefined;\n\tif (mode === \"off\") {\n\t\treturn profileForClass(\"full\", \"detection_disabled\", contextWindow);\n\t}\n\tif (mode !== \"auto\") {\n\t\treturn profileForClass(mode, \"forced_by_setting\", contextWindow);\n\t}\n\n\tif (contextWindow === undefined) {\n\t\t// Metadata missing: defaults, never guesses.\n\t\treturn profileForClass(\"full\", \"unknown_context_window_defaults\", undefined);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_FULL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"full\", \"large_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_LEAN_MIN_CONTEXT) {\n\t\treturn profileForClass(\"lean\", \"lean_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"minimal\", \"minimal_context_window\", contextWindow);\n\t}\n\treturn profileForClass(\"chat\", \"chat_only_context_window\", contextWindow);\n}\n\n/** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */\nexport function filterToolNamesForCapability(toolNames: readonly string[], profile: ModelCapabilityProfile): string[] {\n\tlet filtered = [...toolNames];\n\tif (profile.allowedToolNames !== undefined) {\n\t\tconst allowed = new Set(profile.allowedToolNames);\n\t\tfiltered = filtered.filter((name) => allowed.has(name));\n\t}\n\tif (profile.blockedToolNames !== undefined) {\n\t\tconst blocked = new Set(profile.blockedToolNames);\n\t\tfiltered = filtered.filter((name) => !blocked.has(name));\n\t}\n\treturn filtered;\n}\n\n/**\n * Lane-worker eligibility: a session bound to a worktree-sync lane (`--worktree-lane` /\n * `PI_WORKTREE_LANE`, see worktree-sync/runtime.ts) is expected to drive the FULL multi-step\n * lane-gate/recovery surface -- sync, conflict recovery, land -- unattended. A sub-full capability\n * class or a model with no working native tool-call path cannot reliably drive that surface. This\n * rides the SAME capability system every other adaptation in this file rides (class + context\n * window + the `/toolprobe` verdict) -- no parallel mechanism, no new env var, no new registry field.\n */\nexport type LaneWorkerRefusalReason =\n\t| \"capability_class_below_full\"\n\t| \"context_window_unknown\"\n\t| \"tool_calling_unadvertised\"\n\t| \"tool_calling_demoted\";\n\nexport interface LaneWorkerRefusal {\n\treason: LaneWorkerRefusalReason;\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow?: number;\n}\n\n/**\n * Decide whether the model described by `args` may drive a worktree-sync lane worker. First\n * failure wins, in order: capability class below full; an unknown/undeclared context window (the\n * classifier's own registry-derived SSOT -- see `deriveModelCapabilityProfile`; a full class can\n * still carry an undefined window via the `unknown_context_window_defaults` fallback); no\n * ADVERTISED native tool-call path (`Model.textToolCallProtocol` unset/false -- set true means\n * phone-only); or a GRADED `/toolprobe` demotion to \"text-protocol\"/\"none\". An UNPROBED model (no\n * verdict on record yet) is eligible on its advertised support alone -- unprobed is never treated\n * as demoted. `undefined` means eligible.\n */\nexport function evaluateLaneWorkerRefusal(args: {\n\tcapabilityClass: ModelCapabilityClass;\n\tcontextWindow: number | undefined;\n\ttoolCallingAdvertised: boolean;\n\ttoolCallingDemoted: boolean;\n}): LaneWorkerRefusal | undefined {\n\tconst { capabilityClass, contextWindow, toolCallingAdvertised, toolCallingDemoted } = args;\n\tif (capabilityClass !== \"full\") return { reason: \"capability_class_below_full\", capabilityClass, contextWindow };\n\tif (contextWindow === undefined) return { reason: \"context_window_unknown\", capabilityClass, contextWindow };\n\tif (!toolCallingAdvertised) return { reason: \"tool_calling_unadvertised\", capabilityClass, contextWindow };\n\tif (toolCallingDemoted) return { reason: \"tool_calling_demoted\", capabilityClass, contextWindow };\n\treturn undefined;\n}\n\n/** Stable, greppable prefix for {@link formatLaneWorkerRefusal}'s output. */\nexport const LANE_WORKER_REFUSAL_PREFIX = \"worktree-sync lane-worker refusal:\";\n\n/** Format a refusal into one deterministic, greppable line naming the lane, class, window, and reason. */\nexport function formatLaneWorkerRefusal(refusal: LaneWorkerRefusal, laneKey?: string): string {\n\tconst laneSuffix = laneKey !== undefined ? ` lane=${laneKey}` : \"\";\n\tconst windowText = refusal.contextWindow !== undefined ? String(refusal.contextWindow) : \"unknown\";\n\treturn `${LANE_WORKER_REFUSAL_PREFIX}${laneSuffix} class=${refusal.capabilityClass} contextWindow=${windowText} reason=${refusal.reason}`;\n}\n"]}
|
|
@@ -81,9 +81,11 @@ declare const ModelOverrideSchema: Type.TObject<{
|
|
|
81
81
|
order: Type.TOptional<Type.TArray<Type.TString>>;
|
|
82
82
|
}>>;
|
|
83
83
|
supportsStrictMode: Type.TOptional<Type.TBoolean>;
|
|
84
|
+
sendSessionAffinityHeaders: Type.TOptional<Type.TBoolean>;
|
|
85
|
+
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
84
86
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
85
87
|
}>, Type.TObject<{
|
|
86
|
-
|
|
88
|
+
sessionAffinityFormat: Type.TOptional<Type.TUnion<[Type.TLiteral<"openai">, Type.TLiteral<"openai-nosession">, Type.TLiteral<"openrouter">]>>;
|
|
87
89
|
supportsLongCacheRetention: Type.TOptional<Type.TBoolean>;
|
|
88
90
|
}>, Type.TObject<{
|
|
89
91
|
supportsEagerToolInputStreaming: Type.TOptional<Type.TBoolean>;
|
|
@@ -158,6 +160,9 @@ export declare class ModelRegistry {
|
|
|
158
160
|
* Get API key for a model.
|
|
159
161
|
*/
|
|
160
162
|
hasConfiguredAuth(model: Model<Api>): boolean;
|
|
163
|
+
canUseResolvedRequestAuth(model: Model<Api>, auth: ResolvedRequestAuth): auth is Extract<ResolvedRequestAuth, {
|
|
164
|
+
ok: true;
|
|
165
|
+
}>;
|
|
161
166
|
private getModelRequestKey;
|
|
162
167
|
private storeProviderRequestConfig;
|
|
163
168
|
private storeModelHeaders;
|