@caupulican/pi-adaptative 0.81.38 → 0.81.40
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 +131 -0
- package/README.md +2 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/README.md +18 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts +133 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +198 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +311 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +31 -2
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +823 -79
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +1043 -86
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/__init__.py +43 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/fs.py +270 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/search.py +252 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/strings.py +399 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/text.py +575 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/context.py +52 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/errors.py +49 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/exec.py +734 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/expand.py +238 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/main.py +132 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/nodes.py +116 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/parser.py +287 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/proc.py +137 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/state.py +100 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/tokens.py +579 -0
- package/dist/bundled-resources/skills/tool-call-repair/SKILL.md +19 -9
- package/dist/bundled-resources/skills/tool-call-repair/references/failure-grammar.md +22 -5
- package/dist/bundled-resources/skills/tool-call-repair/references/repair-catalogue.md +7 -7
- package/dist/bundled-resources/skills/tool-call-repair/references/text-protocol-grammar.md +28 -7
- package/dist/cli/args.d.ts +5 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +24 -0
- 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 +66 -0
- package/dist/core/agent-paths.d.ts.map +1 -0
- package/dist/core/agent-paths.js +170 -0
- package/dist/core/agent-paths.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 +397 -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 +4 -3
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +255 -103
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +754 -1173
- package/dist/core/agent-session.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 +26 -9
- 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 +46 -8
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/autonomy/lane-tracker.d.ts +24 -1
- package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tracker.js +43 -1
- 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 +90 -156
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +192 -968
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/bash-execution-controller.d.ts +4 -0
- package/dist/core/bash-execution-controller.d.ts.map +1 -1
- package/dist/core/bash-execution-controller.js +7 -1
- package/dist/core/bash-execution-controller.js.map +1 -1
- 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 +24 -13
- package/dist/core/compaction-support.d.ts.map +1 -1
- package/dist/core/compaction-support.js +43 -7
- 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-audit.d.ts +33 -1
- package/dist/core/context/context-audit.d.ts.map +1 -1
- package/dist/core/context/context-audit.js +31 -5
- package/dist/core/context/context-audit.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 +26 -6
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +26 -4
- package/dist/core/context-pipeline.d.ts.map +1 -1
- package/dist/core/context-pipeline.js +146 -18
- package/dist/core/context-pipeline.js.map +1 -1
- package/dist/core/cost-guard.d.ts +19 -3
- package/dist/core/cost-guard.d.ts.map +1 -1
- package/dist/core/cost-guard.js +18 -3
- package/dist/core/cost-guard.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts.map +1 -1
- package/dist/core/default-tool-surface.js +1 -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-claim.d.ts +56 -0
- package/dist/core/delegation/worker-claim.d.ts.map +1 -0
- package/dist/core/delegation/worker-claim.js +239 -0
- 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/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 +68 -13
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +7 -0
- package/dist/core/extensions/runner.js.map +1 -1
- 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 +101 -1
- 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 +52 -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 +17 -1
- package/dist/core/goal-loop-controller.d.ts.map +1 -1
- package/dist/core/goal-loop-controller.js +79 -11
- package/dist/core/goal-loop-controller.js.map +1 -1
- 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 +25 -0
- package/dist/core/goals/goal-acceptance.js.map +1 -0
- package/dist/core/goals/goal-auto-continue-controller.d.ts +27 -0
- package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -0
- package/dist/core/goals/goal-auto-continue-controller.js +93 -0
- package/dist/core/goals/goal-auto-continue-controller.js.map +1 -0
- package/dist/core/goals/goal-continuation-controller.d.ts +48 -2
- package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-controller.js +87 -0
- package/dist/core/goals/goal-continuation-controller.js.map +1 -1
- package/dist/core/goals/goal-continuation-defaults.d.ts +39 -0
- package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-defaults.js +42 -0
- package/dist/core/goals/goal-continuation-defaults.js.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.d.ts +5 -1
- package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.js +56 -15
- package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
- package/dist/core/goals/goal-lifecycle.d.ts +20 -0
- package/dist/core/goals/goal-lifecycle.d.ts.map +1 -0
- package/dist/core/goals/goal-lifecycle.js +17 -0
- package/dist/core/goals/goal-lifecycle.js.map +1 -0
- package/dist/core/goals/goal-runtime-snapshot.d.ts +105 -4
- package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
- package/dist/core/goals/goal-runtime-snapshot.js +91 -6
- package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
- package/dist/core/goals/goal-state.d.ts +90 -1
- package/dist/core/goals/goal-state.d.ts.map +1 -1
- package/dist/core/goals/goal-state.js +78 -15
- package/dist/core/goals/goal-state.js.map +1 -1
- package/dist/core/goals/goal-tool-core.d.ts +58 -2
- package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
- package/dist/core/goals/goal-tool-core.js +82 -6
- package/dist/core/goals/goal-tool-core.js.map +1 -1
- package/dist/core/goals/session-goal-state.d.ts +13 -6
- package/dist/core/goals/session-goal-state.d.ts.map +1 -1
- package/dist/core/goals/session-goal-state.js +20 -28
- package/dist/core/goals/session-goal-state.js.map +1 -1
- 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 +27 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +34 -8
- 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/observation-store.d.ts +12 -3
- package/dist/core/learning/observation-store.d.ts.map +1 -1
- package/dist/core/learning/observation-store.js +30 -15
- package/dist/core/learning/observation-store.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/learning/skill-curator.d.ts +5 -1
- package/dist/core/learning/skill-curator.d.ts.map +1 -1
- package/dist/core/learning/skill-curator.js +21 -19
- package/dist/core/learning/skill-curator.js.map +1 -1
- package/dist/core/local-runtime-controller.d.ts +65 -3
- package/dist/core/local-runtime-controller.d.ts.map +1 -1
- package/dist/core/local-runtime-controller.js +186 -26
- package/dist/core/local-runtime-controller.js.map +1 -1
- package/dist/core/memory/providers/file-store.d.ts +1 -1
- package/dist/core/memory/providers/file-store.d.ts.map +1 -1
- package/dist/core/memory/providers/file-store.js +6 -6
- package/dist/core/memory/providers/file-store.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 +34 -0
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +43 -1
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +6 -9
- 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/tool-escalation.d.ts +15 -0
- package/dist/core/model-router/tool-escalation.d.ts.map +1 -1
- package/dist/core/model-router/tool-escalation.js +23 -1
- package/dist/core/model-router/tool-escalation.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +34 -7
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js +95 -16
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/model-selection-controller.d.ts +4 -4
- 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 +10 -5
- package/dist/core/models/adaptation-store.d.ts.map +1 -1
- package/dist/core/models/adaptation-store.js +129 -81
- package/dist/core/models/adaptation-store.js.map +1 -1
- package/dist/core/models/default-model-suggestions.d.ts.map +1 -1
- package/dist/core/models/default-model-suggestions.js +17 -0
- package/dist/core/models/default-model-suggestions.js.map +1 -1
- package/dist/core/models/fitness-store.d.ts +4 -11
- package/dist/core/models/fitness-store.d.ts.map +1 -1
- package/dist/core/models/fitness-store.js +87 -51
- 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/models/llamacpp-runtime.d.ts +180 -0
- package/dist/core/models/llamacpp-runtime.d.ts.map +1 -0
- package/dist/core/models/llamacpp-runtime.js +475 -0
- package/dist/core/models/llamacpp-runtime.js.map +1 -0
- package/dist/core/models/local-registration.d.ts +40 -0
- package/dist/core/models/local-registration.d.ts.map +1 -1
- package/dist/core/models/local-registration.js +94 -5
- package/dist/core/models/local-registration.js.map +1 -1
- package/dist/core/models/local-runtime.d.ts.map +1 -1
- package/dist/core/models/local-runtime.js +6 -5
- package/dist/core/models/local-runtime.js.map +1 -1
- package/dist/core/models/model-ref.d.ts +7 -0
- package/dist/core/models/model-ref.d.ts.map +1 -1
- package/dist/core/models/model-ref.js +26 -0
- package/dist/core/models/model-ref.js.map +1 -1
- package/dist/core/models/needle-runtime.d.ts +257 -0
- package/dist/core/models/needle-runtime.d.ts.map +1 -0
- package/dist/core/models/needle-runtime.js +519 -0
- package/dist/core/models/needle-runtime.js.map +1 -0
- package/dist/core/models/prism-llamacpp-lifecycle.d.ts +89 -0
- package/dist/core/models/prism-llamacpp-lifecycle.d.ts.map +1 -0
- package/dist/core/models/prism-llamacpp-lifecycle.js +121 -0
- package/dist/core/models/prism-llamacpp-lifecycle.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 +197 -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 +11 -10
- 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 +83 -0
- package/dist/core/process-matrix/codes.d.ts.map +1 -0
- package/dist/core/process-matrix/codes.js +15 -0
- package/dist/core/process-matrix/codes.js.map +1 -0
- 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 +78 -0
- package/dist/core/process-matrix/runtime.d.ts.map +1 -0
- package/dist/core/process-matrix/runtime.js +633 -0
- package/dist/core/process-matrix/runtime.js.map +1 -0
- package/dist/core/process-matrix/store.d.ts +25 -0
- package/dist/core/process-matrix/store.d.ts.map +1 -0
- package/dist/core/process-matrix/store.js +189 -0
- package/dist/core/process-matrix/store.js.map +1 -0
- package/dist/core/process-matrix/supervisor.d.ts +75 -0
- package/dist/core/process-matrix/supervisor.d.ts.map +1 -0
- package/dist/core/process-matrix/supervisor.js +161 -0
- package/dist/core/process-matrix/supervisor.js.map +1 -0
- package/dist/core/profile-registry.d.ts +7 -0
- package/dist/core/profile-registry.d.ts.map +1 -1
- package/dist/core/profile-registry.js +25 -7
- package/dist/core/profile-registry.js.map +1 -1
- package/dist/core/python-runtime.d.ts.map +1 -1
- package/dist/core/python-runtime.js +3 -3
- package/dist/core/python-runtime.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +33 -9
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +217 -127
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/reload-blockers.d.ts +36 -0
- package/dist/core/reload-blockers.d.ts.map +1 -1
- package/dist/core/reload-blockers.js +50 -8
- package/dist/core/reload-blockers.js.map +1 -1
- 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 +15 -9
- 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 +225 -0
- package/dist/core/risk-classifier.js.map +1 -0
- package/dist/core/runtime-builder.d.ts +76 -17
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +367 -124
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/scout-controller.d.ts +6 -0
- package/dist/core/scout-controller.d.ts.map +1 -1
- package/dist/core/scout-controller.js +66 -52
- package/dist/core/scout-controller.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 +64 -27
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-analytics.d.ts.map +1 -1
- package/dist/core/session-analytics.js +28 -1
- 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 +33 -0
- package/dist/core/session-role.d.ts.map +1 -0
- package/dist/core/session-role.js +58 -0
- package/dist/core/session-role.js.map +1 -0
- 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/settings-manager.d.ts +51 -7
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +168 -82
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt-builder.d.ts +12 -0
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.js +6 -0
- package/dist/core/system-prompt-builder.js.map +1 -1
- package/dist/core/system-prompt.d.ts +14 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +20 -3
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tasks/session-task-state.d.ts +13 -6
- package/dist/core/tasks/session-task-state.d.ts.map +1 -1
- package/dist/core/tasks/session-task-state.js +20 -22
- package/dist/core/tasks/session-task-state.js.map +1 -1
- package/dist/core/tasks/task-contract-monitor.d.ts +45 -0
- package/dist/core/tasks/task-contract-monitor.d.ts.map +1 -0
- package/dist/core/tasks/task-contract-monitor.js +56 -0
- package/dist/core/tasks/task-contract-monitor.js.map +1 -0
- 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 +12 -0
- package/dist/core/tasks/task-state.d.ts.map +1 -1
- package/dist/core/tasks/task-state.js +56 -12
- 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 +85 -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 +5 -0
- package/dist/core/tool-gate-controller.js.map +1 -1
- package/dist/core/tool-protocol-controller.d.ts +91 -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 +6 -0
- package/dist/core/tool-recovery-log-records.d.ts.map +1 -1
- package/dist/core/tool-recovery-log-records.js +13 -31
- package/dist/core/tool-recovery-log-records.js.map +1 -1
- package/dist/core/tool-selection/promotion.d.ts +54 -0
- package/dist/core/tool-selection/promotion.d.ts.map +1 -0
- package/dist/core/tool-selection/promotion.js +81 -0
- package/dist/core/tool-selection/promotion.js.map +1 -0
- package/dist/core/tool-selection/tool-performance-store.d.ts +39 -6
- package/dist/core/tool-selection/tool-performance-store.d.ts.map +1 -1
- package/dist/core/tool-selection/tool-performance-store.js +153 -110
- package/dist/core/tool-selection/tool-performance-store.js.map +1 -1
- package/dist/core/tool-selection/tool-selection-controller.d.ts +45 -0
- package/dist/core/tool-selection/tool-selection-controller.d.ts.map +1 -1
- package/dist/core/tool-selection/tool-selection-controller.js +96 -0
- package/dist/core/tool-selection/tool-selection-controller.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 +18 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +95 -16
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/delegate-status.d.ts +44 -2
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +214 -19
- 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 +124 -22
- 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/goal.d.ts +94 -3
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +165 -15
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/model-fitness.d.ts +7 -0
- package/dist/core/tools/model-fitness.d.ts.map +1 -1
- package/dist/core/tools/model-fitness.js +4 -4
- package/dist/core/tools/model-fitness.js.map +1 -1
- package/dist/core/tools/orchestration-panel.d.ts +43 -0
- package/dist/core/tools/orchestration-panel.d.ts.map +1 -0
- package/dist/core/tools/orchestration-panel.js +168 -0
- package/dist/core/tools/orchestration-panel.js.map +1 -0
- 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/shell-contract-router.d.ts +6 -1
- package/dist/core/tools/shell-contract-router.d.ts.map +1 -1
- package/dist/core/tools/shell-contract-router.js +23 -2
- package/dist/core/tools/shell-contract-router.js.map +1 -1
- package/dist/core/tools/shell-session.d.ts +89 -0
- package/dist/core/tools/shell-session.d.ts.map +1 -0
- package/dist/core/tools/shell-session.js +432 -0
- package/dist/core/tools/shell-session.js.map +1 -0
- package/dist/core/tools/task-steps.d.ts +6 -0
- package/dist/core/tools/task-steps.d.ts.map +1 -1
- package/dist/core/tools/task-steps.js +165 -8
- package/dist/core/tools/task-steps.js.map +1 -1
- package/dist/core/tools/tmux-dispatch.d.ts +84 -0
- package/dist/core/tools/tmux-dispatch.d.ts.map +1 -0
- package/dist/core/tools/tmux-dispatch.js +91 -0
- package/dist/core/tools/tmux-dispatch.js.map +1 -0
- package/dist/core/tools/windows-shell-engine.d.ts +42 -0
- package/dist/core/tools/windows-shell-engine.d.ts.map +1 -0
- package/dist/core/tools/windows-shell-engine.js +151 -0
- package/dist/core/tools/windows-shell-engine.js.map +1 -0
- package/dist/core/tools/windows-shell-state.d.ts +40 -0
- package/dist/core/tools/windows-shell-state.d.ts.map +1 -0
- package/dist/core/tools/windows-shell-state.js +59 -0
- package/dist/core/tools/windows-shell-state.js.map +1 -0
- package/dist/core/tools/worktree-sync.d.ts +24 -0
- package/dist/core/tools/worktree-sync.d.ts.map +1 -0
- package/dist/core/tools/worktree-sync.js +338 -0
- package/dist/core/tools/worktree-sync.js.map +1 -0
- package/dist/core/trust-manager.d.ts +4 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +20 -2
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/util/atomic-file.d.ts +55 -0
- package/dist/core/util/atomic-file.d.ts.map +1 -0
- package/dist/core/util/atomic-file.js +255 -0
- package/dist/core/util/atomic-file.js.map +1 -0
- 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/minimatch-cache.d.ts +33 -0
- package/dist/core/util/minimatch-cache.d.ts.map +1 -0
- package/dist/core/util/minimatch-cache.js +0 -0
- package/dist/core/util/minimatch-cache.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/codes.d.ts +227 -0
- package/dist/core/worktree-sync/codes.d.ts.map +1 -0
- package/dist/core/worktree-sync/codes.js +14 -0
- package/dist/core/worktree-sync/codes.js.map +1 -0
- package/dist/core/worktree-sync/git-engine.d.ts +156 -0
- package/dist/core/worktree-sync/git-engine.d.ts.map +1 -0
- package/dist/core/worktree-sync/git-engine.js +1191 -0
- package/dist/core/worktree-sync/git-engine.js.map +1 -0
- package/dist/core/worktree-sync/lane-gate.d.ts +75 -0
- package/dist/core/worktree-sync/lane-gate.d.ts.map +1 -0
- package/dist/core/worktree-sync/lane-gate.js +360 -0
- package/dist/core/worktree-sync/lane-gate.js.map +1 -0
- package/dist/core/worktree-sync/runtime.d.ts +47 -0
- package/dist/core/worktree-sync/runtime.d.ts.map +1 -0
- package/dist/core/worktree-sync/runtime.js +96 -0
- package/dist/core/worktree-sync/runtime.js.map +1 -0
- package/dist/core/worktree-sync/store.d.ts +69 -0
- package/dist/core/worktree-sync/store.d.ts.map +1 -0
- package/dist/core/worktree-sync/store.js +252 -0
- package/dist/core/worktree-sync/store.js.map +1 -0
- package/dist/core/worktree-sync/watcher.d.ts +29 -0
- package/dist/core/worktree-sync/watcher.d.ts.map +1 -0
- package/dist/core/worktree-sync/watcher.js +93 -0
- package/dist/core/worktree-sync/watcher.js.map +1 -0
- package/dist/index.d.ts +13 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +179 -1
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +7 -0
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +197 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.d.ts +16 -1
- package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -1
- package/dist/modes/interactive/auto-learn-controller.js +50 -8
- package/dist/modes/interactive/auto-learn-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/profile-resource-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/profile-resource-editor.js +23 -1
- package/dist/modes/interactive/components/profile-resource-editor.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +2 -2
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- 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 +76 -15
- package/dist/modes/interactive/extension-ui-host.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +4 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +67 -1
- 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/local-model-commands.d.ts +43 -0
- package/dist/modes/interactive/local-model-commands.d.ts.map +1 -1
- package/dist/modes/interactive/local-model-commands.js +290 -3
- package/dist/modes/interactive/local-model-commands.js.map +1 -1
- 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/session-flow-commands.d.ts +17 -2
- package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-flow-commands.js +74 -21
- 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/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/fs-watch.d.ts +11 -0
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js +20 -2
- package/dist/utils/fs-watch.js.map +1 -1
- package/dist/utils/highlight-js-languages.d.ts +4 -0
- package/dist/utils/highlight-js-languages.d.ts.map +1 -0
- package/dist/utils/highlight-js-languages.js +573 -0
- package/dist/utils/highlight-js-languages.js.map +1 -0
- 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 +7 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +21 -6
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +53 -5
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +112 -1
- package/dist/utils/tools-manager.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 +44 -0
- package/docs/UI_QUALITY_ORCHESTRATION.md +30 -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 +153 -0
- package/docs/rpc.md +45 -2
- package/docs/sessions.md +15 -0
- package/docs/settings.md +128 -11
- package/docs/task-steps.md +8 -0
- package/docs/telemetry.md +19 -0
- package/docs/tmux-agent-manager.md +92 -2
- package/docs/ui-reference/README.md +9 -0
- package/docs/ui-reference/orchestration-after.txt +7 -0
- package/docs/ui-reference/orchestration-before.txt +7 -0
- package/docs/ui-reference/orchestration-reference.txt +6 -0
- package/docs/usage.md +14 -2
- package/docs/windows.md +52 -3
- package/docs/work-directory.md +42 -2
- package/docs/worktree-sync.md +250 -0
- 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 +12 -12
- package/package.json +10 -4
- package/dist/core/delegation/session-worker-result.d.ts +0 -16
- package/dist/core/delegation/session-worker-result.d.ts.map +0 -1
- package/dist/core/delegation/session-worker-result.js +0 -53
- package/dist/core/delegation/session-worker-result.js.map +0 -1
- package/dist/core/delegation/worker-result.d.ts +0 -15
- package/dist/core/delegation/worker-result.d.ts.map +0 -1
- package/dist/core/delegation/worker-result.js +0 -161
- 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
- package/docs/integration-sweep-builder-blueprint-2026-07-09.md +0 -365
- package/docs/integration-sweep-resume-2026-07-09.md +0 -407
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foreground-recovery-controller.d.ts","sourceRoot":"","sources":["../../src/core/foreground-recovery-controller.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAmB,MAAM,2BAA2B,CAAC;AAEpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,KAAK,uBAAuB,GACzB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACzG;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtF,MAAM,WAAW,gCAAgC;IAChD,KAAK,EAAE,KAAK,CAAC;IACb,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,EAAE,aAAa,CAAC;IAC7B,aAAa,EAAE,qBAAqB,CAAC;IACrC,gBAAgB,IAAI,MAAM,CAAC;IAC3B,IAAI,CAAC,KAAK,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC3C,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,qBAAqB,IAAI,IAAI,CAAC;CAC9B;AAED,0FAA0F;AAC1F,qBAAa,4BAA4B;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkB;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA4B;IAC5D,OAAO,CAAC,oBAAoB,CAA+B;IAC3D,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;IAExD,YAAY,IAAI,EAAE,gCAAgC,EA4BjD;IAED,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,UAAU,IAAI,IAAI,CAEjB;IAED,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErC;IAED,iBAAiB,IAAI,yBAAyB,CAE7C;IAED,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAQhD;IAED,sBAAsB,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,WAAW,CAAA;KAAE,CAAC,GAAG,OAAO,CAQjF;IAEK,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC,CA4B3C;IAED,OAAO,CAAC,sBAAsB;CAQ9B","sourcesContent":["import type { Agent, AgentEvent, ClassifiedError } from \"@caupulican/pi-agent-core\";\nimport { classifyFailure, DEFAULT_RETRY_POLICY, RetryController } from \"@caupulican/pi-agent-core\";\nimport type { AssistantMessage } from \"@caupulican/pi-ai\";\nimport { isContextOverflow } from \"@caupulican/pi-ai\";\nimport { BillingFailoverController, ExhaustedProviderRegistry } from \"./billing-failover-controller.ts\";\nimport type { FailureCorpusRecorder } from \"./failure-corpus.ts\";\nimport type { ModelRegistry } from \"./model-registry.ts\";\nimport type { ModelRouterFailoverStatus } from \"./model-router/status.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\ntype ForegroundRecoveryEvent =\n\t| { type: \"warning\"; message: string }\n\t| { type: \"auto_retry_start\"; attempt: number; maxAttempts: number; delayMs: number; errorMessage: string }\n\t| { type: \"auto_retry_end\"; success: boolean; attempt: number; finalError?: string };\n\nexport interface ForegroundRecoveryControllerDeps {\n\tagent: Agent;\n\tsettingsManager: SettingsManager;\n\tmodelRegistry: ModelRegistry;\n\tfailureCorpus: FailureCorpusRecorder;\n\tgetContextWindow(): number;\n\temit(event: ForegroundRecoveryEvent): void;\n\tcheckCompaction(message: AssistantMessage): Promise<boolean>;\n\tonSuccessfulAssistant(): void;\n}\n\n/** Owns foreground retry/failover/compaction recovery ordering and its response latch. */\nexport class ForegroundRecoveryController {\n\tprivate readonly retry: RetryController;\n\tprivate readonly billingFailover: BillingFailoverController;\n\tprivate lastAssistantMessage: AssistantMessage | undefined;\n\tprivate readonly deps: ForegroundRecoveryControllerDeps;\n\n\tconstructor(deps: ForegroundRecoveryControllerDeps) {\n\t\tthis.deps = deps;\n\t\tthis.retry = new RetryController(\n\t\t\tdeps.agent,\n\t\t\t() => {\n\t\t\t\tconst retry = deps.settingsManager.getRetrySettings();\n\t\t\t\treturn {\n\t\t\t\t\tenabled: retry.enabled,\n\t\t\t\t\tmaxAttempts: retry.maxRetries,\n\t\t\t\t\tbaseDelayMs: retry.baseDelayMs,\n\t\t\t\t\tmaxDelayMs: DEFAULT_RETRY_POLICY.maxDelayMs,\n\t\t\t\t\tjitterRatio: 0,\n\t\t\t\t};\n\t\t\t},\n\t\t\t{\n\t\t\t\tonRetryStart: (info) => deps.emit({ type: \"auto_retry_start\", ...info }),\n\t\t\t\tonRetryEnd: (info) => deps.emit({ type: \"auto_retry_end\", ...info }),\n\t\t\t},\n\t\t\tdeps.getContextWindow,\n\t\t);\n\t\tthis.billingFailover = new BillingFailoverController({\n\t\t\tagent: deps.agent,\n\t\t\tmodelRegistry: deps.modelRegistry,\n\t\t\texhausted: new ExhaustedProviderRegistry(),\n\t\t\tsubscriptionHop: deps.settingsManager.getFailoverSettings().subscriptionHop,\n\t\t\temit: deps.emit,\n\t\t\trecordFailure: (record) => deps.failureCorpus.record(record),\n\t\t});\n\t}\n\n\tget attempt(): number {\n\t\treturn this.retry.attempt;\n\t}\n\n\tget isRetrying(): boolean {\n\t\treturn this.retry.isRetrying;\n\t}\n\n\tabortRetry(): void {\n\t\tthis.retry.abort();\n\t}\n\n\tisModelExhausted(ref: string): boolean {\n\t\treturn this.billingFailover.isExhausted(ref);\n\t}\n\n\tgetFailoverStatus(): ModelRouterFailoverStatus {\n\t\treturn this.billingFailover.getStatus();\n\t}\n\n\tobserveAssistant(message: AssistantMessage): void {\n\t\tthis.lastAssistantMessage = message;\n\t\tif (message.stopReason === \"error\") return;\n\t\tthis.deps.onSuccessfulAssistant();\n\t\tif (this.retry.attempt > 0) {\n\t\t\tthis.deps.emit({ type: \"auto_retry_end\", success: true, attempt: this.retry.attempt });\n\t\t\tthis.retry.reset();\n\t\t}\n\t}\n\n\twillRetryAfterAgentEnd(event: Extract<AgentEvent, { type: \"agent_end\" }>): boolean {\n\t\tconst settings = this.deps.settingsManager.getRetrySettings();\n\t\tif (!settings.enabled || this.retry.attempt >= settings.maxRetries) return false;\n\t\tfor (let index = event.messages.length - 1; index >= 0; index--) {\n\t\t\tconst message = event.messages[index];\n\t\t\tif (message.role === \"assistant\") return this.classifyAssistantError(message)?.retryable ?? false;\n\t\t}\n\t\treturn false;\n\t}\n\n\tasync handlePostAgentRun(): Promise<boolean> {\n\t\tconst message = this.lastAssistantMessage;\n\t\tthis.lastAssistantMessage = undefined;\n\t\tif (!message) return false;\n\n\t\tconst classified = this.classifyAssistantError(message);\n\t\tif (classified) {\n\t\t\tthis.deps.failureCorpus.record({\n\t\t\t\tprovider: message.provider,\n\t\t\t\tmodelId: message.model,\n\t\t\t\tmessage: message.errorMessage ?? \"\",\n\t\t\t\tclassified,\n\t\t\t});\n\t\t}\n\t\tif (classified?.retryable && (await this.retry.prepareRetry(message))) return true;\n\t\tif (await this.billingFailover.handleAssistantError(message, classified)) return false;\n\n\t\tif (message.stopReason === \"error\" && this.retry.attempt > 0) {\n\t\t\tthis.deps.emit({\n\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\tsuccess: false,\n\t\t\t\tattempt: this.retry.attempt,\n\t\t\t\tfinalError: message.errorMessage,\n\t\t\t});\n\t\t\tthis.retry.reset();\n\t\t}\n\t\tif (await this.deps.checkCompaction(message)) return true;\n\t\treturn this.deps.agent.hasQueuedMessages();\n\t}\n\n\tprivate classifyAssistantError(message: AssistantMessage): ClassifiedError | undefined {\n\t\tif (message.stopReason !== \"error\" || !message.errorMessage) return undefined;\n\t\treturn classifyFailure({\n\t\t\tmessage: message.errorMessage,\n\t\t\tcontextOverflow: isContextOverflow(message, this.deps.getContextWindow()),\n\t\t\tprovider: message.provider,\n\t\t});\n\t}\n}\n"]}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { classifyFailure, DEFAULT_RETRY_POLICY, RetryController } from "@caupulican/pi-agent-core";
|
|
2
|
+
import { isContextOverflow } from "@caupulican/pi-ai";
|
|
3
|
+
import { BillingFailoverController, ExhaustedProviderRegistry } from "./billing-failover-controller.js";
|
|
4
|
+
/** Owns foreground retry/failover/compaction recovery ordering and its response latch. */
|
|
5
|
+
export class ForegroundRecoveryController {
|
|
6
|
+
retry;
|
|
7
|
+
billingFailover;
|
|
8
|
+
lastAssistantMessage;
|
|
9
|
+
deps;
|
|
10
|
+
constructor(deps) {
|
|
11
|
+
this.deps = deps;
|
|
12
|
+
this.retry = new RetryController(deps.agent, () => {
|
|
13
|
+
const retry = deps.settingsManager.getRetrySettings();
|
|
14
|
+
return {
|
|
15
|
+
enabled: retry.enabled,
|
|
16
|
+
maxAttempts: retry.maxRetries,
|
|
17
|
+
baseDelayMs: retry.baseDelayMs,
|
|
18
|
+
maxDelayMs: DEFAULT_RETRY_POLICY.maxDelayMs,
|
|
19
|
+
jitterRatio: 0,
|
|
20
|
+
};
|
|
21
|
+
}, {
|
|
22
|
+
onRetryStart: (info) => deps.emit({ type: "auto_retry_start", ...info }),
|
|
23
|
+
onRetryEnd: (info) => deps.emit({ type: "auto_retry_end", ...info }),
|
|
24
|
+
}, deps.getContextWindow);
|
|
25
|
+
this.billingFailover = new BillingFailoverController({
|
|
26
|
+
agent: deps.agent,
|
|
27
|
+
modelRegistry: deps.modelRegistry,
|
|
28
|
+
exhausted: new ExhaustedProviderRegistry(),
|
|
29
|
+
subscriptionHop: deps.settingsManager.getFailoverSettings().subscriptionHop,
|
|
30
|
+
emit: deps.emit,
|
|
31
|
+
recordFailure: (record) => deps.failureCorpus.record(record),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
get attempt() {
|
|
35
|
+
return this.retry.attempt;
|
|
36
|
+
}
|
|
37
|
+
get isRetrying() {
|
|
38
|
+
return this.retry.isRetrying;
|
|
39
|
+
}
|
|
40
|
+
abortRetry() {
|
|
41
|
+
this.retry.abort();
|
|
42
|
+
}
|
|
43
|
+
isModelExhausted(ref) {
|
|
44
|
+
return this.billingFailover.isExhausted(ref);
|
|
45
|
+
}
|
|
46
|
+
getFailoverStatus() {
|
|
47
|
+
return this.billingFailover.getStatus();
|
|
48
|
+
}
|
|
49
|
+
observeAssistant(message) {
|
|
50
|
+
this.lastAssistantMessage = message;
|
|
51
|
+
if (message.stopReason === "error")
|
|
52
|
+
return;
|
|
53
|
+
this.deps.onSuccessfulAssistant();
|
|
54
|
+
if (this.retry.attempt > 0) {
|
|
55
|
+
this.deps.emit({ type: "auto_retry_end", success: true, attempt: this.retry.attempt });
|
|
56
|
+
this.retry.reset();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
willRetryAfterAgentEnd(event) {
|
|
60
|
+
const settings = this.deps.settingsManager.getRetrySettings();
|
|
61
|
+
if (!settings.enabled || this.retry.attempt >= settings.maxRetries)
|
|
62
|
+
return false;
|
|
63
|
+
for (let index = event.messages.length - 1; index >= 0; index--) {
|
|
64
|
+
const message = event.messages[index];
|
|
65
|
+
if (message.role === "assistant")
|
|
66
|
+
return this.classifyAssistantError(message)?.retryable ?? false;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
async handlePostAgentRun() {
|
|
71
|
+
const message = this.lastAssistantMessage;
|
|
72
|
+
this.lastAssistantMessage = undefined;
|
|
73
|
+
if (!message)
|
|
74
|
+
return false;
|
|
75
|
+
const classified = this.classifyAssistantError(message);
|
|
76
|
+
if (classified) {
|
|
77
|
+
this.deps.failureCorpus.record({
|
|
78
|
+
provider: message.provider,
|
|
79
|
+
modelId: message.model,
|
|
80
|
+
message: message.errorMessage ?? "",
|
|
81
|
+
classified,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
if (classified?.retryable && (await this.retry.prepareRetry(message)))
|
|
85
|
+
return true;
|
|
86
|
+
if (await this.billingFailover.handleAssistantError(message, classified))
|
|
87
|
+
return false;
|
|
88
|
+
if (message.stopReason === "error" && this.retry.attempt > 0) {
|
|
89
|
+
this.deps.emit({
|
|
90
|
+
type: "auto_retry_end",
|
|
91
|
+
success: false,
|
|
92
|
+
attempt: this.retry.attempt,
|
|
93
|
+
finalError: message.errorMessage,
|
|
94
|
+
});
|
|
95
|
+
this.retry.reset();
|
|
96
|
+
}
|
|
97
|
+
if (await this.deps.checkCompaction(message))
|
|
98
|
+
return true;
|
|
99
|
+
return this.deps.agent.hasQueuedMessages();
|
|
100
|
+
}
|
|
101
|
+
classifyAssistantError(message) {
|
|
102
|
+
if (message.stopReason !== "error" || !message.errorMessage)
|
|
103
|
+
return undefined;
|
|
104
|
+
return classifyFailure({
|
|
105
|
+
message: message.errorMessage,
|
|
106
|
+
contextOverflow: isContextOverflow(message, this.deps.getContextWindow()),
|
|
107
|
+
provider: message.provider,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=foreground-recovery-controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foreground-recovery-controller.js","sourceRoot":"","sources":["../../src/core/foreground-recovery-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Agent, AgentEvent, ClassifiedError } from \"@caupulican/pi-agent-core\";\nimport { classifyFailure, DEFAULT_RETRY_POLICY, RetryController } from \"@caupulican/pi-agent-core\";\nimport type { AssistantMessage } from \"@caupulican/pi-ai\";\nimport { isContextOverflow } from \"@caupulican/pi-ai\";\nimport { BillingFailoverController, ExhaustedProviderRegistry } from \"./billing-failover-controller.ts\";\nimport type { FailureCorpusRecorder } from \"./failure-corpus.ts\";\nimport type { ModelRegistry } from \"./model-registry.ts\";\nimport type { ModelRouterFailoverStatus } from \"./model-router/status.ts\";\nimport type { SettingsManager } from \"./settings-manager.ts\";\n\ntype ForegroundRecoveryEvent =\n\t| { type: \"warning\"; message: string }\n\t| { type: \"auto_retry_start\"; attempt: number; maxAttempts: number; delayMs: number; errorMessage: string }\n\t| { type: \"auto_retry_end\"; success: boolean; attempt: number; finalError?: string };\n\nexport interface ForegroundRecoveryControllerDeps {\n\tagent: Agent;\n\tsettingsManager: SettingsManager;\n\tmodelRegistry: ModelRegistry;\n\tfailureCorpus: FailureCorpusRecorder;\n\tgetContextWindow(): number;\n\temit(event: ForegroundRecoveryEvent): void;\n\tcheckCompaction(message: AssistantMessage): Promise<boolean>;\n\tonSuccessfulAssistant(): void;\n}\n\n/** Owns foreground retry/failover/compaction recovery ordering and its response latch. */\nexport class ForegroundRecoveryController {\n\tprivate readonly retry: RetryController;\n\tprivate readonly billingFailover: BillingFailoverController;\n\tprivate lastAssistantMessage: AssistantMessage | undefined;\n\tprivate readonly deps: ForegroundRecoveryControllerDeps;\n\n\tconstructor(deps: ForegroundRecoveryControllerDeps) {\n\t\tthis.deps = deps;\n\t\tthis.retry = new RetryController(\n\t\t\tdeps.agent,\n\t\t\t() => {\n\t\t\t\tconst retry = deps.settingsManager.getRetrySettings();\n\t\t\t\treturn {\n\t\t\t\t\tenabled: retry.enabled,\n\t\t\t\t\tmaxAttempts: retry.maxRetries,\n\t\t\t\t\tbaseDelayMs: retry.baseDelayMs,\n\t\t\t\t\tmaxDelayMs: DEFAULT_RETRY_POLICY.maxDelayMs,\n\t\t\t\t\tjitterRatio: 0,\n\t\t\t\t};\n\t\t\t},\n\t\t\t{\n\t\t\t\tonRetryStart: (info) => deps.emit({ type: \"auto_retry_start\", ...info }),\n\t\t\t\tonRetryEnd: (info) => deps.emit({ type: \"auto_retry_end\", ...info }),\n\t\t\t},\n\t\t\tdeps.getContextWindow,\n\t\t);\n\t\tthis.billingFailover = new BillingFailoverController({\n\t\t\tagent: deps.agent,\n\t\t\tmodelRegistry: deps.modelRegistry,\n\t\t\texhausted: new ExhaustedProviderRegistry(),\n\t\t\tsubscriptionHop: deps.settingsManager.getFailoverSettings().subscriptionHop,\n\t\t\temit: deps.emit,\n\t\t\trecordFailure: (record) => deps.failureCorpus.record(record),\n\t\t});\n\t}\n\n\tget attempt(): number {\n\t\treturn this.retry.attempt;\n\t}\n\n\tget isRetrying(): boolean {\n\t\treturn this.retry.isRetrying;\n\t}\n\n\tabortRetry(): void {\n\t\tthis.retry.abort();\n\t}\n\n\tisModelExhausted(ref: string): boolean {\n\t\treturn this.billingFailover.isExhausted(ref);\n\t}\n\n\tgetFailoverStatus(): ModelRouterFailoverStatus {\n\t\treturn this.billingFailover.getStatus();\n\t}\n\n\tobserveAssistant(message: AssistantMessage): void {\n\t\tthis.lastAssistantMessage = message;\n\t\tif (message.stopReason === \"error\") return;\n\t\tthis.deps.onSuccessfulAssistant();\n\t\tif (this.retry.attempt > 0) {\n\t\t\tthis.deps.emit({ type: \"auto_retry_end\", success: true, attempt: this.retry.attempt });\n\t\t\tthis.retry.reset();\n\t\t}\n\t}\n\n\twillRetryAfterAgentEnd(event: Extract<AgentEvent, { type: \"agent_end\" }>): boolean {\n\t\tconst settings = this.deps.settingsManager.getRetrySettings();\n\t\tif (!settings.enabled || this.retry.attempt >= settings.maxRetries) return false;\n\t\tfor (let index = event.messages.length - 1; index >= 0; index--) {\n\t\t\tconst message = event.messages[index];\n\t\t\tif (message.role === \"assistant\") return this.classifyAssistantError(message)?.retryable ?? false;\n\t\t}\n\t\treturn false;\n\t}\n\n\tasync handlePostAgentRun(): Promise<boolean> {\n\t\tconst message = this.lastAssistantMessage;\n\t\tthis.lastAssistantMessage = undefined;\n\t\tif (!message) return false;\n\n\t\tconst classified = this.classifyAssistantError(message);\n\t\tif (classified) {\n\t\t\tthis.deps.failureCorpus.record({\n\t\t\t\tprovider: message.provider,\n\t\t\t\tmodelId: message.model,\n\t\t\t\tmessage: message.errorMessage ?? \"\",\n\t\t\t\tclassified,\n\t\t\t});\n\t\t}\n\t\tif (classified?.retryable && (await this.retry.prepareRetry(message))) return true;\n\t\tif (await this.billingFailover.handleAssistantError(message, classified)) return false;\n\n\t\tif (message.stopReason === \"error\" && this.retry.attempt > 0) {\n\t\t\tthis.deps.emit({\n\t\t\t\ttype: \"auto_retry_end\",\n\t\t\t\tsuccess: false,\n\t\t\t\tattempt: this.retry.attempt,\n\t\t\t\tfinalError: message.errorMessage,\n\t\t\t});\n\t\t\tthis.retry.reset();\n\t\t}\n\t\tif (await this.deps.checkCompaction(message)) return true;\n\t\treturn this.deps.agent.hasQueuedMessages();\n\t}\n\n\tprivate classifyAssistantError(message: AssistantMessage): ClassifiedError | undefined {\n\t\tif (message.stopReason !== \"error\" || !message.errorMessage) return undefined;\n\t\treturn classifyFailure({\n\t\t\tmessage: message.errorMessage,\n\t\t\tcontextOverflow: isContextOverflow(message, this.deps.getContextWindow()),\n\t\t\tprovider: message.provider,\n\t\t});\n\t}\n}\n"]}
|
|
@@ -60,6 +60,9 @@ export declare class GatewayRegistry {
|
|
|
60
60
|
private readonly schedulers;
|
|
61
61
|
private started;
|
|
62
62
|
private inboundHandler;
|
|
63
|
+
private readonly pendingLifecycle;
|
|
64
|
+
private trackLifecycle;
|
|
65
|
+
private drainLifecycle;
|
|
63
66
|
registerChannel(provider: ChannelProvider): void;
|
|
64
67
|
registerScheduler(provider: JobSchedulerProvider): void;
|
|
65
68
|
getChannel(name: string): ChannelProvider | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-provider.d.ts","sourceRoot":"","sources":["../../../src/core/gateways/channel-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC9B,4EAA4E;IAC5E,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,mEAAmE;AACnE,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEtF;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,KAAK,CAAC,SAAS,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,gDAAgD;IAChD,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,4CAA4C;IAC5C,IAAI,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED,kCAAkC;AAClC,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,GAAG,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;;;GAIG;AACH,qBAAa,eAAe;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;IAC/D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA2C;IACtE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAmC;
|
|
1
|
+
{"version":3,"file":"channel-provider.d.ts","sourceRoot":"","sources":["../../../src/core/gateways/channel-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,uEAAuE;AACvE,MAAM,WAAW,cAAc;IAC9B,4EAA4E;IAC5E,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,mEAAmE;AACnE,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEtF;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,KAAK,CAAC,SAAS,EAAE,qBAAqB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,gDAAgD;IAChD,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,4CAA4C;IAC5C,IAAI,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED,kCAAkC;AAClC,MAAM,WAAW,YAAY;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,kCAAkC;IAClC,GAAG,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,KAAK,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B;AAED;;;;GAIG;AACH,qBAAa,eAAe;IAC3B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsC;IAC/D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA2C;IACtE,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAmC;IACzD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA4B;IAE7D,OAAO,CAAC,cAAc;YAWR,cAAc;IAM5B,eAAe,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAM/C;IAED,iBAAiB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAKtD;IAED,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEpD;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,2FAA2F;IACrF,KAAK,CAAC,SAAS,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB3D;IAED,uFAAuF;IACjF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAmB1B;CACD","sourcesContent":["/**\n * Interface-driven gateways & scheduling (adaptive-agent design R8).\n *\n * pi does NOT bake transports (Slack/Discord/email/webhooks) or a cron tick loop into the core — that\n * would bloat the agent and couple it to deployment concerns. Instead it exposes two provider contracts\n * that a deployment wrapper (server, headless runner) implements and registers; the core only manages\n * their lifecycle. This keeps the CLI/agent transport- and schedule-agnostic while still offering a\n * first-class, uniform extension point.\n */\n\n/** A message arriving from / sent to an external channel (gateway). */\nexport interface ChannelMessage {\n\t/** Stable conversation/session key for this channel (e.g. `slack_C123`). */\n\tconversationKey: string;\n\t/** Message text. */\n\ttext: string;\n\t/** Optional opaque metadata the provider round-trips. */\n\tmeta?: Record<string, unknown>;\n}\n\n/** Handler the core supplies to a channel for inbound messages. */\nexport type ChannelInboundHandler = (message: ChannelMessage) => void | Promise<void>;\n\n/**\n * A transport channel (Telegram/Slack/email/webhook/...). Implemented by a deployment wrapper and\n * registered via {@link GatewayRegistry}. The core starts it (handing it an inbound handler) and stops\n * it on shutdown; it never imports any transport SDK itself.\n */\nexport interface ChannelProvider {\n\treadonly name: string;\n\t/** Begin listening; deliver inbound messages to `onInbound`. */\n\tstart(onInbound: ChannelInboundHandler): void | Promise<void>;\n\t/** Send an outbound message on this channel. */\n\tsend(message: ChannelMessage): void | Promise<void>;\n\t/** Stop listening and release resources. */\n\tstop(): void | Promise<void>;\n}\n\n/** A scheduled job definition. */\nexport interface ScheduledJob {\n\tid: string;\n\t/** Cron expression or interval spec the provider understands. */\n\tschedule: string;\n\t/** Invoked when the job fires. */\n\trun: () => void | Promise<void>;\n}\n\n/**\n * A scheduler (cron-like). Implemented by a deployment wrapper and registered via\n * {@link GatewayRegistry}. The core registers jobs + starts/stops it; it owns no tick loop itself.\n */\nexport interface JobSchedulerProvider {\n\treadonly name: string;\n\tschedule(job: ScheduledJob): void;\n\tstart(): void | Promise<void>;\n\tstop(): void | Promise<void>;\n}\n\n/**\n * Holds registered channel + scheduler providers and drives their lifecycle. A session starts all\n * registered providers when it binds and stops them on dispose. Registration is additive and idempotent\n * by provider name (last registration wins).\n */\nexport class GatewayRegistry {\n\tprivate readonly channels = new Map<string, ChannelProvider>();\n\tprivate readonly schedulers = new Map<string, JobSchedulerProvider>();\n\tprivate started = false;\n\tprivate inboundHandler: ChannelInboundHandler = () => {};\n\tprivate readonly pendingLifecycle = new Set<Promise<void>>();\n\n\tprivate trackLifecycle(operation: () => void | Promise<void>): void {\n\t\tlet pending: Promise<void>;\n\t\ttry {\n\t\t\tpending = Promise.resolve(operation()).catch(() => {});\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tthis.pendingLifecycle.add(pending);\n\t\tvoid pending.finally(() => this.pendingLifecycle.delete(pending));\n\t}\n\n\tprivate async drainLifecycle(): Promise<void> {\n\t\twhile (this.pendingLifecycle.size > 0) {\n\t\t\tawait Promise.allSettled([...this.pendingLifecycle]);\n\t\t}\n\t}\n\n\tregisterChannel(provider: ChannelProvider): void {\n\t\t// Stop a same-named provider being replaced so its listeners/sockets don't leak (Bug #17).\n\t\tconst existing = this.channels.get(provider.name);\n\t\tif (existing && existing !== provider) this.trackLifecycle(() => existing.stop());\n\t\tthis.channels.set(provider.name, provider);\n\t\tif (this.started) this.trackLifecycle(() => provider.start(this.inboundHandler));\n\t}\n\n\tregisterScheduler(provider: JobSchedulerProvider): void {\n\t\tconst existing = this.schedulers.get(provider.name);\n\t\tif (existing && existing !== provider) this.trackLifecycle(() => existing.stop());\n\t\tthis.schedulers.set(provider.name, provider);\n\t\tif (this.started) this.trackLifecycle(() => provider.start());\n\t}\n\n\tgetChannel(name: string): ChannelProvider | undefined {\n\t\treturn this.channels.get(name);\n\t}\n\n\tget channelCount(): number {\n\t\treturn this.channels.size;\n\t}\n\n\tget schedulerCount(): number {\n\t\treturn this.schedulers.size;\n\t}\n\n\t/** Start every registered provider; inbound channel messages are routed to `onInbound`. */\n\tasync start(onInbound: ChannelInboundHandler): Promise<void> {\n\t\tif (this.started) {\n\t\t\tawait this.drainLifecycle();\n\t\t\treturn;\n\t\t}\n\t\tthis.started = true;\n\t\tthis.inboundHandler = onInbound;\n\t\tfor (const channel of this.channels.values()) {\n\t\t\ttry {\n\t\t\t\tawait channel.start(onInbound);\n\t\t\t} catch {\n\t\t\t\t// a failing channel must not block the others\n\t\t\t}\n\t\t}\n\t\tfor (const scheduler of this.schedulers.values()) {\n\t\t\ttry {\n\t\t\t\tawait scheduler.start();\n\t\t\t} catch {}\n\t\t}\n\t\tawait this.drainLifecycle();\n\t}\n\n\t/** Stop every registered provider. Best-effort; always leaves the registry stopped. */\n\tasync stop(): Promise<void> {\n\t\tif (!this.started) {\n\t\t\tawait this.drainLifecycle();\n\t\t\treturn;\n\t\t}\n\t\tthis.started = false;\n\t\t// Late-registration starts and replacement stops must settle before the final stop pass;\n\t\t// otherwise an async start can complete after shutdown and leak a listener/process.\n\t\tawait this.drainLifecycle();\n\t\tfor (const channel of this.channels.values()) {\n\t\t\ttry {\n\t\t\t\tawait channel.stop();\n\t\t\t} catch {}\n\t\t}\n\t\tfor (const scheduler of this.schedulers.values()) {\n\t\t\ttry {\n\t\t\t\tawait scheduler.stop();\n\t\t\t} catch {}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -17,22 +17,39 @@ export class GatewayRegistry {
|
|
|
17
17
|
schedulers = new Map();
|
|
18
18
|
started = false;
|
|
19
19
|
inboundHandler = () => { };
|
|
20
|
+
pendingLifecycle = new Set();
|
|
21
|
+
trackLifecycle(operation) {
|
|
22
|
+
let pending;
|
|
23
|
+
try {
|
|
24
|
+
pending = Promise.resolve(operation()).catch(() => { });
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this.pendingLifecycle.add(pending);
|
|
30
|
+
void pending.finally(() => this.pendingLifecycle.delete(pending));
|
|
31
|
+
}
|
|
32
|
+
async drainLifecycle() {
|
|
33
|
+
while (this.pendingLifecycle.size > 0) {
|
|
34
|
+
await Promise.allSettled([...this.pendingLifecycle]);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
20
37
|
registerChannel(provider) {
|
|
21
38
|
// Stop a same-named provider being replaced so its listeners/sockets don't leak (Bug #17).
|
|
22
39
|
const existing = this.channels.get(provider.name);
|
|
23
40
|
if (existing && existing !== provider)
|
|
24
|
-
|
|
41
|
+
this.trackLifecycle(() => existing.stop());
|
|
25
42
|
this.channels.set(provider.name, provider);
|
|
26
43
|
if (this.started)
|
|
27
|
-
|
|
44
|
+
this.trackLifecycle(() => provider.start(this.inboundHandler));
|
|
28
45
|
}
|
|
29
46
|
registerScheduler(provider) {
|
|
30
47
|
const existing = this.schedulers.get(provider.name);
|
|
31
48
|
if (existing && existing !== provider)
|
|
32
|
-
|
|
49
|
+
this.trackLifecycle(() => existing.stop());
|
|
33
50
|
this.schedulers.set(provider.name, provider);
|
|
34
51
|
if (this.started)
|
|
35
|
-
|
|
52
|
+
this.trackLifecycle(() => provider.start());
|
|
36
53
|
}
|
|
37
54
|
getChannel(name) {
|
|
38
55
|
return this.channels.get(name);
|
|
@@ -45,8 +62,10 @@ export class GatewayRegistry {
|
|
|
45
62
|
}
|
|
46
63
|
/** Start every registered provider; inbound channel messages are routed to `onInbound`. */
|
|
47
64
|
async start(onInbound) {
|
|
48
|
-
if (this.started)
|
|
65
|
+
if (this.started) {
|
|
66
|
+
await this.drainLifecycle();
|
|
49
67
|
return;
|
|
68
|
+
}
|
|
50
69
|
this.started = true;
|
|
51
70
|
this.inboundHandler = onInbound;
|
|
52
71
|
for (const channel of this.channels.values()) {
|
|
@@ -63,12 +82,18 @@ export class GatewayRegistry {
|
|
|
63
82
|
}
|
|
64
83
|
catch { }
|
|
65
84
|
}
|
|
85
|
+
await this.drainLifecycle();
|
|
66
86
|
}
|
|
67
87
|
/** Stop every registered provider. Best-effort; always leaves the registry stopped. */
|
|
68
88
|
async stop() {
|
|
69
|
-
if (!this.started)
|
|
89
|
+
if (!this.started) {
|
|
90
|
+
await this.drainLifecycle();
|
|
70
91
|
return;
|
|
92
|
+
}
|
|
71
93
|
this.started = false;
|
|
94
|
+
// Late-registration starts and replacement stops must settle before the final stop pass;
|
|
95
|
+
// otherwise an async start can complete after shutdown and leak a listener/process.
|
|
96
|
+
await this.drainLifecycle();
|
|
72
97
|
for (const channel of this.channels.values()) {
|
|
73
98
|
try {
|
|
74
99
|
await channel.stop();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-provider.js","sourceRoot":"","sources":["../../../src/core/gateways/channel-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkDH;;;;GAIG;AACH,MAAM,OAAO,eAAe;IACV,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAC9C,UAAU,GAAG,IAAI,GAAG,EAAgC,CAAC;IAC9D,OAAO,GAAG,KAAK,CAAC;IAChB,cAAc,GAA0B,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"channel-provider.js","sourceRoot":"","sources":["../../../src/core/gateways/channel-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Interface-driven gateways & scheduling (adaptive-agent design R8).\n *\n * pi does NOT bake transports (Slack/Discord/email/webhooks) or a cron tick loop into the core — that\n * would bloat the agent and couple it to deployment concerns. Instead it exposes two provider contracts\n * that a deployment wrapper (server, headless runner) implements and registers; the core only manages\n * their lifecycle. This keeps the CLI/agent transport- and schedule-agnostic while still offering a\n * first-class, uniform extension point.\n */\n\n/** A message arriving from / sent to an external channel (gateway). */\nexport interface ChannelMessage {\n\t/** Stable conversation/session key for this channel (e.g. `slack_C123`). */\n\tconversationKey: string;\n\t/** Message text. */\n\ttext: string;\n\t/** Optional opaque metadata the provider round-trips. */\n\tmeta?: Record<string, unknown>;\n}\n\n/** Handler the core supplies to a channel for inbound messages. */\nexport type ChannelInboundHandler = (message: ChannelMessage) => void | Promise<void>;\n\n/**\n * A transport channel (Telegram/Slack/email/webhook/...). Implemented by a deployment wrapper and\n * registered via {@link GatewayRegistry}. The core starts it (handing it an inbound handler) and stops\n * it on shutdown; it never imports any transport SDK itself.\n */\nexport interface ChannelProvider {\n\treadonly name: string;\n\t/** Begin listening; deliver inbound messages to `onInbound`. */\n\tstart(onInbound: ChannelInboundHandler): void | Promise<void>;\n\t/** Send an outbound message on this channel. */\n\tsend(message: ChannelMessage): void | Promise<void>;\n\t/** Stop listening and release resources. */\n\tstop(): void | Promise<void>;\n}\n\n/** A scheduled job definition. */\nexport interface ScheduledJob {\n\tid: string;\n\t/** Cron expression or interval spec the provider understands. */\n\tschedule: string;\n\t/** Invoked when the job fires. */\n\trun: () => void | Promise<void>;\n}\n\n/**\n * A scheduler (cron-like). Implemented by a deployment wrapper and registered via\n * {@link GatewayRegistry}. The core registers jobs + starts/stops it; it owns no tick loop itself.\n */\nexport interface JobSchedulerProvider {\n\treadonly name: string;\n\tschedule(job: ScheduledJob): void;\n\tstart(): void | Promise<void>;\n\tstop(): void | Promise<void>;\n}\n\n/**\n * Holds registered channel + scheduler providers and drives their lifecycle. A session starts all\n * registered providers when it binds and stops them on dispose. Registration is additive and idempotent\n * by provider name (last registration wins).\n */\nexport class GatewayRegistry {\n\tprivate readonly channels = new Map<string, ChannelProvider>();\n\tprivate readonly schedulers = new Map<string, JobSchedulerProvider>();\n\tprivate started = false;\n\tprivate inboundHandler: ChannelInboundHandler = () => {};\n\tprivate readonly pendingLifecycle = new Set<Promise<void>>();\n\n\tprivate trackLifecycle(operation: () => void | Promise<void>): void {\n\t\tlet pending: Promise<void>;\n\t\ttry {\n\t\t\tpending = Promise.resolve(operation()).catch(() => {});\n\t\t} catch {\n\t\t\treturn;\n\t\t}\n\t\tthis.pendingLifecycle.add(pending);\n\t\tvoid pending.finally(() => this.pendingLifecycle.delete(pending));\n\t}\n\n\tprivate async drainLifecycle(): Promise<void> {\n\t\twhile (this.pendingLifecycle.size > 0) {\n\t\t\tawait Promise.allSettled([...this.pendingLifecycle]);\n\t\t}\n\t}\n\n\tregisterChannel(provider: ChannelProvider): void {\n\t\t// Stop a same-named provider being replaced so its listeners/sockets don't leak (Bug #17).\n\t\tconst existing = this.channels.get(provider.name);\n\t\tif (existing && existing !== provider) this.trackLifecycle(() => existing.stop());\n\t\tthis.channels.set(provider.name, provider);\n\t\tif (this.started) this.trackLifecycle(() => provider.start(this.inboundHandler));\n\t}\n\n\tregisterScheduler(provider: JobSchedulerProvider): void {\n\t\tconst existing = this.schedulers.get(provider.name);\n\t\tif (existing && existing !== provider) this.trackLifecycle(() => existing.stop());\n\t\tthis.schedulers.set(provider.name, provider);\n\t\tif (this.started) this.trackLifecycle(() => provider.start());\n\t}\n\n\tgetChannel(name: string): ChannelProvider | undefined {\n\t\treturn this.channels.get(name);\n\t}\n\n\tget channelCount(): number {\n\t\treturn this.channels.size;\n\t}\n\n\tget schedulerCount(): number {\n\t\treturn this.schedulers.size;\n\t}\n\n\t/** Start every registered provider; inbound channel messages are routed to `onInbound`. */\n\tasync start(onInbound: ChannelInboundHandler): Promise<void> {\n\t\tif (this.started) {\n\t\t\tawait this.drainLifecycle();\n\t\t\treturn;\n\t\t}\n\t\tthis.started = true;\n\t\tthis.inboundHandler = onInbound;\n\t\tfor (const channel of this.channels.values()) {\n\t\t\ttry {\n\t\t\t\tawait channel.start(onInbound);\n\t\t\t} catch {\n\t\t\t\t// a failing channel must not block the others\n\t\t\t}\n\t\t}\n\t\tfor (const scheduler of this.schedulers.values()) {\n\t\t\ttry {\n\t\t\t\tawait scheduler.start();\n\t\t\t} catch {}\n\t\t}\n\t\tawait this.drainLifecycle();\n\t}\n\n\t/** Stop every registered provider. Best-effort; always leaves the registry stopped. */\n\tasync stop(): Promise<void> {\n\t\tif (!this.started) {\n\t\t\tawait this.drainLifecycle();\n\t\t\treturn;\n\t\t}\n\t\tthis.started = false;\n\t\t// Late-registration starts and replacement stops must settle before the final stop pass;\n\t\t// otherwise an async start can complete after shutdown and leak a listener/process.\n\t\tawait this.drainLifecycle();\n\t\tfor (const channel of this.channels.values()) {\n\t\t\ttry {\n\t\t\t\tawait channel.stop();\n\t\t\t} catch {}\n\t\t}\n\t\tfor (const scheduler of this.schedulers.values()) {\n\t\t\ttry {\n\t\t\t\tawait scheduler.stop();\n\t\t\t} catch {}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -5,7 +5,13 @@
|
|
|
5
5
|
* active goal moving" loop: each pass reads the goal runtime snapshot, and — only while the snapshot
|
|
6
6
|
* says `continue` — submits one continuation prompt back through the session's own prompt path. It
|
|
7
7
|
* owns no state; the goal state lives in the session log and is read fresh every pass. Termination is
|
|
8
|
-
* fully budget-gated (turn cap, wall-clock cap,
|
|
8
|
+
* fully budget-gated (per-invocation turn cap, per-invocation wall-clock cap, a DURABLE cumulative
|
|
9
|
+
* per-goal budget — turns + active wall-clock, persisted on `GoalState` across every invocation for
|
|
10
|
+
* the goal's lifetime — and a no-progress guard on a MEANINGFUL progress signature — satisfied-
|
|
11
|
+
* requirement count + ref-backed evidence count — so hollow goal-tool calls (e.g. add_requirement/
|
|
12
|
+
* reopen churn that satisfies nothing) cannot defeat the stall guard). Each submitted pass also
|
|
13
|
+
* reports its turn/wall-clock/spend contribution back to the session via `recordGoalContinuationPass`
|
|
14
|
+
* so the cumulative budget stays accurate.
|
|
9
15
|
*/
|
|
10
16
|
import type { GoalContinuationLoopOptions, GoalContinuationLoopResult, GoalContinuationOnceOptions, GoalContinuationOnceResult, PromptOptions } from "./agent-session.ts";
|
|
11
17
|
import type { GoalRuntimeSnapshot, GoalRuntimeSnapshotSettings } from "./goals/goal-runtime-snapshot.ts";
|
|
@@ -14,6 +20,16 @@ export interface GoalLoopControllerDeps {
|
|
|
14
20
|
getGoalRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot;
|
|
15
21
|
/** Submit a continuation prompt through the session's own prompt path. */
|
|
16
22
|
prompt(text: string, options?: PromptOptions): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Persist one submitted pass's contribution to the active goal's durable cumulative budget
|
|
25
|
+
* (turns + active wall-clock; USD is attributed by the implementation from the session's own
|
|
26
|
+
* spend, not passed in here — see `AgentSession.recordGoalContinuationPass`). Called once per
|
|
27
|
+
* pass actually SUBMITTED (never for a no-op `continueGoalOnce` call).
|
|
28
|
+
*/
|
|
29
|
+
recordGoalContinuationPass(pass: {
|
|
30
|
+
turns: number;
|
|
31
|
+
wallClockMs: number;
|
|
32
|
+
}): void;
|
|
17
33
|
}
|
|
18
34
|
export declare class GoalLoopController {
|
|
19
35
|
private readonly deps;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-loop-controller.d.ts","sourceRoot":"","sources":["../../src/core/goal-loop-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACX,2BAA2B,EAC3B,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC1B,aAAa,EACb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAEzG,MAAM,WAAW,sBAAsB;IACtC,mGAAmG;IACnG,sBAAsB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,mBAAmB,CAAC;IACnF,0EAA0E;IAC1E,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D;AAED,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAE9C,YAAY,IAAI,EAAE,sBAAsB,EAEvC;IAEK,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAehG;IAEK,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA+DhG;CACD","sourcesContent":["/**\n * Goal auto-continuation loop.\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Drives the bounded \"keep the\n * active goal moving\" loop: each pass reads the goal runtime snapshot, and — only while the snapshot\n * says `continue` — submits one continuation prompt back through the session's own prompt path. It\n * owns no state; the goal state lives in the session log and is read fresh every pass. Termination is\n * fully budget-gated (turn cap, wall-clock cap, and a no-progress guard on the goal-state key).\n */\n\nimport type {\n\tGoalContinuationLoopOptions,\n\tGoalContinuationLoopResult,\n\tGoalContinuationOnceOptions,\n\tGoalContinuationOnceResult,\n\tPromptOptions,\n} from \"./agent-session.ts\";\nimport { buildGoalContinuationPrompt } from \"./goals/goal-continuation-prompt.ts\";\nimport type { GoalRuntimeSnapshot, GoalRuntimeSnapshotSettings } from \"./goals/goal-runtime-snapshot.ts\";\n\nexport interface GoalLoopControllerDeps {\n\t/** Read the current goal runtime snapshot (continuation decision + goal state) fresh each pass. */\n\tgetGoalRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot;\n\t/** Submit a continuation prompt through the session's own prompt path. */\n\tprompt(text: string, options?: PromptOptions): Promise<void>;\n}\n\nexport class GoalLoopController {\n\tprivate readonly deps: GoalLoopControllerDeps;\n\n\tconstructor(deps: GoalLoopControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tasync continueGoalOnce(options: GoalContinuationOnceOptions): Promise<GoalContinuationOnceResult> {\n\t\tconst snapshot = this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (snapshot.continuation.action !== \"continue\") {\n\t\t\treturn { submitted: false, snapshot };\n\t\t}\n\n\t\tconst prompt = buildGoalContinuationPrompt({ snapshot, limits: options.promptLimits });\n\t\tawait this.deps.prompt(prompt.text, {\n\t\t\texpandPromptTemplates: false,\n\t\t\tprocessSlashCommands: false,\n\t\t\tautoContinueGoal: false,\n\t\t});\n\n\t\treturn { submitted: true, snapshot, prompt };\n\t}\n\n\tasync continueGoalLoop(options: GoalContinuationLoopOptions): Promise<GoalContinuationLoopResult> {\n\t\tlet turnsSubmitted = 0;\n\t\tconst now = options.now ?? Date.now;\n\t\tconst maxWallClockMs =\n\t\t\ttypeof options.maxWallClockMinutes === \"number\" && options.maxWallClockMinutes > 0\n\t\t\t\t? options.maxWallClockMinutes * 60_000\n\t\t\t\t: undefined;\n\t\tconst startedAt = now();\n\t\tconst hasReachedWallClockBudget = () => maxWallClockMs !== undefined && now() - startedAt >= maxWallClockMs;\n\t\tconst snapshot = () => this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (options.maxTurns <= 0) {\n\t\t\treturn {\n\t\t\t\tturnsSubmitted: 0,\n\t\t\t\tstopReason: \"max_turns_reached\",\n\t\t\t\tfinalSnapshot: snapshot(),\n\t\t\t};\n\t\t}\n\n\t\tif (hasReachedWallClockBudget()) {\n\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: snapshot() };\n\t\t}\n\n\t\twhile (turnsSubmitted < options.maxTurns) {\n\t\t\tconst beforeSnapshot = snapshot();\n\t\t\tif (beforeSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"continuation_not_allowed\", finalSnapshot: beforeSnapshot };\n\t\t\t}\n\n\t\t\tconst state = beforeSnapshot.goalState;\n\t\t\tconst beforeKey = state\n\t\t\t\t? `${state.goalId}:${state.updatedAt}:${state.events.length}:${state.stallTurns}:${state.status}`\n\t\t\t\t: undefined;\n\n\t\t\tconst result = await this.continueGoalOnce(options);\n\t\t\tif (result.submitted) {\n\t\t\t\tturnsSubmitted++;\n\t\t\t}\n\n\t\t\tif (hasReachedWallClockBudget()) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: snapshot() };\n\t\t\t}\n\n\t\t\tconst afterSnapshot = snapshot();\n\t\t\tif (afterSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"continuation_not_allowed\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\n\t\t\tconst afterState = afterSnapshot.goalState;\n\t\t\tconst afterKey = afterState\n\t\t\t\t? `${afterState.goalId}:${afterState.updatedAt}:${afterState.events.length}:${afterState.stallTurns}:${afterState.status}`\n\t\t\t\t: undefined;\n\n\t\t\tif (beforeKey === afterKey) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_state_not_advanced\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tturnsSubmitted,\n\t\t\tstopReason: \"max_turns_reached\",\n\t\t\tfinalSnapshot: snapshot(),\n\t\t};\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"goal-loop-controller.d.ts","sourceRoot":"","sources":["../../src/core/goal-loop-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACX,2BAA2B,EAC3B,0BAA0B,EAE1B,2BAA2B,EAC3B,0BAA0B,EAC1B,aAAa,EACb,MAAM,oBAAoB,CAAC;AAO5B,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAiEzG,MAAM,WAAW,sBAAsB;IACtC,mGAAmG;IACnG,sBAAsB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,mBAAmB,CAAC;IACnF,0EAA0E;IAC1E,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D;;;;;OAKG;IACH,0BAA0B,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC/E;AAED,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAE9C,YAAY,IAAI,EAAE,sBAAsB,EAEvC;IAEK,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAehG;IAEK,gBAAgB,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAkEhG;CACD","sourcesContent":["/**\n * Goal auto-continuation loop.\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Drives the bounded \"keep the\n * active goal moving\" loop: each pass reads the goal runtime snapshot, and — only while the snapshot\n * says `continue` — submits one continuation prompt back through the session's own prompt path. It\n * owns no state; the goal state lives in the session log and is read fresh every pass. Termination is\n * fully budget-gated (per-invocation turn cap, per-invocation wall-clock cap, a DURABLE cumulative\n * per-goal budget — turns + active wall-clock, persisted on `GoalState` across every invocation for\n * the goal's lifetime — and a no-progress guard on a MEANINGFUL progress signature — satisfied-\n * requirement count + ref-backed evidence count — so hollow goal-tool calls (e.g. add_requirement/\n * reopen churn that satisfies nothing) cannot defeat the stall guard). Each submitted pass also\n * reports its turn/wall-clock/spend contribution back to the session via `recordGoalContinuationPass`\n * so the cumulative budget stays accurate.\n */\n\nimport type {\n\tGoalContinuationLoopOptions,\n\tGoalContinuationLoopResult,\n\tGoalContinuationLoopStopReason,\n\tGoalContinuationOnceOptions,\n\tGoalContinuationOnceResult,\n\tPromptOptions,\n} from \"./agent-session.ts\";\nimport {\n\tDEFAULT_GOAL_CUMULATIVE_MAX_TURNS,\n\tDEFAULT_GOAL_CUMULATIVE_MAX_WALL_CLOCK_MS,\n\tDEFAULT_GOAL_CUMULATIVE_MAX_WORKER_SPEND_USD,\n} from \"./goals/goal-continuation-defaults.ts\";\nimport { buildGoalContinuationPrompt } from \"./goals/goal-continuation-prompt.ts\";\nimport type { GoalRuntimeSnapshot, GoalRuntimeSnapshotSettings } from \"./goals/goal-runtime-snapshot.ts\";\nimport type { GoalState } from \"./goals/goal-state.ts\";\n\n/**\n * Progress signature for goal-loop stall detection. Keys ONLY on state that reflects actual\n * progress toward the goal — `goalId`, `status`, the count of satisfied requirements, and the\n * count of evidence entries that carry a ref (`uri`) AND are TRUSTED: either actually validated\n * (`verified === true`) or `kind === \"user\"` (a human-confirmed claim). Deliberately excludes\n * `events.length`, `updatedAt`, and `stallTurns`: those change on every goal-tool call (including\n * no-op churn like re-adding/reopening a requirement without satisfying anything), which let hollow\n * passes look like progress and defeat `goal_state_not_advanced`.\n *\n * `verified` is `undefined` both for evidence that hasn't been checked yet AND for evidence kinds\n * that carry no checkable ref at all (`\"user\"`/`\"finding\"`/`\"test\"` — see the doc comment on\n * `GoalEvidenceRef.verified` in `goal-state.ts`). Treating \"undefined\" as trusted would let a model spam\n * `kind:\"finding\"` evidence with a fabricated `uri` every turn — always undefined, always counted —\n * which is the same class of hollow churn this signature exists to stop. So `undefined` does NOT\n * count; only an explicit `verified === true` (a real, checked ref) or `kind === \"user\"` (mirrors\n * the `complete` gate's trusted set in `goal-tool-core.ts`'s `isVerifiedOrUserEvidence`) counts.\n * `satisfiedRequirementCount` still advances the signature for legitimate-but-unverifiable work\n * (e.g. `kind:\"finding\"`/`\"test\"` evidence cited on a `satisfy_requirement` call), and the\n * continuation controller's own `stallTurns` path remains available for the model to self-report.\n */\nfunction goalProgressSignature(state: GoalState | undefined): string | undefined {\n\tif (!state) return undefined;\n\tconst satisfiedRequirementCount = state.requirements.filter(\n\t\t(requirement) => requirement.status === \"satisfied\",\n\t).length;\n\tconst refEvidenceCount = state.evidence.filter(\n\t\t(evidence) =>\n\t\t\ttypeof evidence.uri === \"string\" &&\n\t\t\tevidence.uri.trim().length > 0 &&\n\t\t\t(evidence.verified === true || evidence.kind === \"user\"),\n\t).length;\n\treturn `${state.goalId}:${state.status}:${satisfiedRequirementCount}:${refEvidenceCount}`;\n}\n\n/**\n * Whether the goal's DURABLE cumulative continuation budget (turns and/or active wall-clock,\n * persisted on `GoalState` and summed across every `continueGoalLoop` invocation for the goal's\n * lifetime) has been exhausted. Read fresh at the top of every pass (not just the top of the\n * invocation), so a single long-running invocation that crosses the ceiling mid-loop stops\n * immediately rather than waiting for the next invocation to notice. `undefined` counters (goal\n * state predating this field, or a fresh goal) count as `0` — never exhausted.\n */\nfunction isGoalContinuationBudgetExhausted(state: GoalState | undefined): boolean {\n\tif (!state) return false;\n\tif ((state.continuationTurnsUsed ?? 0) >= DEFAULT_GOAL_CUMULATIVE_MAX_TURNS) return true;\n\tif ((state.continuationWallClockMs ?? 0) >= DEFAULT_GOAL_CUMULATIVE_MAX_WALL_CLOCK_MS) return true;\n\tif ((state.continuationWorkerSpendUsd ?? 0) >= DEFAULT_GOAL_CUMULATIVE_MAX_WORKER_SPEND_USD) return true;\n\treturn false;\n}\n\n/**\n * Maps a non-\"continue\" continuation action onto the loop's own stopReason vocabulary.\n * `\"waiting\"` (a worker is dispatched against an open requirement) gets its OWN benign stopReason so\n * a wait is never misreported as `continuation_not_allowed` (which reads as a terminal refusal) —\n * callers/telemetry can tell \"paused, will resume on its own\" apart from \"stopped, needs a human or a\n * new decision.\" Every other non-continue action (ask-user/finalize/stop) keeps the existing\n * `continuation_not_allowed` stopReason unchanged.\n */\nfunction nonContinueStopReason(snapshot: GoalRuntimeSnapshot): GoalContinuationLoopStopReason {\n\treturn snapshot.continuation.action === \"waiting\" ? \"worker_in_flight\" : \"continuation_not_allowed\";\n}\n\nexport interface GoalLoopControllerDeps {\n\t/** Read the current goal runtime snapshot (continuation decision + goal state) fresh each pass. */\n\tgetGoalRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot;\n\t/** Submit a continuation prompt through the session's own prompt path. */\n\tprompt(text: string, options?: PromptOptions): Promise<void>;\n\t/**\n\t * Persist one submitted pass's contribution to the active goal's durable cumulative budget\n\t * (turns + active wall-clock; USD is attributed by the implementation from the session's own\n\t * spend, not passed in here — see `AgentSession.recordGoalContinuationPass`). Called once per\n\t * pass actually SUBMITTED (never for a no-op `continueGoalOnce` call).\n\t */\n\trecordGoalContinuationPass(pass: { turns: number; wallClockMs: number }): void;\n}\n\nexport class GoalLoopController {\n\tprivate readonly deps: GoalLoopControllerDeps;\n\n\tconstructor(deps: GoalLoopControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tasync continueGoalOnce(options: GoalContinuationOnceOptions): Promise<GoalContinuationOnceResult> {\n\t\tconst snapshot = this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (snapshot.continuation.action !== \"continue\") {\n\t\t\treturn { submitted: false, snapshot };\n\t\t}\n\n\t\tconst prompt = buildGoalContinuationPrompt({ snapshot, limits: options.promptLimits });\n\t\tawait this.deps.prompt(prompt.text, {\n\t\t\texpandPromptTemplates: false,\n\t\t\tprocessSlashCommands: false,\n\t\t\tautoContinueGoal: false,\n\t\t});\n\n\t\treturn { submitted: true, snapshot, prompt };\n\t}\n\n\tasync continueGoalLoop(options: GoalContinuationLoopOptions): Promise<GoalContinuationLoopResult> {\n\t\tlet turnsSubmitted = 0;\n\t\tconst now = options.now ?? Date.now;\n\t\tconst maxWallClockMs =\n\t\t\ttypeof options.maxWallClockMinutes === \"number\" && options.maxWallClockMinutes > 0\n\t\t\t\t? options.maxWallClockMinutes * 60_000\n\t\t\t\t: undefined;\n\t\tconst startedAt = now();\n\t\tconst hasReachedWallClockBudget = () => maxWallClockMs !== undefined && now() - startedAt >= maxWallClockMs;\n\t\tconst snapshot = () => this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (options.maxTurns <= 0) {\n\t\t\treturn {\n\t\t\t\tturnsSubmitted: 0,\n\t\t\t\tstopReason: \"max_turns_reached\",\n\t\t\t\tfinalSnapshot: snapshot(),\n\t\t\t};\n\t\t}\n\n\t\tif (hasReachedWallClockBudget()) {\n\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: snapshot() };\n\t\t}\n\n\t\twhile (turnsSubmitted < options.maxTurns) {\n\t\t\tconst beforeSnapshot = snapshot();\n\t\t\tif (beforeSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: nonContinueStopReason(beforeSnapshot), finalSnapshot: beforeSnapshot };\n\t\t\t}\n\n\t\t\t// Cumulative (durable, cross-invocation) budget — read fresh every pass, not just at the top\n\t\t\t// of this invocation, so a single long-running call still stops the moment it crosses the\n\t\t\t// ceiling rather than overshooting until the next invocation notices.\n\t\t\tif (isGoalContinuationBudgetExhausted(beforeSnapshot.goalState)) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: beforeSnapshot };\n\t\t\t}\n\n\t\t\tconst beforeKey = goalProgressSignature(beforeSnapshot.goalState);\n\n\t\t\tconst passStartedAt = now();\n\t\t\tconst result = await this.continueGoalOnce(options);\n\t\t\tif (result.submitted) {\n\t\t\t\tturnsSubmitted++;\n\t\t\t\tthis.deps.recordGoalContinuationPass({ turns: 1, wallClockMs: now() - passStartedAt });\n\t\t\t}\n\n\t\t\tif (hasReachedWallClockBudget()) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: snapshot() };\n\t\t\t}\n\n\t\t\tconst afterSnapshot = snapshot();\n\t\t\tif (afterSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: nonContinueStopReason(afterSnapshot), finalSnapshot: afterSnapshot };\n\t\t\t}\n\n\t\t\tconst afterKey = goalProgressSignature(afterSnapshot.goalState);\n\n\t\t\tif (beforeKey === afterKey) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_state_not_advanced\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tturnsSubmitted,\n\t\t\tstopReason: \"max_turns_reached\",\n\t\t\tfinalSnapshot: snapshot(),\n\t\t};\n\t}\n}\n"]}
|
|
@@ -5,9 +5,75 @@
|
|
|
5
5
|
* active goal moving" loop: each pass reads the goal runtime snapshot, and — only while the snapshot
|
|
6
6
|
* says `continue` — submits one continuation prompt back through the session's own prompt path. It
|
|
7
7
|
* owns no state; the goal state lives in the session log and is read fresh every pass. Termination is
|
|
8
|
-
* fully budget-gated (turn cap, wall-clock cap,
|
|
8
|
+
* fully budget-gated (per-invocation turn cap, per-invocation wall-clock cap, a DURABLE cumulative
|
|
9
|
+
* per-goal budget — turns + active wall-clock, persisted on `GoalState` across every invocation for
|
|
10
|
+
* the goal's lifetime — and a no-progress guard on a MEANINGFUL progress signature — satisfied-
|
|
11
|
+
* requirement count + ref-backed evidence count — so hollow goal-tool calls (e.g. add_requirement/
|
|
12
|
+
* reopen churn that satisfies nothing) cannot defeat the stall guard). Each submitted pass also
|
|
13
|
+
* reports its turn/wall-clock/spend contribution back to the session via `recordGoalContinuationPass`
|
|
14
|
+
* so the cumulative budget stays accurate.
|
|
9
15
|
*/
|
|
16
|
+
import { DEFAULT_GOAL_CUMULATIVE_MAX_TURNS, DEFAULT_GOAL_CUMULATIVE_MAX_WALL_CLOCK_MS, DEFAULT_GOAL_CUMULATIVE_MAX_WORKER_SPEND_USD, } from "./goals/goal-continuation-defaults.js";
|
|
10
17
|
import { buildGoalContinuationPrompt } from "./goals/goal-continuation-prompt.js";
|
|
18
|
+
/**
|
|
19
|
+
* Progress signature for goal-loop stall detection. Keys ONLY on state that reflects actual
|
|
20
|
+
* progress toward the goal — `goalId`, `status`, the count of satisfied requirements, and the
|
|
21
|
+
* count of evidence entries that carry a ref (`uri`) AND are TRUSTED: either actually validated
|
|
22
|
+
* (`verified === true`) or `kind === "user"` (a human-confirmed claim). Deliberately excludes
|
|
23
|
+
* `events.length`, `updatedAt`, and `stallTurns`: those change on every goal-tool call (including
|
|
24
|
+
* no-op churn like re-adding/reopening a requirement without satisfying anything), which let hollow
|
|
25
|
+
* passes look like progress and defeat `goal_state_not_advanced`.
|
|
26
|
+
*
|
|
27
|
+
* `verified` is `undefined` both for evidence that hasn't been checked yet AND for evidence kinds
|
|
28
|
+
* that carry no checkable ref at all (`"user"`/`"finding"`/`"test"` — see the doc comment on
|
|
29
|
+
* `GoalEvidenceRef.verified` in `goal-state.ts`). Treating "undefined" as trusted would let a model spam
|
|
30
|
+
* `kind:"finding"` evidence with a fabricated `uri` every turn — always undefined, always counted —
|
|
31
|
+
* which is the same class of hollow churn this signature exists to stop. So `undefined` does NOT
|
|
32
|
+
* count; only an explicit `verified === true` (a real, checked ref) or `kind === "user"` (mirrors
|
|
33
|
+
* the `complete` gate's trusted set in `goal-tool-core.ts`'s `isVerifiedOrUserEvidence`) counts.
|
|
34
|
+
* `satisfiedRequirementCount` still advances the signature for legitimate-but-unverifiable work
|
|
35
|
+
* (e.g. `kind:"finding"`/`"test"` evidence cited on a `satisfy_requirement` call), and the
|
|
36
|
+
* continuation controller's own `stallTurns` path remains available for the model to self-report.
|
|
37
|
+
*/
|
|
38
|
+
function goalProgressSignature(state) {
|
|
39
|
+
if (!state)
|
|
40
|
+
return undefined;
|
|
41
|
+
const satisfiedRequirementCount = state.requirements.filter((requirement) => requirement.status === "satisfied").length;
|
|
42
|
+
const refEvidenceCount = state.evidence.filter((evidence) => typeof evidence.uri === "string" &&
|
|
43
|
+
evidence.uri.trim().length > 0 &&
|
|
44
|
+
(evidence.verified === true || evidence.kind === "user")).length;
|
|
45
|
+
return `${state.goalId}:${state.status}:${satisfiedRequirementCount}:${refEvidenceCount}`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Whether the goal's DURABLE cumulative continuation budget (turns and/or active wall-clock,
|
|
49
|
+
* persisted on `GoalState` and summed across every `continueGoalLoop` invocation for the goal's
|
|
50
|
+
* lifetime) has been exhausted. Read fresh at the top of every pass (not just the top of the
|
|
51
|
+
* invocation), so a single long-running invocation that crosses the ceiling mid-loop stops
|
|
52
|
+
* immediately rather than waiting for the next invocation to notice. `undefined` counters (goal
|
|
53
|
+
* state predating this field, or a fresh goal) count as `0` — never exhausted.
|
|
54
|
+
*/
|
|
55
|
+
function isGoalContinuationBudgetExhausted(state) {
|
|
56
|
+
if (!state)
|
|
57
|
+
return false;
|
|
58
|
+
if ((state.continuationTurnsUsed ?? 0) >= DEFAULT_GOAL_CUMULATIVE_MAX_TURNS)
|
|
59
|
+
return true;
|
|
60
|
+
if ((state.continuationWallClockMs ?? 0) >= DEFAULT_GOAL_CUMULATIVE_MAX_WALL_CLOCK_MS)
|
|
61
|
+
return true;
|
|
62
|
+
if ((state.continuationWorkerSpendUsd ?? 0) >= DEFAULT_GOAL_CUMULATIVE_MAX_WORKER_SPEND_USD)
|
|
63
|
+
return true;
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Maps a non-"continue" continuation action onto the loop's own stopReason vocabulary.
|
|
68
|
+
* `"waiting"` (a worker is dispatched against an open requirement) gets its OWN benign stopReason so
|
|
69
|
+
* a wait is never misreported as `continuation_not_allowed` (which reads as a terminal refusal) —
|
|
70
|
+
* callers/telemetry can tell "paused, will resume on its own" apart from "stopped, needs a human or a
|
|
71
|
+
* new decision." Every other non-continue action (ask-user/finalize/stop) keeps the existing
|
|
72
|
+
* `continuation_not_allowed` stopReason unchanged.
|
|
73
|
+
*/
|
|
74
|
+
function nonContinueStopReason(snapshot) {
|
|
75
|
+
return snapshot.continuation.action === "waiting" ? "worker_in_flight" : "continuation_not_allowed";
|
|
76
|
+
}
|
|
11
77
|
export class GoalLoopController {
|
|
12
78
|
deps;
|
|
13
79
|
constructor(deps) {
|
|
@@ -48,27 +114,29 @@ export class GoalLoopController {
|
|
|
48
114
|
while (turnsSubmitted < options.maxTurns) {
|
|
49
115
|
const beforeSnapshot = snapshot();
|
|
50
116
|
if (beforeSnapshot.continuation.action !== "continue") {
|
|
51
|
-
return { turnsSubmitted, stopReason:
|
|
117
|
+
return { turnsSubmitted, stopReason: nonContinueStopReason(beforeSnapshot), finalSnapshot: beforeSnapshot };
|
|
118
|
+
}
|
|
119
|
+
// Cumulative (durable, cross-invocation) budget — read fresh every pass, not just at the top
|
|
120
|
+
// of this invocation, so a single long-running call still stops the moment it crosses the
|
|
121
|
+
// ceiling rather than overshooting until the next invocation notices.
|
|
122
|
+
if (isGoalContinuationBudgetExhausted(beforeSnapshot.goalState)) {
|
|
123
|
+
return { turnsSubmitted, stopReason: "goal_budget_exhausted", finalSnapshot: beforeSnapshot };
|
|
52
124
|
}
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
? `${state.goalId}:${state.updatedAt}:${state.events.length}:${state.stallTurns}:${state.status}`
|
|
56
|
-
: undefined;
|
|
125
|
+
const beforeKey = goalProgressSignature(beforeSnapshot.goalState);
|
|
126
|
+
const passStartedAt = now();
|
|
57
127
|
const result = await this.continueGoalOnce(options);
|
|
58
128
|
if (result.submitted) {
|
|
59
129
|
turnsSubmitted++;
|
|
130
|
+
this.deps.recordGoalContinuationPass({ turns: 1, wallClockMs: now() - passStartedAt });
|
|
60
131
|
}
|
|
61
132
|
if (hasReachedWallClockBudget()) {
|
|
62
133
|
return { turnsSubmitted, stopReason: "wall_clock_budget_reached", finalSnapshot: snapshot() };
|
|
63
134
|
}
|
|
64
135
|
const afterSnapshot = snapshot();
|
|
65
136
|
if (afterSnapshot.continuation.action !== "continue") {
|
|
66
|
-
return { turnsSubmitted, stopReason:
|
|
137
|
+
return { turnsSubmitted, stopReason: nonContinueStopReason(afterSnapshot), finalSnapshot: afterSnapshot };
|
|
67
138
|
}
|
|
68
|
-
const
|
|
69
|
-
const afterKey = afterState
|
|
70
|
-
? `${afterState.goalId}:${afterState.updatedAt}:${afterState.events.length}:${afterState.stallTurns}:${afterState.status}`
|
|
71
|
-
: undefined;
|
|
139
|
+
const afterKey = goalProgressSignature(afterSnapshot.goalState);
|
|
72
140
|
if (beforeKey === afterKey) {
|
|
73
141
|
return { turnsSubmitted, stopReason: "goal_state_not_advanced", finalSnapshot: afterSnapshot };
|
|
74
142
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goal-loop-controller.js","sourceRoot":"","sources":["../../src/core/goal-loop-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Goal auto-continuation loop.\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Drives the bounded \"keep the\n * active goal moving\" loop: each pass reads the goal runtime snapshot, and — only while the snapshot\n * says `continue` — submits one continuation prompt back through the session's own prompt path. It\n * owns no state; the goal state lives in the session log and is read fresh every pass. Termination is\n * fully budget-gated (turn cap, wall-clock cap, and a no-progress guard on the goal-state key).\n */\n\nimport type {\n\tGoalContinuationLoopOptions,\n\tGoalContinuationLoopResult,\n\tGoalContinuationOnceOptions,\n\tGoalContinuationOnceResult,\n\tPromptOptions,\n} from \"./agent-session.ts\";\nimport { buildGoalContinuationPrompt } from \"./goals/goal-continuation-prompt.ts\";\nimport type { GoalRuntimeSnapshot, GoalRuntimeSnapshotSettings } from \"./goals/goal-runtime-snapshot.ts\";\n\nexport interface GoalLoopControllerDeps {\n\t/** Read the current goal runtime snapshot (continuation decision + goal state) fresh each pass. */\n\tgetGoalRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot;\n\t/** Submit a continuation prompt through the session's own prompt path. */\n\tprompt(text: string, options?: PromptOptions): Promise<void>;\n}\n\nexport class GoalLoopController {\n\tprivate readonly deps: GoalLoopControllerDeps;\n\n\tconstructor(deps: GoalLoopControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tasync continueGoalOnce(options: GoalContinuationOnceOptions): Promise<GoalContinuationOnceResult> {\n\t\tconst snapshot = this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (snapshot.continuation.action !== \"continue\") {\n\t\t\treturn { submitted: false, snapshot };\n\t\t}\n\n\t\tconst prompt = buildGoalContinuationPrompt({ snapshot, limits: options.promptLimits });\n\t\tawait this.deps.prompt(prompt.text, {\n\t\t\texpandPromptTemplates: false,\n\t\t\tprocessSlashCommands: false,\n\t\t\tautoContinueGoal: false,\n\t\t});\n\n\t\treturn { submitted: true, snapshot, prompt };\n\t}\n\n\tasync continueGoalLoop(options: GoalContinuationLoopOptions): Promise<GoalContinuationLoopResult> {\n\t\tlet turnsSubmitted = 0;\n\t\tconst now = options.now ?? Date.now;\n\t\tconst maxWallClockMs =\n\t\t\ttypeof options.maxWallClockMinutes === \"number\" && options.maxWallClockMinutes > 0\n\t\t\t\t? options.maxWallClockMinutes * 60_000\n\t\t\t\t: undefined;\n\t\tconst startedAt = now();\n\t\tconst hasReachedWallClockBudget = () => maxWallClockMs !== undefined && now() - startedAt >= maxWallClockMs;\n\t\tconst snapshot = () => this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (options.maxTurns <= 0) {\n\t\t\treturn {\n\t\t\t\tturnsSubmitted: 0,\n\t\t\t\tstopReason: \"max_turns_reached\",\n\t\t\t\tfinalSnapshot: snapshot(),\n\t\t\t};\n\t\t}\n\n\t\tif (hasReachedWallClockBudget()) {\n\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: snapshot() };\n\t\t}\n\n\t\twhile (turnsSubmitted < options.maxTurns) {\n\t\t\tconst beforeSnapshot = snapshot();\n\t\t\tif (beforeSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"continuation_not_allowed\", finalSnapshot: beforeSnapshot };\n\t\t\t}\n\n\t\t\tconst state = beforeSnapshot.goalState;\n\t\t\tconst beforeKey = state\n\t\t\t\t? `${state.goalId}:${state.updatedAt}:${state.events.length}:${state.stallTurns}:${state.status}`\n\t\t\t\t: undefined;\n\n\t\t\tconst result = await this.continueGoalOnce(options);\n\t\t\tif (result.submitted) {\n\t\t\t\tturnsSubmitted++;\n\t\t\t}\n\n\t\t\tif (hasReachedWallClockBudget()) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: snapshot() };\n\t\t\t}\n\n\t\t\tconst afterSnapshot = snapshot();\n\t\t\tif (afterSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"continuation_not_allowed\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\n\t\t\tconst afterState = afterSnapshot.goalState;\n\t\t\tconst afterKey = afterState\n\t\t\t\t? `${afterState.goalId}:${afterState.updatedAt}:${afterState.events.length}:${afterState.stallTurns}:${afterState.status}`\n\t\t\t\t: undefined;\n\n\t\t\tif (beforeKey === afterKey) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_state_not_advanced\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tturnsSubmitted,\n\t\t\tstopReason: \"max_turns_reached\",\n\t\t\tfinalSnapshot: snapshot(),\n\t\t};\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"goal-loop-controller.js","sourceRoot":"","sources":["../../src/core/goal-loop-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Goal auto-continuation loop.\n *\n * Extracted verbatim from agent-session.ts (god-file decomposition). Drives the bounded \"keep the\n * active goal moving\" loop: each pass reads the goal runtime snapshot, and — only while the snapshot\n * says `continue` — submits one continuation prompt back through the session's own prompt path. It\n * owns no state; the goal state lives in the session log and is read fresh every pass. Termination is\n * fully budget-gated (per-invocation turn cap, per-invocation wall-clock cap, a DURABLE cumulative\n * per-goal budget — turns + active wall-clock, persisted on `GoalState` across every invocation for\n * the goal's lifetime — and a no-progress guard on a MEANINGFUL progress signature — satisfied-\n * requirement count + ref-backed evidence count — so hollow goal-tool calls (e.g. add_requirement/\n * reopen churn that satisfies nothing) cannot defeat the stall guard). Each submitted pass also\n * reports its turn/wall-clock/spend contribution back to the session via `recordGoalContinuationPass`\n * so the cumulative budget stays accurate.\n */\n\nimport type {\n\tGoalContinuationLoopOptions,\n\tGoalContinuationLoopResult,\n\tGoalContinuationLoopStopReason,\n\tGoalContinuationOnceOptions,\n\tGoalContinuationOnceResult,\n\tPromptOptions,\n} from \"./agent-session.ts\";\nimport {\n\tDEFAULT_GOAL_CUMULATIVE_MAX_TURNS,\n\tDEFAULT_GOAL_CUMULATIVE_MAX_WALL_CLOCK_MS,\n\tDEFAULT_GOAL_CUMULATIVE_MAX_WORKER_SPEND_USD,\n} from \"./goals/goal-continuation-defaults.ts\";\nimport { buildGoalContinuationPrompt } from \"./goals/goal-continuation-prompt.ts\";\nimport type { GoalRuntimeSnapshot, GoalRuntimeSnapshotSettings } from \"./goals/goal-runtime-snapshot.ts\";\nimport type { GoalState } from \"./goals/goal-state.ts\";\n\n/**\n * Progress signature for goal-loop stall detection. Keys ONLY on state that reflects actual\n * progress toward the goal — `goalId`, `status`, the count of satisfied requirements, and the\n * count of evidence entries that carry a ref (`uri`) AND are TRUSTED: either actually validated\n * (`verified === true`) or `kind === \"user\"` (a human-confirmed claim). Deliberately excludes\n * `events.length`, `updatedAt`, and `stallTurns`: those change on every goal-tool call (including\n * no-op churn like re-adding/reopening a requirement without satisfying anything), which let hollow\n * passes look like progress and defeat `goal_state_not_advanced`.\n *\n * `verified` is `undefined` both for evidence that hasn't been checked yet AND for evidence kinds\n * that carry no checkable ref at all (`\"user\"`/`\"finding\"`/`\"test\"` — see the doc comment on\n * `GoalEvidenceRef.verified` in `goal-state.ts`). Treating \"undefined\" as trusted would let a model spam\n * `kind:\"finding\"` evidence with a fabricated `uri` every turn — always undefined, always counted —\n * which is the same class of hollow churn this signature exists to stop. So `undefined` does NOT\n * count; only an explicit `verified === true` (a real, checked ref) or `kind === \"user\"` (mirrors\n * the `complete` gate's trusted set in `goal-tool-core.ts`'s `isVerifiedOrUserEvidence`) counts.\n * `satisfiedRequirementCount` still advances the signature for legitimate-but-unverifiable work\n * (e.g. `kind:\"finding\"`/`\"test\"` evidence cited on a `satisfy_requirement` call), and the\n * continuation controller's own `stallTurns` path remains available for the model to self-report.\n */\nfunction goalProgressSignature(state: GoalState | undefined): string | undefined {\n\tif (!state) return undefined;\n\tconst satisfiedRequirementCount = state.requirements.filter(\n\t\t(requirement) => requirement.status === \"satisfied\",\n\t).length;\n\tconst refEvidenceCount = state.evidence.filter(\n\t\t(evidence) =>\n\t\t\ttypeof evidence.uri === \"string\" &&\n\t\t\tevidence.uri.trim().length > 0 &&\n\t\t\t(evidence.verified === true || evidence.kind === \"user\"),\n\t).length;\n\treturn `${state.goalId}:${state.status}:${satisfiedRequirementCount}:${refEvidenceCount}`;\n}\n\n/**\n * Whether the goal's DURABLE cumulative continuation budget (turns and/or active wall-clock,\n * persisted on `GoalState` and summed across every `continueGoalLoop` invocation for the goal's\n * lifetime) has been exhausted. Read fresh at the top of every pass (not just the top of the\n * invocation), so a single long-running invocation that crosses the ceiling mid-loop stops\n * immediately rather than waiting for the next invocation to notice. `undefined` counters (goal\n * state predating this field, or a fresh goal) count as `0` — never exhausted.\n */\nfunction isGoalContinuationBudgetExhausted(state: GoalState | undefined): boolean {\n\tif (!state) return false;\n\tif ((state.continuationTurnsUsed ?? 0) >= DEFAULT_GOAL_CUMULATIVE_MAX_TURNS) return true;\n\tif ((state.continuationWallClockMs ?? 0) >= DEFAULT_GOAL_CUMULATIVE_MAX_WALL_CLOCK_MS) return true;\n\tif ((state.continuationWorkerSpendUsd ?? 0) >= DEFAULT_GOAL_CUMULATIVE_MAX_WORKER_SPEND_USD) return true;\n\treturn false;\n}\n\n/**\n * Maps a non-\"continue\" continuation action onto the loop's own stopReason vocabulary.\n * `\"waiting\"` (a worker is dispatched against an open requirement) gets its OWN benign stopReason so\n * a wait is never misreported as `continuation_not_allowed` (which reads as a terminal refusal) —\n * callers/telemetry can tell \"paused, will resume on its own\" apart from \"stopped, needs a human or a\n * new decision.\" Every other non-continue action (ask-user/finalize/stop) keeps the existing\n * `continuation_not_allowed` stopReason unchanged.\n */\nfunction nonContinueStopReason(snapshot: GoalRuntimeSnapshot): GoalContinuationLoopStopReason {\n\treturn snapshot.continuation.action === \"waiting\" ? \"worker_in_flight\" : \"continuation_not_allowed\";\n}\n\nexport interface GoalLoopControllerDeps {\n\t/** Read the current goal runtime snapshot (continuation decision + goal state) fresh each pass. */\n\tgetGoalRuntimeSnapshot(settings: GoalRuntimeSnapshotSettings): GoalRuntimeSnapshot;\n\t/** Submit a continuation prompt through the session's own prompt path. */\n\tprompt(text: string, options?: PromptOptions): Promise<void>;\n\t/**\n\t * Persist one submitted pass's contribution to the active goal's durable cumulative budget\n\t * (turns + active wall-clock; USD is attributed by the implementation from the session's own\n\t * spend, not passed in here — see `AgentSession.recordGoalContinuationPass`). Called once per\n\t * pass actually SUBMITTED (never for a no-op `continueGoalOnce` call).\n\t */\n\trecordGoalContinuationPass(pass: { turns: number; wallClockMs: number }): void;\n}\n\nexport class GoalLoopController {\n\tprivate readonly deps: GoalLoopControllerDeps;\n\n\tconstructor(deps: GoalLoopControllerDeps) {\n\t\tthis.deps = deps;\n\t}\n\n\tasync continueGoalOnce(options: GoalContinuationOnceOptions): Promise<GoalContinuationOnceResult> {\n\t\tconst snapshot = this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (snapshot.continuation.action !== \"continue\") {\n\t\t\treturn { submitted: false, snapshot };\n\t\t}\n\n\t\tconst prompt = buildGoalContinuationPrompt({ snapshot, limits: options.promptLimits });\n\t\tawait this.deps.prompt(prompt.text, {\n\t\t\texpandPromptTemplates: false,\n\t\t\tprocessSlashCommands: false,\n\t\t\tautoContinueGoal: false,\n\t\t});\n\n\t\treturn { submitted: true, snapshot, prompt };\n\t}\n\n\tasync continueGoalLoop(options: GoalContinuationLoopOptions): Promise<GoalContinuationLoopResult> {\n\t\tlet turnsSubmitted = 0;\n\t\tconst now = options.now ?? Date.now;\n\t\tconst maxWallClockMs =\n\t\t\ttypeof options.maxWallClockMinutes === \"number\" && options.maxWallClockMinutes > 0\n\t\t\t\t? options.maxWallClockMinutes * 60_000\n\t\t\t\t: undefined;\n\t\tconst startedAt = now();\n\t\tconst hasReachedWallClockBudget = () => maxWallClockMs !== undefined && now() - startedAt >= maxWallClockMs;\n\t\tconst snapshot = () => this.deps.getGoalRuntimeSnapshot({ maxStallTurns: options.maxStallTurns });\n\n\t\tif (options.maxTurns <= 0) {\n\t\t\treturn {\n\t\t\t\tturnsSubmitted: 0,\n\t\t\t\tstopReason: \"max_turns_reached\",\n\t\t\t\tfinalSnapshot: snapshot(),\n\t\t\t};\n\t\t}\n\n\t\tif (hasReachedWallClockBudget()) {\n\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: snapshot() };\n\t\t}\n\n\t\twhile (turnsSubmitted < options.maxTurns) {\n\t\t\tconst beforeSnapshot = snapshot();\n\t\t\tif (beforeSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: nonContinueStopReason(beforeSnapshot), finalSnapshot: beforeSnapshot };\n\t\t\t}\n\n\t\t\t// Cumulative (durable, cross-invocation) budget — read fresh every pass, not just at the top\n\t\t\t// of this invocation, so a single long-running call still stops the moment it crosses the\n\t\t\t// ceiling rather than overshooting until the next invocation notices.\n\t\t\tif (isGoalContinuationBudgetExhausted(beforeSnapshot.goalState)) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_budget_exhausted\", finalSnapshot: beforeSnapshot };\n\t\t\t}\n\n\t\t\tconst beforeKey = goalProgressSignature(beforeSnapshot.goalState);\n\n\t\t\tconst passStartedAt = now();\n\t\t\tconst result = await this.continueGoalOnce(options);\n\t\t\tif (result.submitted) {\n\t\t\t\tturnsSubmitted++;\n\t\t\t\tthis.deps.recordGoalContinuationPass({ turns: 1, wallClockMs: now() - passStartedAt });\n\t\t\t}\n\n\t\t\tif (hasReachedWallClockBudget()) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"wall_clock_budget_reached\", finalSnapshot: snapshot() };\n\t\t\t}\n\n\t\t\tconst afterSnapshot = snapshot();\n\t\t\tif (afterSnapshot.continuation.action !== \"continue\") {\n\t\t\t\treturn { turnsSubmitted, stopReason: nonContinueStopReason(afterSnapshot), finalSnapshot: afterSnapshot };\n\t\t\t}\n\n\t\t\tconst afterKey = goalProgressSignature(afterSnapshot.goalState);\n\n\t\t\tif (beforeKey === afterKey) {\n\t\t\t\treturn { turnsSubmitted, stopReason: \"goal_state_not_advanced\", finalSnapshot: afterSnapshot };\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tturnsSubmitted,\n\t\t\tstopReason: \"max_turns_reached\",\n\t\t\tfinalSnapshot: snapshot(),\n\t\t};\n\t}\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GoalEvidenceRef, GoalState, Requirement } from "./goal-state.ts";
|
|
2
|
+
export declare function isTrustedGoalEvidence(evidence: GoalEvidenceRef): boolean;
|
|
3
|
+
export declare function getTrustedRequirementEvidence(state: GoalState, requirement: Requirement): GoalEvidenceRef[];
|
|
4
|
+
export declare function getUnprovenGoalRequirementIds(state: GoalState): string[];
|
|
5
|
+
/**
|
|
6
|
+
* Human/manual completion and the explicit evidence-gate opt-out are authoritative overrides.
|
|
7
|
+
* Completion events written before the flag existed are treated as legacy owner decisions so an
|
|
8
|
+
* already-completed persisted goal cannot strand durable work during resume.
|
|
9
|
+
*/
|
|
10
|
+
export declare function hasGoalAcceptanceOverride(state: GoalState): boolean;
|
|
11
|
+
//# sourceMappingURL=goal-acceptance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goal-acceptance.d.ts","sourceRoot":"","sources":["../../../src/core/goals/goal-acceptance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE/E,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAExE;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,GAAG,eAAe,EAAE,CAG3G;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,EAAE,CAOxE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAQnE","sourcesContent":["import type { GoalEvidenceRef, GoalState, Requirement } from \"./goal-state.ts\";\n\nexport function isTrustedGoalEvidence(evidence: GoalEvidenceRef): boolean {\n\treturn evidence.kind === \"user\" || evidence.verified === true;\n}\n\nexport function getTrustedRequirementEvidence(state: GoalState, requirement: Requirement): GoalEvidenceRef[] {\n\tconst evidenceIds = new Set(requirement.evidenceIds);\n\treturn state.evidence.filter((evidence) => evidenceIds.has(evidence.id) && isTrustedGoalEvidence(evidence));\n}\n\nexport function getUnprovenGoalRequirementIds(state: GoalState): string[] {\n\treturn state.requirements\n\t\t.filter(\n\t\t\t(requirement) =>\n\t\t\t\trequirement.status !== \"satisfied\" || getTrustedRequirementEvidence(state, requirement).length === 0,\n\t\t)\n\t\t.map((requirement) => requirement.id);\n}\n\n/**\n * Human/manual completion and the explicit evidence-gate opt-out are authoritative overrides.\n * Completion events written before the flag existed are treated as legacy owner decisions so an\n * already-completed persisted goal cannot strand durable work during resume.\n */\nexport function hasGoalAcceptanceOverride(state: GoalState): boolean {\n\tconst completion = [...state.events]\n\t\t.reverse()\n\t\t.find((event) => event.type === \"complete_goal\" || event.type === \"complete_goal_manually\");\n\treturn (\n\t\tcompletion?.type === \"complete_goal_manually\" ||\n\t\t(completion?.type === \"complete_goal\" && completion.acceptanceOverride !== false)\n\t);\n}\n"]}
|