@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/dist/src/agent.js
CHANGED
|
@@ -65,15 +65,38 @@ export class Agent {
|
|
|
65
65
|
* closure) so the next activation can close whatever its predecessor left
|
|
66
66
|
* open — see failOpenKvSubmissions. */
|
|
67
67
|
kvOpenQueue = null;
|
|
68
|
+
/** The current stream's fresh input so far, as membrane's usage event
|
|
69
|
+
* reports it (cumulative across the tool loop): what the maxStreamTokens
|
|
70
|
+
* budget checks. */
|
|
68
71
|
lastStreamInputTokens = 0;
|
|
69
|
-
/** Real
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
+
/** Real prompt size of the stream's latest provider call that reported a
|
|
73
|
+
* prompt, which is what the provider billed it: fresh + cache creation +
|
|
74
|
+
* cache read. A call that reports none leaves it as it was (see
|
|
75
|
+
* lastStreamUnreportedTokens). Membrane's usage events are cumulative, so
|
|
76
|
+
* this is the call's share of its event (cumulativeDelta): the whole event
|
|
77
|
+
* for a stream's first call, and the event's own value where a counter
|
|
78
|
+
* went back. THE window-shaped number — `lastStreamInputTokens` alone
|
|
79
|
+
* omits cached tokens, which are most of a warm stream's window. 0 until a
|
|
80
|
+
* call on this stream reports a prompt, and the physical-window
|
|
81
|
+
* projection runs only once one has. */
|
|
72
82
|
lastStreamRealInputTokens = 0;
|
|
73
|
-
/** Output tokens of the
|
|
74
|
-
*
|
|
75
|
-
*
|
|
83
|
+
/** Output tokens of the same call as lastStreamRealInputTokens, or
|
|
84
|
+
* maxTokens, the bound on them, when it reported none (a call that ends at
|
|
85
|
+
* a tool boundary wrote a tool_use, so a 0 is a count left unreported) —
|
|
86
|
+
* the prior round's generated thinking/text/tool_use, which becomes part
|
|
87
|
+
* of the NEXT round's input and so belongs in the physical-window
|
|
88
|
+
* projection. */
|
|
76
89
|
lastStreamOutputTokens = 0;
|
|
90
|
+
/** What the stream has grown by since the call lastStreamRealInputTokens
|
|
91
|
+
* describes, for the physical-window projection: the blocks appended at
|
|
92
|
+
* each boundary the stream continued past (counted only for an agent with
|
|
93
|
+
* physicalWindowTokens, whose projection is this field's one reader), and
|
|
94
|
+
* the output of each call that reported no prompt (its reported output,
|
|
95
|
+
* or maxTokens, the bound on it, when it reported none either). After
|
|
96
|
+
* calls that report no prompt, the next request holds the prompt and
|
|
97
|
+
* output of the call lastStreamRealInputTokens describes, plus this. 0 at
|
|
98
|
+
* stream start and whenever a call reports a prompt. */
|
|
99
|
+
lastStreamUnreportedTokens = 0;
|
|
77
100
|
maxStreamTokens;
|
|
78
101
|
/** Provider hard context cap (see AgentConfig.physicalWindowTokens). */
|
|
79
102
|
physicalWindowTokens;
|
|
@@ -87,6 +110,51 @@ export class Agent {
|
|
|
87
110
|
configuredSameRoundThinkTextPolicy;
|
|
88
111
|
contextBudgetTargetTokens;
|
|
89
112
|
runtimeSettingsOverrides = {};
|
|
113
|
+
/**
|
|
114
|
+
* Counts changes of the live budget (an update, a reset, a restore, a
|
|
115
|
+
* settle). A compile speaks for the budget it planned at only if the live
|
|
116
|
+
* budget didn't change while it ran, and what it showed stands only until
|
|
117
|
+
* the next change.
|
|
118
|
+
*/
|
|
119
|
+
liveBudgetEpoch = 0;
|
|
120
|
+
/**
|
|
121
|
+
* Counts changes of the descent (each arm of one, the same target included,
|
|
122
|
+
* a reset, a cancel, a settle). A settle proves its target only to a
|
|
123
|
+
* compile that began under that same descent.
|
|
124
|
+
*/
|
|
125
|
+
descentEpoch = 0;
|
|
126
|
+
/** The live budget the last compile planned at, whether it fit, and the live budget's epoch then. */
|
|
127
|
+
lastCompiledBudget;
|
|
128
|
+
/** Counts compiles at the live budget as they start. */
|
|
129
|
+
compilesStarted = 0;
|
|
130
|
+
/** The start numbers of the compiles at the live budget still running. */
|
|
131
|
+
compilesRunning = new Set();
|
|
132
|
+
/**
|
|
133
|
+
* For each budget, the start of the latest-started compile that has ended
|
|
134
|
+
* there with a fit or a refusal, whether or not what it showed was
|
|
135
|
+
* credited. Of two compiles at one budget, the later-started one planned
|
|
136
|
+
* at the newer store, so an earlier-started one that ends after it is
|
|
137
|
+
* ignored. That rests on the context manager selecting at the start of
|
|
138
|
+
* `compile`, before anything it awaits, so start order is selection order;
|
|
139
|
+
* a context manager that awaits before its select breaks it. (Injections
|
|
140
|
+
* are added after the select, so compiles with and without them plan
|
|
141
|
+
* alike.) An entry is
|
|
142
|
+
* kept only while a compile that started before it is still running, the
|
|
143
|
+
* only kind it can turn away, so the map is empty whenever no compile
|
|
144
|
+
* runs.
|
|
145
|
+
*/
|
|
146
|
+
latestEndedStart = new Map();
|
|
147
|
+
/** The last outcome the listener recorded; a failed record is told again, and so is any after a change. */
|
|
148
|
+
recordedCompiledBudget;
|
|
149
|
+
/**
|
|
150
|
+
* A boot restore applied a proven budget below the live one at once. Until
|
|
151
|
+
* the budget is next written (an update that carries one, or a reset of
|
|
152
|
+
* it) or a compile at it fits, a refusal of a compile at it restores it
|
|
153
|
+
* paced instead.
|
|
154
|
+
*/
|
|
155
|
+
restoredAtOnce = false;
|
|
156
|
+
/** Told when that changes (the framework records it beside the persisted budget). */
|
|
157
|
+
compiledBudgetListener;
|
|
90
158
|
contextManager;
|
|
91
159
|
membrane;
|
|
92
160
|
constructor(config, contextManager, membrane) {
|
|
@@ -208,9 +276,15 @@ export class Agent {
|
|
|
208
276
|
getRuntimeSettings() {
|
|
209
277
|
const hot = this.getHotContextSettings();
|
|
210
278
|
return {
|
|
211
|
-
|
|
279
|
+
// The budget it's set to: the override, where there is one. That is
|
|
280
|
+
// the target of a descent toward it, or else the live budget, except
|
|
281
|
+
// while it's kept unapplied: at boot (keepRuntimeSettings), or after a
|
|
282
|
+
// refused at-once budget couldn't be restored paced (compileAtLiveBudget).
|
|
283
|
+
contextBudgetTokens: this.runtimeSettingsOverrides.contextBudgetTokens ??
|
|
284
|
+
this.contextBudgetTargetTokens ??
|
|
212
285
|
this.contextBudgetTokens ??
|
|
213
286
|
DEFAULT_CONTEXT_BUDGET_TOKENS,
|
|
287
|
+
effectiveContextBudgetTokens: this.contextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS,
|
|
214
288
|
...(hot ? { tailTokens: hot.tailTokens } : {}),
|
|
215
289
|
...(hot?.transitionPaceTokens !== undefined
|
|
216
290
|
? { transitionPaceTokens: hot.transitionPaceTokens }
|
|
@@ -232,6 +306,179 @@ export class Agent {
|
|
|
232
306
|
getRuntimeSettingsOverrides() {
|
|
233
307
|
return { ...this.runtimeSettingsOverrides };
|
|
234
308
|
}
|
|
309
|
+
/**
|
|
310
|
+
* Set (or clear) the one listener told when a compile at the live budget
|
|
311
|
+
* comes out differently from the last: it fit at a budget the last one
|
|
312
|
+
* didn't plan at (after a settle, the target), or the context manager
|
|
313
|
+
* refused a budget the last one fit at.
|
|
314
|
+
*/
|
|
315
|
+
onContextBudgetCompiled(listener) {
|
|
316
|
+
this.compiledBudgetListener = listener;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* The live budget the last compile planned at and fit, if it fit and the
|
|
320
|
+
* live budget hasn't changed since.
|
|
321
|
+
*/
|
|
322
|
+
getProvenContextBudgetTokens() {
|
|
323
|
+
const last = this.lastCompiledBudget;
|
|
324
|
+
return last?.fit && last.epoch === this.liveBudgetEpoch ? last.budget : undefined;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Set the live budget and the descent target, counting a change of each.
|
|
328
|
+
* `armed` counts a descent armed here as a change even when its target is
|
|
329
|
+
* the one already set: a compile that began under the earlier arm isn't
|
|
330
|
+
* credited with this one's settle.
|
|
331
|
+
*/
|
|
332
|
+
setContextBudget(budget, target, armed = false) {
|
|
333
|
+
if (budget !== this.contextBudgetTokens)
|
|
334
|
+
this.liveBudgetEpoch++;
|
|
335
|
+
if (armed || target !== this.contextBudgetTargetTokens)
|
|
336
|
+
this.descentEpoch++;
|
|
337
|
+
this.contextBudgetTokens = budget;
|
|
338
|
+
this.contextBudgetTargetTokens = target;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Claim the place of the latest compile to end at `budget` for the one that
|
|
342
|
+
* started as the `started`th, and say whether it got it: a compile that
|
|
343
|
+
* started before one that has already ended there is ignored, whichever
|
|
344
|
+
* finishes last.
|
|
345
|
+
*/
|
|
346
|
+
claimLatestAt(budget, started) {
|
|
347
|
+
if (started < (this.latestEndedStart.get(budget) ?? 0))
|
|
348
|
+
return false;
|
|
349
|
+
this.latestEndedStart.set(budget, started);
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Note what a compile at `budget`, planned at the live budget's `epoch`,
|
|
354
|
+
* showed. It speaks for the live budget only if that hasn't changed since;
|
|
355
|
+
* the listener is told either way, so a refusal withdraws the record's
|
|
356
|
+
* marker for the budget it planned at whatever changed meanwhile.
|
|
357
|
+
*/
|
|
358
|
+
noteCompiledBudget(budget, fit, epoch) {
|
|
359
|
+
if (epoch === this.liveBudgetEpoch)
|
|
360
|
+
this.lastCompiledBudget = { budget, fit, epoch };
|
|
361
|
+
const recorded = this.recordedCompiledBudget;
|
|
362
|
+
if (recorded?.budget === budget && recorded.fit === fit && recorded.epoch === epoch)
|
|
363
|
+
return;
|
|
364
|
+
// A listener that couldn't record it returns false: nothing is assumed
|
|
365
|
+
// recorded then, so the next compile tells it again whatever it shows.
|
|
366
|
+
this.recordedCompiledBudget = this.compiledBudgetListener?.(budget, fit) !== false ? { budget, fit, epoch } : undefined;
|
|
367
|
+
}
|
|
368
|
+
/** Compile at the live budget (no explicit one), noting whether it fit. */
|
|
369
|
+
async compileAtLiveBudget(compile) {
|
|
370
|
+
const started = ++this.compilesStarted;
|
|
371
|
+
this.compilesRunning.add(started);
|
|
372
|
+
try {
|
|
373
|
+
return await this.compileAtLiveBudgetNoting(compile, started);
|
|
374
|
+
}
|
|
375
|
+
finally {
|
|
376
|
+
this.compilesRunning.delete(started);
|
|
377
|
+
const earliest = Math.min(...this.compilesRunning);
|
|
378
|
+
for (const [budget, start] of this.latestEndedStart) {
|
|
379
|
+
if (start < earliest)
|
|
380
|
+
this.latestEndedStart.delete(budget);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
/** The compile at the live budget that started as the `started`th, and what it showed. */
|
|
385
|
+
async compileAtLiveBudgetNoting(compile, started) {
|
|
386
|
+
// The budget this compile plans at, and the descent under way when it
|
|
387
|
+
// started: a change of either while it runs is no part of what it shows.
|
|
388
|
+
const live = this.contextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS;
|
|
389
|
+
const epoch = this.liveBudgetEpoch;
|
|
390
|
+
const descent = this.descentEpoch;
|
|
391
|
+
let result;
|
|
392
|
+
try {
|
|
393
|
+
result = await compile();
|
|
394
|
+
}
|
|
395
|
+
catch (error) {
|
|
396
|
+
if (error?.name !== 'OverBudgetError')
|
|
397
|
+
throw error;
|
|
398
|
+
// A refusal shows the budget it planned at doesn't fit, whatever
|
|
399
|
+
// changed while it ran: the record's marker for it is withdrawn, and
|
|
400
|
+
// nothing is credited, unless a compile that started later has already
|
|
401
|
+
// ended at that budget.
|
|
402
|
+
if (this.claimLatestAt(live, started))
|
|
403
|
+
this.noteCompiledBudget(live, false, epoch);
|
|
404
|
+
// A budget a boot restore applied at once, refused at its first test,
|
|
405
|
+
// before anything wrote the budget: restore it paced instead, as the
|
|
406
|
+
// boot would have without its proof, and compile again from the
|
|
407
|
+
// recipe's budget. (While restoredAtOnce holds, the live budget is the
|
|
408
|
+
// one the boot applied: every write of the budget clears it, and no
|
|
409
|
+
// compile runs before the boot's restore.)
|
|
410
|
+
if (!this.restoredAtOnce)
|
|
411
|
+
throw error;
|
|
412
|
+
this.restoredAtOnce = false;
|
|
413
|
+
// The persisted budget stays in the overrides, so if it can't be
|
|
414
|
+
// restored paced, no later write erases it.
|
|
415
|
+
this.setContextBudget(this.configuredContextBudgetTokens, undefined);
|
|
416
|
+
let outcome;
|
|
417
|
+
try {
|
|
418
|
+
this.updateRuntimeSettings({ contextBudgetTokens: live });
|
|
419
|
+
outcome = 'restored it as a paced descent from the recipe\'s budget';
|
|
420
|
+
}
|
|
421
|
+
catch (fallback) {
|
|
422
|
+
outcome = `couldn't restore it paced (${fallback instanceof Error ? fallback.message : String(fallback)}), ` +
|
|
423
|
+
`so it compiles at the recipe's budget, with contextBudgetTokens=${live} kept set`;
|
|
424
|
+
}
|
|
425
|
+
console.error(`[agent-settings] ${this.name}: the context manager refused contextBudgetTokens=${live}, which the boot ` +
|
|
426
|
+
`applied at once; ${outcome}`);
|
|
427
|
+
return this.compileAtLiveBudget(compile);
|
|
428
|
+
}
|
|
429
|
+
this.restoredAtOnce = false;
|
|
430
|
+
// A settle, here, of the descent this compile began under proves its
|
|
431
|
+
// target: the frontier fits the window prepared for it. Without a settle,
|
|
432
|
+
// the compile proves the budget it planned at. Either only if the live
|
|
433
|
+
// budget didn't change while it ran; a settle of a descent armed while it
|
|
434
|
+
// ran proves nothing (the next compile at the target does).
|
|
435
|
+
// A compile that ends here with a fit takes its place in the start order
|
|
436
|
+
// at the budget it planned at, credited or not; a settle credits its
|
|
437
|
+
// target only from the latest compile to end there.
|
|
438
|
+
const latest = this.claimLatestAt(live, started);
|
|
439
|
+
const sameLive = this.liveBudgetEpoch === epoch;
|
|
440
|
+
const sameDescent = this.descentEpoch === descent;
|
|
441
|
+
const settled = this.settleRuntimeSettingsTransition();
|
|
442
|
+
if (latest && sameLive && settled && sameDescent && this.claimLatestAt(this.contextBudgetTokens, started)) {
|
|
443
|
+
this.noteCompiledBudget(this.contextBudgetTokens, true, this.liveBudgetEpoch);
|
|
444
|
+
}
|
|
445
|
+
else if (latest && sameLive && !settled)
|
|
446
|
+
this.noteCompiledBudget(live, true, epoch);
|
|
447
|
+
return result;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* The budget compiles plan at, the path a patch's budget takes from it, and
|
|
451
|
+
* whether a descent is in flight, from the agent's own state alone: what a
|
|
452
|
+
* runtime-settings preview can still say while the context manager refuses
|
|
453
|
+
* its queries.
|
|
454
|
+
* @internal For the framework's runtime-settings preview; not a host API.
|
|
455
|
+
*/
|
|
456
|
+
runtimeBudgetPath(patch) {
|
|
457
|
+
const live = this.contextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS;
|
|
458
|
+
const budget = patch?.contextBudgetTokens;
|
|
459
|
+
return {
|
|
460
|
+
liveBudgetTokens: live,
|
|
461
|
+
path: budget === undefined ? 'none' : budget >= live || patch?.immediate ? 'immediate' : 'paced',
|
|
462
|
+
transition: this.contextBudgetTargetTokens === undefined ? 'stable' : 'converging',
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Whether the context manager answers its queries, as its readiness says.
|
|
467
|
+
* It refuses them while its strategy's initialization is pending or has
|
|
468
|
+
* failed, until a switchBranch or setStrategy succeeds, and a strategy can
|
|
469
|
+
* refuse its readiness on its own, as the autobiographical one does for a
|
|
470
|
+
* branch it hasn't reloaded.
|
|
471
|
+
* @internal For the framework's runtime-settings preview; not a host API.
|
|
472
|
+
*/
|
|
473
|
+
contextManagerAnswers() {
|
|
474
|
+
try {
|
|
475
|
+
this.contextManager.isReady();
|
|
476
|
+
return true;
|
|
477
|
+
}
|
|
478
|
+
catch {
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
235
482
|
/**
|
|
236
483
|
* Read-only mirror of `updateRuntimeSettings`' budget semantics: derive what
|
|
237
484
|
* the next compile would actually plan at if `patch` were applied, WITHOUT
|
|
@@ -248,41 +495,48 @@ export class Agent {
|
|
|
248
495
|
* - `path: 'none'` — patch absent or budget untouched.
|
|
249
496
|
*
|
|
250
497
|
* `overrides` uses strategy-config names (`recentWindowTokens`,
|
|
251
|
-
* `kvStableReachTokens`) suitable for `previewContext`.
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
498
|
+
* `kvStableReachTokens`) suitable for `previewContext`. The reach is the one
|
|
499
|
+
* the next compile plans at (context-manager's kv-stable picker): a
|
|
500
|
+
* descent's pace while a window is prepared for it, one this patch arms (a
|
|
501
|
+
* paced decrease) or one in flight that it leaves alone (a patch without a
|
|
502
|
+
* budget), and the configured reach otherwise. Config is a preview's only
|
|
503
|
+
* lever: `preparedWindowTokens` and the live runtime pace are strategy
|
|
504
|
+
* instance state, which a preview can't set. So a preview taken during a
|
|
505
|
+
* descent plans under that descent's prepared window, and at its live pace
|
|
506
|
+
* whenever the strategy carries one, which the picker reads before the
|
|
507
|
+
* configured reach. A boot restore's preflight never meets this: a new
|
|
508
|
+
* strategy has no window.
|
|
256
509
|
*/
|
|
257
510
|
planRuntimeSettings(patch) {
|
|
258
511
|
if (patch && Object.keys(patch).length > 0) {
|
|
259
512
|
this.validateRuntimeSettingsPatch(patch);
|
|
260
513
|
}
|
|
261
514
|
const hot = this.getHotContextSettings();
|
|
262
|
-
const live = this.
|
|
515
|
+
const { liveBudgetTokens: live, path } = this.runtimeBudgetPath(patch);
|
|
516
|
+
const budget = patch?.contextBudgetTokens;
|
|
263
517
|
const overrides = {};
|
|
264
518
|
if (patch?.tailTokens !== undefined) {
|
|
265
519
|
overrides.recentWindowTokens = patch.tailTokens;
|
|
266
520
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
521
|
+
// A window is prepared at the next compile when this patch arms a
|
|
522
|
+
// descent, or leaves one in flight alone; an immediate change clears it.
|
|
523
|
+
const prepared = hot !== null && (path === 'paced' || (path === 'none' && hot.preparedWindowTokens !== undefined));
|
|
524
|
+
const reach = prepared
|
|
525
|
+
? patch?.transitionPaceTokens ?? hot.transitionPaceTokens ?? DEFAULT_TRANSITION_PACE_TOKENS
|
|
526
|
+
: this.configuredTransitionPaceTokens;
|
|
527
|
+
if (reach !== undefined && reach !== this.configuredTransitionPaceTokens) {
|
|
528
|
+
overrides.kvStableReachTokens = reach;
|
|
270
529
|
}
|
|
271
|
-
if (
|
|
530
|
+
if (budget === undefined) {
|
|
272
531
|
return { effectiveBudgetTokens: live, liveBudgetTokens: live, path: 'none', overrides };
|
|
273
532
|
}
|
|
274
|
-
if (
|
|
275
|
-
return {
|
|
276
|
-
effectiveBudgetTokens: patch.contextBudgetTokens,
|
|
277
|
-
liveBudgetTokens: live,
|
|
278
|
-
path: 'immediate',
|
|
279
|
-
overrides,
|
|
280
|
-
};
|
|
533
|
+
if (path === 'immediate') {
|
|
534
|
+
return { effectiveBudgetTokens: budget, liveBudgetTokens: live, path, overrides };
|
|
281
535
|
}
|
|
282
536
|
return {
|
|
283
537
|
effectiveBudgetTokens: live,
|
|
284
538
|
liveBudgetTokens: live,
|
|
285
|
-
advisoryTargetTokens:
|
|
539
|
+
advisoryTargetTokens: budget,
|
|
286
540
|
path: 'paced',
|
|
287
541
|
overrides,
|
|
288
542
|
};
|
|
@@ -306,6 +560,8 @@ export class Agent {
|
|
|
306
560
|
let nextContextBudget = this.contextBudgetTokens;
|
|
307
561
|
let nextContextTarget = this.contextBudgetTargetTokens;
|
|
308
562
|
let appliedDefaultPace = false;
|
|
563
|
+
// A paced decrease arms a descent, even to the target already set.
|
|
564
|
+
let armed = false;
|
|
309
565
|
const hotPatch = {};
|
|
310
566
|
if (patch.tailTokens !== undefined)
|
|
311
567
|
hotPatch.tailTokens = patch.tailTokens;
|
|
@@ -335,23 +591,25 @@ export class Agent {
|
|
|
335
591
|
}
|
|
336
592
|
hotPatch.preparedWindowTokens = patch.contextBudgetTokens - this.maxTokens;
|
|
337
593
|
nextContextTarget = patch.contextBudgetTokens;
|
|
594
|
+
armed = true;
|
|
338
595
|
}
|
|
339
596
|
}
|
|
340
597
|
if (Object.keys(hotPatch).length > 0) {
|
|
341
598
|
this.updateHotContextSettings(hotPatch);
|
|
342
599
|
}
|
|
343
|
-
this.
|
|
344
|
-
|
|
600
|
+
this.setContextBudget(nextContextBudget, nextContextTarget, armed);
|
|
601
|
+
// A budget written here is a decision about it, whatever its value: the
|
|
602
|
+
// boot's at-once fallback (restoredAtOnce) no longer speaks for it.
|
|
603
|
+
if (patch.contextBudgetTokens !== undefined)
|
|
604
|
+
this.restoredAtOnce = false;
|
|
345
605
|
if (appliedDefaultPace) {
|
|
346
606
|
this.runtimeSettingsOverrides.transitionPaceTokens = DEFAULT_TRANSITION_PACE_TOKENS;
|
|
347
607
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
if (key
|
|
352
|
-
|
|
353
|
-
if (value !== undefined)
|
|
354
|
-
this.runtimeSettingsOverrides[key] = value;
|
|
608
|
+
// Only settings reach the override map: `immediate` is a mode for this
|
|
609
|
+
// apply, and nothing else a caller passes is a setting.
|
|
610
|
+
for (const key of ['contextBudgetTokens', 'tailTokens', 'transitionPaceTokens']) {
|
|
611
|
+
if (patch[key] !== undefined)
|
|
612
|
+
this.runtimeSettingsOverrides[key] = patch[key];
|
|
355
613
|
}
|
|
356
614
|
if (patch.sameRoundThinkTextPolicy !== undefined) {
|
|
357
615
|
this.runtimeSettingsOverrides.sameRoundThinkTextPolicy = patch.sameRoundThinkTextPolicy;
|
|
@@ -362,6 +620,8 @@ export class Agent {
|
|
|
362
620
|
const reset = new Set(keys ?? ['contextBudgetTokens', 'tailTokens', 'transitionPaceTokens', 'sameRoundThinkTextPolicy']);
|
|
363
621
|
let nextContextBudget = this.contextBudgetTokens;
|
|
364
622
|
let nextContextTarget = this.contextBudgetTargetTokens;
|
|
623
|
+
// A reset to a recipe budget below the live one arms a descent to it.
|
|
624
|
+
let armed = false;
|
|
365
625
|
const hotPatch = {};
|
|
366
626
|
if (reset.has('contextBudgetTokens')) {
|
|
367
627
|
const configured = this.configuredContextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS;
|
|
@@ -375,6 +635,7 @@ export class Agent {
|
|
|
375
635
|
hotPatch.transitionPaceTokens = DEFAULT_TRANSITION_PACE_TOKENS;
|
|
376
636
|
}
|
|
377
637
|
nextContextTarget = configured;
|
|
638
|
+
armed = true;
|
|
378
639
|
}
|
|
379
640
|
else {
|
|
380
641
|
nextContextBudget = this.configuredContextBudgetTokens;
|
|
@@ -395,10 +656,11 @@ export class Agent {
|
|
|
395
656
|
}
|
|
396
657
|
if (Object.keys(hotPatch).length > 0)
|
|
397
658
|
this.updateHotContextSettings(hotPatch);
|
|
398
|
-
this.
|
|
399
|
-
|
|
400
|
-
if (reset.has('contextBudgetTokens'))
|
|
659
|
+
this.setContextBudget(nextContextBudget, nextContextTarget, armed);
|
|
660
|
+
if (reset.has('contextBudgetTokens')) {
|
|
401
661
|
delete this.runtimeSettingsOverrides.contextBudgetTokens;
|
|
662
|
+
this.restoredAtOnce = false;
|
|
663
|
+
}
|
|
402
664
|
if (reset.has('tailTokens'))
|
|
403
665
|
delete this.runtimeSettingsOverrides.tailTokens;
|
|
404
666
|
if (reset.has('transitionPaceTokens')) {
|
|
@@ -412,7 +674,7 @@ export class Agent {
|
|
|
412
674
|
cancelRuntimeSettingsTransition() {
|
|
413
675
|
if (this.contextBudgetTargetTokens !== undefined) {
|
|
414
676
|
this.updateHotContextSettings({ preparedWindowTokens: null });
|
|
415
|
-
this.
|
|
677
|
+
this.setContextBudget(this.contextBudgetTokens, undefined);
|
|
416
678
|
const live = this.contextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS;
|
|
417
679
|
if (live === (this.configuredContextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS)) {
|
|
418
680
|
delete this.runtimeSettingsOverrides.contextBudgetTokens;
|
|
@@ -423,10 +685,52 @@ export class Agent {
|
|
|
423
685
|
}
|
|
424
686
|
return this.getRuntimeSettings();
|
|
425
687
|
}
|
|
426
|
-
|
|
427
|
-
|
|
688
|
+
/**
|
|
689
|
+
* Apply persisted settings at construction. `provenBudget` is a budget the
|
|
690
|
+
* caller has shown fits (the framework, from the record and a preflight),
|
|
691
|
+
* applied at once: it stands as the last compile's until a compile here
|
|
692
|
+
* says otherwise. When it's below the live budget, where the proof is what
|
|
693
|
+
* took the restore off the paced path, a refusal of a compile at it
|
|
694
|
+
* restores it paced instead, until the budget is next written or a compile
|
|
695
|
+
* at it fits. At or above the live budget, the restore is at once either
|
|
696
|
+
* way, and a refusal has nothing to fall back to.
|
|
697
|
+
*/
|
|
698
|
+
restoreRuntimeSettings(settings, opts) {
|
|
699
|
+
if (Object.keys(settings).length === 0)
|
|
700
|
+
return this.getRuntimeSettings();
|
|
701
|
+
const live = this.contextBudgetTokens ?? DEFAULT_CONTEXT_BUDGET_TOKENS;
|
|
702
|
+
const snapshot = this.updateRuntimeSettings(settings);
|
|
703
|
+
if (opts?.provenBudget !== undefined) {
|
|
704
|
+
this.lastCompiledBudget = { budget: opts.provenBudget, fit: true, epoch: this.liveBudgetEpoch };
|
|
705
|
+
this.restoredAtOnce = opts.provenBudget < live;
|
|
706
|
+
}
|
|
707
|
+
return snapshot;
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Keep a persisted budget, tail or pace that couldn't be applied at
|
|
711
|
+
* construction: it stays in the override map, unapplied, so a later
|
|
712
|
+
* persisting write keeps it in the record. A budget is reported as the one
|
|
713
|
+
* set (`contextBudgetTokens`) beside the one compiles plan at
|
|
714
|
+
* (`effectiveContextBudgetTokens`); a tail or pace stays the strategy's.
|
|
715
|
+
*/
|
|
716
|
+
keepRuntimeSettings(settings) {
|
|
717
|
+
for (const key of ['contextBudgetTokens', 'tailTokens', 'transitionPaceTokens']) {
|
|
718
|
+
if (settings[key] !== undefined)
|
|
719
|
+
this.runtimeSettingsOverrides[key] = settings[key];
|
|
720
|
+
}
|
|
428
721
|
}
|
|
429
722
|
validateRuntimeSettingsPatch(patch) {
|
|
723
|
+
this.checkRuntimeSettingsPatch(patch);
|
|
724
|
+
if ((patch.tailTokens !== undefined || patch.transitionPaceTokens !== undefined) &&
|
|
725
|
+
!this.getHotContextSettings()) {
|
|
726
|
+
throw new Error('The active context strategy does not support live tail/transition settings');
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* The checks of a runtime-settings patch that need nothing from the context manager.
|
|
731
|
+
* @internal For the framework's runtime-settings preview; not a host API.
|
|
732
|
+
*/
|
|
733
|
+
checkRuntimeSettingsPatch(patch) {
|
|
430
734
|
if (Object.keys(patch).length === 0)
|
|
431
735
|
throw new Error('At least one setting is required');
|
|
432
736
|
if (patch.contextBudgetTokens !== undefined) {
|
|
@@ -447,20 +751,17 @@ export class Agent {
|
|
|
447
751
|
patch.sameRoundThinkTextPolicy !== 'private') {
|
|
448
752
|
throw new Error("sameRoundThinkTextPolicy must be 'public' or 'private'");
|
|
449
753
|
}
|
|
450
|
-
if ((patch.tailTokens !== undefined || patch.transitionPaceTokens !== undefined) &&
|
|
451
|
-
!this.getHotContextSettings()) {
|
|
452
|
-
throw new Error('The active context strategy does not support live tail/transition settings');
|
|
453
|
-
}
|
|
454
754
|
}
|
|
755
|
+
/** Settle a converging budget once the window is prepared; true if it settled. */
|
|
455
756
|
settleRuntimeSettingsTransition() {
|
|
456
757
|
if (this.contextBudgetTargetTokens === undefined)
|
|
457
|
-
return;
|
|
758
|
+
return false;
|
|
458
759
|
const hot = this.getHotContextSettings();
|
|
459
760
|
if (!hot?.prepared)
|
|
460
|
-
return;
|
|
461
|
-
this.
|
|
462
|
-
this.contextBudgetTargetTokens = undefined;
|
|
761
|
+
return false;
|
|
762
|
+
this.setContextBudget(this.contextBudgetTargetTokens, undefined);
|
|
463
763
|
this.updateHotContextSettings({ preparedWindowTokens: null });
|
|
764
|
+
return true;
|
|
464
765
|
}
|
|
465
766
|
/**
|
|
466
767
|
* RFC-006 consumed watermark: the newest stored message at the last compile
|
|
@@ -498,29 +799,56 @@ export class Agent {
|
|
|
498
799
|
return null;
|
|
499
800
|
}
|
|
500
801
|
}
|
|
802
|
+
/** A committing compile, as for a request that is sent: the context
|
|
803
|
+
* manager commits what it commits for one, the consumed watermark moves,
|
|
804
|
+
* and a prepared budget change settles. To inspect what the agent would
|
|
805
|
+
* see, use the framework's `previewActivation`, which compiles as a dry
|
|
806
|
+
* run. */
|
|
501
807
|
async compileContext(budget) {
|
|
502
808
|
// RFC-006 §3.3: consumption is determined at assembly — a compile that
|
|
503
809
|
// fails assembled nothing, so the watermark moves only on success.
|
|
504
810
|
const watermark = this.pendingWatermark();
|
|
505
|
-
const
|
|
811
|
+
const compile = () => this.contextManager.compile(this.compileBudget(budget));
|
|
812
|
+
const result = budget ? await compile() : await this.compileAtLiveBudget(compile);
|
|
506
813
|
if (watermark)
|
|
507
814
|
this.consumedWatermark = watermark;
|
|
508
|
-
if (!budget)
|
|
509
|
-
this.settleRuntimeSettingsTransition();
|
|
510
815
|
return result;
|
|
511
816
|
}
|
|
512
817
|
/**
|
|
513
|
-
* Compile the context with injections.
|
|
514
|
-
*
|
|
515
|
-
*
|
|
818
|
+
* Compile the context with injections (e.g. from MCPL servers), which the
|
|
819
|
+
* context manager merges into the compiled messages. Without
|
|
820
|
+
* `opts.dryRun` it commits as `compileContext` does: the consumed
|
|
821
|
+
* watermark moves, and a compile at the live window settles a prepared
|
|
822
|
+
* budget change. With `opts.dryRun`, for a compile that will never be
|
|
823
|
+
* sent, it does neither (see below).
|
|
516
824
|
*/
|
|
517
825
|
async compileWithInjections(budget, injections, opts) {
|
|
518
|
-
|
|
519
|
-
|
|
826
|
+
// A dry run is a compile that will never be sent. The context manager
|
|
827
|
+
// persists no fold resolutions for it and queues none of the compression
|
|
828
|
+
// or merge work its fold plan calls for. Its thinking binding
|
|
829
|
+
// (context-manager#160, not yet released) will commit stamps and add a
|
|
830
|
+
// compile awaiting acceptance for a committing compile only. Here nothing
|
|
831
|
+
// moves either: the agent never read what a dry run assembled, so the
|
|
832
|
+
// consumed watermark stays. A dry run proves nothing about the budget
|
|
833
|
+
// either, so it goes straight to the compile, around
|
|
834
|
+
// compileAtLiveBudget: it settles no descent (a prepared budget change
|
|
835
|
+
// waits for the compile that is sent), notes no compiled budget, and
|
|
836
|
+
// restores nothing the boot applied at once, whether it fits or is
|
|
837
|
+
// refused.
|
|
838
|
+
//
|
|
839
|
+
// Context-manager 0.14 leaves what a select leaves behind as the last
|
|
840
|
+
// committing compile left it, on every path out of a dry run, throws
|
|
841
|
+
// included: no chunk record and no compression queued for a chunk the
|
|
842
|
+
// dry run closes, no calibration, and none of the bookkeeping the next
|
|
843
|
+
// compile or an observer reads (its `SelectOptions.dryRun` gives the
|
|
844
|
+
// contract). The one thing a dry run can still leave is the release of a
|
|
845
|
+
// compression hold whose deadline has passed, which `compile` does for
|
|
846
|
+
// any compile before it selects.
|
|
847
|
+
const watermark = opts?.dryRun ? null : this.pendingWatermark();
|
|
848
|
+
const compile = () => this.contextManager.compile(this.compileBudget(budget), injections, opts);
|
|
849
|
+
const result = budget || opts?.dryRun ? await compile() : await this.compileAtLiveBudget(compile);
|
|
520
850
|
if (watermark)
|
|
521
851
|
this.consumedWatermark = watermark;
|
|
522
|
-
if (!budget)
|
|
523
|
-
this.settleRuntimeSettingsTransition();
|
|
524
852
|
return result;
|
|
525
853
|
}
|
|
526
854
|
// ==========================================================================
|
|
@@ -673,10 +1001,13 @@ export class Agent {
|
|
|
673
1001
|
*
|
|
674
1002
|
* This is the single source of truth for request assembly, shared by the
|
|
675
1003
|
* real activation path (`startStreamWithInjections`) and debug/preview
|
|
676
|
-
* tooling (`Framework.previewActivation`). It
|
|
677
|
-
*
|
|
678
|
-
*
|
|
679
|
-
*
|
|
1004
|
+
* tooling (`Framework.previewActivation`). It does not call the membrane.
|
|
1005
|
+
* A compile that is sent commits what the context manager commits for it
|
|
1006
|
+
* (fold resolutions, the compression its fold plan calls for, the consumed
|
|
1007
|
+
* watermark); a preview passes `options.dryRun`, so its compile commits
|
|
1008
|
+
* none of that (see `compileWithInjections` for what a dry run still
|
|
1009
|
+
* leaves). Either way the context manager is handed the compression tool
|
|
1010
|
+
* definitions. Safe to call regardless of the agent's current status.
|
|
680
1011
|
* It doesn't wait for the tool-result guard's annotations, so a preview
|
|
681
1012
|
* never waits on a workspace write (rollback, undo and redo report one), and
|
|
682
1013
|
* may show a withheld stub before its place is added; the activation waits
|
|
@@ -704,7 +1035,12 @@ export class Agent {
|
|
|
704
1035
|
system: this.buildSystemPrompt(prospectiveSystemInjections),
|
|
705
1036
|
})
|
|
706
1037
|
: undefined;
|
|
707
|
-
let { messages, systemInjections } = await this.compileWithInjections(budget, injections, immutablePrefixHash
|
|
1038
|
+
let { messages, systemInjections } = await this.compileWithInjections(budget, injections, immutablePrefixHash || options.dryRun
|
|
1039
|
+
? {
|
|
1040
|
+
...(immutablePrefixHash ? { kvUnifiedImmutablePrefixHash: immutablePrefixHash } : {}),
|
|
1041
|
+
...(options.dryRun ? { dryRun: true } : {}),
|
|
1042
|
+
}
|
|
1043
|
+
: undefined);
|
|
708
1044
|
// Sanitize: strip empty/whitespace text blocks and drop messages left with
|
|
709
1045
|
// no content. The Anthropic API rejects empty text blocks with 400
|
|
710
1046
|
// "messages: text content blocks must be non-empty"; when such a block
|
|
@@ -817,10 +1153,13 @@ export class Agent {
|
|
|
817
1153
|
// the prior stream's window size — on the physical-window restart path
|
|
818
1154
|
// that inherited value IS the oversized number that caused the restart,
|
|
819
1155
|
// and projecting on it before this stream's first usage event would
|
|
820
|
-
// restart again (loop). The `> 0` guard downstream means "no
|
|
821
|
-
//
|
|
1156
|
+
// restart again (loop). The `> 0` guard downstream means "no call on
|
|
1157
|
+
// THIS stream has reported a prompt yet" only because of this reset (a
|
|
1158
|
+
// call that reports none leaves these as they were, and adds to
|
|
1159
|
+
// lastStreamUnreportedTokens instead).
|
|
822
1160
|
this.lastStreamRealInputTokens = 0;
|
|
823
1161
|
this.lastStreamOutputTokens = 0;
|
|
1162
|
+
this.lastStreamUnreportedTokens = 0;
|
|
824
1163
|
// Compiled only once each withheld stub's annotation has finished,
|
|
825
1164
|
// including one that began during the compile, and after a stub edit that
|
|
826
1165
|
// failed has been retried (see afterAnnotations).
|