@code-yeongyu/senpi 2026.8.29 → 2026.8.30-3
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 +172 -0
- package/dist/core/agent-session.d.ts +47 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +406 -39
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +155 -37
- package/dist/core/bash-executor.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/credential-accounts.d.ts.map +1 -1
- package/dist/core/credential-accounts.js +23 -9
- package/dist/core/credential-accounts.js.map +1 -1
- package/dist/core/credential-pool/env-slots.d.ts.map +1 -1
- package/dist/core/credential-pool/env-slots.js +2 -0
- package/dist/core/credential-pool/env-slots.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +18 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.js +32 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +8 -2
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +164 -48
- 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 +148 -150
- 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/retained-message-safety.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/retained-message-safety.js +31 -8
- package/dist/core/extensions/builtin/compaction/retained-message-safety.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 +22 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative-summary.js +131 -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 +7 -196
- 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/cursor-cli-oauth/stream.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js +8 -28
- package/dist/core/extensions/builtin/cursor-cli-oauth/stream.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/external-dir.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/external-dir.js +15 -5
- package/dist/core/extensions/builtin/permission-system/external-dir.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/parsers.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/parsers.js +16 -1
- package/dist/core/extensions/builtin/permission-system/parsers.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/manager.d.ts +5 -0
- package/dist/core/extensions/builtin/terminal/manager.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/manager.js +31 -3
- package/dist/core/extensions/builtin/terminal/manager.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts +8 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.js +16 -0
- package/dist/core/extensions/builtin/terminal/monitor-permission.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts +13 -0
- package/dist/core/extensions/builtin/terminal/monitor-registry.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/monitor-registry.js +403 -3
- package/dist/core/extensions/builtin/terminal/monitor-registry.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/terminal/session-bundle.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/session-bundle.js +1 -0
- package/dist/core/extensions/builtin/terminal/session-bundle.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.js +5 -2
- package/dist/core/extensions/builtin/terminal/tools/kill-bash.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts +4 -0
- package/dist/core/extensions/builtin/terminal/tools/monitor.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/monitor.js +40 -2
- package/dist/core/extensions/builtin/terminal/tools/monitor.js.map +1 -1
- package/dist/core/model-resolver.js +2 -2
- package/dist/core/model-resolver.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-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +10 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +15 -85
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +15 -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/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +97 -15
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +8 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +76 -34
- package/dist/core/tools/output-accumulator.js.map +1 -1
- 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.map +1 -1
- package/dist/main.js +17 -5
- package/dist/main.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/components/footer.d.ts +7 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +34 -8
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/grok/chrome.d.ts +2 -0
- package/dist/modes/interactive/grok/chrome.d.ts.map +1 -1
- package/dist/modes/interactive/grok/chrome.js.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts +132 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.js +633 -117
- package/dist/modes/interactive/interactive-host-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +7 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +114 -2
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/connection-handler.d.ts +8 -1
- package/dist/modes/rpc/connection-handler.d.ts.map +1 -1
- package/dist/modes/rpc/connection-handler.js +158 -49
- package/dist/modes/rpc/connection-handler.js.map +1 -1
- package/dist/modes/rpc/host-ensure.d.ts +19 -0
- package/dist/modes/rpc/host-ensure.d.ts.map +1 -1
- package/dist/modes/rpc/host-ensure.js +79 -15
- package/dist/modes/rpc/host-ensure.js.map +1 -1
- package/dist/modes/rpc/host-lifecycle.d.ts +29 -0
- package/dist/modes/rpc/host-lifecycle.d.ts.map +1 -1
- package/dist/modes/rpc/host-lifecycle.js +96 -25
- package/dist/modes/rpc/host-lifecycle.js.map +1 -1
- package/dist/modes/rpc/host-watchdog.d.ts +2 -0
- package/dist/modes/rpc/host-watchdog.d.ts.map +1 -1
- package/dist/modes/rpc/host-watchdog.js +23 -12
- package/dist/modes/rpc/host-watchdog.js.map +1 -1
- package/dist/modes/rpc/multi-session-host.js +6 -4
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +20 -4
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +76 -17
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.d.ts +1 -0
- package/dist/modes/rpc/rpc-input-validation.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.js +66 -0
- package/dist/modes/rpc/rpc-input-validation.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +86 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-binding.d.ts +1 -0
- package/dist/modes/rpc/session-binding.d.ts.map +1 -1
- package/dist/modes/rpc/session-binding.js +21 -1
- package/dist/modes/rpc/session-binding.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +1 -0
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +2 -0
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +54 -7
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-extension-ui-requests.d.ts +1 -0
- package/dist/modes/rpc/session-extension-ui-requests.d.ts.map +1 -1
- package/dist/modes/rpc/session-extension-ui-requests.js +5 -0
- package/dist/modes/rpc/session-extension-ui-requests.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts +10 -2
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +58 -4
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/dist/modes/rpc/socket-event-fanout.d.ts +22 -0
- package/dist/modes/rpc/socket-event-fanout.d.ts.map +1 -0
- package/dist/modes/rpc/socket-event-fanout.js +84 -0
- package/dist/modes/rpc/socket-event-fanout.js.map +1 -0
- package/docs/rpc.md +22 -2
- package/docs/settings.md +34 -0
- package/docs/windows.md +2 -0
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +62 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@code-yeongyu/senpi-codemode/src/kernels/js/worker-indirect-eval.js +139 -90
- package/node_modules/@code-yeongyu/senpi-codemode/src/prompt/eval-prompt.ts +4 -4
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js +40 -20
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/env/nodejs.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts +3 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js +28 -9
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/utils/shell-output.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -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 +67 -38
- 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/measure.d.ts +20 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js +443 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +2 -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 +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.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/cloudflare-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-workers-ai.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/opencode-go.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.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/together.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai.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/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts +7 -0
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +5 -0
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/mux.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/mux.js +2 -2
- package/node_modules/@earendil-works/pi-tui/dist/mux.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js +19 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { sanitizeAnthropicToolPairs as sanitizeAnthropicPayload, } from "@earendil-works/pi-ai";
|
|
2
|
+
import { stream } from "@earendil-works/pi-ai/compat";
|
|
3
|
+
import { consumeStreamWithIdleTimeout, DEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS, DEFAULT_SUMMARIZATION_MAX_DURATION_MS, } from "../../../compaction/stream-watchdog.js";
|
|
4
|
+
import { convertToLlm } from "../../../messages.js";
|
|
5
|
+
import { repairOrphanedToolResults } from "./repair-tool-pairs.js";
|
|
6
|
+
import { normalizeSummarizationTurnOrder } from "./summarization-turn-order.js";
|
|
7
|
+
const SUMMARY_TOKEN_HEADROOM = 32_768;
|
|
8
|
+
const SUMMARY_CONTEXT_WINDOW_RESERVE_RATIO = 0.5;
|
|
9
|
+
function summaryMaxTokens(model, contextWindow) {
|
|
10
|
+
const headroom = model.maxTokens > 0 ? Math.min(SUMMARY_TOKEN_HEADROOM, model.maxTokens) : SUMMARY_TOKEN_HEADROOM;
|
|
11
|
+
if (contextWindow > 0) {
|
|
12
|
+
return Math.min(headroom, Math.floor(contextWindow * SUMMARY_CONTEXT_WINDOW_RESERVE_RATIO));
|
|
13
|
+
}
|
|
14
|
+
return headroom;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Reasoning override for summarization requests. Compaction must be fast: a
|
|
18
|
+
* summarization request that inherits the provider's default reasoning mode
|
|
19
|
+
* burns its latency (and output budget) on invisible thinking before emitting
|
|
20
|
+
* the summary. Disable or minimize reasoning per wire family; adapters ignore
|
|
21
|
+
* options their provider does not support. Mirrors how OpenAI Codex keeps its
|
|
22
|
+
* compaction turn cheap.
|
|
23
|
+
*/
|
|
24
|
+
function summarizationReasoningOptions(model) {
|
|
25
|
+
if (!model.reasoning)
|
|
26
|
+
return {};
|
|
27
|
+
if (model.api === "anthropic-messages")
|
|
28
|
+
return { thinkingEnabled: false };
|
|
29
|
+
const reasoningEffort = ["low", "medium", "high"].find((level) => model.thinkingLevelMap?.[level] !== null);
|
|
30
|
+
if (!reasoningEffort)
|
|
31
|
+
return {};
|
|
32
|
+
switch (model.api) {
|
|
33
|
+
case "openai-responses":
|
|
34
|
+
case "openai-codex-responses":
|
|
35
|
+
case "azure-openai-responses":
|
|
36
|
+
return { reasoningEffort, reasoningSummary: null };
|
|
37
|
+
case "openai-completions":
|
|
38
|
+
return { reasoningEffort };
|
|
39
|
+
default:
|
|
40
|
+
return {};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function getSummaryText(message) {
|
|
44
|
+
const content = Array.isArray(message.content)
|
|
45
|
+
? message.content
|
|
46
|
+
: [{ type: "text", text: message.content }];
|
|
47
|
+
return content
|
|
48
|
+
.filter((content) => content.type === "text")
|
|
49
|
+
.map((content) => content.text)
|
|
50
|
+
.join("\n")
|
|
51
|
+
.trim();
|
|
52
|
+
}
|
|
53
|
+
export function isAssistantMessage(message) {
|
|
54
|
+
return message.role === "assistant" && "stopReason" in message;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Providers registered through `pi.registerProvider()` (claude-sdk-oauth, Kiro, any
|
|
58
|
+
* extension provider) exist only in Senpi's ModelRuntime, never in compat's builtin
|
|
59
|
+
* api-registry, which rejects their api id outright. Dispatch through the runtime
|
|
60
|
+
* whenever it is reachable and keep compat for contexts constructed without a registry.
|
|
61
|
+
*/
|
|
62
|
+
function summarizationStream(context, model, requestContext, options) {
|
|
63
|
+
const runtime = context.modelRegistry?.modelRuntime;
|
|
64
|
+
return runtime ? runtime.stream(model, requestContext, options) : stream(model, requestContext, options);
|
|
65
|
+
}
|
|
66
|
+
export async function generateSummaryMessage(options) {
|
|
67
|
+
// Send the conversation as native LLM messages with the summarization
|
|
68
|
+
// instruction as a trailing user message, mirroring normal agent traffic.
|
|
69
|
+
// A single serialized `<conversation>` text dump of a large session is
|
|
70
|
+
// deterministically refused by Anthropic's anti-distillation classifier
|
|
71
|
+
// ("reverse engineering or duplicating model outputs"), while the same
|
|
72
|
+
// content as native blocks with the agent's system prompt and tools passes.
|
|
73
|
+
// Request-local controller: the idle watchdog must be able to tear down a
|
|
74
|
+
// stalled summarization request without aborting the caller's own signal.
|
|
75
|
+
const requestController = new AbortController();
|
|
76
|
+
const onCallerAbort = () => requestController.abort(options.signal?.reason);
|
|
77
|
+
if (options.signal) {
|
|
78
|
+
if (options.signal.aborted)
|
|
79
|
+
onCallerAbort();
|
|
80
|
+
else
|
|
81
|
+
options.signal.addEventListener("abort", onCallerAbort, { once: true });
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
const requestMessages = [
|
|
85
|
+
...options.messages,
|
|
86
|
+
{
|
|
87
|
+
role: "user",
|
|
88
|
+
content: [{ type: "text", text: options.prompt.user }],
|
|
89
|
+
timestamp: Date.now(),
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
const providerRequest = await options.context.prepareProviderRequest?.(requestMessages);
|
|
93
|
+
const requestContext = {
|
|
94
|
+
systemPrompt: options.snapshot.systemPrompt ?? options.prompt.system,
|
|
95
|
+
messages: repairOrphanedToolResults(normalizeSummarizationTurnOrder(convertToLlm(providerRequest?.messages ?? requestMessages))),
|
|
96
|
+
...(options.snapshot.tools && options.snapshot.tools.length > 0 ? { tools: options.snapshot.tools } : {}),
|
|
97
|
+
};
|
|
98
|
+
const headers = providerRequest
|
|
99
|
+
? await providerRequest.transformHeaders(options.auth.headers ?? {})
|
|
100
|
+
: options.auth.headers;
|
|
101
|
+
const responseStream = summarizationStream(options.context, options.snapshot.model, requestContext, {
|
|
102
|
+
apiKey: options.auth.apiKey,
|
|
103
|
+
headers,
|
|
104
|
+
extraBody: options.auth.extraBody,
|
|
105
|
+
onPayload: async (payload, model) => {
|
|
106
|
+
const sanitized = model.api === "anthropic-messages" ? sanitizeAnthropicPayload(payload) : payload;
|
|
107
|
+
return providerRequest ? await providerRequest.transformPayload(sanitized) : sanitized;
|
|
108
|
+
},
|
|
109
|
+
maxTokens: summaryMaxTokens(options.snapshot.model, options.snapshot.contextWindow),
|
|
110
|
+
signal: requestController.signal,
|
|
111
|
+
...summarizationReasoningOptions(options.snapshot.model),
|
|
112
|
+
});
|
|
113
|
+
await consumeStreamWithIdleTimeout(responseStream, {
|
|
114
|
+
idleTimeoutMs: DEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS,
|
|
115
|
+
maxDurationMs: DEFAULT_SUMMARIZATION_MAX_DURATION_MS,
|
|
116
|
+
abort: () => requestController.abort(),
|
|
117
|
+
signal: options.signal,
|
|
118
|
+
onEvent: (event) => {
|
|
119
|
+
if (event.type === "text_delta" && event.delta) {
|
|
120
|
+
options.onProgress?.(event.delta);
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
return await responseStream.result();
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
if (options.signal)
|
|
128
|
+
options.signal.removeEventListener("abort", onCallerAbort);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=speculative-summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speculative-summary.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculative-summary.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\ttype Message,\n\ttype Model,\n\ttype ProviderHeaders,\n\ttype StreamOptions,\n\tsanitizeAnthropicToolPairs as sanitizeAnthropicPayload,\n\ttype TextContent,\n} from \"@earendil-works/pi-ai\";\nimport { stream } from \"@earendil-works/pi-ai/compat\";\nimport {\n\tconsumeStreamWithIdleTimeout,\n\tDEFAULT_SUMMARIZATION_IDLE_TIMEOUT_MS,\n\tDEFAULT_SUMMARIZATION_MAX_DURATION_MS,\n} from \"../../../compaction/stream-watchdog.ts\";\nimport { convertToLlm } from \"../../../messages.ts\";\nimport type { buildPrompt } from \"./prompts.ts\";\nimport { repairOrphanedToolResults } from \"./repair-tool-pairs.ts\";\nimport type { SpeculativeCompactionContext, SpeculativeCompactionSnapshot } from \"./speculative.ts\";\nimport { normalizeSummarizationTurnOrder } from \"./summarization-turn-order.ts\";\n\nconst SUMMARY_TOKEN_HEADROOM = 32_768;\nconst SUMMARY_CONTEXT_WINDOW_RESERVE_RATIO = 0.5;\ntype CompactionProgressCallback = (delta: string) => void;\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\nexport function 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\nexport function 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\nexport async 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"]}
|
|
@@ -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);
|
|
@@ -81,187 +76,6 @@ export class SummaryGenerationError extends Error {
|
|
|
81
76
|
* would otherwise reject the request for models advertising contextWindow ==
|
|
82
77
|
* maxTokens (every summarization request also carries conversation input).
|
|
83
78
|
*/
|
|
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
79
|
export function getPromptVariant(options) {
|
|
266
80
|
if (options.reason === "branch")
|
|
267
81
|
return "branch";
|
|
@@ -287,17 +101,14 @@ export function createSpeculativeCompactionSnapshot(context, options) {
|
|
|
287
101
|
if (!preparation)
|
|
288
102
|
return undefined;
|
|
289
103
|
return {
|
|
290
|
-
|
|
104
|
+
...options,
|
|
291
105
|
expectedRevision,
|
|
292
106
|
model,
|
|
293
107
|
contextWindow,
|
|
294
108
|
preparation,
|
|
295
109
|
branchEntries,
|
|
296
110
|
promptVariant: getPromptVariant({ reason: "extension", preparation }),
|
|
297
|
-
...(options.origin ? { origin: options.origin } : {}),
|
|
298
|
-
customInstructions: options.customInstructions,
|
|
299
111
|
systemPrompt: context.getSystemPrompt?.(),
|
|
300
|
-
tools: options.tools,
|
|
301
112
|
};
|
|
302
113
|
}
|
|
303
114
|
/**
|