@animalabs/agent-framework 0.22.1 → 0.22.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/src/agent.d.ts +192 -19
- package/dist/src/agent.d.ts.map +1 -1
- package/dist/src/agent.js +404 -65
- package/dist/src/agent.js.map +1 -1
- package/dist/src/api/mcp-server-core.d.ts +41 -0
- package/dist/src/api/mcp-server-core.d.ts.map +1 -0
- package/dist/src/api/mcp-server-core.js +593 -0
- package/dist/src/api/mcp-server-core.js.map +1 -0
- package/dist/src/api/mcp-server.d.ts +2 -36
- package/dist/src/api/mcp-server.d.ts.map +1 -1
- package/dist/src/api/mcp-server.js +15 -595
- package/dist/src/api/mcp-server.js.map +1 -1
- package/dist/src/api/server.d.ts +9 -1
- package/dist/src/api/server.d.ts.map +1 -1
- package/dist/src/api/server.js +50 -26
- package/dist/src/api/server.js.map +1 -1
- package/dist/src/api/types.d.ts +9 -1
- package/dist/src/api/types.d.ts.map +1 -1
- package/dist/src/code-execution/py-runner.d.ts.map +1 -1
- package/dist/src/code-execution/py-runner.js.map +1 -1
- package/dist/src/framework.d.ts +393 -113
- package/dist/src/framework.d.ts.map +1 -1
- package/dist/src/framework.js +1748 -582
- package/dist/src/framework.js.map +1 -1
- package/dist/src/gate/event-gate.d.ts.map +1 -1
- package/dist/src/gate/gate-script.d.ts.map +1 -1
- package/dist/src/gate/gate-script.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcpl/capability-grant.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.d.ts +26 -7
- package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
- package/dist/src/mcpl/channel-registry.js +102 -22
- package/dist/src/mcpl/channel-registry.js.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
- package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
- package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
- package/dist/src/mcpl/errors.js.map +1 -1
- package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
- package/dist/src/mcpl/feature-set-manager.js +4 -3
- package/dist/src/mcpl/feature-set-manager.js.map +1 -1
- package/dist/src/mcpl/hook-orchestrator.d.ts.map +1 -1
- package/dist/src/mcpl/inference-router.d.ts.map +1 -1
- package/dist/src/mcpl/log-value.d.ts +54 -0
- package/dist/src/mcpl/log-value.d.ts.map +1 -0
- package/dist/src/mcpl/log-value.js +109 -0
- package/dist/src/mcpl/log-value.js.map +1 -0
- package/dist/src/mcpl/prose-stream-router.d.ts +6 -6
- package/dist/src/mcpl/prose-stream-router.d.ts.map +1 -1
- package/dist/src/mcpl/prose-stream-router.js +4 -4
- package/dist/src/mcpl/prose-stream-router.js.map +1 -1
- package/dist/src/mcpl/push-coalescer.d.ts +38 -3
- package/dist/src/mcpl/push-coalescer.d.ts.map +1 -1
- package/dist/src/mcpl/push-coalescer.js +81 -16
- package/dist/src/mcpl/push-coalescer.js.map +1 -1
- package/dist/src/mcpl/push-handler.d.ts +26 -3
- package/dist/src/mcpl/push-handler.d.ts.map +1 -1
- package/dist/src/mcpl/push-handler.js +87 -23
- package/dist/src/mcpl/push-handler.js.map +1 -1
- package/dist/src/mcpl/reference-fetcher.d.ts.map +1 -1
- package/dist/src/mcpl/reference-fetcher.js.map +1 -1
- package/dist/src/mcpl/references.d.ts +2 -2
- package/dist/src/mcpl/references.d.ts.map +1 -1
- package/dist/src/mcpl/references.js.map +1 -1
- package/dist/src/mcpl/refusal-lines.d.ts +37 -0
- package/dist/src/mcpl/refusal-lines.d.ts.map +1 -0
- package/dist/src/mcpl/refusal-lines.js +61 -0
- package/dist/src/mcpl/refusal-lines.js.map +1 -0
- package/dist/src/mcpl/scope-manager.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.d.ts +18 -2
- package/dist/src/mcpl/server-connection.d.ts.map +1 -1
- package/dist/src/mcpl/server-connection.js +66 -11
- package/dist/src/mcpl/server-connection.js.map +1 -1
- package/dist/src/mcpl/server-registry.d.ts.map +1 -1
- package/dist/src/mcpl/tool-classes.d.ts +1 -1
- package/dist/src/mcpl/tool-classes.d.ts.map +1 -1
- package/dist/src/mcpl/tool-classes.js +3 -2
- package/dist/src/mcpl/tool-classes.js.map +1 -1
- package/dist/src/mcpl/tool-lifecycle.d.ts.map +1 -1
- package/dist/src/mcpl/tool-lifecycle.js.map +1 -1
- package/dist/src/mcpl/transport.d.ts +23 -5
- package/dist/src/mcpl/transport.d.ts.map +1 -1
- package/dist/src/mcpl/transport.js +103 -10
- package/dist/src/mcpl/transport.js.map +1 -1
- package/dist/src/mcpl/types.d.ts +30 -26
- package/dist/src/mcpl/types.d.ts.map +1 -1
- package/dist/src/mcpl/types.js.map +1 -1
- package/dist/src/module-registry.d.ts.map +1 -1
- package/dist/src/module-registry.js.map +1 -1
- package/dist/src/modules/api/index.d.ts.map +1 -1
- package/dist/src/modules/discord/discord-js-client.d.ts.map +1 -1
- package/dist/src/modules/discord/discord-js-client.js.map +1 -1
- package/dist/src/modules/discord/index.d.ts.map +1 -1
- package/dist/src/modules/discord/index.js +4 -2
- package/dist/src/modules/discord/index.js.map +1 -1
- package/dist/src/modules/health/index.d.ts.map +1 -1
- package/dist/src/modules/health/index.js.map +1 -1
- package/dist/src/modules/history/index.d.ts.map +1 -1
- package/dist/src/modules/history/index.js.map +1 -1
- package/dist/src/modules/history/semantic.d.ts.map +1 -1
- package/dist/src/modules/history/semantic.js.map +1 -1
- package/dist/src/modules/workspace/branch-intent.d.ts.map +1 -1
- package/dist/src/modules/workspace/branch-intent.js.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.d.ts +22 -4
- package/dist/src/modules/workspace/disk-agreement.d.ts.map +1 -1
- package/dist/src/modules/workspace/disk-agreement.js +63 -25
- package/dist/src/modules/workspace/disk-agreement.js.map +1 -1
- package/dist/src/modules/workspace/effects.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.d.ts +8 -4
- package/dist/src/modules/workspace/index.d.ts.map +1 -1
- package/dist/src/modules/workspace/index.js +39 -12
- package/dist/src/modules/workspace/index.js.map +1 -1
- package/dist/src/modules/workspace/observe.d.ts +43 -8
- package/dist/src/modules/workspace/observe.d.ts.map +1 -1
- package/dist/src/modules/workspace/observe.js +264 -39
- package/dist/src/modules/workspace/observe.js.map +1 -1
- package/dist/src/modules/workspace/reconcile.d.ts +17 -1
- package/dist/src/modules/workspace/reconcile.d.ts.map +1 -1
- package/dist/src/modules/workspace/reconcile.js +57 -14
- package/dist/src/modules/workspace/reconcile.js.map +1 -1
- package/dist/src/modules/workspace/types.d.ts +27 -2
- package/dist/src/modules/workspace/types.d.ts.map +1 -1
- package/dist/src/modules/workspace/types.js.map +1 -1
- package/dist/src/modules/workspace/watcher.d.ts.map +1 -1
- package/dist/src/modules/workspace/watcher.js.map +1 -1
- package/dist/src/operator-log.d.ts.map +1 -1
- package/dist/src/operator-log.js.map +1 -1
- package/dist/src/provider-waits.d.ts.map +1 -1
- package/dist/src/provider-waits.js.map +1 -1
- package/dist/src/queue.d.ts.map +1 -1
- package/dist/src/record-journal.d.ts.map +1 -1
- package/dist/src/record-journal.js.map +1 -1
- package/dist/src/recovery/discord-awareness-outbox.d.ts.map +1 -1
- package/dist/src/recovery/discord-awareness-outbox.js.map +1 -1
- package/dist/src/recovery/offline-branch.d.ts.map +1 -1
- package/dist/src/recovery/offline-branch.js +29 -24
- package/dist/src/recovery/offline-branch.js.map +1 -1
- package/dist/src/recovery/recover-cli.js.map +1 -1
- package/dist/src/runtime/liveness-watchdog.d.ts.map +1 -1
- package/dist/src/runtime/liveness-watchdog.js.map +1 -1
- package/dist/src/shutdown.d.ts.map +1 -1
- package/dist/src/shutdown.js.map +1 -1
- package/dist/src/stored-removal.d.ts +73 -0
- package/dist/src/stored-removal.d.ts.map +1 -0
- package/dist/src/stored-removal.js +100 -0
- package/dist/src/stored-removal.js.map +1 -0
- package/dist/src/thinking-token-stamp.js.map +1 -1
- package/dist/src/tool-image-ledger.d.ts.map +1 -1
- package/dist/src/tool-image-ledger.js.map +1 -1
- package/dist/src/tool-presentation.d.ts.map +1 -1
- package/dist/src/tool-presentation.js.map +1 -1
- package/dist/src/tool-result-guard.d.ts.map +1 -1
- package/dist/src/tool-result-guard.js.map +1 -1
- package/dist/src/tune-out/coordinator.d.ts.map +1 -1
- package/dist/src/tune-out/coordinator.js.map +1 -1
- package/dist/src/tune-out/tools.d.ts +1 -1
- package/dist/src/tune-out/tools.d.ts.map +1 -1
- package/dist/src/types/agent.d.ts +42 -6
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/framework.d.ts +10 -0
- package/dist/src/types/framework.d.ts.map +1 -1
- package/dist/src/types/module.d.ts +8 -4
- package/dist/src/types/module.d.ts.map +1 -1
- package/dist/src/types/trace.d.ts +61 -10
- package/dist/src/types/trace.d.ts.map +1 -1
- package/dist/src/usage/usage-tracker.d.ts.map +1 -1
- package/dist/test/agent-runtime-settings.test.js +1139 -3
- package/dist/test/agent-runtime-settings.test.js.map +1 -1
- package/dist/test/batched-wake-locus.test.js.map +1 -1
- package/dist/test/channel-label-history.test.js.map +1 -1
- package/dist/test/code-execution.test.js.map +1 -1
- package/dist/test/conversation-fork-injection-scoping.test.js.map +1 -1
- package/dist/test/conversation-router.test.js.map +1 -1
- package/dist/test/conversation-routing.test.js +240 -6
- package/dist/test/conversation-routing.test.js.map +1 -1
- package/dist/test/discord-awareness-outbox.test.js +104 -0
- package/dist/test/discord-awareness-outbox.test.js.map +1 -1
- package/dist/test/discord-typing-keepalive.test.d.ts +2 -0
- package/dist/test/discord-typing-keepalive.test.d.ts.map +1 -0
- package/dist/test/discord-typing-keepalive.test.js +77 -0
- package/dist/test/discord-typing-keepalive.test.js.map +1 -0
- package/dist/test/ephemeral-settle.test.js.map +1 -1
- package/dist/test/event-gate-passthrough.test.js.map +1 -1
- package/dist/test/event-gate-policy-mutation.test.js.map +1 -1
- package/dist/test/event-gate-rate-limit.test.js.map +1 -1
- package/dist/test/event-gate-script.test.js.map +1 -1
- package/dist/test/event-gate-selfwake.test.js.map +1 -1
- package/dist/test/event-gate-tags.test.js.map +1 -1
- package/dist/test/event-gate.test.js.map +1 -1
- package/dist/test/explicit-prose-routing.test.js +363 -42
- package/dist/test/explicit-prose-routing.test.js.map +1 -1
- package/dist/test/framework.test.js.map +1 -1
- package/dist/test/helpers/coalescing-fixture.d.ts +2 -0
- package/dist/test/helpers/coalescing-fixture.d.ts.map +1 -1
- package/dist/test/helpers/coalescing-fixture.js +8 -2
- package/dist/test/helpers/coalescing-fixture.js.map +1 -1
- package/dist/test/helpers/mock-membrane.d.ts.map +1 -1
- package/dist/test/helpers/mock-membrane.js.map +1 -1
- package/dist/test/hide-then-turn.test.d.ts +2 -0
- package/dist/test/hide-then-turn.test.d.ts.map +1 -0
- package/dist/test/hide-then-turn.test.js +101 -0
- package/dist/test/hide-then-turn.test.js.map +1 -0
- package/dist/test/history-module-overview.test.js.map +1 -1
- package/dist/test/history-module-semantic.test.js.map +1 -1
- package/dist/test/history-module.test.js.map +1 -1
- package/dist/test/history-semantic-review-findings.test.js.map +1 -1
- package/dist/test/host-quiesce.test.js +125 -0
- package/dist/test/host-quiesce.test.js.map +1 -1
- package/dist/test/inference-exhaustion-rewind.test.js +81 -3
- package/dist/test/inference-exhaustion-rewind.test.js.map +1 -1
- package/dist/test/inference-failure-bounds.test.js +1 -0
- package/dist/test/inference-failure-bounds.test.js.map +1 -1
- package/dist/test/kv-unified-open-flight-retry.test.js.map +1 -1
- package/dist/test/liveness-watchdog.test.js.map +1 -1
- package/dist/test/maintenance-timer.test.js +1564 -2
- package/dist/test/maintenance-timer.test.js.map +1 -1
- package/dist/test/mcp-server-bin.test.d.ts +2 -0
- package/dist/test/mcp-server-bin.test.d.ts.map +1 -0
- package/dist/test/mcp-server-bin.test.js +142 -0
- package/dist/test/mcp-server-bin.test.js.map +1 -0
- package/dist/test/mcpl-awareness-barrier.test.js.map +1 -1
- package/dist/test/mcpl-child-env.test.js +1 -1
- package/dist/test/mcpl-child-env.test.js.map +1 -1
- package/dist/test/mcpl-coalesced-content-parity.test.d.ts +2 -0
- package/dist/test/mcpl-coalesced-content-parity.test.d.ts.map +1 -0
- package/dist/test/mcpl-coalesced-content-parity.test.js +532 -0
- package/dist/test/mcpl-coalesced-content-parity.test.js.map +1 -0
- package/dist/test/mcpl-coalescing.test.js.map +1 -1
- package/dist/test/mcpl-config-diagnostics.test.js.map +1 -1
- package/dist/test/mcpl-gate-roundtrip.test.js.map +1 -1
- package/dist/test/mcpl-manifest-changed.test.js.map +1 -1
- package/dist/test/mcpl-reconnect-events.test.js.map +1 -1
- package/dist/test/mcpl-reconnect-reregistration.test.js +2 -0
- package/dist/test/mcpl-reconnect-reregistration.test.js.map +1 -1
- package/dist/test/mcpl-reference-fetcher.test.js.map +1 -1
- package/dist/test/mcpl-reference-fields.test.js.map +1 -1
- package/dist/test/mcpl-rejection-log-lines.test.d.ts +2 -0
- package/dist/test/mcpl-rejection-log-lines.test.d.ts.map +1 -0
- package/dist/test/mcpl-rejection-log-lines.test.js +349 -0
- package/dist/test/mcpl-rejection-log-lines.test.js.map +1 -0
- package/dist/test/mcpl-stderr-tail.test.d.ts +2 -0
- package/dist/test/mcpl-stderr-tail.test.d.ts.map +1 -0
- package/dist/test/mcpl-stderr-tail.test.js +210 -0
- package/dist/test/mcpl-stderr-tail.test.js.map +1 -0
- package/dist/test/mcpl-tool-lifecycle-e2e.test.js.map +1 -1
- package/dist/test/mcpl-tool-lifecycle-emitter.test.js.map +1 -1
- package/dist/test/mcpl-tool-lifecycle-script.test.js.map +1 -1
- package/dist/test/mcpl-tool-lifecycle.test.js.map +1 -1
- package/dist/test/mcpl-transport-close.test.d.ts +2 -0
- package/dist/test/mcpl-transport-close.test.d.ts.map +1 -0
- package/dist/test/mcpl-transport-close.test.js +373 -0
- package/dist/test/mcpl-transport-close.test.js.map +1 -0
- package/dist/test/mcpl-transport-spawn.test.d.ts +2 -0
- package/dist/test/mcpl-transport-spawn.test.d.ts.map +1 -0
- package/dist/test/mcpl-transport-spawn.test.js +58 -0
- package/dist/test/mcpl-transport-spawn.test.js.map +1 -0
- package/dist/test/mcpl-ws-transport.test.js +1 -0
- package/dist/test/mcpl-ws-transport.test.js.map +1 -1
- package/dist/test/offline-recovery-branch.test.js +344 -0
- package/dist/test/offline-recovery-branch.test.js.map +1 -1
- package/dist/test/operator-surgery.test.js +197 -0
- package/dist/test/operator-surgery.test.js.map +1 -1
- package/dist/test/overbudget-drain-breaker.test.js +1 -0
- package/dist/test/overbudget-drain-breaker.test.js.map +1 -1
- package/dist/test/pack-installs-alone.test.d.ts +2 -0
- package/dist/test/pack-installs-alone.test.d.ts.map +1 -0
- package/dist/test/pack-installs-alone.test.js +284 -0
- package/dist/test/pack-installs-alone.test.js.map +1 -0
- package/dist/test/physical-window-restart.test.d.ts +6 -4
- package/dist/test/physical-window-restart.test.d.ts.map +1 -1
- package/dist/test/physical-window-restart.test.js +275 -10
- package/dist/test/physical-window-restart.test.js.map +1 -1
- package/dist/test/placed-reaction-baseline.test.js.map +1 -1
- package/dist/test/present-while-acting.test.js +949 -6
- package/dist/test/present-while-acting.test.js.map +1 -1
- package/dist/test/provider-acceleration-cooldown.test.js.map +1 -1
- package/dist/test/provider-waits.test.js +67 -4
- package/dist/test/provider-waits.test.js.map +1 -1
- package/dist/test/puppet-tool-call.test.js +2 -0
- package/dist/test/puppet-tool-call.test.js.map +1 -1
- package/dist/test/reaction-baseline-platform.test.js.map +1 -1
- package/dist/test/record-journal.test.js.map +1 -1
- package/dist/test/refusal-rewind.test.js +9 -0
- package/dist/test/refusal-rewind.test.js.map +1 -1
- package/dist/test/refusal-single-call.test.js.map +1 -1
- package/dist/test/release-bump.test.d.ts +2 -0
- package/dist/test/release-bump.test.d.ts.map +1 -0
- package/dist/test/release-bump.test.js +248 -0
- package/dist/test/release-bump.test.js.map +1 -0
- package/dist/test/release-changelog.test.js.map +1 -1
- package/dist/test/release-holds.test.d.ts +2 -0
- package/dist/test/release-holds.test.d.ts.map +1 -0
- package/dist/test/release-holds.test.js +456 -0
- package/dist/test/release-holds.test.js.map +1 -0
- package/dist/test/same-round-think-policy.test.js.map +1 -1
- package/dist/test/shutdown-errors.test.js.map +1 -1
- package/dist/test/silent-heartbeat-rows.test.js.map +1 -1
- package/dist/test/stop-with-host-operations.test.d.ts +20 -0
- package/dist/test/stop-with-host-operations.test.d.ts.map +1 -0
- package/dist/test/stop-with-host-operations.test.js +1174 -0
- package/dist/test/stop-with-host-operations.test.js.map +1 -0
- package/dist/test/stop-with-work-in-flight.test.js +162 -50
- package/dist/test/stop-with-work-in-flight.test.js.map +1 -1
- package/dist/test/surgery-marks-receipt.test.js.map +1 -1
- package/dist/test/tool-batch-hook.test.js.map +1 -1
- package/dist/test/tool-result-guard.test.js +131 -9
- package/dist/test/tool-result-guard.test.js.map +1 -1
- package/dist/test/tool-result-spill.test.js.map +1 -1
- package/dist/test/tool-wrapper-prose-guard-integration.test.js.map +1 -1
- package/dist/test/trunk-channel-routing.test.js +330 -7
- package/dist/test/trunk-channel-routing.test.js.map +1 -1
- package/dist/test/tune-out-e2e.test.js.map +1 -1
- package/dist/test/unconvertible-tool-result.test.js.map +1 -1
- package/dist/test/unsent-compiles.test.d.ts +2 -0
- package/dist/test/unsent-compiles.test.d.ts.map +1 -0
- package/dist/test/unsent-compiles.test.js +139 -0
- package/dist/test/unsent-compiles.test.js.map +1 -0
- package/dist/test/workspace-branch-continuation.test.js.map +1 -1
- package/dist/test/workspace-materialize-freshness.test.js.map +1 -1
- package/dist/test/workspace-read-text.test.js.map +1 -1
- package/dist/test/workspace-three-way.test.js +907 -7
- package/dist/test/workspace-three-way.test.js.map +1 -1
- package/dist/test/workspace-watcher.test.js.map +1 -1
- package/dist/test/xml-round-persist.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -6
- package/src/agent.ts +411 -66
- package/src/api/mcp-server-core.ts +681 -0
- package/src/api/mcp-server.ts +16 -685
- package/src/api/server.ts +51 -29
- package/src/api/types.ts +9 -1
- package/src/framework.ts +1899 -641
- package/src/index.ts +2 -2
- package/src/mcpl/channel-registry.ts +126 -31
- package/src/mcpl/feature-set-manager.ts +4 -3
- package/src/mcpl/log-value.ts +116 -0
- package/src/mcpl/prose-stream-router.ts +6 -6
- package/src/mcpl/push-coalescer.ts +76 -12
- package/src/mcpl/push-handler.ts +95 -23
- package/src/mcpl/refusal-lines.ts +59 -0
- package/src/mcpl/server-connection.ts +70 -11
- package/src/mcpl/tool-classes.ts +3 -2
- package/src/mcpl/transport.ts +105 -14
- package/src/mcpl/types.ts +5 -1
- package/src/modules/discord/index.ts +4 -2
- package/src/modules/workspace/disk-agreement.ts +74 -18
- package/src/modules/workspace/index.ts +41 -11
- package/src/modules/workspace/observe.ts +265 -39
- package/src/modules/workspace/reconcile.ts +71 -14
- package/src/modules/workspace/types.ts +26 -1
- package/src/recovery/offline-branch.ts +32 -28
- package/src/stored-removal.ts +126 -0
- package/src/types/agent.ts +42 -6
- package/src/types/framework.ts +10 -0
- package/src/types/module.ts +8 -4
- package/src/types/trace.ts +62 -11
package/src/agent.ts
CHANGED
|
@@ -20,6 +20,9 @@ import {
|
|
|
20
20
|
export interface ActivationRequestOptions {
|
|
21
21
|
/** The silent heartbeat tick this request answers, if any. */
|
|
22
22
|
silentHeartbeat?: SilentHeartbeatTick;
|
|
23
|
+
/** A request that will never be sent (a preview): compile it as a dry
|
|
24
|
+
* run (see `compileWithInjections` for what that leaves alone). */
|
|
25
|
+
dryRun?: boolean;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
export interface StartStreamResult {
|
|
@@ -120,15 +123,38 @@ export class Agent {
|
|
|
120
123
|
* closure) so the next activation can close whatever its predecessor left
|
|
121
124
|
* open — see failOpenKvSubmissions. */
|
|
122
125
|
private kvOpenQueue: Array<{ submissionId: string; wireReceipt: CacheWireReceipt }> | null = null;
|
|
126
|
+
/** The current stream's fresh input so far, as membrane's usage event
|
|
127
|
+
* reports it (cumulative across the tool loop): what the maxStreamTokens
|
|
128
|
+
* budget checks. */
|
|
123
129
|
lastStreamInputTokens = 0;
|
|
124
|
-
/** Real
|
|
125
|
-
*
|
|
126
|
-
*
|
|
130
|
+
/** Real prompt size of the stream's latest provider call that reported a
|
|
131
|
+
* prompt, which is what the provider billed it: fresh + cache creation +
|
|
132
|
+
* cache read. A call that reports none leaves it as it was (see
|
|
133
|
+
* lastStreamUnreportedTokens). Membrane's usage events are cumulative, so
|
|
134
|
+
* this is the call's share of its event (cumulativeDelta): the whole event
|
|
135
|
+
* for a stream's first call, and the event's own value where a counter
|
|
136
|
+
* went back. THE window-shaped number — `lastStreamInputTokens` alone
|
|
137
|
+
* omits cached tokens, which are most of a warm stream's window. 0 until a
|
|
138
|
+
* call on this stream reports a prompt, and the physical-window
|
|
139
|
+
* projection runs only once one has. */
|
|
127
140
|
lastStreamRealInputTokens = 0;
|
|
128
|
-
/** Output tokens of the
|
|
129
|
-
*
|
|
130
|
-
*
|
|
141
|
+
/** Output tokens of the same call as lastStreamRealInputTokens, or
|
|
142
|
+
* maxTokens, the bound on them, when it reported none (a call that ends at
|
|
143
|
+
* a tool boundary wrote a tool_use, so a 0 is a count left unreported) —
|
|
144
|
+
* the prior round's generated thinking/text/tool_use, which becomes part
|
|
145
|
+
* of the NEXT round's input and so belongs in the physical-window
|
|
146
|
+
* projection. */
|
|
131
147
|
lastStreamOutputTokens = 0;
|
|
148
|
+
/** What the stream has grown by since the call lastStreamRealInputTokens
|
|
149
|
+
* describes, for the physical-window projection: the blocks appended at
|
|
150
|
+
* each boundary the stream continued past (counted only for an agent with
|
|
151
|
+
* physicalWindowTokens, whose projection is this field's one reader), and
|
|
152
|
+
* the output of each call that reported no prompt (its reported output,
|
|
153
|
+
* or maxTokens, the bound on it, when it reported none either). After
|
|
154
|
+
* calls that report no prompt, the next request holds the prompt and
|
|
155
|
+
* output of the call lastStreamRealInputTokens describes, plus this. 0 at
|
|
156
|
+
* stream start and whenever a call reports a prompt. */
|
|
157
|
+
lastStreamUnreportedTokens = 0;
|
|
132
158
|
maxStreamTokens: number;
|
|
133
159
|
/** Provider hard context cap (see AgentConfig.physicalWindowTokens). */
|
|
134
160
|
readonly physicalWindowTokens?: number;
|
|
@@ -141,7 +167,52 @@ export class Agent {
|
|
|
141
167
|
private readonly configuredTransitionPaceTokens?: number;
|
|
142
168
|
private readonly configuredSameRoundThinkTextPolicy?: SameRoundThinkTextPolicy;
|
|
143
169
|
private contextBudgetTargetTokens?: number;
|
|
144
|
-
private runtimeSettingsOverrides:
|
|
170
|
+
private runtimeSettingsOverrides: AgentRuntimeSettingsPatch = {};
|
|
171
|
+
/**
|
|
172
|
+
* Counts changes of the live budget (an update, a reset, a restore, a
|
|
173
|
+
* settle). A compile speaks for the budget it planned at only if the live
|
|
174
|
+
* budget didn't change while it ran, and what it showed stands only until
|
|
175
|
+
* the next change.
|
|
176
|
+
*/
|
|
177
|
+
private liveBudgetEpoch = 0;
|
|
178
|
+
/**
|
|
179
|
+
* Counts changes of the descent (each arm of one, the same target included,
|
|
180
|
+
* a reset, a cancel, a settle). A settle proves its target only to a
|
|
181
|
+
* compile that began under that same descent.
|
|
182
|
+
*/
|
|
183
|
+
private descentEpoch = 0;
|
|
184
|
+
/** The live budget the last compile planned at, whether it fit, and the live budget's epoch then. */
|
|
185
|
+
private lastCompiledBudget?: { budget: number; fit: boolean; epoch: number };
|
|
186
|
+
/** Counts compiles at the live budget as they start. */
|
|
187
|
+
private compilesStarted = 0;
|
|
188
|
+
/** The start numbers of the compiles at the live budget still running. */
|
|
189
|
+
private readonly compilesRunning = new Set<number>();
|
|
190
|
+
/**
|
|
191
|
+
* For each budget, the start of the latest-started compile that has ended
|
|
192
|
+
* there with a fit or a refusal, whether or not what it showed was
|
|
193
|
+
* credited. Of two compiles at one budget, the later-started one planned
|
|
194
|
+
* at the newer store, so an earlier-started one that ends after it is
|
|
195
|
+
* ignored. That rests on the context manager selecting at the start of
|
|
196
|
+
* `compile`, before anything it awaits, so start order is selection order;
|
|
197
|
+
* a context manager that awaits before its select breaks it. (Injections
|
|
198
|
+
* are added after the select, so compiles with and without them plan
|
|
199
|
+
* alike.) An entry is
|
|
200
|
+
* kept only while a compile that started before it is still running, the
|
|
201
|
+
* only kind it can turn away, so the map is empty whenever no compile
|
|
202
|
+
* runs.
|
|
203
|
+
*/
|
|
204
|
+
private readonly latestEndedStart = new Map<number, number>();
|
|
205
|
+
/** The last outcome the listener recorded; a failed record is told again, and so is any after a change. */
|
|
206
|
+
private recordedCompiledBudget?: { budget: number; fit: boolean; epoch: number };
|
|
207
|
+
/**
|
|
208
|
+
* A boot restore applied a proven budget below the live one at once. Until
|
|
209
|
+
* the budget is next written (an update that carries one, or a reset of
|
|
210
|
+
* it) or a compile at it fits, a refusal of a compile at it restores it
|
|
211
|
+
* paced instead.
|
|
212
|
+
*/
|
|
213
|
+
private restoredAtOnce = false;
|
|
214
|
+
/** Told when that changes (the framework records it beside the persisted budget). */
|
|
215
|
+
private compiledBudgetListener?: (budget: number, fit: boolean) => boolean;
|
|
145
216
|
private contextManager: ContextManager;
|
|
146
217
|
private membrane: Membrane;
|
|
147
218
|
|
|
@@ -280,10 +351,16 @@ export class Agent {
|
|
|
280
351
|
getRuntimeSettings(): AgentRuntimeSettingsSnapshot {
|
|
281
352
|
const hot = this.getHotContextSettings();
|
|
282
353
|
return {
|
|
354
|
+
// The budget it's set to: the override, where there is one. That is
|
|
355
|
+
// the target of a descent toward it, or else the live budget, except
|
|
356
|
+
// while it's kept unapplied: at boot (keepRuntimeSettings), or after a
|
|
357
|
+
// refused at-once budget couldn't be restored paced (compileAtLiveBudget).
|
|
283
358
|
contextBudgetTokens:
|
|
359
|
+
this.runtimeSettingsOverrides.contextBudgetTokens ??
|
|
284
360
|
this.contextBudgetTargetTokens ??
|
|
285
361
|
this.contextBudgetTokens ??
|
|
286
362
|
DEFAULT_CONTEXT_BUDGET_TOKENS,
|
|
363
|
+
effectiveContextBudgetTokens: this.contextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS,
|
|
287
364
|
...(hot ? { tailTokens: hot.tailTokens } : {}),
|
|
288
365
|
...(hot?.transitionPaceTokens !== undefined
|
|
289
366
|
? { transitionPaceTokens: hot.transitionPaceTokens }
|
|
@@ -307,6 +384,179 @@ export class Agent {
|
|
|
307
384
|
return { ...this.runtimeSettingsOverrides };
|
|
308
385
|
}
|
|
309
386
|
|
|
387
|
+
/**
|
|
388
|
+
* Set (or clear) the one listener told when a compile at the live budget
|
|
389
|
+
* comes out differently from the last: it fit at a budget the last one
|
|
390
|
+
* didn't plan at (after a settle, the target), or the context manager
|
|
391
|
+
* refused a budget the last one fit at.
|
|
392
|
+
*/
|
|
393
|
+
onContextBudgetCompiled(listener: ((budget: number, fit: boolean) => boolean) | undefined): void {
|
|
394
|
+
this.compiledBudgetListener = listener;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* The live budget the last compile planned at and fit, if it fit and the
|
|
399
|
+
* live budget hasn't changed since.
|
|
400
|
+
*/
|
|
401
|
+
getProvenContextBudgetTokens(): number | undefined {
|
|
402
|
+
const last = this.lastCompiledBudget;
|
|
403
|
+
return last?.fit && last.epoch === this.liveBudgetEpoch ? last.budget : undefined;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Set the live budget and the descent target, counting a change of each.
|
|
408
|
+
* `armed` counts a descent armed here as a change even when its target is
|
|
409
|
+
* the one already set: a compile that began under the earlier arm isn't
|
|
410
|
+
* credited with this one's settle.
|
|
411
|
+
*/
|
|
412
|
+
private setContextBudget(budget: number | undefined, target: number | undefined, armed = false): void {
|
|
413
|
+
if (budget !== this.contextBudgetTokens) this.liveBudgetEpoch++;
|
|
414
|
+
if (armed || target !== this.contextBudgetTargetTokens) this.descentEpoch++;
|
|
415
|
+
this.contextBudgetTokens = budget;
|
|
416
|
+
this.contextBudgetTargetTokens = target;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Claim the place of the latest compile to end at `budget` for the one that
|
|
421
|
+
* started as the `started`th, and say whether it got it: a compile that
|
|
422
|
+
* started before one that has already ended there is ignored, whichever
|
|
423
|
+
* finishes last.
|
|
424
|
+
*/
|
|
425
|
+
private claimLatestAt(budget: number, started: number): boolean {
|
|
426
|
+
if (started < (this.latestEndedStart.get(budget) ?? 0)) return false;
|
|
427
|
+
this.latestEndedStart.set(budget, started);
|
|
428
|
+
return true;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Note what a compile at `budget`, planned at the live budget's `epoch`,
|
|
433
|
+
* showed. It speaks for the live budget only if that hasn't changed since;
|
|
434
|
+
* the listener is told either way, so a refusal withdraws the record's
|
|
435
|
+
* marker for the budget it planned at whatever changed meanwhile.
|
|
436
|
+
*/
|
|
437
|
+
private noteCompiledBudget(budget: number, fit: boolean, epoch: number): void {
|
|
438
|
+
if (epoch === this.liveBudgetEpoch) this.lastCompiledBudget = { budget, fit, epoch };
|
|
439
|
+
const recorded = this.recordedCompiledBudget;
|
|
440
|
+
if (recorded?.budget === budget && recorded.fit === fit && recorded.epoch === epoch) return;
|
|
441
|
+
// A listener that couldn't record it returns false: nothing is assumed
|
|
442
|
+
// recorded then, so the next compile tells it again whatever it shows.
|
|
443
|
+
this.recordedCompiledBudget = this.compiledBudgetListener?.(budget, fit) !== false ? { budget, fit, epoch } : undefined;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/** Compile at the live budget (no explicit one), noting whether it fit. */
|
|
447
|
+
private async compileAtLiveBudget(compile: () => Promise<CompileResult>): Promise<CompileResult> {
|
|
448
|
+
const started = ++this.compilesStarted;
|
|
449
|
+
this.compilesRunning.add(started);
|
|
450
|
+
try {
|
|
451
|
+
return await this.compileAtLiveBudgetNoting(compile, started);
|
|
452
|
+
} finally {
|
|
453
|
+
this.compilesRunning.delete(started);
|
|
454
|
+
const earliest = Math.min(...this.compilesRunning);
|
|
455
|
+
for (const [budget, start] of this.latestEndedStart) {
|
|
456
|
+
if (start < earliest) this.latestEndedStart.delete(budget);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/** The compile at the live budget that started as the `started`th, and what it showed. */
|
|
462
|
+
private async compileAtLiveBudgetNoting(compile: () => Promise<CompileResult>, started: number): Promise<CompileResult> {
|
|
463
|
+
// The budget this compile plans at, and the descent under way when it
|
|
464
|
+
// started: a change of either while it runs is no part of what it shows.
|
|
465
|
+
const live = this.contextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS;
|
|
466
|
+
const epoch = this.liveBudgetEpoch;
|
|
467
|
+
const descent = this.descentEpoch;
|
|
468
|
+
let result: CompileResult;
|
|
469
|
+
try {
|
|
470
|
+
result = await compile();
|
|
471
|
+
} catch (error) {
|
|
472
|
+
if ((error as { name?: unknown } | null)?.name !== 'OverBudgetError') throw error;
|
|
473
|
+
// A refusal shows the budget it planned at doesn't fit, whatever
|
|
474
|
+
// changed while it ran: the record's marker for it is withdrawn, and
|
|
475
|
+
// nothing is credited, unless a compile that started later has already
|
|
476
|
+
// ended at that budget.
|
|
477
|
+
if (this.claimLatestAt(live, started)) this.noteCompiledBudget(live, false, epoch);
|
|
478
|
+
// A budget a boot restore applied at once, refused at its first test,
|
|
479
|
+
// before anything wrote the budget: restore it paced instead, as the
|
|
480
|
+
// boot would have without its proof, and compile again from the
|
|
481
|
+
// recipe's budget. (While restoredAtOnce holds, the live budget is the
|
|
482
|
+
// one the boot applied: every write of the budget clears it, and no
|
|
483
|
+
// compile runs before the boot's restore.)
|
|
484
|
+
if (!this.restoredAtOnce) throw error;
|
|
485
|
+
this.restoredAtOnce = false;
|
|
486
|
+
// The persisted budget stays in the overrides, so if it can't be
|
|
487
|
+
// restored paced, no later write erases it.
|
|
488
|
+
this.setContextBudget(this.configuredContextBudgetTokens, undefined);
|
|
489
|
+
let outcome: string;
|
|
490
|
+
try {
|
|
491
|
+
this.updateRuntimeSettings({ contextBudgetTokens: live });
|
|
492
|
+
outcome = 'restored it as a paced descent from the recipe\'s budget';
|
|
493
|
+
} catch (fallback) {
|
|
494
|
+
outcome = `couldn't restore it paced (${fallback instanceof Error ? fallback.message : String(fallback)}), ` +
|
|
495
|
+
`so it compiles at the recipe's budget, with contextBudgetTokens=${live} kept set`;
|
|
496
|
+
}
|
|
497
|
+
console.error(
|
|
498
|
+
`[agent-settings] ${this.name}: the context manager refused contextBudgetTokens=${live}, which the boot ` +
|
|
499
|
+
`applied at once; ${outcome}`,
|
|
500
|
+
);
|
|
501
|
+
return this.compileAtLiveBudget(compile);
|
|
502
|
+
}
|
|
503
|
+
this.restoredAtOnce = false;
|
|
504
|
+
// A settle, here, of the descent this compile began under proves its
|
|
505
|
+
// target: the frontier fits the window prepared for it. Without a settle,
|
|
506
|
+
// the compile proves the budget it planned at. Either only if the live
|
|
507
|
+
// budget didn't change while it ran; a settle of a descent armed while it
|
|
508
|
+
// ran proves nothing (the next compile at the target does).
|
|
509
|
+
// A compile that ends here with a fit takes its place in the start order
|
|
510
|
+
// at the budget it planned at, credited or not; a settle credits its
|
|
511
|
+
// target only from the latest compile to end there.
|
|
512
|
+
const latest = this.claimLatestAt(live, started);
|
|
513
|
+
const sameLive = this.liveBudgetEpoch === epoch;
|
|
514
|
+
const sameDescent = this.descentEpoch === descent;
|
|
515
|
+
const settled = this.settleRuntimeSettingsTransition();
|
|
516
|
+
if (latest && sameLive && settled && sameDescent && this.claimLatestAt(this.contextBudgetTokens!, started)) {
|
|
517
|
+
this.noteCompiledBudget(this.contextBudgetTokens!, true, this.liveBudgetEpoch);
|
|
518
|
+
} else if (latest && sameLive && !settled) this.noteCompiledBudget(live, true, epoch);
|
|
519
|
+
return result;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* The budget compiles plan at, the path a patch's budget takes from it, and
|
|
524
|
+
* whether a descent is in flight, from the agent's own state alone: what a
|
|
525
|
+
* runtime-settings preview can still say while the context manager refuses
|
|
526
|
+
* its queries.
|
|
527
|
+
* @internal For the framework's runtime-settings preview; not a host API.
|
|
528
|
+
*/
|
|
529
|
+
runtimeBudgetPath(patch?: AgentRuntimeSettingsPatch): {
|
|
530
|
+
liveBudgetTokens: number;
|
|
531
|
+
path: 'immediate' | 'paced' | 'none';
|
|
532
|
+
transition: 'stable' | 'converging';
|
|
533
|
+
} {
|
|
534
|
+
const live = this.contextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS;
|
|
535
|
+
const budget = patch?.contextBudgetTokens;
|
|
536
|
+
return {
|
|
537
|
+
liveBudgetTokens: live,
|
|
538
|
+
path: budget === undefined ? 'none' : budget >= live || patch?.immediate ? 'immediate' : 'paced',
|
|
539
|
+
transition: this.contextBudgetTargetTokens === undefined ? 'stable' : 'converging',
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Whether the context manager answers its queries, as its readiness says.
|
|
545
|
+
* It refuses them while its strategy's initialization is pending or has
|
|
546
|
+
* failed, until a switchBranch or setStrategy succeeds, and a strategy can
|
|
547
|
+
* refuse its readiness on its own, as the autobiographical one does for a
|
|
548
|
+
* branch it hasn't reloaded.
|
|
549
|
+
* @internal For the framework's runtime-settings preview; not a host API.
|
|
550
|
+
*/
|
|
551
|
+
contextManagerAnswers(): boolean {
|
|
552
|
+
try {
|
|
553
|
+
this.contextManager.isReady();
|
|
554
|
+
return true;
|
|
555
|
+
} catch {
|
|
556
|
+
return false;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
310
560
|
/**
|
|
311
561
|
* Read-only mirror of `updateRuntimeSettings`' budget semantics: derive what
|
|
312
562
|
* the next compile would actually plan at if `patch` were applied, WITHOUT
|
|
@@ -323,11 +573,17 @@ export class Agent {
|
|
|
323
573
|
* - `path: 'none'` — patch absent or budget untouched.
|
|
324
574
|
*
|
|
325
575
|
* `overrides` uses strategy-config names (`recentWindowTokens`,
|
|
326
|
-
* `kvStableReachTokens`) suitable for `previewContext`.
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
576
|
+
* `kvStableReachTokens`) suitable for `previewContext`. The reach is the one
|
|
577
|
+
* the next compile plans at (context-manager's kv-stable picker): a
|
|
578
|
+
* descent's pace while a window is prepared for it, one this patch arms (a
|
|
579
|
+
* paced decrease) or one in flight that it leaves alone (a patch without a
|
|
580
|
+
* budget), and the configured reach otherwise. Config is a preview's only
|
|
581
|
+
* lever: `preparedWindowTokens` and the live runtime pace are strategy
|
|
582
|
+
* instance state, which a preview can't set. So a preview taken during a
|
|
583
|
+
* descent plans under that descent's prepared window, and at its live pace
|
|
584
|
+
* whenever the strategy carries one, which the picker reads before the
|
|
585
|
+
* configured reach. A boot restore's preflight never meets this: a new
|
|
586
|
+
* strategy has no window.
|
|
331
587
|
*/
|
|
332
588
|
planRuntimeSettings(patch?: AgentRuntimeSettingsPatch): {
|
|
333
589
|
effectiveBudgetTokens: number;
|
|
@@ -343,34 +599,33 @@ export class Agent {
|
|
|
343
599
|
this.validateRuntimeSettingsPatch(patch);
|
|
344
600
|
}
|
|
345
601
|
const hot = this.getHotContextSettings();
|
|
346
|
-
const live = this.
|
|
602
|
+
const { liveBudgetTokens: live, path } = this.runtimeBudgetPath(patch);
|
|
603
|
+
const budget = patch?.contextBudgetTokens;
|
|
347
604
|
|
|
348
605
|
const overrides: Record<string, unknown> = {};
|
|
349
606
|
if (patch?.tailTokens !== undefined) {
|
|
350
607
|
overrides.recentWindowTokens = patch.tailTokens;
|
|
351
608
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
609
|
+
// A window is prepared at the next compile when this patch arms a
|
|
610
|
+
// descent, or leaves one in flight alone; an immediate change clears it.
|
|
611
|
+
const prepared = hot !== null && (path === 'paced' || (path === 'none' && hot.preparedWindowTokens !== undefined));
|
|
612
|
+
const reach = prepared
|
|
613
|
+
? patch?.transitionPaceTokens ?? hot.transitionPaceTokens ?? DEFAULT_TRANSITION_PACE_TOKENS
|
|
614
|
+
: this.configuredTransitionPaceTokens;
|
|
615
|
+
if (reach !== undefined && reach !== this.configuredTransitionPaceTokens) {
|
|
616
|
+
overrides.kvStableReachTokens = reach;
|
|
357
617
|
}
|
|
358
618
|
|
|
359
|
-
if (
|
|
619
|
+
if (budget === undefined) {
|
|
360
620
|
return { effectiveBudgetTokens: live, liveBudgetTokens: live, path: 'none', overrides };
|
|
361
621
|
}
|
|
362
|
-
if (
|
|
363
|
-
return {
|
|
364
|
-
effectiveBudgetTokens: patch.contextBudgetTokens,
|
|
365
|
-
liveBudgetTokens: live,
|
|
366
|
-
path: 'immediate',
|
|
367
|
-
overrides,
|
|
368
|
-
};
|
|
622
|
+
if (path === 'immediate') {
|
|
623
|
+
return { effectiveBudgetTokens: budget, liveBudgetTokens: live, path, overrides };
|
|
369
624
|
}
|
|
370
625
|
return {
|
|
371
626
|
effectiveBudgetTokens: live,
|
|
372
627
|
liveBudgetTokens: live,
|
|
373
|
-
advisoryTargetTokens:
|
|
628
|
+
advisoryTargetTokens: budget,
|
|
374
629
|
path: 'paced',
|
|
375
630
|
overrides,
|
|
376
631
|
};
|
|
@@ -397,6 +652,8 @@ export class Agent {
|
|
|
397
652
|
let nextContextBudget = this.contextBudgetTokens;
|
|
398
653
|
let nextContextTarget = this.contextBudgetTargetTokens;
|
|
399
654
|
let appliedDefaultPace = false;
|
|
655
|
+
// A paced decrease arms a descent, even to the target already set.
|
|
656
|
+
let armed = false;
|
|
400
657
|
const hotPatch: {
|
|
401
658
|
tailTokens?: number;
|
|
402
659
|
transitionPaceTokens?: number | null;
|
|
@@ -428,21 +685,24 @@ export class Agent {
|
|
|
428
685
|
}
|
|
429
686
|
hotPatch.preparedWindowTokens = patch.contextBudgetTokens - this.maxTokens;
|
|
430
687
|
nextContextTarget = patch.contextBudgetTokens;
|
|
688
|
+
armed = true;
|
|
431
689
|
}
|
|
432
690
|
}
|
|
433
691
|
|
|
434
692
|
if (Object.keys(hotPatch).length > 0) {
|
|
435
693
|
this.updateHotContextSettings(hotPatch);
|
|
436
694
|
}
|
|
437
|
-
this.
|
|
438
|
-
|
|
695
|
+
this.setContextBudget(nextContextBudget, nextContextTarget, armed);
|
|
696
|
+
// A budget written here is a decision about it, whatever its value: the
|
|
697
|
+
// boot's at-once fallback (restoredAtOnce) no longer speaks for it.
|
|
698
|
+
if (patch.contextBudgetTokens !== undefined) this.restoredAtOnce = false;
|
|
439
699
|
if (appliedDefaultPace) {
|
|
440
700
|
this.runtimeSettingsOverrides.transitionPaceTokens = DEFAULT_TRANSITION_PACE_TOKENS;
|
|
441
701
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
if (
|
|
702
|
+
// Only settings reach the override map: `immediate` is a mode for this
|
|
703
|
+
// apply, and nothing else a caller passes is a setting.
|
|
704
|
+
for (const key of ['contextBudgetTokens', 'tailTokens', 'transitionPaceTokens'] as const) {
|
|
705
|
+
if (patch[key] !== undefined) this.runtimeSettingsOverrides[key] = patch[key];
|
|
446
706
|
}
|
|
447
707
|
if (patch.sameRoundThinkTextPolicy !== undefined) {
|
|
448
708
|
this.runtimeSettingsOverrides.sameRoundThinkTextPolicy = patch.sameRoundThinkTextPolicy;
|
|
@@ -454,6 +714,8 @@ export class Agent {
|
|
|
454
714
|
const reset = new Set(keys ?? ['contextBudgetTokens', 'tailTokens', 'transitionPaceTokens', 'sameRoundThinkTextPolicy']);
|
|
455
715
|
let nextContextBudget = this.contextBudgetTokens;
|
|
456
716
|
let nextContextTarget = this.contextBudgetTargetTokens;
|
|
717
|
+
// A reset to a recipe budget below the live one arms a descent to it.
|
|
718
|
+
let armed = false;
|
|
457
719
|
const hotPatch: {
|
|
458
720
|
tailTokens?: number;
|
|
459
721
|
transitionPaceTokens?: number | null;
|
|
@@ -471,6 +733,7 @@ export class Agent {
|
|
|
471
733
|
hotPatch.transitionPaceTokens = DEFAULT_TRANSITION_PACE_TOKENS;
|
|
472
734
|
}
|
|
473
735
|
nextContextTarget = configured;
|
|
736
|
+
armed = true;
|
|
474
737
|
} else {
|
|
475
738
|
nextContextBudget = this.configuredContextBudgetTokens;
|
|
476
739
|
nextContextTarget = undefined;
|
|
@@ -487,9 +750,11 @@ export class Agent {
|
|
|
487
750
|
: this.configuredTransitionPaceTokens ?? null;
|
|
488
751
|
}
|
|
489
752
|
if (Object.keys(hotPatch).length > 0) this.updateHotContextSettings(hotPatch);
|
|
490
|
-
this.
|
|
491
|
-
|
|
492
|
-
|
|
753
|
+
this.setContextBudget(nextContextBudget, nextContextTarget, armed);
|
|
754
|
+
if (reset.has('contextBudgetTokens')) {
|
|
755
|
+
delete this.runtimeSettingsOverrides.contextBudgetTokens;
|
|
756
|
+
this.restoredAtOnce = false;
|
|
757
|
+
}
|
|
493
758
|
if (reset.has('tailTokens')) delete this.runtimeSettingsOverrides.tailTokens;
|
|
494
759
|
if (reset.has('transitionPaceTokens')) {
|
|
495
760
|
delete this.runtimeSettingsOverrides.transitionPaceTokens;
|
|
@@ -503,7 +768,7 @@ export class Agent {
|
|
|
503
768
|
cancelRuntimeSettingsTransition(): AgentRuntimeSettingsSnapshot {
|
|
504
769
|
if (this.contextBudgetTargetTokens !== undefined) {
|
|
505
770
|
this.updateHotContextSettings({ preparedWindowTokens: null });
|
|
506
|
-
this.
|
|
771
|
+
this.setContextBudget(this.contextBudgetTokens, undefined);
|
|
507
772
|
const live = this.contextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS;
|
|
508
773
|
if (live === (this.configuredContextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS)) {
|
|
509
774
|
delete this.runtimeSettingsOverrides.contextBudgetTokens;
|
|
@@ -514,11 +779,56 @@ export class Agent {
|
|
|
514
779
|
return this.getRuntimeSettings();
|
|
515
780
|
}
|
|
516
781
|
|
|
517
|
-
|
|
518
|
-
|
|
782
|
+
/**
|
|
783
|
+
* Apply persisted settings at construction. `provenBudget` is a budget the
|
|
784
|
+
* caller has shown fits (the framework, from the record and a preflight),
|
|
785
|
+
* applied at once: it stands as the last compile's until a compile here
|
|
786
|
+
* says otherwise. When it's below the live budget, where the proof is what
|
|
787
|
+
* took the restore off the paced path, a refusal of a compile at it
|
|
788
|
+
* restores it paced instead, until the budget is next written or a compile
|
|
789
|
+
* at it fits. At or above the live budget, the restore is at once either
|
|
790
|
+
* way, and a refusal has nothing to fall back to.
|
|
791
|
+
*/
|
|
792
|
+
restoreRuntimeSettings(
|
|
793
|
+
settings: AgentRuntimeSettingsPatch,
|
|
794
|
+
opts?: { provenBudget?: number },
|
|
795
|
+
): AgentRuntimeSettingsSnapshot {
|
|
796
|
+
if (Object.keys(settings).length === 0) return this.getRuntimeSettings();
|
|
797
|
+
const live = this.contextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS;
|
|
798
|
+
const snapshot = this.updateRuntimeSettings(settings);
|
|
799
|
+
if (opts?.provenBudget !== undefined) {
|
|
800
|
+
this.lastCompiledBudget = { budget: opts.provenBudget, fit: true, epoch: this.liveBudgetEpoch };
|
|
801
|
+
this.restoredAtOnce = opts.provenBudget < live;
|
|
802
|
+
}
|
|
803
|
+
return snapshot;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* Keep a persisted budget, tail or pace that couldn't be applied at
|
|
808
|
+
* construction: it stays in the override map, unapplied, so a later
|
|
809
|
+
* persisting write keeps it in the record. A budget is reported as the one
|
|
810
|
+
* set (`contextBudgetTokens`) beside the one compiles plan at
|
|
811
|
+
* (`effectiveContextBudgetTokens`); a tail or pace stays the strategy's.
|
|
812
|
+
*/
|
|
813
|
+
keepRuntimeSettings(settings: Pick<AgentRuntimeSettingsPatch, 'contextBudgetTokens' | 'tailTokens' | 'transitionPaceTokens'>): void {
|
|
814
|
+
for (const key of ['contextBudgetTokens', 'tailTokens', 'transitionPaceTokens'] as const) {
|
|
815
|
+
if (settings[key] !== undefined) this.runtimeSettingsOverrides[key] = settings[key];
|
|
816
|
+
}
|
|
519
817
|
}
|
|
520
818
|
|
|
521
819
|
private validateRuntimeSettingsPatch(patch: AgentRuntimeSettingsPatch): void {
|
|
820
|
+
this.checkRuntimeSettingsPatch(patch);
|
|
821
|
+
if ((patch.tailTokens !== undefined || patch.transitionPaceTokens !== undefined) &&
|
|
822
|
+
!this.getHotContextSettings()) {
|
|
823
|
+
throw new Error('The active context strategy does not support live tail/transition settings');
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* The checks of a runtime-settings patch that need nothing from the context manager.
|
|
829
|
+
* @internal For the framework's runtime-settings preview; not a host API.
|
|
830
|
+
*/
|
|
831
|
+
checkRuntimeSettingsPatch(patch: AgentRuntimeSettingsPatch): void {
|
|
522
832
|
if (Object.keys(patch).length === 0) throw new Error('At least one setting is required');
|
|
523
833
|
if (patch.contextBudgetTokens !== undefined) {
|
|
524
834
|
if (!Number.isSafeInteger(patch.contextBudgetTokens) || patch.contextBudgetTokens <= this.maxTokens) {
|
|
@@ -538,19 +848,16 @@ export class Agent {
|
|
|
538
848
|
patch.sameRoundThinkTextPolicy !== 'private') {
|
|
539
849
|
throw new Error("sameRoundThinkTextPolicy must be 'public' or 'private'");
|
|
540
850
|
}
|
|
541
|
-
if ((patch.tailTokens !== undefined || patch.transitionPaceTokens !== undefined) &&
|
|
542
|
-
!this.getHotContextSettings()) {
|
|
543
|
-
throw new Error('The active context strategy does not support live tail/transition settings');
|
|
544
|
-
}
|
|
545
851
|
}
|
|
546
852
|
|
|
547
|
-
|
|
548
|
-
|
|
853
|
+
/** Settle a converging budget once the window is prepared; true if it settled. */
|
|
854
|
+
private settleRuntimeSettingsTransition(): boolean {
|
|
855
|
+
if (this.contextBudgetTargetTokens === undefined) return false;
|
|
549
856
|
const hot = this.getHotContextSettings();
|
|
550
|
-
if (!hot?.prepared) return;
|
|
551
|
-
this.
|
|
552
|
-
this.contextBudgetTargetTokens = undefined;
|
|
857
|
+
if (!hot?.prepared) return false;
|
|
858
|
+
this.setContextBudget(this.contextBudgetTargetTokens, undefined);
|
|
553
859
|
this.updateHotContextSettings({ preparedWindowTokens: null });
|
|
860
|
+
return true;
|
|
554
861
|
}
|
|
555
862
|
|
|
556
863
|
/**
|
|
@@ -591,32 +898,59 @@ export class Agent {
|
|
|
591
898
|
}
|
|
592
899
|
}
|
|
593
900
|
|
|
901
|
+
/** A committing compile, as for a request that is sent: the context
|
|
902
|
+
* manager commits what it commits for one, the consumed watermark moves,
|
|
903
|
+
* and a prepared budget change settles. To inspect what the agent would
|
|
904
|
+
* see, use the framework's `previewActivation`, which compiles as a dry
|
|
905
|
+
* run. */
|
|
594
906
|
async compileContext(budget?: TokenBudget): Promise<CompileResult> {
|
|
595
907
|
// RFC-006 §3.3: consumption is determined at assembly — a compile that
|
|
596
908
|
// fails assembled nothing, so the watermark moves only on success.
|
|
597
909
|
const watermark = this.pendingWatermark();
|
|
598
|
-
const
|
|
910
|
+
const compile = () => this.contextManager.compile(this.compileBudget(budget));
|
|
911
|
+
const result = budget ? await compile() : await this.compileAtLiveBudget(compile);
|
|
599
912
|
if (watermark) this.consumedWatermark = watermark;
|
|
600
|
-
if (!budget) this.settleRuntimeSettingsTransition();
|
|
601
913
|
return result;
|
|
602
914
|
}
|
|
603
915
|
|
|
604
916
|
/**
|
|
605
|
-
* Compile the context with injections.
|
|
606
|
-
*
|
|
607
|
-
*
|
|
917
|
+
* Compile the context with injections (e.g. from MCPL servers), which the
|
|
918
|
+
* context manager merges into the compiled messages. Without
|
|
919
|
+
* `opts.dryRun` it commits as `compileContext` does: the consumed
|
|
920
|
+
* watermark moves, and a compile at the live window settles a prepared
|
|
921
|
+
* budget change. With `opts.dryRun`, for a compile that will never be
|
|
922
|
+
* sent, it does neither (see below).
|
|
608
923
|
*/
|
|
609
924
|
async compileWithInjections(
|
|
610
925
|
budget?: TokenBudget,
|
|
611
926
|
injections?: ContextInjection[],
|
|
612
|
-
opts?: { kvUnifiedImmutablePrefixHash?: string },
|
|
927
|
+
opts?: { kvUnifiedImmutablePrefixHash?: string; dryRun?: boolean },
|
|
613
928
|
): Promise<CompileResult> {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
)
|
|
929
|
+
// A dry run is a compile that will never be sent. The context manager
|
|
930
|
+
// persists no fold resolutions for it and queues none of the compression
|
|
931
|
+
// or merge work its fold plan calls for. Its thinking binding
|
|
932
|
+
// (context-manager#160, not yet released) will commit stamps and add a
|
|
933
|
+
// compile awaiting acceptance for a committing compile only. Here nothing
|
|
934
|
+
// moves either: the agent never read what a dry run assembled, so the
|
|
935
|
+
// consumed watermark stays. A dry run proves nothing about the budget
|
|
936
|
+
// either, so it goes straight to the compile, around
|
|
937
|
+
// compileAtLiveBudget: it settles no descent (a prepared budget change
|
|
938
|
+
// waits for the compile that is sent), notes no compiled budget, and
|
|
939
|
+
// restores nothing the boot applied at once, whether it fits or is
|
|
940
|
+
// refused.
|
|
941
|
+
//
|
|
942
|
+
// Context-manager 0.14 leaves what a select leaves behind as the last
|
|
943
|
+
// committing compile left it, on every path out of a dry run, throws
|
|
944
|
+
// included: no chunk record and no compression queued for a chunk the
|
|
945
|
+
// dry run closes, no calibration, and none of the bookkeeping the next
|
|
946
|
+
// compile or an observer reads (its `SelectOptions.dryRun` gives the
|
|
947
|
+
// contract). The one thing a dry run can still leave is the release of a
|
|
948
|
+
// compression hold whose deadline has passed, which `compile` does for
|
|
949
|
+
// any compile before it selects.
|
|
950
|
+
const watermark = opts?.dryRun ? null : this.pendingWatermark();
|
|
951
|
+
const compile = () => this.contextManager.compile(this.compileBudget(budget), injections, opts as never);
|
|
952
|
+
const result = budget || opts?.dryRun ? await compile() : await this.compileAtLiveBudget(compile);
|
|
618
953
|
if (watermark) this.consumedWatermark = watermark;
|
|
619
|
-
if (!budget) this.settleRuntimeSettingsTransition();
|
|
620
954
|
return result;
|
|
621
955
|
}
|
|
622
956
|
|
|
@@ -801,10 +1135,13 @@ export class Agent {
|
|
|
801
1135
|
*
|
|
802
1136
|
* This is the single source of truth for request assembly, shared by the
|
|
803
1137
|
* real activation path (`startStreamWithInjections`) and debug/preview
|
|
804
|
-
* tooling (`Framework.previewActivation`). It
|
|
805
|
-
*
|
|
806
|
-
*
|
|
807
|
-
*
|
|
1138
|
+
* tooling (`Framework.previewActivation`). It does not call the membrane.
|
|
1139
|
+
* A compile that is sent commits what the context manager commits for it
|
|
1140
|
+
* (fold resolutions, the compression its fold plan calls for, the consumed
|
|
1141
|
+
* watermark); a preview passes `options.dryRun`, so its compile commits
|
|
1142
|
+
* none of that (see `compileWithInjections` for what a dry run still
|
|
1143
|
+
* leaves). Either way the context manager is handed the compression tool
|
|
1144
|
+
* definitions. Safe to call regardless of the agent's current status.
|
|
808
1145
|
* It doesn't wait for the tool-result guard's annotations, so a preview
|
|
809
1146
|
* never waits on a workspace write (rollback, undo and redo report one), and
|
|
810
1147
|
* may show a withheld stub before its place is added; the activation waits
|
|
@@ -845,7 +1182,12 @@ export class Agent {
|
|
|
845
1182
|
let { messages, systemInjections } = await this.compileWithInjections(
|
|
846
1183
|
budget,
|
|
847
1184
|
injections,
|
|
848
|
-
immutablePrefixHash
|
|
1185
|
+
immutablePrefixHash || options.dryRun
|
|
1186
|
+
? {
|
|
1187
|
+
...(immutablePrefixHash ? { kvUnifiedImmutablePrefixHash: immutablePrefixHash } : {}),
|
|
1188
|
+
...(options.dryRun ? { dryRun: true } : {}),
|
|
1189
|
+
}
|
|
1190
|
+
: undefined,
|
|
849
1191
|
);
|
|
850
1192
|
|
|
851
1193
|
// Sanitize: strip empty/whitespace text blocks and drop messages left with
|
|
@@ -972,10 +1314,13 @@ export class Agent {
|
|
|
972
1314
|
// the prior stream's window size — on the physical-window restart path
|
|
973
1315
|
// that inherited value IS the oversized number that caused the restart,
|
|
974
1316
|
// and projecting on it before this stream's first usage event would
|
|
975
|
-
// restart again (loop). The `> 0` guard downstream means "no
|
|
976
|
-
//
|
|
1317
|
+
// restart again (loop). The `> 0` guard downstream means "no call on
|
|
1318
|
+
// THIS stream has reported a prompt yet" only because of this reset (a
|
|
1319
|
+
// call that reports none leaves these as they were, and adds to
|
|
1320
|
+
// lastStreamUnreportedTokens instead).
|
|
977
1321
|
this.lastStreamRealInputTokens = 0;
|
|
978
1322
|
this.lastStreamOutputTokens = 0;
|
|
1323
|
+
this.lastStreamUnreportedTokens = 0;
|
|
979
1324
|
|
|
980
1325
|
// Compiled only once each withheld stub's annotation has finished,
|
|
981
1326
|
// including one that began during the compile, and after a stub edit that
|