@code-yeongyu/senpi 2026.8.30 → 2026.9.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/CHANGELOG.md +174 -2
- package/README.md +3 -0
- package/dist/core/agent-session.d.ts +28 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +161 -14
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction-execution.d.ts +14 -0
- package/dist/core/compaction/compaction-execution.d.ts.map +1 -0
- package/dist/core/compaction/compaction-execution.js +121 -0
- package/dist/core/compaction/compaction-execution.js.map +1 -0
- package/dist/core/compaction/compaction-settings.d.ts +17 -0
- package/dist/core/compaction/compaction-settings.d.ts.map +1 -0
- package/dist/core/compaction/compaction-settings.js +17 -0
- package/dist/core/compaction/compaction-settings.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +13 -26
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +7 -136
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/ideal-compaction-settings.d.ts +9 -0
- package/dist/core/compaction/ideal-compaction-settings.d.ts.map +1 -0
- package/dist/core/compaction/ideal-compaction-settings.js +7 -0
- package/dist/core/compaction/ideal-compaction-settings.js.map +1 -0
- package/dist/core/compaction-settings-access.d.ts +19 -0
- package/dist/core/compaction-settings-access.d.ts.map +1 -0
- package/dist/core/compaction-settings-access.js +10 -0
- package/dist/core/compaction-settings-access.js.map +1 -0
- package/dist/core/compaction-settings-resolver.d.ts +22 -0
- package/dist/core/compaction-settings-resolver.d.ts.map +1 -0
- package/dist/core/compaction-settings-resolver.js +46 -0
- package/dist/core/compaction-settings-resolver.js.map +1 -0
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts +9 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js +10 -3
- package/dist/core/extensions/builtin/claude-sdk-oauth/session-registry.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +24 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.js +43 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +8 -2
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts +17 -0
- package/dist/core/extensions/builtin/compaction/emergency-prune.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/emergency-prune.js +64 -0
- package/dist/core/extensions/builtin/compaction/emergency-prune.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts +27 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.js +84 -0
- package/dist/core/extensions/builtin/compaction/extension-wiring.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/idle-retry.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/idle-retry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/idle-retry.js +1 -1
- package/dist/core/extensions/builtin/compaction/idle-retry.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/idle.d.ts +1 -0
- package/dist/core/extensions/builtin/compaction/idle.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/idle.js +13 -2
- package/dist/core/extensions/builtin/compaction/idle.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +152 -154
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts +1 -1
- package/dist/core/extensions/builtin/compaction/log.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/log.js +2 -0
- package/dist/core/extensions/builtin/compaction/log.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/model-selection.d.ts +14 -0
- package/dist/core/extensions/builtin/compaction/model-selection.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/model-selection.js +37 -0
- package/dist/core/extensions/builtin/compaction/model-selection.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts +30 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.js +74 -0
- package/dist/core/extensions/builtin/compaction/model-usability-budget.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts +9 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js +2 -0
- package/dist/core/extensions/builtin/compaction/openai-remote-dependencies.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +3 -6
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/orchestration.d.ts +46 -0
- package/dist/core/extensions/builtin/compaction/orchestration.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/orchestration.js +103 -0
- package/dist/core/extensions/builtin/compaction/orchestration.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/policy.d.ts +12 -2
- package/dist/core/extensions/builtin/compaction/policy.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/policy.js +52 -26
- package/dist/core/extensions/builtin/compaction/policy.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts +8 -0
- package/dist/core/extensions/builtin/compaction/speculation-lead.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculation-lead.js +17 -0
- package/dist/core/extensions/builtin/compaction/speculation-lead.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.d.ts +22 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.js +16 -0
- package/dist/core/extensions/builtin/compaction/speculative-job.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts +23 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.js +132 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +8 -13
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +21 -197
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts +24 -0
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.js +25 -0
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.d.ts +27 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.js +56 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.js.map +1 -0
- package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts +5 -0
- package/dist/core/extensions/builtin/hooks/trust-state-json.d.ts.map +1 -0
- package/dist/core/extensions/builtin/hooks/trust-state-json.js +76 -0
- package/dist/core/extensions/builtin/hooks/trust-state-json.js.map +1 -0
- package/dist/core/extensions/builtin/hooks/trust-storage.d.ts +7 -1
- package/dist/core/extensions/builtin/hooks/trust-storage.d.ts.map +1 -1
- package/dist/core/extensions/builtin/hooks/trust-storage.js +60 -8
- package/dist/core/extensions/builtin/hooks/trust-storage.js.map +1 -1
- package/dist/core/extensions/builtin/hooks/trust.d.ts +1 -2
- package/dist/core/extensions/builtin/hooks/trust.d.ts.map +1 -1
- package/dist/core/extensions/builtin/hooks/trust.js +1 -72
- package/dist/core/extensions/builtin/hooks/trust.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts +3 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.d.ts.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +108 -0
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/presets.js +11 -0
- package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
- package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.d.ts +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.js +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +11 -0
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.js +18 -2
- package/dist/core/extensions/builtin/terminal/runtime-session.js.map +1 -1
- package/dist/core/extensions/builtin/ttsr/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ttsr/index.js +4 -0
- package/dist/core/extensions/builtin/ttsr/index.js.map +1 -1
- package/dist/core/extensions/builtin/ttsr/manager.d.ts +2 -0
- package/dist/core/extensions/builtin/ttsr/manager.d.ts.map +1 -1
- package/dist/core/extensions/builtin/ttsr/manager.js +28 -1
- package/dist/core/extensions/builtin/ttsr/manager.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +5 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +7 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/retry-fallback/controller.d.ts +14 -0
- package/dist/core/retry-fallback/controller.d.ts.map +1 -1
- package/dist/core/retry-fallback/controller.js +33 -3
- package/dist/core/retry-fallback/controller.js.map +1 -1
- package/dist/core/retry-fallback/log.js +1 -1
- package/dist/core/retry-fallback/log.js.map +1 -1
- package/dist/core/retry-fallback/settings.d.ts.map +1 -1
- package/dist/core/retry-fallback/settings.js +1 -0
- package/dist/core/retry-fallback/settings.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +5 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-activity.d.ts +47 -0
- package/dist/core/session-activity.d.ts.map +1 -0
- package/dist/core/session-activity.js +58 -0
- package/dist/core/session-activity.js.map +1 -0
- package/dist/core/session-manager.d.ts +8 -12
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +118 -7
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-resident-store.d.ts +8 -1
- package/dist/core/session-resident-store.d.ts.map +1 -1
- package/dist/core/session-resident-store.js +12 -5
- package/dist/core/session-resident-store.js.map +1 -1
- package/dist/core/settings-manager.d.ts +8 -85
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +9 -17
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-public-types.d.ts +11 -0
- package/dist/core/settings-public-types.d.ts.map +1 -0
- package/dist/core/settings-public-types.js +2 -0
- package/dist/core/settings-public-types.js.map +1 -0
- package/dist/core/settings-shapes.d.ts +36 -0
- package/dist/core/settings-shapes.d.ts.map +1 -0
- package/dist/core/settings-shapes.js +2 -0
- package/dist/core/settings-shapes.js.map +1 -0
- package/dist/core/shared-host-policy.d.ts +6 -0
- package/dist/core/shared-host-policy.d.ts.map +1 -0
- package/dist/core/shared-host-policy.js +7 -0
- package/dist/core/shared-host-policy.js.map +1 -0
- package/dist/core/terminal-settings.d.ts +22 -0
- package/dist/core/terminal-settings.d.ts.map +1 -0
- package/dist/core/terminal-settings.js +2 -0
- package/dist/core/terminal-settings.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +4 -4
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +27 -11
- package/dist/main.js.map +1 -1
- package/dist/modes/app-server/daemon/process.d.ts +13 -2
- package/dist/modes/app-server/daemon/process.d.ts.map +1 -1
- package/dist/modes/app-server/daemon/process.js +58 -12
- package/dist/modes/app-server/daemon/process.js.map +1 -1
- package/dist/modes/app-server/daemon.js +65 -7
- package/dist/modes/app-server/daemon.js.map +1 -1
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts +84 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.js +435 -112
- package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +11 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +59 -6
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tips/catalog/ethos-tips.js +1 -1
- package/dist/modes/interactive/tips/catalog/ethos-tips.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts +12 -5
- package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
- package/dist/modes/rpc/connection-handler.js +180 -25
- package/dist/modes/rpc/connection-handler.js.map +1 -1
- package/dist/modes/rpc/custom-capability.d.ts +2 -0
- package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
- package/dist/modes/rpc/custom-capability.js +2 -0
- package/dist/modes/rpc/custom-capability.js.map +1 -1
- package/dist/modes/rpc/host-ensure.d.ts +17 -0
- package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
- package/dist/modes/rpc/host-ensure.js +150 -23
- package/dist/modes/rpc/host-ensure.js.map +1 -1
- package/dist/modes/rpc/host-lifecycle.d.ts +54 -0
- package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
- package/dist/modes/rpc/host-lifecycle.js +259 -69
- package/dist/modes/rpc/host-lifecycle.js.map +1 -1
- package/dist/modes/rpc/host-watchdog.d.ts +2 -2
- package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
- package/dist/modes/rpc/host-watchdog.js +89 -21
- package/dist/modes/rpc/host-watchdog.js.map +1 -1
- package/dist/modes/rpc/multi-session-host.d.ts +38 -0
- package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
- package/dist/modes/rpc/multi-session-host.js +149 -61
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/ownership-safe-lock.d.ts +14 -0
- package/dist/modes/rpc/ownership-safe-lock.d.ts.map +1 -0
- package/dist/modes/rpc/ownership-safe-lock.js +87 -0
- package/dist/modes/rpc/ownership-safe-lock.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +13 -2
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +46 -12
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +21 -3
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js +1 -0
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-binding.d.ts +2 -1
- package/dist/modes/rpc/session-binding.d.ts.map +1 -1
- package/dist/modes/rpc/session-binding.js +1 -0
- package/dist/modes/rpc/session-binding.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts +54 -1
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +180 -3
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +18 -0
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +88 -8
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts +11 -1
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +25 -0
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/dist/modes/rpc/socket-transport.d.ts +13 -0
- package/dist/modes/rpc/socket-transport.d.ts.map +1 -0
- package/dist/modes/rpc/socket-transport.js +92 -0
- package/dist/modes/rpc/socket-transport.js.map +1 -0
- package/dist/modes/rpc/widget-line-renderer.d.ts +17 -0
- package/dist/modes/rpc/widget-line-renderer.d.ts.map +1 -0
- package/dist/modes/rpc/widget-line-renderer.js +73 -0
- package/dist/modes/rpc/widget-line-renderer.js.map +1 -0
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js +11 -2
- package/dist/utils/fs-watch.js.map +1 -1
- package/docs/app-server.md +2 -2
- package/docs/containerization.md +2 -2
- package/docs/development.md +7 -7
- package/docs/extensions.md +5 -5
- package/docs/grok-neo.md +1 -1
- package/docs/index.md +1 -1
- package/docs/packages.md +2 -2
- package/docs/quickstart.md +4 -4
- package/docs/release-guide.md +21 -21
- package/docs/rpc.md +83 -6
- package/docs/sdk.md +1 -1
- package/docs/settings.md +4 -4
- package/docs/skills.md +2 -2
- package/docs/terminal-tools.md +1 -1
- package/docs/termux.md +1 -1
- package/docs/tui.md +1 -1
- package/examples/AGENTS.md +1 -1
- package/examples/sdk/README.md +1 -1
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +52 -0
- package/node_modules/@code-yeongyu/senpi-codemode/README.md +2 -2
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/extension/skill-contribution.ts +71 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/index.ts +3 -1
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/SKILL.md +44 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/breaking-changes.md +75 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/build.md +114 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/dev-tooling.md +34 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/http-networking.md +113 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/install.md +93 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/node-compat-platforms.md +36 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/performance.md +33 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/runtime-apis.md +156 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/security.md +52 -0
- package/node_modules/@code-yeongyu/senpi-codemode/src/skill/bun-1-4/references/test.md +103 -0
- package/node_modules/@earendil-works/pi-agent-core/README.md +3 -0
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/README.md +6 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +24 -7
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +7 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +316 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js +23 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-conversation-rotation.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts +24 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js +20 -2
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/anthropic.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/fireworks.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/groq.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/nvidia.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opengateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts +42 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js +34 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-operations.js.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts +8 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.js +51 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen-text.js.map +1 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts +45 -0
- package/node_modules/@earendil-works/pi-pty/dist/screen.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-pty/dist/screen.js +178 -55
- package/node_modules/@earendil-works/pi-pty/dist/screen.js.map +1 -1
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/README.md +6 -3
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/README.md +5 -4
- package/node_modules/@earendil-works/pi-tui/native/darwin/README.md +2 -2
- package/node_modules/@earendil-works/pi-tui/native/win32/README.md +2 -2
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -6,6 +6,7 @@ import type { ModelRegistry } from "../../../model-registry.ts";
|
|
|
6
6
|
import type { ReadonlySessionManager } from "../../../session-manager.ts";
|
|
7
7
|
import type { ApplyCompactionResult, ContextUsage, ProviderRequestPreparation } from "../../types.ts";
|
|
8
8
|
import { type MergedCompactionPromptVariant } from "./prompts.ts";
|
|
9
|
+
export { createEmergencyPruneLatch, type EmergencyPruneLatch, hardLimitEmergencyPrune, truncateContextMessages, } from "./emergency-prune.ts";
|
|
9
10
|
type CompactionProgressCallback = (delta: string) => void;
|
|
10
11
|
export interface SpeculativeCompactionContext {
|
|
11
12
|
model: Model<any> | undefined;
|
|
@@ -64,20 +65,15 @@ export declare class SummaryGenerationError extends Error {
|
|
|
64
65
|
readonly kind: "auth" | "empty-summary";
|
|
65
66
|
constructor(kind: "auth" | "empty-summary", message: string);
|
|
66
67
|
}
|
|
67
|
-
export declare function truncateContextMessages(messages: AgentMessage[]): AgentMessage[];
|
|
68
68
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
69
|
+
* Output budget for one summarization request. Adaptive-thinking models emit
|
|
70
|
+
* reasoning tokens before the summary text, so the legacy flat 8192 cap could
|
|
71
|
+
* be consumed entirely by thinking, ending the stream with zero text blocks.
|
|
72
|
+
* Grant generous headroom, clamped to what the model can actually emit and to
|
|
73
|
+
* half the context window: providers that enforce input + output <= window
|
|
74
|
+
* would otherwise reject the request for models advertising contextWindow ==
|
|
75
|
+
* maxTokens (every summarization request also carries conversation input).
|
|
72
76
|
*/
|
|
73
|
-
export interface EmergencyPruneLatch {
|
|
74
|
-
engaged: boolean;
|
|
75
|
-
}
|
|
76
|
-
export declare function createEmergencyPruneLatch(): EmergencyPruneLatch;
|
|
77
|
-
export declare function hardLimitEmergencyPrune(messages: AgentMessage[], contextWindow: number, latch?: EmergencyPruneLatch): {
|
|
78
|
-
messages: AgentMessage[];
|
|
79
|
-
needsAggressiveCompaction: boolean;
|
|
80
|
-
};
|
|
81
77
|
export declare function getPromptVariant(options: {
|
|
82
78
|
reason: string;
|
|
83
79
|
preparation: {
|
|
@@ -102,5 +98,4 @@ export declare function createSpeculativeCompactionSnapshot(context: Speculative
|
|
|
102
98
|
export declare function runExtensionCompaction(context: SpeculativeCompactionContext, snapshot: SpeculativeCompactionSnapshot, signal?: AbortSignal, onProgress?: CompactionProgressCallback): Promise<CompactionResult | undefined>;
|
|
103
99
|
export declare function applyGeneratedCompaction(context: SpeculativeCompactionContext, snapshot: SpeculativeCompactionSnapshot | undefined, getCurrentGeneration: () => number, compaction: CompactionResult | undefined, signal?: AbortSignal): Promise<SpeculativeCompactionResult>;
|
|
104
100
|
export declare function applySpeculativeCompaction(context: SpeculativeCompactionContext, snapshot: SpeculativeCompactionSnapshot | undefined, getCurrentGeneration: () => number, generate: () => Promise<CompactionResult | undefined>): Promise<SpeculativeCompactionResult>;
|
|
105
|
-
export {};
|
|
106
101
|
//# sourceMappingURL=speculative.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"speculative.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculative.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,
|
|
1
|
+
{"version":3,"file":"speculative.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculative.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,28 +1,23 @@
|
|
|
1
|
-
import { hasCredentialHeaders, isContextOverflow, isRetryableAssistantError, isRetryableErrorMessage, retryTransientCall,
|
|
2
|
-
import { stream } from "@earendil-works/pi-ai/compat";
|
|
1
|
+
import { hasCredentialHeaders, isContextOverflow, isRetryableAssistantError, isRetryableErrorMessage, retryTransientCall, } from "@earendil-works/pi-ai";
|
|
3
2
|
import { DEFAULT_COMPACTION_SETTINGS, estimateContextTokens, prepareCompaction, } from "../../../compaction/index.js";
|
|
4
|
-
import {
|
|
3
|
+
import { StreamDurationBudgetError, StreamIdleTimeoutError } from "../../../compaction/stream-watchdog.js";
|
|
5
4
|
import { createWarmAnchorSnapshot, isWarmSummaryAnchorValid, } from "../../../compaction/warm-anchor.js";
|
|
6
5
|
import { convertToLlm } from "../../../messages.js";
|
|
7
|
-
import {
|
|
6
|
+
import { pruneToolResults } from "./emergency-prune.js";
|
|
7
|
+
import { allowOverflowRetry, boundSummarizationInput, SUMMARIZATION_INPUT_BUDGET_RATIO, SummarizationOverflowExhaustedError, shrinkSummarizationInputForOverflowRetry, } from "./overflow-retry.js";
|
|
8
8
|
import { computeEffectiveKeepRecentTokens, computeEffectiveThreshold } from "./policy.js";
|
|
9
9
|
import { buildPrompt } from "./prompts.js";
|
|
10
|
-
import {
|
|
10
|
+
import { generateSummaryMessage, getSummaryText, isAssistantMessage } from "./speculative-summary.js";
|
|
11
11
|
import { allowSummarizationRetry, DEFAULT_SUMMARIZATION_RETRY_POLICY } from "./summarization-retry.js";
|
|
12
|
-
import { normalizeSummarizationTurnOrder } from "./summarization-turn-order.js";
|
|
13
12
|
import { extractTaskIntent, resolveInheritedTaskIntent } from "./task-intent.js";
|
|
14
|
-
|
|
13
|
+
export { createEmergencyPruneLatch, hardLimitEmergencyPrune, truncateContextMessages, } from "./emergency-prune.js";
|
|
15
14
|
import { computeStructuralYield } from "./yield.js";
|
|
16
15
|
const DEFAULT_CONTEXT_WINDOW = 200_000;
|
|
17
|
-
const EMERGENCY_CONTEXT_TARGET_RATIO = 0.95;
|
|
18
16
|
// Hysteresis: the emergency prune engages at EMERGENCY_CONTEXT_TARGET_RATIO but only
|
|
19
17
|
// releases once the context falls below this lower ratio. A single threshold makes a
|
|
20
18
|
// session parked near the limit alternate between the pruned and un-pruned history on
|
|
21
19
|
// consecutive requests; because pruning rewrites old tool results, every alternation
|
|
22
20
|
// invalidates the provider prompt-cache prefix and re-bills the whole conversation.
|
|
23
|
-
const EMERGENCY_CONTEXT_RELEASE_RATIO = 0.85;
|
|
24
|
-
const SUMMARY_TOKEN_HEADROOM = 32_768;
|
|
25
|
-
const SUMMARY_CONTEXT_WINDOW_RESERVE_RATIO = 0.5;
|
|
26
21
|
const SUMMARY_SCHEMA = "senpi.compaction.summary.v1";
|
|
27
22
|
function approxTokens(text) {
|
|
28
23
|
return Math.ceil(text.length / 4);
|
|
@@ -40,7 +35,8 @@ const UPSTREAM_STREAM_TRUNCATED_PATTERN = /(?:^|[^A-Za-z0-9_])upstream_stream_tr
|
|
|
40
35
|
* Only failures with no cheaper recovery earn another billed request.
|
|
41
36
|
*
|
|
42
37
|
* Every class that `classifyRequiredCompactionFallbackFailure` recognizes
|
|
43
|
-
* (watchdog timeouts, `upstream-stream-truncated`, overflow exhaustion
|
|
38
|
+
* (watchdog timeouts, `upstream-stream-truncated`, overflow exhaustion,
|
|
39
|
+
* empty-summary generation failures) already
|
|
44
40
|
* has a deterministic zero-LLM recovery, and context overflow is answered by
|
|
45
41
|
* shrinking the input in the surrounding loop - replaying those would pay for a
|
|
46
42
|
* summarization the fallback can rebuild for free. The classes checked here are
|
|
@@ -81,187 +77,6 @@ export class SummaryGenerationError extends Error {
|
|
|
81
77
|
* would otherwise reject the request for models advertising contextWindow ==
|
|
82
78
|
* maxTokens (every summarization request also carries conversation input).
|
|
83
79
|
*/
|
|
84
|
-
function summaryMaxTokens(model, contextWindow) {
|
|
85
|
-
const headroom = model.maxTokens > 0 ? Math.min(SUMMARY_TOKEN_HEADROOM, model.maxTokens) : SUMMARY_TOKEN_HEADROOM;
|
|
86
|
-
if (contextWindow > 0) {
|
|
87
|
-
return Math.min(headroom, Math.floor(contextWindow * SUMMARY_CONTEXT_WINDOW_RESERVE_RATIO));
|
|
88
|
-
}
|
|
89
|
-
return headroom;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Reasoning override for summarization requests. Compaction must be fast: a
|
|
93
|
-
* summarization request that inherits the provider's default reasoning mode
|
|
94
|
-
* burns its latency (and output budget) on invisible thinking before emitting
|
|
95
|
-
* the summary. Disable or minimize reasoning per wire family; adapters ignore
|
|
96
|
-
* options their provider does not support. Mirrors how OpenAI Codex keeps its
|
|
97
|
-
* compaction turn cheap.
|
|
98
|
-
*/
|
|
99
|
-
function summarizationReasoningOptions(model) {
|
|
100
|
-
if (!model.reasoning)
|
|
101
|
-
return {};
|
|
102
|
-
if (model.api === "anthropic-messages")
|
|
103
|
-
return { thinkingEnabled: false };
|
|
104
|
-
const reasoningEffort = ["low", "medium", "high"].find((level) => model.thinkingLevelMap?.[level] !== null);
|
|
105
|
-
if (!reasoningEffort)
|
|
106
|
-
return {};
|
|
107
|
-
switch (model.api) {
|
|
108
|
-
case "openai-responses":
|
|
109
|
-
case "openai-codex-responses":
|
|
110
|
-
case "azure-openai-responses":
|
|
111
|
-
return { reasoningEffort, reasoningSummary: null };
|
|
112
|
-
case "openai-completions":
|
|
113
|
-
return { reasoningEffort };
|
|
114
|
-
default:
|
|
115
|
-
return {};
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
function getSummaryText(message) {
|
|
119
|
-
const content = Array.isArray(message.content)
|
|
120
|
-
? message.content
|
|
121
|
-
: [{ type: "text", text: message.content }];
|
|
122
|
-
return content
|
|
123
|
-
.filter((content) => content.type === "text")
|
|
124
|
-
.map((content) => content.text)
|
|
125
|
-
.join("\n")
|
|
126
|
-
.trim();
|
|
127
|
-
}
|
|
128
|
-
function isAssistantMessage(message) {
|
|
129
|
-
return message.role === "assistant" && "stopReason" in message;
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Providers registered through `pi.registerProvider()` (claude-sdk-oauth, Kiro, any
|
|
133
|
-
* extension provider) exist only in Senpi's ModelRuntime, never in compat's builtin
|
|
134
|
-
* api-registry, which rejects their api id outright. Dispatch through the runtime
|
|
135
|
-
* whenever it is reachable and keep compat for contexts constructed without a registry.
|
|
136
|
-
*/
|
|
137
|
-
function summarizationStream(context, model, requestContext, options) {
|
|
138
|
-
const runtime = context.modelRegistry?.modelRuntime;
|
|
139
|
-
return runtime ? runtime.stream(model, requestContext, options) : stream(model, requestContext, options);
|
|
140
|
-
}
|
|
141
|
-
async function generateSummaryMessage(options) {
|
|
142
|
-
// Send the conversation as native LLM messages with the summarization
|
|
143
|
-
// instruction as a trailing user message, mirroring normal agent traffic.
|
|
144
|
-
// A single serialized `<conversation>` text dump of a large session is
|
|
145
|
-
// deterministically refused by Anthropic's anti-distillation classifier
|
|
146
|
-
// ("reverse engineering or duplicating model outputs"), while the same
|
|
147
|
-
// content as native blocks with the agent's system prompt and tools passes.
|
|
148
|
-
// Request-local controller: the idle watchdog must be able to tear down a
|
|
149
|
-
// stalled summarization request without aborting the caller's own signal.
|
|
150
|
-
const requestController = new AbortController();
|
|
151
|
-
const onCallerAbort = () => requestController.abort(options.signal?.reason);
|
|
152
|
-
if (options.signal) {
|
|
153
|
-
if (options.signal.aborted)
|
|
154
|
-
onCallerAbort();
|
|
155
|
-
else
|
|
156
|
-
options.signal.addEventListener("abort", onCallerAbort, { once: true });
|
|
157
|
-
}
|
|
158
|
-
try {
|
|
159
|
-
const requestMessages = [
|
|
160
|
-
...options.messages,
|
|
161
|
-
{
|
|
162
|
-
role: "user",
|
|
163
|
-
content: [{ type: "text", text: options.prompt.user }],
|
|
164
|
-
timestamp: Date.now(),
|
|
165
|
-
},
|
|
166
|
-
];
|
|
167
|
-
const providerRequest = await options.context.prepareProviderRequest?.(requestMessages);
|
|
168
|
-
const requestContext = {
|
|
169
|
-
systemPrompt: options.snapshot.systemPrompt ?? options.prompt.system,
|
|
170
|
-
messages: repairOrphanedToolResults(normalizeSummarizationTurnOrder(convertToLlm(providerRequest?.messages ?? requestMessages))),
|
|
171
|
-
...(options.snapshot.tools && options.snapshot.tools.length > 0 ? { tools: options.snapshot.tools } : {}),
|
|
172
|
-
};
|
|
173
|
-
const headers = providerRequest
|
|
174
|
-
? await providerRequest.transformHeaders(options.auth.headers ?? {})
|
|
175
|
-
: options.auth.headers;
|
|
176
|
-
const responseStream = summarizationStream(options.context, options.snapshot.model, requestContext, {
|
|
177
|
-
apiKey: options.auth.apiKey,
|
|
178
|
-
headers,
|
|
179
|
-
extraBody: options.auth.extraBody,
|
|
180
|
-
onPayload: async (payload, model) => {
|
|
181
|
-
const sanitized = model.api === "anthropic-messages" ? sanitizeAnthropicPayload(payload) : payload;
|
|
182
|
-
return providerRequest ? await providerRequest.transformPayload(sanitized) : sanitized;
|
|
183
|
-
},
|
|
184
|
-
maxTokens: summaryMaxTokens(options.snapshot.model, options.snapshot.contextWindow),
|
|
185
|
-
signal: requestController.signal,
|
|
186
|
-
...summarizationReasoningOptions(options.snapshot.model),
|
|
187
|
-
});
|
|
188
|
-
await consumeStreamWithIdleTimeout(responseStream, {
|
|
189
|
-
idleTimeoutMs: DEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS,
|
|
190
|
-
maxDurationMs: DEFAULT_SUMMARIZATION_MAX_DURATION_MS,
|
|
191
|
-
abort: () => requestController.abort(),
|
|
192
|
-
signal: options.signal,
|
|
193
|
-
onEvent: (event) => {
|
|
194
|
-
if (event.type === "text_delta" && event.delta) {
|
|
195
|
-
options.onProgress?.(event.delta);
|
|
196
|
-
}
|
|
197
|
-
},
|
|
198
|
-
});
|
|
199
|
-
return await responseStream.result();
|
|
200
|
-
}
|
|
201
|
-
finally {
|
|
202
|
-
if (options.signal)
|
|
203
|
-
options.signal.removeEventListener("abort", onCallerAbort);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
function pruneToolResults(messages, contextWindow, budgetRatio) {
|
|
207
|
-
const toolResults = messages
|
|
208
|
-
.filter((message) => message.role === "toolResult")
|
|
209
|
-
.map((message) => ({ content: message.content, details: undefined }));
|
|
210
|
-
if (toolResults.length === 0)
|
|
211
|
-
return messages;
|
|
212
|
-
const prunedResults = truncation.prePruneToolOutputsToBudget(toolResults, contextWindow * budgetRatio);
|
|
213
|
-
let resultIndex = 0;
|
|
214
|
-
return messages.map((message) => {
|
|
215
|
-
if (message.role !== "toolResult")
|
|
216
|
-
return message;
|
|
217
|
-
const pruned = prunedResults[resultIndex];
|
|
218
|
-
resultIndex++;
|
|
219
|
-
return pruned ? { ...message, content: pruned.content } : message;
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
export function truncateContextMessages(messages) {
|
|
223
|
-
const toolResults = messages
|
|
224
|
-
.filter((message) => message.role === "toolResult")
|
|
225
|
-
.map((message) => ({ content: message.content, details: undefined }));
|
|
226
|
-
if (toolResults.length === 0)
|
|
227
|
-
return messages;
|
|
228
|
-
const truncatedResults = truncation.truncateOversizedToolResults(toolResults);
|
|
229
|
-
let resultIndex = 0;
|
|
230
|
-
return messages.map((message) => {
|
|
231
|
-
if (message.role !== "toolResult")
|
|
232
|
-
return message;
|
|
233
|
-
const truncated = truncatedResults[resultIndex];
|
|
234
|
-
resultIndex++;
|
|
235
|
-
return truncated ? { ...message, content: truncated.content } : message;
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
export function createEmergencyPruneLatch() {
|
|
239
|
-
return { engaged: false };
|
|
240
|
-
}
|
|
241
|
-
export function hardLimitEmergencyPrune(messages, contextWindow, latch) {
|
|
242
|
-
const targetTokens = Math.floor(contextWindow * EMERGENCY_CONTEXT_TARGET_RATIO);
|
|
243
|
-
const releaseTokens = Math.floor(contextWindow * EMERGENCY_CONTEXT_RELEASE_RATIO);
|
|
244
|
-
const totalTokens = estimateTotalTokens(messages);
|
|
245
|
-
// Without a latch this keeps the historical single-threshold behaviour.
|
|
246
|
-
const engaged = latch
|
|
247
|
-
? latch.engaged
|
|
248
|
-
? totalTokens > releaseTokens
|
|
249
|
-
: totalTokens > targetTokens
|
|
250
|
-
: totalTokens > targetTokens;
|
|
251
|
-
if (latch)
|
|
252
|
-
latch.engaged = engaged;
|
|
253
|
-
if (!engaged) {
|
|
254
|
-
return { messages, needsAggressiveCompaction: false };
|
|
255
|
-
}
|
|
256
|
-
const noLlmPruned = truncateContextMessages(pruneToolResults(messages, contextWindow, SUMMARIZATION_INPUT_BUDGET_RATIO));
|
|
257
|
-
if (estimateTotalTokens(noLlmPruned) <= targetTokens) {
|
|
258
|
-
return { messages: noLlmPruned, needsAggressiveCompaction: false };
|
|
259
|
-
}
|
|
260
|
-
return {
|
|
261
|
-
messages: pruneOldMessagesToBudget(noLlmPruned, targetTokens),
|
|
262
|
-
needsAggressiveCompaction: true,
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
80
|
export function getPromptVariant(options) {
|
|
266
81
|
if (options.reason === "branch")
|
|
267
82
|
return "branch";
|
|
@@ -287,17 +102,14 @@ export function createSpeculativeCompactionSnapshot(context, options) {
|
|
|
287
102
|
if (!preparation)
|
|
288
103
|
return undefined;
|
|
289
104
|
return {
|
|
290
|
-
|
|
105
|
+
...options,
|
|
291
106
|
expectedRevision,
|
|
292
107
|
model,
|
|
293
108
|
contextWindow,
|
|
294
109
|
preparation,
|
|
295
110
|
branchEntries,
|
|
296
111
|
promptVariant: getPromptVariant({ reason: "extension", preparation }),
|
|
297
|
-
...(options.origin ? { origin: options.origin } : {}),
|
|
298
|
-
customInstructions: options.customInstructions,
|
|
299
112
|
systemPrompt: context.getSystemPrompt?.(),
|
|
300
|
-
tools: options.tools,
|
|
301
113
|
};
|
|
302
114
|
}
|
|
303
115
|
/**
|
|
@@ -335,6 +147,8 @@ export async function runExtensionCompaction(context, snapshot, signal, onProgre
|
|
|
335
147
|
let messages = boundSummarizationInput(pruneToolResults([...requestSnapshot.preparation.messagesToSummarize, ...requestSnapshot.preparation.turnPrefixMessages], requestSnapshot.contextWindow, SUMMARIZATION_INPUT_BUDGET_RATIO), requestSnapshot.contextWindow, promptTokens);
|
|
336
148
|
const overflowRetryStartMs = Date.now();
|
|
337
149
|
let overflowAttempts = 0;
|
|
150
|
+
const summarizationToolsOffered = (requestSnapshot.tools?.length ?? 0) > 0;
|
|
151
|
+
let toolUseRetrySpent = false;
|
|
338
152
|
while (true) {
|
|
339
153
|
if (signal?.aborted)
|
|
340
154
|
return undefined;
|
|
@@ -355,6 +169,7 @@ export async function runExtensionCompaction(context, snapshot, signal, onProgre
|
|
|
355
169
|
response = await retryTransientCall(async () => {
|
|
356
170
|
const attempt = await generateSummaryMessage({
|
|
357
171
|
context,
|
|
172
|
+
forbidToolCalls: toolUseRetrySpent,
|
|
358
173
|
messages: currentMessages,
|
|
359
174
|
onProgress,
|
|
360
175
|
prompt,
|
|
@@ -412,6 +227,15 @@ export async function runExtensionCompaction(context, snapshot, signal, onProgre
|
|
|
412
227
|
const summary = getSummaryText(response);
|
|
413
228
|
if (!summary) {
|
|
414
229
|
const stopReason = isAssistantMessage(response) ? response.stopReason : "unknown";
|
|
230
|
+
// A summarizer can hijack the forwarded agent tools and answer with a
|
|
231
|
+
// bare tool call (observed on openai-codex gpt-5.6-sol, 2026-08-31),
|
|
232
|
+
// which used to surface as a terminal empty-summary failure. Spend one
|
|
233
|
+
// retry with tool calling forbidden; the tools stay in the request
|
|
234
|
+
// because Anthropic rejects tool_use history without the tools param.
|
|
235
|
+
if (stopReason === "toolUse" && summarizationToolsOffered && !toolUseRetrySpent) {
|
|
236
|
+
toolUseRetrySpent = true;
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
415
239
|
throw new SummaryGenerationError("empty-summary", `summarization response contained no text (stopReason: ${stopReason})`);
|
|
416
240
|
}
|
|
417
241
|
// Informational only: the core rejects an applied compaction that would
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"speculative.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculative.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype AssistantMessage,\n\ttype AssistantMessageEventStream,\n\ttype Context,\n\thasCredentialHeaders,\n\tisContextOverflow,\n\tisRetryableAssistantError,\n\tisRetryableErrorMessage,\n\ttype Message,\n\ttype Model,\n\ttype ProviderHeaders,\n\tretryTransientCall,\n\ttype StreamOptions,\n\tsanitizeAnthropicToolPairs as sanitizeAnthropicPayload,\n\ttype TextContent,\n\ttype Tool,\n} from \"@earendil-works/pi-ai\";\nimport { stream } from \"@earendil-works/pi-ai/compat\";\nimport {\n\ttype CompactionPreparation,\n\ttype CompactionResult,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\tprepareCompaction,\n} from \"../../../compaction/index.ts\";\nimport {\n\tconsumeStreamWithIdleTimeout,\n\tDEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS,\n\tDEFAULT_SUMMARIZATION_MAX_DURATION_MS,\n\tStreamDurationBudgetError,\n\tStreamIdleTimeoutError,\n} from \"../../../compaction/stream-watchdog.ts\";\nimport {\n\tcreateWarmAnchorSnapshot,\n\tisWarmSummaryAnchorValid,\n\ttype WarmAnchorSnapshot,\n} from \"../../../compaction/warm-anchor.ts\";\nimport { convertToLlm } from \"../../../messages.ts\";\nimport type { ModelRegistry } from \"../../../model-registry.ts\";\nimport type { ReadonlySessionManager } from \"../../../session-manager.ts\";\nimport type { ApplyCompactionResult, ContextUsage, ProviderRequestPreparation } from \"../../types.ts\";\nimport {\n\tallowOverflowRetry,\n\tboundSummarizationInput,\n\testimateTotalTokens,\n\tpruneOldMessagesToBudget,\n\tSUMMARIZATION_INPUT_BUDGET_RATIO,\n\tSummarizationOverflowExhaustedError,\n\tshrinkSummarizationInputForOverflowRetry,\n} from \"./overflow-retry.ts\";\nimport { computeEffectiveKeepRecentTokens, computeEffectiveThreshold } from \"./policy.ts\";\nimport { buildPrompt, type MergedCompactionPromptVariant } from \"./prompts.ts\";\nimport { repairOrphanedToolResults } from \"./repair-tool-pairs.ts\";\nimport { allowSummarizationRetry, DEFAULT_SUMMARIZATION_RETRY_POLICY } from \"./summarization-retry.ts\";\nimport { normalizeSummarizationTurnOrder } from \"./summarization-turn-order.ts\";\nimport { extractTaskIntent, resolveInheritedTaskIntent } from \"./task-intent.ts\";\nimport * as truncation from \"./tool-truncation.ts\";\nimport { computeStructuralYield } from \"./yield.ts\";\n\nconst DEFAULT_CONTEXT_WINDOW = 200_000;\nconst EMERGENCY_CONTEXT_TARGET_RATIO = 0.95;\n// Hysteresis: the emergency prune engages at EMERGENCY_CONTEXT_TARGET_RATIO but only\n// releases once the context falls below this lower ratio. A single threshold makes a\n// session parked near the limit alternate between the pruned and un-pruned history on\n// consecutive requests; because pruning rewrites old tool results, every alternation\n// invalidates the provider prompt-cache prefix and re-bills the whole conversation.\nconst EMERGENCY_CONTEXT_RELEASE_RATIO = 0.85;\nconst SUMMARY_TOKEN_HEADROOM = 32_768;\nconst SUMMARY_CONTEXT_WINDOW_RESERVE_RATIO = 0.5;\nconst SUMMARY_SCHEMA = \"senpi.compaction.summary.v1\";\ntype CompactionProgressCallback = (delta: string) => void;\n\nexport interface SpeculativeCompactionContext {\n\tmodel: Model<any> | undefined;\n\tsessionManager: ReadonlySessionManager;\n\tmodelRegistry?: ModelRegistry;\n\tgetContextUsage(): ContextUsage | undefined;\n\tgetCompactionSettings?(): CompactionPreparation[\"settings\"];\n\tgetMessageRevision(): number;\n\tgetSystemPrompt?(): string;\n\tprepareProviderRequest?(messages: AgentMessage[]): Promise<ProviderRequestPreparation>;\n\tisIdle?(): boolean;\n\tapplyCompaction(\n\t\tprecomputed: CompactionResult,\n\t\toptions: {\n\t\t\treason: \"extension\";\n\t\t\texpectedRevision?: number;\n\t\t\texpectedWarmAnchor?: WarmAnchorSnapshot;\n\t\t\tsignal?: AbortSignal;\n\t\t},\n\t): Promise<ApplyCompactionResult>;\n}\n\nexport interface SpeculativeCompactionSnapshot {\n\tgeneration: number;\n\texpectedRevision: number;\n\tmodel: Model<any>;\n\tcontextWindow: number;\n\tpreparation: CompactionPreparation;\n\tbranchEntries?: ReturnType<ReadonlySessionManager[\"getBranch\"]>;\n\tpromptVariant: MergedCompactionPromptVariant;\n\torigin?: \"speculative\" | \"blocking\" | \"core-route\";\n\tcustomInstructions?: string;\n\t/** Agent system prompt; used to make the summarization request look like normal agent traffic. */\n\tsystemPrompt?: string;\n\t/** Agent tool definitions; forwarded so the request shape matches normal agent traffic. */\n\ttools?: Tool[];\n}\n\nexport type SpeculativeCompactionResult = ApplyCompactionResult | { applied: false; reason: \"unavailable\" | \"failed\" };\n\nfunction approxTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\n/**\n * Summary-generation failure with a user-facing diagnosis. Distinct from a\n * user abort (which resolves `undefined`): callers surface `message` on the\n * manual route and degrade to \"unavailable\" on automatic routes.\n */\n/**\n * Provider `error` stop during summarization, carrying the metadata-aware\n * transient classification from the full assistant message. A refusal whose\n * text happens to look retryable must still surface loudly; the message\n * string alone cannot encode that.\n */\nexport type SummaryRequestFailureKind = \"upstream-stream-truncated\";\n\nexport class SummaryRequestError extends Error {\n\treadonly transient: boolean;\n\treadonly failureKind?: SummaryRequestFailureKind;\n\n\tconstructor(message: string, transient: boolean, failureKind?: SummaryRequestFailureKind) {\n\t\tsuper(message);\n\t\tthis.name = \"SummaryRequestError\";\n\t\tthis.transient = transient;\n\t\tthis.failureKind = failureKind;\n\t}\n}\n\nconst UPSTREAM_STREAM_TRUNCATED_PATTERN = /(?:^|[^A-Za-z0-9_])upstream_stream_truncated(?:[^A-Za-z0-9_]|$)/;\n\n/**\n * Only failures with no cheaper recovery earn another billed request.\n *\n * Every class that `classifyRequiredCompactionFallbackFailure` recognizes\n * (watchdog timeouts, `upstream-stream-truncated`, overflow exhaustion) already\n * has a deterministic zero-LLM recovery, and context overflow is answered by\n * shrinking the input in the surrounding loop - replaying those would pay for a\n * summarization the fallback can rebuild for free. The classes checked here are\n * mirrored from that classifier rather than imported, because\n * `deterministic-fallback.ts` imports this module.\n */\nfunction isRetryableSummaryAttempt(error: unknown): boolean {\n\tif (error instanceof StreamDurationBudgetError || error instanceof StreamIdleTimeoutError) return false;\n\tif (error instanceof SummarizationOverflowExhaustedError) return false;\n\tif (error instanceof SummaryGenerationError) return false;\n\tif (error instanceof SummaryRequestError) return error.failureKind === undefined && error.transient;\n\tif (error instanceof Error) return isRetryableErrorMessage(error.message);\n\treturn false;\n}\n\nfunction summaryRequestFailureKind(response: AssistantMessage): SummaryRequestFailureKind | undefined {\n\tif (response.stopDetails?.type === \"refusal\" || response.stopDetails?.type === \"sensitive\") return undefined;\n\treturn UPSTREAM_STREAM_TRUNCATED_PATTERN.test(response.errorMessage ?? \"\") ? \"upstream-stream-truncated\" : undefined;\n}\n\nexport class SummaryGenerationError extends Error {\n\treadonly kind: \"auth\" | \"empty-summary\";\n\n\tconstructor(kind: \"auth\" | \"empty-summary\", message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"SummaryGenerationError\";\n\t\tthis.kind = kind;\n\t}\n}\n\n/**\n * Output budget for one summarization request. Adaptive-thinking models emit\n * reasoning tokens before the summary text, so the legacy flat 8192 cap could\n * be consumed entirely by thinking, ending the stream with zero text blocks.\n * Grant generous headroom, clamped to what the model can actually emit and to\n * half the context window: providers that enforce input + output <= window\n * would otherwise reject the request for models advertising contextWindow ==\n * maxTokens (every summarization request also carries conversation input).\n */\nfunction summaryMaxTokens(model: Model<any>, contextWindow: number): number {\n\tconst headroom = model.maxTokens > 0 ? Math.min(SUMMARY_TOKEN_HEADROOM, model.maxTokens) : SUMMARY_TOKEN_HEADROOM;\n\tif (contextWindow > 0) {\n\t\treturn Math.min(headroom, Math.floor(contextWindow * SUMMARY_CONTEXT_WINDOW_RESERVE_RATIO));\n\t}\n\treturn headroom;\n}\n\n/**\n * Reasoning override for summarization requests. Compaction must be fast: a\n * summarization request that inherits the provider's default reasoning mode\n * burns its latency (and output budget) on invisible thinking before emitting\n * the summary. Disable or minimize reasoning per wire family; adapters ignore\n * options their provider does not support. Mirrors how OpenAI Codex keeps its\n * compaction turn cheap.\n */\nfunction summarizationReasoningOptions(model: Model<any>): Record<string, unknown> {\n\tif (!model.reasoning) return {};\n\tif (model.api === \"anthropic-messages\") return { thinkingEnabled: false };\n\tconst reasoningEffort = ([\"low\", \"medium\", \"high\"] as const).find(\n\t\t(level) => model.thinkingLevelMap?.[level] !== null,\n\t);\n\tif (!reasoningEffort) return {};\n\tswitch (model.api) {\n\t\tcase \"openai-responses\":\n\t\tcase \"openai-codex-responses\":\n\t\tcase \"azure-openai-responses\":\n\t\t\treturn { reasoningEffort, reasoningSummary: null };\n\t\tcase \"openai-completions\":\n\t\t\treturn { reasoningEffort };\n\t\tdefault:\n\t\t\treturn {};\n\t}\n}\n\nfunction getSummaryText(message: Message): string {\n\tconst content = Array.isArray(message.content)\n\t\t? message.content\n\t\t: [{ type: \"text\" as const, text: message.content }];\n\treturn content\n\t\t.filter((content): content is TextContent => content.type === \"text\")\n\t\t.map((content) => content.text)\n\t\t.join(\"\\n\")\n\t\t.trim();\n}\n\nfunction isAssistantMessage(message: Message): message is AssistantMessage {\n\treturn message.role === \"assistant\" && \"stopReason\" in message;\n}\n\n/**\n * Providers registered through `pi.registerProvider()` (claude-sdk-oauth, Kiro, any\n * extension provider) exist only in Senpi's ModelRuntime, never in compat's builtin\n * api-registry, which rejects their api id outright. Dispatch through the runtime\n * whenever it is reachable and keep compat for contexts constructed without a registry.\n */\nfunction summarizationStream(\n\tcontext: SpeculativeCompactionContext,\n\tmodel: Model<any>,\n\trequestContext: Context,\n\toptions: StreamOptions & Record<string, unknown>,\n): AssistantMessageEventStream {\n\tconst runtime = context.modelRegistry?.modelRuntime;\n\treturn runtime ? runtime.stream(model, requestContext, options) : stream(model, requestContext, options);\n}\n\nasync function generateSummaryMessage(options: {\n\tcontext: SpeculativeCompactionContext;\n\tmessages: AgentMessage[];\n\tonProgress?: CompactionProgressCallback;\n\tprompt: ReturnType<typeof buildPrompt>;\n\tsignal?: AbortSignal;\n\tsnapshot: SpeculativeCompactionSnapshot;\n\tauth: {\n\t\tapiKey?: string;\n\t\theaders?: ProviderHeaders;\n\t\textraBody?: Record<string, unknown>;\n\t};\n}): Promise<Message | undefined> {\n\t// Send the conversation as native LLM messages with the summarization\n\t// instruction as a trailing user message, mirroring normal agent traffic.\n\t// A single serialized `<conversation>` text dump of a large session is\n\t// deterministically refused by Anthropic's anti-distillation classifier\n\t// (\"reverse engineering or duplicating model outputs\"), while the same\n\t// content as native blocks with the agent's system prompt and tools passes.\n\t// Request-local controller: the idle watchdog must be able to tear down a\n\t// stalled summarization request without aborting the caller's own signal.\n\tconst requestController = new AbortController();\n\tconst onCallerAbort = () => requestController.abort(options.signal?.reason);\n\tif (options.signal) {\n\t\tif (options.signal.aborted) onCallerAbort();\n\t\telse options.signal.addEventListener(\"abort\", onCallerAbort, { once: true });\n\t}\n\ttry {\n\t\tconst requestMessages: AgentMessage[] = [\n\t\t\t...options.messages,\n\t\t\t{\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: [{ type: \"text\", text: options.prompt.user }],\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t},\n\t\t];\n\t\tconst providerRequest = await options.context.prepareProviderRequest?.(requestMessages);\n\t\tconst requestContext = {\n\t\t\tsystemPrompt: options.snapshot.systemPrompt ?? options.prompt.system,\n\t\t\tmessages: repairOrphanedToolResults(\n\t\t\t\tnormalizeSummarizationTurnOrder(convertToLlm(providerRequest?.messages ?? requestMessages)),\n\t\t\t),\n\t\t\t...(options.snapshot.tools && options.snapshot.tools.length > 0 ? { tools: options.snapshot.tools } : {}),\n\t\t};\n\t\tconst headers = providerRequest\n\t\t\t? await providerRequest.transformHeaders(options.auth.headers ?? {})\n\t\t\t: options.auth.headers;\n\t\tconst responseStream = summarizationStream(options.context, options.snapshot.model, requestContext, {\n\t\t\tapiKey: options.auth.apiKey,\n\t\t\theaders,\n\t\t\textraBody: options.auth.extraBody,\n\t\t\tonPayload: async (payload, model) => {\n\t\t\t\tconst sanitized = model.api === \"anthropic-messages\" ? sanitizeAnthropicPayload(payload) : payload;\n\t\t\t\treturn providerRequest ? await providerRequest.transformPayload(sanitized) : sanitized;\n\t\t\t},\n\t\t\tmaxTokens: summaryMaxTokens(options.snapshot.model, options.snapshot.contextWindow),\n\t\t\tsignal: requestController.signal,\n\t\t\t...summarizationReasoningOptions(options.snapshot.model),\n\t\t});\n\t\tawait consumeStreamWithIdleTimeout(responseStream, {\n\t\t\tidleTimeoutMs: DEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS,\n\t\t\tmaxDurationMs: DEFAULT_SUMMARIZATION_MAX_DURATION_MS,\n\t\t\tabort: () => requestController.abort(),\n\t\t\tsignal: options.signal,\n\t\t\tonEvent: (event) => {\n\t\t\t\tif (event.type === \"text_delta\" && event.delta) {\n\t\t\t\t\toptions.onProgress?.(event.delta);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\treturn await responseStream.result();\n\t} finally {\n\t\tif (options.signal) options.signal.removeEventListener(\"abort\", onCallerAbort);\n\t}\n}\n\nfunction pruneToolResults(messages: AgentMessage[], contextWindow: number, budgetRatio: number): AgentMessage[] {\n\tconst toolResults = messages\n\t\t.filter((message) => message.role === \"toolResult\")\n\t\t.map((message) => ({ content: message.content, details: undefined }));\n\tif (toolResults.length === 0) return messages;\n\n\tconst prunedResults = truncation.prePruneToolOutputsToBudget(toolResults, contextWindow * budgetRatio);\n\tlet resultIndex = 0;\n\treturn messages.map((message) => {\n\t\tif (message.role !== \"toolResult\") return message;\n\t\tconst pruned = prunedResults[resultIndex];\n\t\tresultIndex++;\n\t\treturn pruned ? { ...message, content: pruned.content } : message;\n\t});\n}\n\nexport function truncateContextMessages(messages: AgentMessage[]): AgentMessage[] {\n\tconst toolResults = messages\n\t\t.filter((message) => message.role === \"toolResult\")\n\t\t.map((message) => ({ content: message.content, details: undefined }));\n\tif (toolResults.length === 0) return messages;\n\n\tconst truncatedResults = truncation.truncateOversizedToolResults(toolResults);\n\tlet resultIndex = 0;\n\treturn messages.map((message) => {\n\t\tif (message.role !== \"toolResult\") return message;\n\t\tconst truncated = truncatedResults[resultIndex];\n\t\tresultIndex++;\n\t\treturn truncated ? { ...message, content: truncated.content } : message;\n\t});\n}\n\n/**\n * Sticky engage/release state for {@link hardLimitEmergencyPrune}. Callers that\n * issue many requests for one session share a single latch so the emitted context\n * shape stays stable while the estimate hovers around the engage threshold.\n */\nexport interface EmergencyPruneLatch {\n\tengaged: boolean;\n}\n\nexport function createEmergencyPruneLatch(): EmergencyPruneLatch {\n\treturn { engaged: false };\n}\n\nexport function hardLimitEmergencyPrune(\n\tmessages: AgentMessage[],\n\tcontextWindow: number,\n\tlatch?: EmergencyPruneLatch,\n): {\n\tmessages: AgentMessage[];\n\tneedsAggressiveCompaction: boolean;\n} {\n\tconst targetTokens = Math.floor(contextWindow * EMERGENCY_CONTEXT_TARGET_RATIO);\n\tconst releaseTokens = Math.floor(contextWindow * EMERGENCY_CONTEXT_RELEASE_RATIO);\n\tconst totalTokens = estimateTotalTokens(messages);\n\t// Without a latch this keeps the historical single-threshold behaviour.\n\tconst engaged = latch\n\t\t? latch.engaged\n\t\t\t? totalTokens > releaseTokens\n\t\t\t: totalTokens > targetTokens\n\t\t: totalTokens > targetTokens;\n\tif (latch) latch.engaged = engaged;\n\tif (!engaged) {\n\t\treturn { messages, needsAggressiveCompaction: false };\n\t}\n\tconst noLlmPruned = truncateContextMessages(\n\t\tpruneToolResults(messages, contextWindow, SUMMARIZATION_INPUT_BUDGET_RATIO),\n\t);\n\tif (estimateTotalTokens(noLlmPruned) <= targetTokens) {\n\t\treturn { messages: noLlmPruned, needsAggressiveCompaction: false };\n\t}\n\treturn {\n\t\tmessages: pruneOldMessagesToBudget(noLlmPruned, targetTokens),\n\t\tneedsAggressiveCompaction: true,\n\t};\n}\n\nexport function getPromptVariant(options: {\n\treason: string;\n\tpreparation: { previousSummary?: string; isSplitTurn: boolean };\n}): MergedCompactionPromptVariant {\n\tif (options.reason === \"branch\") return \"branch\";\n\tif (options.preparation.previousSummary) return \"update\";\n\tif (options.preparation.isSplitTurn) return \"turn_prefix\";\n\treturn \"default\";\n}\n\nexport function createSpeculativeCompactionSnapshot(\n\tcontext: SpeculativeCompactionContext,\n\toptions: {\n\t\tcustomInstructions?: string;\n\t\tgeneration: number;\n\t\torigin?: \"speculative\" | \"blocking\" | \"core-route\";\n\t\ttools?: Tool[];\n\t},\n): SpeculativeCompactionSnapshot | undefined {\n\tconst model = context.model;\n\tif (!model) return undefined;\n\n\tconst expectedRevision = context.getMessageRevision();\n\tconst branchEntries = context.sessionManager.getBranch();\n\tconst contextWindow = context.getContextUsage()?.contextWindow ?? model.contextWindow ?? DEFAULT_CONTEXT_WINDOW;\n\tconst settings = context.getCompactionSettings?.() ?? DEFAULT_COMPACTION_SETTINGS;\n\tconst thresholdRatio = computeEffectiveThreshold(contextWindow);\n\tconst preparation = prepareCompaction(branchEntries, {\n\t\t...settings,\n\t\tkeepRecentTokens: computeEffectiveKeepRecentTokens(settings.keepRecentTokens, contextWindow, thresholdRatio),\n\t});\n\tif (!preparation) return undefined;\n\n\treturn {\n\t\tgeneration: options.generation,\n\t\texpectedRevision,\n\t\tmodel,\n\t\tcontextWindow,\n\t\tpreparation,\n\t\tbranchEntries,\n\t\tpromptVariant: getPromptVariant({ reason: \"extension\", preparation }),\n\t\t...(options.origin ? { origin: options.origin } : {}),\n\t\tcustomInstructions: options.customInstructions,\n\t\tsystemPrompt: context.getSystemPrompt?.(),\n\t\ttools: options.tools,\n\t};\n}\n\n/**\n * Generate a compaction summary for the snapshot. Resolves `undefined` only\n * when the request was aborted (caller signal or an aborted stream); every\n * other failure throws — {@link SummaryGenerationError} for diagnosable\n * generation failures, the raw provider error otherwise. Abort is checked\n * before and after credential resolution so a cancelled request never\n * misreports as an auth failure.\n */\nexport async function runExtensionCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot,\n\tsignal?: AbortSignal,\n\tonProgress?: CompactionProgressCallback,\n): Promise<CompactionResult | undefined> {\n\tif (signal?.aborted) return undefined;\n\tconst auth = await context.modelRegistry?.getApiKeyAndHeaders(snapshot.model);\n\tif (signal?.aborted) return undefined;\n\t// A provider is authenticated for summarization by either a resolved key or a\n\t// credential request header: `headers`-authenticated providers (models.json and\n\t// extension providers alike) never resolve an apiKey, yet their normal agent\n\t// turns are fully authenticated.\n\tif (!auth?.ok || !(auth.apiKey || hasCredentialHeaders(auth.headers))) {\n\t\tconst detail =\n\t\t\tauth && !auth.ok ? auth.error : `no credentials resolved for provider \"${snapshot.model.provider}\"`;\n\t\tthrow new SummaryGenerationError(\"auth\", `summarization credentials unavailable: ${detail}`);\n\t}\n\tconst requestSnapshot = auth.baseUrl\n\t\t? { ...snapshot, model: { ...snapshot.model, baseUrl: auth.baseUrl } }\n\t\t: snapshot;\n\n\tconst prompt = buildPrompt({\n\t\tvariant: requestSnapshot.promptVariant,\n\t\tpreviousSummary: requestSnapshot.preparation.previousSummary,\n\t\ttaskIntent: resolveInheritedTaskIntent(requestSnapshot.branchEntries ?? []),\n\t\tcustomInstructions: requestSnapshot.customInstructions,\n\t});\n\tconst promptTokens = approxTokens(prompt.user);\n\tlet messages = boundSummarizationInput(\n\t\tpruneToolResults(\n\t\t\t[...requestSnapshot.preparation.messagesToSummarize, ...requestSnapshot.preparation.turnPrefixMessages],\n\t\t\trequestSnapshot.contextWindow,\n\t\t\tSUMMARIZATION_INPUT_BUDGET_RATIO,\n\t\t),\n\t\trequestSnapshot.contextWindow,\n\t\tpromptTokens,\n\t);\n\tconst overflowRetryStartMs = Date.now();\n\tlet overflowAttempts = 0;\n\n\twhile (true) {\n\t\tif (signal?.aborted) return undefined;\n\t\tlet response: Message | undefined;\n\t\tconst currentMessages = messages;\n\t\tconst retryStartedMs = Date.now();\n\t\t// Only the routes that block the user's turn retry here. The speculative\n\t\t// warm-up owns its own bounded retry (`idle-retry.ts`) with idle/breaker\n\t\t// guards re-evaluated between attempts, and a failed warm job must stay\n\t\t// inheritable so the next blocking route degrades on it instead of paying\n\t\t// for a second request.\n\t\tconst retryEligible = snapshot.origin === \"core-route\" || snapshot.origin === \"blocking\";\n\t\ttry {\n\t\t\t// The provider `error` stop is raised INSIDE the retried producer so a\n\t\t\t// transient summarization failure spends the shared retry budget. The\n\t\t\t// surrounding loop keeps overflow shrinking and abort handling, which\n\t\t\t// must never be answered by replaying the same request.\n\t\t\tresponse = await retryTransientCall(\n\t\t\t\tasync () => {\n\t\t\t\t\tconst attempt = await generateSummaryMessage({\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tmessages: currentMessages,\n\t\t\t\t\t\tonProgress,\n\t\t\t\t\t\tprompt,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\tsnapshot: requestSnapshot,\n\t\t\t\t\t\tauth: {\n\t\t\t\t\t\t\tapiKey: auth.apiKey,\n\t\t\t\t\t\t\theaders: auth.headers,\n\t\t\t\t\t\t\textraBody: auth.extraBody,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tif (\n\t\t\t\t\t\tattempt &&\n\t\t\t\t\t\tisAssistantMessage(attempt) &&\n\t\t\t\t\t\tattempt.stopReason === \"error\" &&\n\t\t\t\t\t\t!isContextOverflow(attempt, snapshot.contextWindow)\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst failureKind = summaryRequestFailureKind(attempt);\n\t\t\t\t\t\tthrow new SummaryRequestError(\n\t\t\t\t\t\t\tattempt.errorMessage || \"Compaction summary request failed\",\n\t\t\t\t\t\t\tfailureKind !== undefined || isRetryableAssistantError(attempt),\n\t\t\t\t\t\t\tfailureKind,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn attempt;\n\t\t\t\t},\n\t\t\t\t(error) =>\n\t\t\t\t\tretryEligible &&\n\t\t\t\t\tallowSummarizationRetry(Date.now() - retryStartedMs) &&\n\t\t\t\t\tisRetryableSummaryAttempt(error),\n\t\t\t\tDEFAULT_SUMMARIZATION_RETRY_POLICY,\n\t\t\t\tsignal,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (signal?.aborted) return undefined;\n\t\t\tthrow error;\n\t\t}\n\t\tif (!response) return undefined;\n\n\t\tif (isAssistantMessage(response) && isContextOverflow(response, snapshot.contextWindow)) {\n\t\t\toverflowAttempts++;\n\t\t\tconst elapsedMs = Date.now() - overflowRetryStartMs;\n\t\t\tconst retryMessages = allowOverflowRetry(overflowAttempts, elapsedMs)\n\t\t\t\t? shrinkSummarizationInputForOverflowRetry(messages, snapshot.contextWindow, promptTokens)\n\t\t\t\t: undefined;\n\t\t\tif (!retryMessages) {\n\t\t\t\tthrow new SummarizationOverflowExhaustedError(overflowAttempts, elapsedMs);\n\t\t\t}\n\t\t\tmessages = retryMessages;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isAssistantMessage(response) && response.stopReason === \"aborted\") {\n\t\t\t// A partial summary from an aborted stream must never be applied.\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (isAssistantMessage(response) && response.stopReason === \"error\") {\n\t\t\t// Surface the real provider failure instead of silently degrading\n\t\t\t// into a generic \"Compaction cancelled\". Preserve the structured\n\t\t\t// truncation class here so downstream recovery never trusts arbitrary\n\t\t\t// thrown error text as authorization for destructive context reduction.\n\t\t\tconst failureKind = summaryRequestFailureKind(response);\n\t\t\tthrow new SummaryRequestError(\n\t\t\t\tresponse.errorMessage || \"Compaction summary request failed\",\n\t\t\t\tfailureKind !== undefined || isRetryableAssistantError(response),\n\t\t\t\tfailureKind,\n\t\t\t);\n\t\t}\n\n\t\tconst summary = getSummaryText(response);\n\t\tif (!summary) {\n\t\t\tconst stopReason = isAssistantMessage(response) ? response.stopReason : \"unknown\";\n\t\t\tthrow new SummaryGenerationError(\n\t\t\t\t\"empty-summary\",\n\t\t\t\t`summarization response contained no text (stopReason: ${stopReason})`,\n\t\t\t);\n\t\t}\n\n\t\t// Informational only: the core rejects an applied compaction that would\n\t\t// still overflow (_wouldCompactionOverflow). Rejecting here based on the\n\t\t// size of the *discarded* input made large sessions uncompactable.\n\t\tconst tokenEstimate = estimateContextTokens(convertToLlm(messages)).tokens + approxTokens(summary);\n\t\tconst parsedSummary = extractTaskIntent(summary);\n\t\tconst taskIntent = parsedSummary.taskIntent ?? resolveInheritedTaskIntent(snapshot.branchEntries ?? []);\n\n\t\treturn {\n\t\t\tsummary: parsedSummary.summaryText,\n\t\t\tfirstKeptEntryId: snapshot.preparation.firstKeptEntryId,\n\t\t\ttokensBefore: snapshot.preparation.tokensBefore,\n\t\t\tdetails: {\n\t\t\t\tschema: SUMMARY_SCHEMA,\n\t\t\t\tpromptVariant: snapshot.promptVariant,\n\t\t\t\ttokenEstimate,\n\t\t\t\tstructuralYield: computeStructuralYield({\n\t\t\t\t\tpreviousSummary: snapshot.preparation.previousSummary ?? \"\",\n\t\t\t\t\tmessagesToSummarize: snapshot.preparation.messagesToSummarize,\n\t\t\t\t\tturnPrefixMessages: snapshot.preparation.turnPrefixMessages,\n\t\t\t\t\tsummary: parsedSummary.summaryText,\n\t\t\t\t\ttokensBefore: snapshot.preparation.tokensBefore,\n\t\t\t\t}),\n\t\t\t\t...(snapshot.origin ? { origin: snapshot.origin } : {}),\n\t\t\t\t...(taskIntent ? { taskIntent } : {}),\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function applyGeneratedCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot | undefined,\n\tgetCurrentGeneration: () => number,\n\tcompaction: CompactionResult | undefined,\n\tsignal?: AbortSignal,\n): Promise<SpeculativeCompactionResult> {\n\tconst provider = context.model?.provider;\n\tif ((provider === \"cursor\" || provider === \"cursor-cli-oauth\") && context.isIdle && !context.isIdle()) {\n\t\treturn { applied: false, reason: \"rejected\" };\n\t}\n\tif (!snapshot || !compaction) return { applied: false, reason: \"unavailable\" };\n\n\tif (snapshot.generation !== getCurrentGeneration()) {\n\t\treturn { applied: false, reason: \"stale\" };\n\t}\n\n\tconst revisionUnchanged = snapshot.expectedRevision === context.getMessageRevision();\n\tconst warmAnchor = createWarmAnchorSnapshot(snapshot.preparation.firstKeptEntryId, snapshot.branchEntries ?? []);\n\tif (\n\t\t!revisionUnchanged &&\n\t\t(!warmAnchor || !isWarmSummaryAnchorValid(warmAnchor, context.sessionManager.getBranch()))\n\t) {\n\t\treturn { applied: false, reason: \"stale\" };\n\t}\n\n\treturn await context.applyCompaction(compaction, {\n\t\treason: \"extension\",\n\t\t...(revisionUnchanged || !warmAnchor\n\t\t\t? { expectedRevision: snapshot.expectedRevision }\n\t\t\t: { expectedWarmAnchor: warmAnchor }),\n\t\tsignal,\n\t});\n}\n\nexport async function applySpeculativeCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot | undefined,\n\tgetCurrentGeneration: () => number,\n\tgenerate: () => Promise<CompactionResult | undefined>,\n): Promise<SpeculativeCompactionResult> {\n\tif (!snapshot) return { applied: false, reason: \"unavailable\" };\n\n\tconst compaction = await generate();\n\treturn await applyGeneratedCompaction(context, snapshot, getCurrentGeneration, compaction);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"speculative.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculative.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,oBAAoB,EACpB,iBAAiB,EACjB,yBAAyB,EACzB,uBAAuB,EAGvB,kBAAkB,GAElB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAGN,2BAA2B,EAC3B,qBAAqB,EACrB,iBAAiB,GACjB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAC3G,OAAO,EACN,wBAAwB,EACxB,wBAAwB,GAExB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EACN,kBAAkB,EAClB,uBAAuB,EACvB,gCAAgC,EAChC,mCAAmC,EACnC,wCAAwC,GACxC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,gCAAgC,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAsC,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEtG,OAAO,EAAE,uBAAuB,EAAE,kCAAkC,EAAE,MAAM,0BAA0B,CAAC;AAEvG,OAAO,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAEjF,OAAO,EACN,yBAAyB,EAEzB,uBAAuB,EACvB,uBAAuB,GACvB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,sBAAsB,GAAG,OAAO,CAAC;AACvC,qFAAqF;AACrF,qFAAqF;AACrF,sFAAsF;AACtF,qFAAqF;AACrF,oFAAoF;AACpF,MAAM,cAAc,GAAG,6BAA6B,CAAC;AA0CrD,SAAS,YAAY,CAAC,IAAY;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACnC,CAAC;AAeD,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAI7C,YAAY,OAAe,EAAE,SAAkB,EAAE,WAAuC;QACvF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IAChC,CAAC;CACD;AAED,MAAM,iCAAiC,GAAG,iEAAiE,CAAC;AAE5G;;;;;;;;;;;GAWG;AACH,SAAS,yBAAyB,CAAC,KAAc;IAChD,IAAI,KAAK,YAAY,yBAAyB,IAAI,KAAK,YAAY,sBAAsB;QAAE,OAAO,KAAK,CAAC;IACxG,IAAI,KAAK,YAAY,mCAAmC;QAAE,OAAO,KAAK,CAAC;IACvE,IAAI,KAAK,YAAY,sBAAsB;QAAE,OAAO,KAAK,CAAC;IAC1D,IAAI,KAAK,YAAY,mBAAmB;QAAE,OAAO,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC;IACpG,IAAI,KAAK,YAAY,KAAK;QAAE,OAAO,uBAAuB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1E,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,yBAAyB,CAAC,QAA0B;IAC5D,IAAI,QAAQ,CAAC,WAAW,EAAE,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,WAAW,EAAE,IAAI,KAAK,WAAW;QAAE,OAAO,SAAS,CAAC;IAC7G,OAAO,iCAAiC,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,SAAS,CAAC;AACtH,CAAC;AAED,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAGhD,YAAY,IAA8B,EAAE,OAAe;QAC1D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;QACrC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,CAAC;CACD;AAED;;;;;;;;GAQG;AAEH,MAAM,UAAU,gBAAgB,CAAC,OAGhC;IACA,IAAI,OAAO,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IACjD,IAAI,OAAO,CAAC,WAAW,CAAC,eAAe;QAAE,OAAO,QAAQ,CAAC;IACzD,IAAI,OAAO,CAAC,WAAW,CAAC,WAAW;QAAE,OAAO,aAAa,CAAC;IAC1D,OAAO,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,mCAAmC,CAClD,OAAqC,EACrC,OAKC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC5B,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAE7B,MAAM,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IACtD,MAAM,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC;IACzD,MAAM,aAAa,GAAG,OAAO,CAAC,eAAe,EAAE,EAAE,aAAa,IAAI,KAAK,CAAC,aAAa,IAAI,sBAAsB,CAAC;IAChH,MAAM,QAAQ,GAAG,OAAO,CAAC,qBAAqB,EAAE,EAAE,IAAI,2BAA2B,CAAC;IAClF,MAAM,cAAc,GAAG,yBAAyB,CAAC,aAAa,CAAC,CAAC;IAChE,MAAM,WAAW,GAAG,iBAAiB,CAAC,aAAa,EAAE;QACpD,GAAG,QAAQ;QACX,gBAAgB,EAAE,gCAAgC,CAAC,QAAQ,CAAC,gBAAgB,EAAE,aAAa,EAAE,cAAc,CAAC;KAC5G,CAAC,CAAC;IACH,IAAI,CAAC,WAAW;QAAE,OAAO,SAAS,CAAC;IAEnC,OAAO;QACN,GAAG,OAAO;QACV,gBAAgB;QAChB,KAAK;QACL,aAAa;QACb,WAAW;QACX,aAAa;QACb,aAAa,EAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;QACrE,YAAY,EAAE,OAAO,CAAC,eAAe,EAAE,EAAE;KACzC,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC3C,OAAqC,EACrC,QAAuC,EACvC,MAAoB,EACpB,UAAuC;IAEvC,IAAI,MAAM,EAAE,OAAO;QAAE,OAAO,SAAS,CAAC;IACtC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,mBAAmB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9E,IAAI,MAAM,EAAE,OAAO;QAAE,OAAO,SAAS,CAAC;IACtC,8EAA8E;IAC9E,gFAAgF;IAChF,6EAA6E;IAC7E,iCAAiC;IACjC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACvE,MAAM,MAAM,GACX,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,yCAAyC,QAAQ,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC;QACrG,MAAM,IAAI,sBAAsB,CAAC,MAAM,EAAE,0CAA0C,MAAM,EAAE,CAAC,CAAC;IAC9F,CAAC;IACD,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO;QACnC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,KAAK,EAAE,EAAE,GAAG,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE;QACtE,CAAC,CAAC,QAAQ,CAAC;IAEZ,MAAM,MAAM,GAAG,WAAW,CAAC;QAC1B,OAAO,EAAE,eAAe,CAAC,aAAa;QACtC,eAAe,EAAE,eAAe,CAAC,WAAW,CAAC,eAAe;QAC5D,UAAU,EAAE,0BAA0B,CAAC,eAAe,CAAC,aAAa,IAAI,EAAE,CAAC;QAC3E,kBAAkB,EAAE,eAAe,CAAC,kBAAkB;KACtD,CAAC,CAAC;IACH,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,QAAQ,GAAG,uBAAuB,CACrC,gBAAgB,CACf,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,mBAAmB,EAAE,GAAG,eAAe,CAAC,WAAW,CAAC,kBAAkB,CAAC,EACvG,eAAe,CAAC,aAAa,EAC7B,gCAAgC,CAChC,EACD,eAAe,CAAC,aAAa,EAC7B,YAAY,CACZ,CAAC;IACF,MAAM,oBAAoB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACxC,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,MAAM,yBAAyB,GAAG,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3E,IAAI,iBAAiB,GAAG,KAAK,CAAC;IAE9B,OAAO,IAAI,EAAE,CAAC;QACb,IAAI,MAAM,EAAE,OAAO;YAAE,OAAO,SAAS,CAAC;QACtC,IAAI,QAA6B,CAAC;QAClC,MAAM,eAAe,GAAG,QAAQ,CAAC;QACjC,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAClC,yEAAyE;QACzE,yEAAyE;QACzE,wEAAwE;QACxE,0EAA0E;QAC1E,wBAAwB;QACxB,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,KAAK,YAAY,IAAI,QAAQ,CAAC,MAAM,KAAK,UAAU,CAAC;QACzF,IAAI,CAAC;YACJ,uEAAuE;YACvE,sEAAsE;YACtE,sEAAsE;YACtE,wDAAwD;YACxD,QAAQ,GAAG,MAAM,kBAAkB,CAClC,KAAK,IAAI,EAAE;gBACV,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC;oBAC5C,OAAO;oBACP,eAAe,EAAE,iBAAiB;oBAClC,QAAQ,EAAE,eAAe;oBACzB,UAAU;oBACV,MAAM;oBACN,MAAM;oBACN,QAAQ,EAAE,eAAe;oBACzB,IAAI,EAAE;wBACL,MAAM,EAAE,IAAI,CAAC,MAAM;wBACnB,OAAO,EAAE,IAAI,CAAC,OAAO;wBACrB,SAAS,EAAE,IAAI,CAAC,SAAS;qBACzB;iBACD,CAAC,CAAC;gBACH,IACC,OAAO;oBACP,kBAAkB,CAAC,OAAO,CAAC;oBAC3B,OAAO,CAAC,UAAU,KAAK,OAAO;oBAC9B,CAAC,iBAAiB,CAAC,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,EAClD,CAAC;oBACF,MAAM,WAAW,GAAG,yBAAyB,CAAC,OAAO,CAAC,CAAC;oBACvD,MAAM,IAAI,mBAAmB,CAC5B,OAAO,CAAC,YAAY,IAAI,mCAAmC,EAC3D,WAAW,KAAK,SAAS,IAAI,yBAAyB,CAAC,OAAO,CAAC,EAC/D,WAAW,CACX,CAAC;gBACH,CAAC;gBACD,OAAO,OAAO,CAAC;YAChB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE,CACT,aAAa;gBACb,uBAAuB,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,CAAC;gBACpD,yBAAyB,CAAC,KAAK,CAAC,EACjC,kCAAkC,EAClC,MAAM,CACN,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,MAAM,EAAE,OAAO;gBAAE,OAAO,SAAS,CAAC;YACtC,MAAM,KAAK,CAAC;QACb,CAAC;QACD,IAAI,CAAC,QAAQ;YAAE,OAAO,SAAS,CAAC;QAEhC,IAAI,kBAAkB,CAAC,QAAQ,CAAC,IAAI,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACzF,gBAAgB,EAAE,CAAC;YACnB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,oBAAoB,CAAC;YACpD,MAAM,aAAa,GAAG,kBAAkB,CAAC,gBAAgB,EAAE,SAAS,CAAC;gBACpE,CAAC,CAAC,wCAAwC,CAAC,QAAQ,EAAE,QAAQ,CAAC,aAAa,EAAE,YAAY,CAAC;gBAC1F,CAAC,CAAC,SAAS,CAAC;YACb,IAAI,CAAC,aAAa,EAAE,CAAC;gBACpB,MAAM,IAAI,mCAAmC,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;YAC5E,CAAC;YACD,QAAQ,GAAG,aAAa,CAAC;YACzB,SAAS;QACV,CAAC;QAED,IAAI,kBAAkB,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACvE,kEAAkE;YAClE,OAAO,SAAS,CAAC;QAClB,CAAC;QAED,IAAI,kBAAkB,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;YACrE,kEAAkE;YAClE,iEAAiE;YACjE,sEAAsE;YACtE,wEAAwE;YACxE,MAAM,WAAW,GAAG,yBAAyB,CAAC,QAAQ,CAAC,CAAC;YACxD,MAAM,IAAI,mBAAmB,CAC5B,QAAQ,CAAC,YAAY,IAAI,mCAAmC,EAC5D,WAAW,KAAK,SAAS,IAAI,yBAAyB,CAAC,QAAQ,CAAC,EAChE,WAAW,CACX,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;YACd,MAAM,UAAU,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;YAClF,sEAAsE;YACtE,qEAAqE;YACrE,uEAAuE;YACvE,mEAAmE;YACnE,sEAAsE;YACtE,IAAI,UAAU,KAAK,SAAS,IAAI,yBAAyB,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBACjF,iBAAiB,GAAG,IAAI,CAAC;gBACzB,SAAS;YACV,CAAC;YACD,MAAM,IAAI,sBAAsB,CAC/B,eAAe,EACf,yDAAyD,UAAU,GAAG,CACtE,CAAC;QACH,CAAC;QAED,wEAAwE;QACxE,yEAAyE;QACzE,mEAAmE;QACnE,MAAM,aAAa,GAAG,qBAAqB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;QACnG,MAAM,aAAa,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,IAAI,0BAA0B,CAAC,QAAQ,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;QAExG,OAAO;YACN,OAAO,EAAE,aAAa,CAAC,WAAW;YAClC,gBAAgB,EAAE,QAAQ,CAAC,WAAW,CAAC,gBAAgB;YACvD,YAAY,EAAE,QAAQ,CAAC,WAAW,CAAC,YAAY;YAC/C,OAAO,EAAE;gBACR,MAAM,EAAE,cAAc;gBACtB,aAAa,EAAE,QAAQ,CAAC,aAAa;gBACrC,aAAa;gBACb,eAAe,EAAE,sBAAsB,CAAC;oBACvC,eAAe,EAAE,QAAQ,CAAC,WAAW,CAAC,eAAe,IAAI,EAAE;oBAC3D,mBAAmB,EAAE,QAAQ,CAAC,WAAW,CAAC,mBAAmB;oBAC7D,kBAAkB,EAAE,QAAQ,CAAC,WAAW,CAAC,kBAAkB;oBAC3D,OAAO,EAAE,aAAa,CAAC,WAAW;oBAClC,YAAY,EAAE,QAAQ,CAAC,WAAW,CAAC,YAAY;iBAC/C,CAAC;gBACF,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACvD,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACrC;SACD,CAAC;IACH,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC7C,OAAqC,EACrC,QAAmD,EACnD,oBAAkC,EAClC,UAAwC,EACxC,MAAoB;IAEpB,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzC,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,kBAAkB,CAAC,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACvG,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC/C,CAAC;IACD,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IAE/E,IAAI,QAAQ,CAAC,UAAU,KAAK,oBAAoB,EAAE,EAAE,CAAC;QACpD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC5C,CAAC;IAED,MAAM,iBAAiB,GAAG,QAAQ,CAAC,gBAAgB,KAAK,OAAO,CAAC,kBAAkB,EAAE,CAAC;IACrF,MAAM,UAAU,GAAG,wBAAwB,CAAC,QAAQ,CAAC,WAAW,CAAC,gBAAgB,EAAE,QAAQ,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;IACjH,IACC,CAAC,iBAAiB;QAClB,CAAC,CAAC,UAAU,IAAI,CAAC,wBAAwB,CAAC,UAAU,EAAE,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,EACzF,CAAC;QACF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAC5C,CAAC;IAED,OAAO,MAAM,OAAO,CAAC,eAAe,CAAC,UAAU,EAAE;QAChD,MAAM,EAAE,WAAW;QACnB,GAAG,CAAC,iBAAiB,IAAI,CAAC,UAAU;YACnC,CAAC,CAAC,EAAE,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB,EAAE;YACjD,CAAC,CAAC,EAAE,kBAAkB,EAAE,UAAU,EAAE,CAAC;QACtC,MAAM;KACN,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC/C,OAAqC,EACrC,QAAmD,EACnD,oBAAkC,EAClC,QAAqD;IAErD,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IAEhE,MAAM,UAAU,GAAG,MAAM,QAAQ,EAAE,CAAC;IACpC,OAAO,MAAM,wBAAwB,CAAC,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,UAAU,CAAC,CAAC;AAC5F,CAAC","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype AssistantMessage,\n\thasCredentialHeaders,\n\tisContextOverflow,\n\tisRetryableAssistantError,\n\tisRetryableErrorMessage,\n\ttype Message,\n\ttype Model,\n\tretryTransientCall,\n\ttype Tool,\n} from \"@earendil-works/pi-ai\";\nimport {\n\ttype CompactionPreparation,\n\ttype CompactionResult,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\tprepareCompaction,\n} from \"../../../compaction/index.ts\";\nimport { StreamDurationBudgetError, StreamIdleTimeoutError } from \"../../../compaction/stream-watchdog.ts\";\nimport {\n\tcreateWarmAnchorSnapshot,\n\tisWarmSummaryAnchorValid,\n\ttype WarmAnchorSnapshot,\n} from \"../../../compaction/warm-anchor.ts\";\nimport { convertToLlm } from \"../../../messages.ts\";\nimport type { ModelRegistry } from \"../../../model-registry.ts\";\nimport type { ReadonlySessionManager } from \"../../../session-manager.ts\";\nimport type { ApplyCompactionResult, ContextUsage, ProviderRequestPreparation } from \"../../types.ts\";\nimport { pruneToolResults } from \"./emergency-prune.ts\";\nimport {\n\tallowOverflowRetry,\n\tboundSummarizationInput,\n\tSUMMARIZATION_INPUT_BUDGET_RATIO,\n\tSummarizationOverflowExhaustedError,\n\tshrinkSummarizationInputForOverflowRetry,\n} from \"./overflow-retry.ts\";\nimport { computeEffectiveKeepRecentTokens, computeEffectiveThreshold } from \"./policy.ts\";\nimport { buildPrompt, type MergedCompactionPromptVariant } from \"./prompts.ts\";\nimport { generateSummaryMessage, getSummaryText, isAssistantMessage } from \"./speculative-summary.ts\";\n\nimport { allowSummarizationRetry, DEFAULT_SUMMARIZATION_RETRY_POLICY } from \"./summarization-retry.ts\";\n\nimport { extractTaskIntent, resolveInheritedTaskIntent } from \"./task-intent.ts\";\n\nexport {\n\tcreateEmergencyPruneLatch,\n\ttype EmergencyPruneLatch,\n\thardLimitEmergencyPrune,\n\ttruncateContextMessages,\n} from \"./emergency-prune.ts\";\n\nimport { computeStructuralYield } from \"./yield.ts\";\n\nconst DEFAULT_CONTEXT_WINDOW = 200_000;\n// Hysteresis: the emergency prune engages at EMERGENCY_CONTEXT_TARGET_RATIO but only\n// releases once the context falls below this lower ratio. A single threshold makes a\n// session parked near the limit alternate between the pruned and un-pruned history on\n// consecutive requests; because pruning rewrites old tool results, every alternation\n// invalidates the provider prompt-cache prefix and re-bills the whole conversation.\nconst SUMMARY_SCHEMA = \"senpi.compaction.summary.v1\";\ntype CompactionProgressCallback = (delta: string) => void;\n\nexport interface SpeculativeCompactionContext {\n\tmodel: Model<any> | undefined;\n\tsessionManager: ReadonlySessionManager;\n\tmodelRegistry?: ModelRegistry;\n\tgetContextUsage(): ContextUsage | undefined;\n\tgetCompactionSettings?(): CompactionPreparation[\"settings\"];\n\tgetMessageRevision(): number;\n\tgetSystemPrompt?(): string;\n\tprepareProviderRequest?(messages: AgentMessage[]): Promise<ProviderRequestPreparation>;\n\tisIdle?(): boolean;\n\tapplyCompaction(\n\t\tprecomputed: CompactionResult,\n\t\toptions: {\n\t\t\treason: \"extension\";\n\t\t\texpectedRevision?: number;\n\t\t\texpectedWarmAnchor?: WarmAnchorSnapshot;\n\t\t\tsignal?: AbortSignal;\n\t\t},\n\t): Promise<ApplyCompactionResult>;\n}\n\nexport interface SpeculativeCompactionSnapshot {\n\tgeneration: number;\n\texpectedRevision: number;\n\tmodel: Model<any>;\n\tcontextWindow: number;\n\tpreparation: CompactionPreparation;\n\tbranchEntries?: ReturnType<ReadonlySessionManager[\"getBranch\"]>;\n\tpromptVariant: MergedCompactionPromptVariant;\n\torigin?: \"speculative\" | \"blocking\" | \"core-route\";\n\tcustomInstructions?: string;\n\t/** Agent system prompt; used to make the summarization request look like normal agent traffic. */\n\tsystemPrompt?: string;\n\t/** Agent tool definitions; forwarded so the request shape matches normal agent traffic. */\n\ttools?: Tool[];\n}\n\nexport type SpeculativeCompactionResult = ApplyCompactionResult | { applied: false; reason: \"unavailable\" | \"failed\" };\n\nfunction approxTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\n/**\n * Summary-generation failure with a user-facing diagnosis. Distinct from a\n * user abort (which resolves `undefined`): callers surface `message` on the\n * manual route and degrade to \"unavailable\" on automatic routes.\n */\n/**\n * Provider `error` stop during summarization, carrying the metadata-aware\n * transient classification from the full assistant message. A refusal whose\n * text happens to look retryable must still surface loudly; the message\n * string alone cannot encode that.\n */\nexport type SummaryRequestFailureKind = \"upstream-stream-truncated\";\n\nexport class SummaryRequestError extends Error {\n\treadonly transient: boolean;\n\treadonly failureKind?: SummaryRequestFailureKind;\n\n\tconstructor(message: string, transient: boolean, failureKind?: SummaryRequestFailureKind) {\n\t\tsuper(message);\n\t\tthis.name = \"SummaryRequestError\";\n\t\tthis.transient = transient;\n\t\tthis.failureKind = failureKind;\n\t}\n}\n\nconst UPSTREAM_STREAM_TRUNCATED_PATTERN = /(?:^|[^A-Za-z0-9_])upstream_stream_truncated(?:[^A-Za-z0-9_]|$)/;\n\n/**\n * Only failures with no cheaper recovery earn another billed request.\n *\n * Every class that `classifyRequiredCompactionFallbackFailure` recognizes\n * (watchdog timeouts, `upstream-stream-truncated`, overflow exhaustion,\n * empty-summary generation failures) already\n * has a deterministic zero-LLM recovery, and context overflow is answered by\n * shrinking the input in the surrounding loop - replaying those would pay for a\n * summarization the fallback can rebuild for free. The classes checked here are\n * mirrored from that classifier rather than imported, because\n * `deterministic-fallback.ts` imports this module.\n */\nfunction isRetryableSummaryAttempt(error: unknown): boolean {\n\tif (error instanceof StreamDurationBudgetError || error instanceof StreamIdleTimeoutError) return false;\n\tif (error instanceof SummarizationOverflowExhaustedError) return false;\n\tif (error instanceof SummaryGenerationError) return false;\n\tif (error instanceof SummaryRequestError) return error.failureKind === undefined && error.transient;\n\tif (error instanceof Error) return isRetryableErrorMessage(error.message);\n\treturn false;\n}\n\nfunction summaryRequestFailureKind(response: AssistantMessage): SummaryRequestFailureKind | undefined {\n\tif (response.stopDetails?.type === \"refusal\" || response.stopDetails?.type === \"sensitive\") return undefined;\n\treturn UPSTREAM_STREAM_TRUNCATED_PATTERN.test(response.errorMessage ?? \"\") ? \"upstream-stream-truncated\" : undefined;\n}\n\nexport class SummaryGenerationError extends Error {\n\treadonly kind: \"auth\" | \"empty-summary\";\n\n\tconstructor(kind: \"auth\" | \"empty-summary\", message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"SummaryGenerationError\";\n\t\tthis.kind = kind;\n\t}\n}\n\n/**\n * Output budget for one summarization request. Adaptive-thinking models emit\n * reasoning tokens before the summary text, so the legacy flat 8192 cap could\n * be consumed entirely by thinking, ending the stream with zero text blocks.\n * Grant generous headroom, clamped to what the model can actually emit and to\n * half the context window: providers that enforce input + output <= window\n * would otherwise reject the request for models advertising contextWindow ==\n * maxTokens (every summarization request also carries conversation input).\n */\n\nexport function getPromptVariant(options: {\n\treason: string;\n\tpreparation: { previousSummary?: string; isSplitTurn: boolean };\n}): MergedCompactionPromptVariant {\n\tif (options.reason === \"branch\") return \"branch\";\n\tif (options.preparation.previousSummary) return \"update\";\n\tif (options.preparation.isSplitTurn) return \"turn_prefix\";\n\treturn \"default\";\n}\n\nexport function createSpeculativeCompactionSnapshot(\n\tcontext: SpeculativeCompactionContext,\n\toptions: {\n\t\tcustomInstructions?: string;\n\t\tgeneration: number;\n\t\torigin?: \"speculative\" | \"blocking\" | \"core-route\";\n\t\ttools?: Tool[];\n\t},\n): SpeculativeCompactionSnapshot | undefined {\n\tconst model = context.model;\n\tif (!model) return undefined;\n\n\tconst expectedRevision = context.getMessageRevision();\n\tconst branchEntries = context.sessionManager.getBranch();\n\tconst contextWindow = context.getContextUsage()?.contextWindow ?? model.contextWindow ?? DEFAULT_CONTEXT_WINDOW;\n\tconst settings = context.getCompactionSettings?.() ?? DEFAULT_COMPACTION_SETTINGS;\n\tconst thresholdRatio = computeEffectiveThreshold(contextWindow);\n\tconst preparation = prepareCompaction(branchEntries, {\n\t\t...settings,\n\t\tkeepRecentTokens: computeEffectiveKeepRecentTokens(settings.keepRecentTokens, contextWindow, thresholdRatio),\n\t});\n\tif (!preparation) return undefined;\n\n\treturn {\n\t\t...options,\n\t\texpectedRevision,\n\t\tmodel,\n\t\tcontextWindow,\n\t\tpreparation,\n\t\tbranchEntries,\n\t\tpromptVariant: getPromptVariant({ reason: \"extension\", preparation }),\n\t\tsystemPrompt: context.getSystemPrompt?.(),\n\t};\n}\n\n/**\n * Generate a compaction summary for the snapshot. Resolves `undefined` only\n * when the request was aborted (caller signal or an aborted stream); every\n * other failure throws — {@link SummaryGenerationError} for diagnosable\n * generation failures, the raw provider error otherwise. Abort is checked\n * before and after credential resolution so a cancelled request never\n * misreports as an auth failure.\n */\nexport async function runExtensionCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot,\n\tsignal?: AbortSignal,\n\tonProgress?: CompactionProgressCallback,\n): Promise<CompactionResult | undefined> {\n\tif (signal?.aborted) return undefined;\n\tconst auth = await context.modelRegistry?.getApiKeyAndHeaders(snapshot.model);\n\tif (signal?.aborted) return undefined;\n\t// A provider is authenticated for summarization by either a resolved key or a\n\t// credential request header: `headers`-authenticated providers (models.json and\n\t// extension providers alike) never resolve an apiKey, yet their normal agent\n\t// turns are fully authenticated.\n\tif (!auth?.ok || !(auth.apiKey || hasCredentialHeaders(auth.headers))) {\n\t\tconst detail =\n\t\t\tauth && !auth.ok ? auth.error : `no credentials resolved for provider \"${snapshot.model.provider}\"`;\n\t\tthrow new SummaryGenerationError(\"auth\", `summarization credentials unavailable: ${detail}`);\n\t}\n\tconst requestSnapshot = auth.baseUrl\n\t\t? { ...snapshot, model: { ...snapshot.model, baseUrl: auth.baseUrl } }\n\t\t: snapshot;\n\n\tconst prompt = buildPrompt({\n\t\tvariant: requestSnapshot.promptVariant,\n\t\tpreviousSummary: requestSnapshot.preparation.previousSummary,\n\t\ttaskIntent: resolveInheritedTaskIntent(requestSnapshot.branchEntries ?? []),\n\t\tcustomInstructions: requestSnapshot.customInstructions,\n\t});\n\tconst promptTokens = approxTokens(prompt.user);\n\tlet messages = boundSummarizationInput(\n\t\tpruneToolResults(\n\t\t\t[...requestSnapshot.preparation.messagesToSummarize, ...requestSnapshot.preparation.turnPrefixMessages],\n\t\t\trequestSnapshot.contextWindow,\n\t\t\tSUMMARIZATION_INPUT_BUDGET_RATIO,\n\t\t),\n\t\trequestSnapshot.contextWindow,\n\t\tpromptTokens,\n\t);\n\tconst overflowRetryStartMs = Date.now();\n\tlet overflowAttempts = 0;\n\tconst summarizationToolsOffered = (requestSnapshot.tools?.length ?? 0) > 0;\n\tlet toolUseRetrySpent = false;\n\n\twhile (true) {\n\t\tif (signal?.aborted) return undefined;\n\t\tlet response: Message | undefined;\n\t\tconst currentMessages = messages;\n\t\tconst retryStartedMs = Date.now();\n\t\t// Only the routes that block the user's turn retry here. The speculative\n\t\t// warm-up owns its own bounded retry (`idle-retry.ts`) with idle/breaker\n\t\t// guards re-evaluated between attempts, and a failed warm job must stay\n\t\t// inheritable so the next blocking route degrades on it instead of paying\n\t\t// for a second request.\n\t\tconst retryEligible = snapshot.origin === \"core-route\" || snapshot.origin === \"blocking\";\n\t\ttry {\n\t\t\t// The provider `error` stop is raised INSIDE the retried producer so a\n\t\t\t// transient summarization failure spends the shared retry budget. The\n\t\t\t// surrounding loop keeps overflow shrinking and abort handling, which\n\t\t\t// must never be answered by replaying the same request.\n\t\t\tresponse = await retryTransientCall(\n\t\t\t\tasync () => {\n\t\t\t\t\tconst attempt = await generateSummaryMessage({\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tforbidToolCalls: toolUseRetrySpent,\n\t\t\t\t\t\tmessages: currentMessages,\n\t\t\t\t\t\tonProgress,\n\t\t\t\t\t\tprompt,\n\t\t\t\t\t\tsignal,\n\t\t\t\t\t\tsnapshot: requestSnapshot,\n\t\t\t\t\t\tauth: {\n\t\t\t\t\t\t\tapiKey: auth.apiKey,\n\t\t\t\t\t\t\theaders: auth.headers,\n\t\t\t\t\t\t\textraBody: auth.extraBody,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tif (\n\t\t\t\t\t\tattempt &&\n\t\t\t\t\t\tisAssistantMessage(attempt) &&\n\t\t\t\t\t\tattempt.stopReason === \"error\" &&\n\t\t\t\t\t\t!isContextOverflow(attempt, snapshot.contextWindow)\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst failureKind = summaryRequestFailureKind(attempt);\n\t\t\t\t\t\tthrow new SummaryRequestError(\n\t\t\t\t\t\t\tattempt.errorMessage || \"Compaction summary request failed\",\n\t\t\t\t\t\t\tfailureKind !== undefined || isRetryableAssistantError(attempt),\n\t\t\t\t\t\t\tfailureKind,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn attempt;\n\t\t\t\t},\n\t\t\t\t(error) =>\n\t\t\t\t\tretryEligible &&\n\t\t\t\t\tallowSummarizationRetry(Date.now() - retryStartedMs) &&\n\t\t\t\t\tisRetryableSummaryAttempt(error),\n\t\t\t\tDEFAULT_SUMMARIZATION_RETRY_POLICY,\n\t\t\t\tsignal,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (signal?.aborted) return undefined;\n\t\t\tthrow error;\n\t\t}\n\t\tif (!response) return undefined;\n\n\t\tif (isAssistantMessage(response) && isContextOverflow(response, snapshot.contextWindow)) {\n\t\t\toverflowAttempts++;\n\t\t\tconst elapsedMs = Date.now() - overflowRetryStartMs;\n\t\t\tconst retryMessages = allowOverflowRetry(overflowAttempts, elapsedMs)\n\t\t\t\t? shrinkSummarizationInputForOverflowRetry(messages, snapshot.contextWindow, promptTokens)\n\t\t\t\t: undefined;\n\t\t\tif (!retryMessages) {\n\t\t\t\tthrow new SummarizationOverflowExhaustedError(overflowAttempts, elapsedMs);\n\t\t\t}\n\t\t\tmessages = retryMessages;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isAssistantMessage(response) && response.stopReason === \"aborted\") {\n\t\t\t// A partial summary from an aborted stream must never be applied.\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (isAssistantMessage(response) && response.stopReason === \"error\") {\n\t\t\t// Surface the real provider failure instead of silently degrading\n\t\t\t// into a generic \"Compaction cancelled\". Preserve the structured\n\t\t\t// truncation class here so downstream recovery never trusts arbitrary\n\t\t\t// thrown error text as authorization for destructive context reduction.\n\t\t\tconst failureKind = summaryRequestFailureKind(response);\n\t\t\tthrow new SummaryRequestError(\n\t\t\t\tresponse.errorMessage || \"Compaction summary request failed\",\n\t\t\t\tfailureKind !== undefined || isRetryableAssistantError(response),\n\t\t\t\tfailureKind,\n\t\t\t);\n\t\t}\n\n\t\tconst summary = getSummaryText(response);\n\t\tif (!summary) {\n\t\t\tconst stopReason = isAssistantMessage(response) ? response.stopReason : \"unknown\";\n\t\t\t// A summarizer can hijack the forwarded agent tools and answer with a\n\t\t\t// bare tool call (observed on openai-codex gpt-5.6-sol, 2026-08-31),\n\t\t\t// which used to surface as a terminal empty-summary failure. Spend one\n\t\t\t// retry with tool calling forbidden; the tools stay in the request\n\t\t\t// because Anthropic rejects tool_use history without the tools param.\n\t\t\tif (stopReason === \"toolUse\" && summarizationToolsOffered && !toolUseRetrySpent) {\n\t\t\t\ttoolUseRetrySpent = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new SummaryGenerationError(\n\t\t\t\t\"empty-summary\",\n\t\t\t\t`summarization response contained no text (stopReason: ${stopReason})`,\n\t\t\t);\n\t\t}\n\n\t\t// Informational only: the core rejects an applied compaction that would\n\t\t// still overflow (_wouldCompactionOverflow). Rejecting here based on the\n\t\t// size of the *discarded* input made large sessions uncompactable.\n\t\tconst tokenEstimate = estimateContextTokens(convertToLlm(messages)).tokens + approxTokens(summary);\n\t\tconst parsedSummary = extractTaskIntent(summary);\n\t\tconst taskIntent = parsedSummary.taskIntent ?? resolveInheritedTaskIntent(snapshot.branchEntries ?? []);\n\n\t\treturn {\n\t\t\tsummary: parsedSummary.summaryText,\n\t\t\tfirstKeptEntryId: snapshot.preparation.firstKeptEntryId,\n\t\t\ttokensBefore: snapshot.preparation.tokensBefore,\n\t\t\tdetails: {\n\t\t\t\tschema: SUMMARY_SCHEMA,\n\t\t\t\tpromptVariant: snapshot.promptVariant,\n\t\t\t\ttokenEstimate,\n\t\t\t\tstructuralYield: computeStructuralYield({\n\t\t\t\t\tpreviousSummary: snapshot.preparation.previousSummary ?? \"\",\n\t\t\t\t\tmessagesToSummarize: snapshot.preparation.messagesToSummarize,\n\t\t\t\t\tturnPrefixMessages: snapshot.preparation.turnPrefixMessages,\n\t\t\t\t\tsummary: parsedSummary.summaryText,\n\t\t\t\t\ttokensBefore: snapshot.preparation.tokensBefore,\n\t\t\t\t}),\n\t\t\t\t...(snapshot.origin ? { origin: snapshot.origin } : {}),\n\t\t\t\t...(taskIntent ? { taskIntent } : {}),\n\t\t\t},\n\t\t};\n\t}\n}\n\nexport async function applyGeneratedCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot | undefined,\n\tgetCurrentGeneration: () => number,\n\tcompaction: CompactionResult | undefined,\n\tsignal?: AbortSignal,\n): Promise<SpeculativeCompactionResult> {\n\tconst provider = context.model?.provider;\n\tif ((provider === \"cursor\" || provider === \"cursor-cli-oauth\") && context.isIdle && !context.isIdle()) {\n\t\treturn { applied: false, reason: \"rejected\" };\n\t}\n\tif (!snapshot || !compaction) return { applied: false, reason: \"unavailable\" };\n\n\tif (snapshot.generation !== getCurrentGeneration()) {\n\t\treturn { applied: false, reason: \"stale\" };\n\t}\n\n\tconst revisionUnchanged = snapshot.expectedRevision === context.getMessageRevision();\n\tconst warmAnchor = createWarmAnchorSnapshot(snapshot.preparation.firstKeptEntryId, snapshot.branchEntries ?? []);\n\tif (\n\t\t!revisionUnchanged &&\n\t\t(!warmAnchor || !isWarmSummaryAnchorValid(warmAnchor, context.sessionManager.getBranch()))\n\t) {\n\t\treturn { applied: false, reason: \"stale\" };\n\t}\n\n\treturn await context.applyCompaction(compaction, {\n\t\treason: \"extension\",\n\t\t...(revisionUnchanged || !warmAnchor\n\t\t\t? { expectedRevision: snapshot.expectedRevision }\n\t\t\t: { expectedWarmAnchor: warmAnchor }),\n\t\tsignal,\n\t});\n}\n\nexport async function applySpeculativeCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot | undefined,\n\tgetCurrentGeneration: () => number,\n\tgenerate: () => Promise<CompactionResult | undefined>,\n): Promise<SpeculativeCompactionResult> {\n\tif (!snapshot) return { applied: false, reason: \"unavailable\" };\n\n\tconst compaction = await generate();\n\treturn await applyGeneratedCompaction(context, snapshot, getCurrentGeneration, compaction);\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface TokenBudgetReminderLease {
|
|
2
|
+
compactionEpoch: number;
|
|
3
|
+
message: string;
|
|
4
|
+
}
|
|
5
|
+
export interface TokenBudgetReminderState {
|
|
6
|
+
lastFiredEpoch: number | null;
|
|
7
|
+
lease?: TokenBudgetReminderLease;
|
|
8
|
+
}
|
|
9
|
+
export interface TokenBudgetReminderInput {
|
|
10
|
+
contextTokens: number;
|
|
11
|
+
contextWindow: number;
|
|
12
|
+
thresholdTokens: number;
|
|
13
|
+
leadTokens: number;
|
|
14
|
+
compactionEpoch: number;
|
|
15
|
+
state: TokenBudgetReminderState;
|
|
16
|
+
}
|
|
17
|
+
export interface TokenBudgetReminderResult {
|
|
18
|
+
message?: string;
|
|
19
|
+
nextState: TokenBudgetReminderState;
|
|
20
|
+
}
|
|
21
|
+
export declare function createInitialReminderState(): TokenBudgetReminderState;
|
|
22
|
+
export declare function clearTokenBudgetReminderLease(state: TokenBudgetReminderState): TokenBudgetReminderState;
|
|
23
|
+
export declare function computeTokenBudgetReminder(input: TokenBudgetReminderInput): TokenBudgetReminderResult;
|
|
24
|
+
//# sourceMappingURL=token-budget-reminder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-budget-reminder.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/token-budget-reminder.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACxC,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,wBAAwB;IACxC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,CAAC,EAAE,wBAAwB,CAAC;CACjC;AAED,MAAM,WAAW,wBAAwB;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,wBAAwB,CAAC;CAChC;AAED,MAAM,WAAW,yBAAyB;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,wBAAwB,CAAC;CACpC;AAED,wBAAgB,0BAA0B,IAAI,wBAAwB,CAErE;AAMD,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,wBAAwB,GAAG,wBAAwB,CAEvG;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,wBAAwB,GAAG,yBAAyB,CAcrG"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function createInitialReminderState() {
|
|
2
|
+
return { lastFiredEpoch: null };
|
|
3
|
+
}
|
|
4
|
+
function formatReminderMessage(remaining) {
|
|
5
|
+
return `[context budget] Approximately ${remaining} tokens remain before automatic compaction. Wrap up verbose exploration, prefer concise summaries over full dumps, and front-load conclusions.`;
|
|
6
|
+
}
|
|
7
|
+
export function clearTokenBudgetReminderLease(state) {
|
|
8
|
+
return state.lease ? { lastFiredEpoch: state.lastFiredEpoch } : state;
|
|
9
|
+
}
|
|
10
|
+
export function computeTokenBudgetReminder(input) {
|
|
11
|
+
const remaining = input.thresholdTokens - input.contextTokens;
|
|
12
|
+
const inZone = remaining > 0 && remaining <= 2 * input.leadTokens;
|
|
13
|
+
if (!inZone || input.state.lastFiredEpoch === input.compactionEpoch) {
|
|
14
|
+
return { nextState: clearTokenBudgetReminderLease(input.state) };
|
|
15
|
+
}
|
|
16
|
+
const message = formatReminderMessage(remaining);
|
|
17
|
+
return {
|
|
18
|
+
message,
|
|
19
|
+
nextState: {
|
|
20
|
+
lastFiredEpoch: input.compactionEpoch,
|
|
21
|
+
lease: { compactionEpoch: input.compactionEpoch, message },
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=token-budget-reminder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-budget-reminder.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/token-budget-reminder.ts"],"names":[],"mappings":"AAwBA,MAAM,UAAU,0BAA0B;IACzC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,qBAAqB,CAAC,SAAiB;IAC/C,OAAO,kCAAkC,SAAS,gJAAgJ,CAAC;AACpM,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,KAA+B;IAC5E,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAA+B;IACzE,MAAM,SAAS,GAAG,KAAK,CAAC,eAAe,GAAG,KAAK,CAAC,aAAa,CAAC;IAC9D,MAAM,MAAM,GAAG,SAAS,GAAG,CAAC,IAAI,SAAS,IAAI,CAAC,GAAG,KAAK,CAAC,UAAU,CAAC;IAClE,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,cAAc,KAAK,KAAK,CAAC,eAAe,EAAE,CAAC;QACrE,OAAO,EAAE,SAAS,EAAE,6BAA6B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;IAClE,CAAC;IACD,MAAM,OAAO,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACjD,OAAO;QACN,OAAO;QACP,SAAS,EAAE;YACV,cAAc,EAAE,KAAK,CAAC,eAAe;YACrC,KAAK,EAAE,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE,OAAO,EAAE;SAC1D;KACD,CAAC;AACH,CAAC","sourcesContent":["export interface TokenBudgetReminderLease {\n\tcompactionEpoch: number;\n\tmessage: string;\n}\n\nexport interface TokenBudgetReminderState {\n\tlastFiredEpoch: number | null;\n\tlease?: TokenBudgetReminderLease;\n}\n\nexport interface TokenBudgetReminderInput {\n\tcontextTokens: number;\n\tcontextWindow: number;\n\tthresholdTokens: number;\n\tleadTokens: number;\n\tcompactionEpoch: number;\n\tstate: TokenBudgetReminderState;\n}\n\nexport interface TokenBudgetReminderResult {\n\tmessage?: string;\n\tnextState: TokenBudgetReminderState;\n}\n\nexport function createInitialReminderState(): TokenBudgetReminderState {\n\treturn { lastFiredEpoch: null };\n}\n\nfunction formatReminderMessage(remaining: number): string {\n\treturn `[context budget] Approximately ${remaining} tokens remain before automatic compaction. Wrap up verbose exploration, prefer concise summaries over full dumps, and front-load conclusions.`;\n}\n\nexport function clearTokenBudgetReminderLease(state: TokenBudgetReminderState): TokenBudgetReminderState {\n\treturn state.lease ? { lastFiredEpoch: state.lastFiredEpoch } : state;\n}\n\nexport function computeTokenBudgetReminder(input: TokenBudgetReminderInput): TokenBudgetReminderResult {\n\tconst remaining = input.thresholdTokens - input.contextTokens;\n\tconst inZone = remaining > 0 && remaining <= 2 * input.leadTokens;\n\tif (!inZone || input.state.lastFiredEpoch === input.compactionEpoch) {\n\t\treturn { nextState: clearTokenBudgetReminderLease(input.state) };\n\t}\n\tconst message = formatReminderMessage(remaining);\n\treturn {\n\t\tmessage,\n\t\tnextState: {\n\t\t\tlastFiredEpoch: input.compactionEpoch,\n\t\t\tlease: { compactionEpoch: input.compactionEpoch, message },\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Always-on admission cap for tool results.
|
|
3
|
+
*
|
|
4
|
+
* Oversized tool output is the dominant driver of single-step context bursts, so it is
|
|
5
|
+
* projected to a deterministic head/tail excerpt at the entrance instead of waiting for
|
|
6
|
+
* an emergency/compaction-budget pass (see `tool-truncation.ts`). Admission is derived
|
|
7
|
+
* from the supplied text on every request; model-visible marker text is never state.
|
|
8
|
+
*/
|
|
9
|
+
export declare const TOOL_ADMISSION_MARKER_PREFIX = "[tool result projected:";
|
|
10
|
+
export interface AdmitToolResultInput {
|
|
11
|
+
readonly text: string;
|
|
12
|
+
readonly contextWindow: number;
|
|
13
|
+
}
|
|
14
|
+
export interface AdmitToolResultOutput {
|
|
15
|
+
readonly text: string;
|
|
16
|
+
readonly projected: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** Token budget a single tool result may occupy before it is projected. */
|
|
19
|
+
export declare function resolveToolResultAdmissionCapTokens(contextWindow: number): number;
|
|
20
|
+
/**
|
|
21
|
+
* Cap a tool result at admission time. Under-cap text passes through untouched; over-cap
|
|
22
|
+
* text becomes a deterministic, diskless head/tail projection. Re-evaluating projected
|
|
23
|
+
* text under a smaller model window is safe because admission never trusts marker text.
|
|
24
|
+
*/
|
|
25
|
+
export declare function admitToolResultWithinBudget(text: string, budgetTokens: number): AdmitToolResultOutput;
|
|
26
|
+
export declare function admitToolResult(input: AdmitToolResultInput): AdmitToolResultOutput;
|
|
27
|
+
//# sourceMappingURL=tool-admission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-admission.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/tool-admission.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAUH,eAAO,MAAM,4BAA4B,4BAA4B,CAAC;AAEtE,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC5B;AAED,2EAA2E;AAC3E,wBAAgB,mCAAmC,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAKjF;AAeD;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,qBAAqB,CAgBrG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,qBAAqB,CAElF"}
|