@code-yeongyu/senpi 2026.8.28 → 2026.8.30-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 +196 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +4 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +2 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +50 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +330 -29
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +1 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -0
- package/dist/core/auth-storage.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 +45 -21
- package/dist/core/credential-accounts.js.map +1 -1
- package/dist/core/credential-pool/classify.d.ts +6 -1
- package/dist/core/credential-pool/classify.d.ts.map +1 -1
- package/dist/core/credential-pool/classify.js +22 -5
- package/dist/core/credential-pool/classify.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/credential-pool/failover.d.ts +8 -0
- package/dist/core/credential-pool/failover.d.ts.map +1 -1
- package/dist/core/credential-pool/failover.js +24 -6
- package/dist/core/credential-pool/failover.js.map +1 -1
- package/dist/core/credential-pool/rotation-stream.d.ts +13 -2
- package/dist/core/credential-pool/rotation-stream.d.ts.map +1 -1
- package/dist/core/credential-pool/rotation-stream.js +97 -10
- package/dist/core/credential-pool/rotation-stream.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts +17 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/context-pipeline.js +28 -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 +163 -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.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 +121 -147
- 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/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 +56 -0
- package/dist/core/extensions/builtin/compaction/orchestration.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/orchestration.js +136 -0
- package/dist/core/extensions/builtin/compaction/orchestration.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/policy.d.ts +5 -2
- package/dist/core/extensions/builtin/compaction/policy.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/policy.js +43 -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 +18 -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 +18 -0
- package/dist/core/extensions/builtin/compaction/token-budget-reminder.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.d.ts +36 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/tool-admission.js +92 -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/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +7 -0
- package/dist/core/extensions/builtin/goal/index.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/service-tier.d.ts.map +1 -1
- package/dist/core/extensions/builtin/service-tier.js +13 -0
- package/dist/core/extensions/builtin/service-tier.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/extension.js +4 -2
- package/dist/core/extensions/builtin/terminal/extension.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/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-config-schema.d.ts +4 -4
- package/dist/core/model-resolver.js +2 -2
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +2 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +74 -37
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/retry-fallback/chains.d.ts +23 -1
- package/dist/core/retry-fallback/chains.d.ts.map +1 -1
- package/dist/core/retry-fallback/chains.js +59 -3
- package/dist/core/retry-fallback/chains.js.map +1 -1
- package/dist/core/retry-fallback/controller.d.ts.map +1 -1
- package/dist/core/retry-fallback/controller.js +9 -2
- package/dist/core/retry-fallback/controller.js.map +1 -1
- package/dist/core/retry-fallback/settings.d.ts.map +1 -1
- package/dist/core/retry-fallback/settings.js +9 -0
- package/dist/core/retry-fallback/settings.js.map +1 -1
- package/dist/core/retry-fallback/validate.js +1 -1
- package/dist/core/retry-fallback/validate.js.map +1 -1
- package/dist/core/sdk.js +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +9 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +40 -0
- 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/main.d.ts +7 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +27 -6
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/favorite-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/favorite-models-selector.js +2 -2
- package/dist/modes/interactive/components/favorite-models-selector.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 +121 -1
- package/dist/modes/interactive/interactive-host-runtime.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-host-runtime.js +606 -45
- 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 +390 -239
- 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 +268 -63
- 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 +20 -8
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +91 -16
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +131 -37
- 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-mode.d.ts +3 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +3 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +248 -3
- 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 +22 -0
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +148 -16
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +4 -0
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +58 -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 +17 -2
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +67 -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 +55 -2
- package/docs/settings.md +34 -0
- package/docs/windows.md +2 -0
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +74 -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/agent-loop.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +6 -3
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- 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/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/baseten.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/huggingface.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/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/vercel-ai-gateway.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/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
|
@@ -14,10 +14,11 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { randomUUID } from "node:crypto";
|
|
16
16
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
17
|
+
import { rm } from "node:fs/promises";
|
|
17
18
|
import { basename, dirname } from "node:path";
|
|
18
19
|
import { isDeepStrictEqual } from "node:util";
|
|
19
20
|
import { ProviderRetryWatchdogAbortError, prepareAgentToolCall } from "@earendil-works/pi-agent-core";
|
|
20
|
-
import { contentText, SERVER_FALLBACK_ABORTED_DIAGNOSTIC } from "@earendil-works/pi-ai";
|
|
21
|
+
import { contentText, measureCursorHistorySerializedBytes, SERVER_FALLBACK_ABORTED_DIAGNOSTIC, } from "@earendil-works/pi-ai";
|
|
21
22
|
import { cleanupSessionResources, cursorOverflowCompactionSettings, isClassifierRefusal, isContextOverflow, isCursorPayloadResourceExhausted, isCursorQuotaResourceExhausted, isCursorZeroTokenResourceExhausted, isProviderStreamStallError, isProviderTimeoutError, isRecoverableLength, isRetryableAssistantError, modelsAreEqual, resetApiProviders, shouldRetryOverflowWithoutCompact, streamSimple, } from "@earendil-works/pi-ai/compat";
|
|
22
23
|
import { extract429RetryAfterMs, parseRetryAfterMsMarker } from "@earendil-works/pi-ai/utils/retry-hint";
|
|
23
24
|
import { retryBackoffDelayMs } from "@earendil-works/pi-ai/utils/retry-profile/backoff";
|
|
@@ -40,6 +41,7 @@ import { buildDynamicSystemPrompt } from "./dynamic-prompt/index.js";
|
|
|
40
41
|
import { areExperimentalFeaturesEnabled } from "./experimental.js";
|
|
41
42
|
import { exportSessionToHtml } from "./export-html/index.js";
|
|
42
43
|
import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
|
|
44
|
+
import { resolveReserveTokens } from "./extensions/builtin/compaction/policy.js";
|
|
43
45
|
import { CODEX_RESPONSES_API } from "./extensions/builtin/service-tier.js";
|
|
44
46
|
import { deriveExtensionRegistrationId } from "./extensions/builtin/tool-search/engine/marker.js";
|
|
45
47
|
import { getToolSearchService } from "./extensions/builtin/tool-search/service.js";
|
|
@@ -47,7 +49,7 @@ import { ExecuteToolError, ExtensionRunner, wrapRegisteredTools, } from "./exten
|
|
|
47
49
|
import { emitSessionShutdownEvent } from "./extensions/runner.js";
|
|
48
50
|
import { normalizeToolExposure, RUNTIME_EXTENSION_PATH } from "./extensions/types.js";
|
|
49
51
|
import { shouldWarnHighReasoning } from "./high-reasoning-warning.js";
|
|
50
|
-
import { filterContextExcludedMessages } from "./messages.js";
|
|
52
|
+
import { convertToLlm, filterContextExcludedMessages, } from "./messages.js";
|
|
51
53
|
import { ModelRegistry } from "./model-registry.js";
|
|
52
54
|
import { getModelNarrowingPatterns, resolveModelScope } from "./model-resolver.js";
|
|
53
55
|
import { PROMPT_CACHE_SAFE_WAIT_ENV, resolvePromptCacheSafeWaitSeconds } from "./prompt-cache-budget.js";
|
|
@@ -70,9 +72,21 @@ import { getSupportedThinkingLevels, supportsMax, supportsXhigh } from "./thinki
|
|
|
70
72
|
import { resetTimings, time } from "./timings.js";
|
|
71
73
|
import { createLocalBashOperations } from "./tools/bash.js";
|
|
72
74
|
import { composeFilesystemPolicies } from "./tools/filesystem-policy.js";
|
|
73
|
-
import { createAllToolDefinitions } from "./tools/index.js";
|
|
75
|
+
import { createAllToolDefinitions, temporarilyDisabledToolNames } from "./tools/index.js";
|
|
74
76
|
import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
|
|
75
77
|
import { addUsageToTotals, createUsageTotals } from "./usage-totals.js";
|
|
78
|
+
/** Built-in shell tools routed exclusively through eval when experimental.bashEvalOnly is enabled. */
|
|
79
|
+
const EVAL_ONLY_SHELL_TOOL_NAMES = ["bash", "powershell"];
|
|
80
|
+
/** Workflow tool routed exclusively through eval when experimental.workflowEvalOnly is enabled. */
|
|
81
|
+
const EVAL_ONLY_WORKFLOW_TOOL_NAMES = ["workflow"];
|
|
82
|
+
/** Sample eval-cell call for an eval-only tool, using the argument name that tool actually takes. */
|
|
83
|
+
function evalHelperCall(name) {
|
|
84
|
+
if (EVAL_ONLY_SHELL_TOOL_NAMES.includes(name))
|
|
85
|
+
return `tool.${name}({ command: "..." })`;
|
|
86
|
+
if (EVAL_ONLY_WORKFLOW_TOOL_NAMES.includes(name))
|
|
87
|
+
return `tool.${name}({ action: "..." })`;
|
|
88
|
+
return `tool.${name}({ ... })`;
|
|
89
|
+
}
|
|
76
90
|
const TURN_RETRY_SUPPRESSION_PREFIX = "senpi:no-turn-retry:";
|
|
77
91
|
const DEFERRED_RETRY_QUEUE_OWNERS = new WeakSet();
|
|
78
92
|
/** Format the user-attributed payload for one or more explicit skill invocations. */
|
|
@@ -310,6 +324,121 @@ function isSameOverflowSource(message, model, upstreamModelId) {
|
|
|
310
324
|
const THINKING_LEVELS_WITH_MAX = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
311
325
|
/** Caps explicit skill expansion so one prompt cannot consume unbounded context. */
|
|
312
326
|
export const MAX_SKILL_EXPANSIONS_PER_PROMPT = 5;
|
|
327
|
+
/** Cursor ingest rejects large verbatim tool payloads. The bound is UTF-8 bytes. */
|
|
328
|
+
export const CURSOR_TOOL_RESULT_MAX_CHARS = 2000;
|
|
329
|
+
export const CURSOR_TOOL_RESULT_MAX_BYTES = 50_000;
|
|
330
|
+
const CURSOR_TRUNCATION_MARKER = "\n...[truncated]";
|
|
331
|
+
export function truncateToolResultBodies(messages, maxChars = CURSOR_TOOL_RESULT_MAX_CHARS, maxBytes = CURSOR_TOOL_RESULT_MAX_BYTES, convert = (candidate) => convertToLlm(candidate)) {
|
|
332
|
+
if (!Array.isArray(messages) || messages.length === 0)
|
|
333
|
+
return { messages, changed: false };
|
|
334
|
+
const segmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
335
|
+
const markerChars = [...segmenter.segment(CURSOR_TRUNCATION_MARKER)].length;
|
|
336
|
+
const result = messages.slice();
|
|
337
|
+
let changed = false;
|
|
338
|
+
// Apply the per-result character cap first, independent of the aggregate wire cap.
|
|
339
|
+
for (let messageIndex = result.length - 1; messageIndex >= 0; messageIndex--) {
|
|
340
|
+
const message = result[messageIndex];
|
|
341
|
+
if (message.role !== "toolResult" || !Array.isArray(message.content))
|
|
342
|
+
continue;
|
|
343
|
+
let content = message.content;
|
|
344
|
+
for (let partIndex = content.length - 1; partIndex >= 0; partIndex--) {
|
|
345
|
+
const part = content[partIndex];
|
|
346
|
+
if (part.type === "image" && typeof part.data === "string")
|
|
347
|
+
continue;
|
|
348
|
+
if (part.type !== "text" || typeof part.text !== "string")
|
|
349
|
+
continue;
|
|
350
|
+
const graphemes = [...segmenter.segment(part.text)].map((item) => item.segment);
|
|
351
|
+
if (graphemes.length <= maxChars)
|
|
352
|
+
continue;
|
|
353
|
+
const kept = graphemes.slice(0, Math.max(0, maxChars - markerChars)).join("");
|
|
354
|
+
const nextText = kept + CURSOR_TRUNCATION_MARKER;
|
|
355
|
+
content = content === message.content ? content.slice() : content;
|
|
356
|
+
content[partIndex] = { ...part, text: nextText };
|
|
357
|
+
result[messageIndex] = { ...message, content };
|
|
358
|
+
changed = true;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
const measure = (candidate) => {
|
|
362
|
+
const converted = convert(candidate);
|
|
363
|
+
const activeUserMessageIndex = converted.at(-1)?.role === "user" ? converted.length - 1 : -1;
|
|
364
|
+
return measureCursorHistorySerializedBytes(converted, activeUserMessageIndex);
|
|
365
|
+
};
|
|
366
|
+
const fits = (candidate = result) => measure(candidate) <= maxBytes;
|
|
367
|
+
if (fits())
|
|
368
|
+
return { messages: changed ? result : messages, changed };
|
|
369
|
+
// Empty the oldest result bodies. Search the monotonic prefix of candidates
|
|
370
|
+
// rather than serializing once for every result (admission must stay bounded).
|
|
371
|
+
const emptyToolResult = (message) => {
|
|
372
|
+
if (message.role !== "toolResult" || !Array.isArray(message.content))
|
|
373
|
+
return message;
|
|
374
|
+
const emptiedContent = message.content.map((part) => part.type === "text" ? { ...part, text: "" } : part.type === "image" ? { ...part, data: "" } : part);
|
|
375
|
+
const content = emptiedContent.filter((part, index) => {
|
|
376
|
+
if (index === 0)
|
|
377
|
+
return true;
|
|
378
|
+
const previous = emptiedContent[index - 1];
|
|
379
|
+
const empty = part.type === "text" ? part.text === "" : part.type === "image" && part.data === "";
|
|
380
|
+
const previousEmpty = previous.type === "text" ? previous.text === "" : previous.type === "image" && previous.data === "";
|
|
381
|
+
return !empty || !previousEmpty;
|
|
382
|
+
});
|
|
383
|
+
return { ...message, content };
|
|
384
|
+
};
|
|
385
|
+
const toolResultIndexes = result.flatMap((message, index) => message.role === "toolResult" && Array.isArray(message.content) ? [index] : []);
|
|
386
|
+
const withEmptyPrefix = (count) => {
|
|
387
|
+
const candidate = result.slice();
|
|
388
|
+
for (let i = 0; i < count; i++)
|
|
389
|
+
candidate[toolResultIndexes[i]] = emptyToolResult(candidate[toolResultIndexes[i]]);
|
|
390
|
+
return candidate;
|
|
391
|
+
};
|
|
392
|
+
let low = 0;
|
|
393
|
+
let high = toolResultIndexes.length;
|
|
394
|
+
while (low < high) {
|
|
395
|
+
const middle = Math.floor((low + high) / 2);
|
|
396
|
+
if (fits(withEmptyPrefix(middle + 1)))
|
|
397
|
+
high = middle;
|
|
398
|
+
else
|
|
399
|
+
low = middle + 1;
|
|
400
|
+
}
|
|
401
|
+
const emptyCount = Math.min(low + 1, toolResultIndexes.length);
|
|
402
|
+
if (emptyCount > 0) {
|
|
403
|
+
result.splice(0, result.length, ...withEmptyPrefix(emptyCount));
|
|
404
|
+
changed = true;
|
|
405
|
+
}
|
|
406
|
+
if (fits())
|
|
407
|
+
return { messages: changed ? result : messages, changed };
|
|
408
|
+
// If metadata alone exceeds the cap, discard the oldest complete turns. This
|
|
409
|
+
// search is also monotonic and avoids quadratic whole-history reserialization.
|
|
410
|
+
const turnRanges = [];
|
|
411
|
+
const isConvertedUser = (message) => convert([message])[0]?.role === "user";
|
|
412
|
+
for (let index = 0; index < result.length; index++) {
|
|
413
|
+
if (!isConvertedUser(result[index]))
|
|
414
|
+
continue;
|
|
415
|
+
const nextUser = result.findIndex((message, nextIndex) => nextIndex > index && isConvertedUser(message));
|
|
416
|
+
turnRanges.push([index, nextUser < 0 ? result.length : nextUser]);
|
|
417
|
+
}
|
|
418
|
+
const withoutTurns = (count) => {
|
|
419
|
+
if (count === 0)
|
|
420
|
+
return result;
|
|
421
|
+
const start = turnRanges[0]?.[0] ?? 0;
|
|
422
|
+
const end = turnRanges[count - 1]?.[1] ?? start;
|
|
423
|
+
return [...result.slice(0, start), ...result.slice(end)];
|
|
424
|
+
};
|
|
425
|
+
low = 0;
|
|
426
|
+
high = turnRanges.length;
|
|
427
|
+
while (low < high) {
|
|
428
|
+
const middle = Math.floor((low + high) / 2);
|
|
429
|
+
if (fits(withoutTurns(middle + 1)))
|
|
430
|
+
high = middle;
|
|
431
|
+
else
|
|
432
|
+
low = middle + 1;
|
|
433
|
+
}
|
|
434
|
+
const turnCount = Math.min(low + 1, turnRanges.length);
|
|
435
|
+
if (turnCount > 0) {
|
|
436
|
+
const next = withoutTurns(turnCount);
|
|
437
|
+
result.splice(0, result.length, ...next);
|
|
438
|
+
changed = true;
|
|
439
|
+
}
|
|
440
|
+
return { messages: changed ? result : messages, changed };
|
|
441
|
+
}
|
|
313
442
|
// ============================================================================
|
|
314
443
|
// AgentSession Class
|
|
315
444
|
// ============================================================================
|
|
@@ -395,6 +524,10 @@ export class AgentSession {
|
|
|
395
524
|
this._pendingBashMessages = [];
|
|
396
525
|
this._turnIndex = 0;
|
|
397
526
|
this._baseToolDefinitions = new Map();
|
|
527
|
+
/** Policy tools withheld from the model, retained so disarming can restore direct access. */
|
|
528
|
+
this._withheldEvalOnlyToolNames = new Set();
|
|
529
|
+
/** Eval-only hint names this session published, so a disarm can withdraw exactly those. */
|
|
530
|
+
this._publishedEvalOnlyHintNames = new Set();
|
|
398
531
|
this._extensionMode = "print";
|
|
399
532
|
// Tool registry for extension getTools/setTools
|
|
400
533
|
this._toolRegistry = new Map();
|
|
@@ -516,6 +649,8 @@ export class AgentSession {
|
|
|
516
649
|
this._extensionRunnerRef = config.extensionRunnerRef;
|
|
517
650
|
this._initialActiveToolNames = config.initialActiveToolNames;
|
|
518
651
|
this._defaultToolNames = config.defaultToolNames ? new Set(config.defaultToolNames) : undefined;
|
|
652
|
+
this._evalOnlyToolNamesOverride = config.evalOnlyToolNames ? new Set(config.evalOnlyToolNames) : undefined;
|
|
653
|
+
this._evalOnlyToolNames = this._resolveEvalOnlyToolNames();
|
|
519
654
|
this._allowedToolNames = config.allowedToolNames ? new Set(config.allowedToolNames) : undefined;
|
|
520
655
|
this._excludedToolNames = config.excludedToolNames ? new Set(config.excludedToolNames) : undefined;
|
|
521
656
|
this._baseToolsOverride = config.baseToolsOverride;
|
|
@@ -727,6 +862,14 @@ export class AgentSession {
|
|
|
727
862
|
(this.agent.prepareNextTurn
|
|
728
863
|
? async (_turn, signal) => await this.agent.prepareNextTurn?.(signal)
|
|
729
864
|
: undefined);
|
|
865
|
+
const previousTransformContext = this.agent.transformContext;
|
|
866
|
+
this.agent.transformContext = async (messages, signal) => {
|
|
867
|
+
const transformed = previousTransformContext ? await previousTransformContext(messages, signal) : messages;
|
|
868
|
+
if (this.model?.provider === "cursor" || this.model?.provider === "cursor-cli-oauth") {
|
|
869
|
+
return ((await truncateToolResultBodies(transformed, CURSOR_TOOL_RESULT_MAX_CHARS, CURSOR_TOOL_RESULT_MAX_BYTES, (candidate) => this.agent.convertToLlm(candidate))).messages ?? transformed);
|
|
870
|
+
}
|
|
871
|
+
return transformed;
|
|
872
|
+
};
|
|
730
873
|
this.agent.prepareNextTurnWithContext = async (turn, signal) => {
|
|
731
874
|
// Enforce compaction only when this prepare precedes an actual provider
|
|
732
875
|
// admission: a tool continuation or queued steer/follow-up messages. A
|
|
@@ -735,7 +878,8 @@ export class AgentSession {
|
|
|
735
878
|
const compactBeforeNextAdmission = async () => {
|
|
736
879
|
const provider = this.model?.provider;
|
|
737
880
|
// Cursor rebuilds the full conversation each hop. Compacting here
|
|
738
|
-
// mutates rootPrompt mid-run and poisons conversationId.
|
|
881
|
+
// mutates rootPrompt mid-run and poisons conversationId (#984).
|
|
882
|
+
// Still truncate verbatim toolResult bodies so the skip cannot send MB-scale payloads (#1043).
|
|
739
883
|
if (provider === "cursor" || provider === "cursor-cli-oauth") {
|
|
740
884
|
return false;
|
|
741
885
|
}
|
|
@@ -816,6 +960,19 @@ export class AgentSession {
|
|
|
816
960
|
// Event Subscription
|
|
817
961
|
// =========================================================================
|
|
818
962
|
/** Emit an event to all listeners */
|
|
963
|
+
_emitEntryAppended(entryId) {
|
|
964
|
+
if (this._extensionMode !== "rpc")
|
|
965
|
+
return;
|
|
966
|
+
const entry = this.sessionManager.getEntry(entryId);
|
|
967
|
+
if (entry)
|
|
968
|
+
this._emit({ type: "entry_appended", entry });
|
|
969
|
+
}
|
|
970
|
+
/** Append a transport-provided entry and publish it on the RPC event stream. */
|
|
971
|
+
appendSessionEntry(entry) {
|
|
972
|
+
this.sessionManager.appendEntry(entry);
|
|
973
|
+
this.agent.state.messages = this.sessionManager.buildSessionContext().messages;
|
|
974
|
+
this._emitEntryAppended(entry.id);
|
|
975
|
+
}
|
|
819
976
|
_emit(event) {
|
|
820
977
|
this._logSessionEvent(event);
|
|
821
978
|
for (const l of this._eventListeners) {
|
|
@@ -934,6 +1091,7 @@ export class AgentSession {
|
|
|
934
1091
|
type: "queue_update",
|
|
935
1092
|
steering: [...this._steeringMessages],
|
|
936
1093
|
followUp: [...this._followUpMessages],
|
|
1094
|
+
ordered: [...this._queuedInputOrder].sort((a, b) => a.enqueueOrder - b.enqueueOrder),
|
|
937
1095
|
});
|
|
938
1096
|
}
|
|
939
1097
|
_incrementMessageRevision() {
|
|
@@ -975,6 +1133,7 @@ export class AgentSession {
|
|
|
975
1133
|
_invalidateCompactionForModelSelection() {
|
|
976
1134
|
this.abortCompaction();
|
|
977
1135
|
this.abortBranchSummary();
|
|
1136
|
+
this._delegatedCompactionKey = undefined;
|
|
978
1137
|
this._incrementMessageRevision();
|
|
979
1138
|
}
|
|
980
1139
|
_getIdleWaitPromise() {
|
|
@@ -1366,7 +1525,7 @@ export class AgentSession {
|
|
|
1366
1525
|
event.message.role === "assistant" ||
|
|
1367
1526
|
event.message.role === "toolResult") {
|
|
1368
1527
|
// Regular LLM message - persist as SessionMessageEntry
|
|
1369
|
-
this.sessionManager.appendMessage(event.message);
|
|
1528
|
+
this._emitEntryAppended(this.sessionManager.appendMessage(event.message));
|
|
1370
1529
|
this._incrementMessageRevision();
|
|
1371
1530
|
}
|
|
1372
1531
|
// Other message types (bashExecution, compactionSummary, branchSummary) are persisted elsewhere
|
|
@@ -2000,6 +2159,9 @@ export class AgentSession {
|
|
|
2000
2159
|
async executeTool(toolName, params, options) {
|
|
2001
2160
|
let activeTools = this.getActiveToolNames();
|
|
2002
2161
|
let tool = this.agent.state.tools.find((candidate) => candidate.name === toolName);
|
|
2162
|
+
if (!tool && this._isEvalOnlyPolicyArmed() && this._evalOnlyToolNames?.has(toolName)) {
|
|
2163
|
+
tool = this._toolRegistry.get(toolName);
|
|
2164
|
+
}
|
|
2003
2165
|
if (!tool &&
|
|
2004
2166
|
options?.activateInactiveTool === true &&
|
|
2005
2167
|
this._toolDefinitions.has(toolName) &&
|
|
@@ -2074,6 +2236,45 @@ export class AgentSession {
|
|
|
2074
2236
|
return false;
|
|
2075
2237
|
return this._lazyToolActivators.some((activate) => activate(toolName));
|
|
2076
2238
|
}
|
|
2239
|
+
_isEvalOnlyPolicyArmed() {
|
|
2240
|
+
return this._evalOnlyToolNames !== undefined && this._toolRegistry.has("eval");
|
|
2241
|
+
}
|
|
2242
|
+
/**
|
|
2243
|
+
* Resolve the eval-only policy from settings so a reload picks up a flag change.
|
|
2244
|
+
* An explicitly configured set stays authoritative for SDK embedders and tests.
|
|
2245
|
+
*/
|
|
2246
|
+
_resolveEvalOnlyToolNames() {
|
|
2247
|
+
if (this._evalOnlyToolNamesOverride !== undefined)
|
|
2248
|
+
return this._evalOnlyToolNamesOverride;
|
|
2249
|
+
const names = [
|
|
2250
|
+
...(this.settingsManager.getExperimentalBashEvalOnly() ? EVAL_ONLY_SHELL_TOOL_NAMES : []),
|
|
2251
|
+
...(this.settingsManager.getExperimentalWorkflowEvalOnly() ? EVAL_ONLY_WORKFLOW_TOOL_NAMES : []),
|
|
2252
|
+
];
|
|
2253
|
+
return names.length > 0 ? new Set(names) : undefined;
|
|
2254
|
+
}
|
|
2255
|
+
/**
|
|
2256
|
+
* Publish per-tool eval-only redirect hints so a direct call names its own eval helper.
|
|
2257
|
+
*
|
|
2258
|
+
* Hints published here are tracked so a disarm - or a shrinking armed set, e.g. bash+workflow
|
|
2259
|
+
* down to workflow only - withdraws the stale ones. Only tracked names are ever deleted, so
|
|
2260
|
+
* hints owned by other publishers survive.
|
|
2261
|
+
*/
|
|
2262
|
+
_publishEvalOnlyToolHints() {
|
|
2263
|
+
const armed = this._isEvalOnlyPolicyArmed() ? (this._evalOnlyToolNames ?? new Set()) : undefined;
|
|
2264
|
+
for (const name of this._publishedEvalOnlyHintNames) {
|
|
2265
|
+
if (armed?.has(name))
|
|
2266
|
+
continue;
|
|
2267
|
+
delete this.agent.removedToolHints[name];
|
|
2268
|
+
}
|
|
2269
|
+
this._publishedEvalOnlyHintNames.clear();
|
|
2270
|
+
if (!armed)
|
|
2271
|
+
return;
|
|
2272
|
+
for (const name of armed) {
|
|
2273
|
+
this.agent.removedToolHints[name] =
|
|
2274
|
+
`Run ${name} inside an eval cell via ${evalHelperCall(name)}; hooks and permissions still apply.`;
|
|
2275
|
+
this._publishedEvalOnlyHintNames.add(name);
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2077
2278
|
/**
|
|
2078
2279
|
* Set active tools by name.
|
|
2079
2280
|
* Only tools in the registry can be enabled. Unknown tool names are ignored.
|
|
@@ -2101,7 +2302,23 @@ export class AgentSession {
|
|
|
2101
2302
|
setActiveToolsByName(toolNames) {
|
|
2102
2303
|
const tools = [];
|
|
2103
2304
|
const validToolNames = [];
|
|
2104
|
-
|
|
2305
|
+
const policyArmed = this._isEvalOnlyPolicyArmed();
|
|
2306
|
+
this._publishEvalOnlyToolHints();
|
|
2307
|
+
const policyNames = this._evalOnlyToolNames;
|
|
2308
|
+
let filteredToolNames = toolNames;
|
|
2309
|
+
if (policyArmed && policyNames) {
|
|
2310
|
+
for (const name of toolNames) {
|
|
2311
|
+
if (policyNames.has(name))
|
|
2312
|
+
this._withheldEvalOnlyToolNames.add(name);
|
|
2313
|
+
}
|
|
2314
|
+
filteredToolNames = toolNames.filter((name) => !policyNames.has(name));
|
|
2315
|
+
}
|
|
2316
|
+
else {
|
|
2317
|
+
this._withheldEvalOnlyToolNames.clear();
|
|
2318
|
+
}
|
|
2319
|
+
// Remember the unfiltered request so a later disarm can restore withheld shell tools.
|
|
2320
|
+
this._requestedActiveToolNames = [...new Set([...toolNames, ...this._withheldEvalOnlyToolNames])];
|
|
2321
|
+
for (const name of filteredToolNames) {
|
|
2105
2322
|
const tool = this._toolRegistry.get(name);
|
|
2106
2323
|
if (tool) {
|
|
2107
2324
|
tools.push(tool);
|
|
@@ -2115,8 +2332,14 @@ export class AgentSession {
|
|
|
2115
2332
|
this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames);
|
|
2116
2333
|
this.agent.state.systemPrompt = this._systemPromptOverride ?? this._baseSystemPrompt;
|
|
2117
2334
|
if (activeToolNamesChanged) {
|
|
2118
|
-
|
|
2119
|
-
|
|
2335
|
+
// A tool change emitted while extensions are still binding belongs to the
|
|
2336
|
+
// binding itself, not to a mid-session change. The session was already
|
|
2337
|
+
// committed to the client, so cancelling or invalidating work it started
|
|
2338
|
+
// against that session would be spurious.
|
|
2339
|
+
if (this._extensionBindingPromptReadiness === undefined) {
|
|
2340
|
+
this.abortCompaction();
|
|
2341
|
+
this._incrementMessageRevision();
|
|
2342
|
+
}
|
|
2120
2343
|
}
|
|
2121
2344
|
}
|
|
2122
2345
|
/** Whether compaction or branch summarization is currently running */
|
|
@@ -2258,9 +2481,26 @@ export class AgentSession {
|
|
|
2258
2481
|
appendSystemPrompt: loaderAppendSystemPrompt.length > 0 ? loaderAppendSystemPrompt.join("\n\n") : undefined,
|
|
2259
2482
|
};
|
|
2260
2483
|
const basePrompt = loaderSystemPrompt ?? buildDynamicSystemPrompt(this._baseSystemPromptOptions);
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2484
|
+
const prompt = loaderAppendSystemPrompt.length > 0 ? `${basePrompt}\n\n${loaderAppendSystemPrompt.join("\n\n")}` : basePrompt;
|
|
2485
|
+
if (!this._isEvalOnlyPolicyArmed())
|
|
2486
|
+
return prompt;
|
|
2487
|
+
const armed = this._evalOnlyToolNames ?? new Set();
|
|
2488
|
+
const sentences = [];
|
|
2489
|
+
const shellHelpers = EVAL_ONLY_SHELL_TOOL_NAMES.filter((name) => armed.has(name)).map(evalHelperCall);
|
|
2490
|
+
if (shellHelpers.length > 0) {
|
|
2491
|
+
sentences.push(`Shell commands run ONLY inside eval cells via ${shellHelpers.join(" or ")}; hooks and permissions still apply.`);
|
|
2492
|
+
}
|
|
2493
|
+
if (armed.has("workflow")) {
|
|
2494
|
+
sentences.push(`The workflow tool runs ONLY inside eval cells via ${evalHelperCall("workflow")}; hooks and permissions still apply.`);
|
|
2495
|
+
}
|
|
2496
|
+
// SDK embedders can arm names outside the built-in groups; they still need eval guidance.
|
|
2497
|
+
const otherHelpers = [...armed]
|
|
2498
|
+
.filter((name) => !EVAL_ONLY_SHELL_TOOL_NAMES.includes(name) && name !== "workflow")
|
|
2499
|
+
.map(evalHelperCall);
|
|
2500
|
+
if (otherHelpers.length > 0) {
|
|
2501
|
+
sentences.push(`These tools run ONLY inside eval cells via ${otherHelpers.join(" or ")}; hooks and permissions still apply.`);
|
|
2502
|
+
}
|
|
2503
|
+
return sentences.length > 0 ? `${prompt}\n\n${sentences.join("\n\n")}` : prompt;
|
|
2264
2504
|
}
|
|
2265
2505
|
/**
|
|
2266
2506
|
* Send a prompt to the agent.
|
|
@@ -3052,7 +3292,7 @@ export class AgentSession {
|
|
|
3052
3292
|
}
|
|
3053
3293
|
_appendCustomMessage(appMessage) {
|
|
3054
3294
|
this.agent.state.messages.push(appMessage);
|
|
3055
|
-
this.sessionManager.appendCustomMessageEntry(appMessage.customType, appMessage.content, appMessage.display, appMessage.details);
|
|
3295
|
+
this._emitEntryAppended(this.sessionManager.appendCustomMessageEntry(appMessage.customType, appMessage.content, appMessage.display, appMessage.details));
|
|
3056
3296
|
this._incrementMessageRevision();
|
|
3057
3297
|
this._emit({ type: "message_start", message: appMessage });
|
|
3058
3298
|
this._emit({ type: "message_end", message: appMessage });
|
|
@@ -3335,7 +3575,10 @@ export class AgentSession {
|
|
|
3335
3575
|
}
|
|
3336
3576
|
async _switchActiveModel(model, opts) {
|
|
3337
3577
|
const previousModel = this.model;
|
|
3338
|
-
if (opts.invalidateCompaction &&
|
|
3578
|
+
if (opts.invalidateCompaction &&
|
|
3579
|
+
(this._modelSelectionChangesContext(previousModel, model) ||
|
|
3580
|
+
previousModel?.provider !== model.provider ||
|
|
3581
|
+
previousModel?.id !== model.id)) {
|
|
3339
3582
|
this._invalidateCompactionForModelSelection();
|
|
3340
3583
|
}
|
|
3341
3584
|
const thinking = this._getThinkingForModelSwitch(model, opts.ephemeralThinkingLevel);
|
|
@@ -3407,7 +3650,9 @@ export class AgentSession {
|
|
|
3407
3650
|
nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
|
|
3408
3651
|
}
|
|
3409
3652
|
const next = favoriteModels[nextIndex];
|
|
3410
|
-
const invalidatesCompaction = this._modelSelectionChangesContext(currentModel, next.model)
|
|
3653
|
+
const invalidatesCompaction = this._modelSelectionChangesContext(currentModel, next.model) ||
|
|
3654
|
+
currentModel?.provider !== next.model.provider ||
|
|
3655
|
+
currentModel?.id !== next.model.id;
|
|
3411
3656
|
if (invalidatesCompaction) {
|
|
3412
3657
|
this._invalidateCompactionForModelSelection();
|
|
3413
3658
|
}
|
|
@@ -3609,6 +3854,7 @@ export class AgentSession {
|
|
|
3609
3854
|
setSteeringMode(mode) {
|
|
3610
3855
|
this.agent.steeringMode = mode;
|
|
3611
3856
|
this.settingsManager.setSteeringMode(mode);
|
|
3857
|
+
this._emitSessionSettingsChanged();
|
|
3612
3858
|
}
|
|
3613
3859
|
/**
|
|
3614
3860
|
* Set follow-up message mode.
|
|
@@ -3617,6 +3863,7 @@ export class AgentSession {
|
|
|
3617
3863
|
setFollowUpMode(mode) {
|
|
3618
3864
|
this.agent.followUpMode = mode;
|
|
3619
3865
|
this.settingsManager.setFollowUpMode(mode);
|
|
3866
|
+
this._emitSessionSettingsChanged();
|
|
3620
3867
|
}
|
|
3621
3868
|
// =========================================================================
|
|
3622
3869
|
// Compaction
|
|
@@ -4099,7 +4346,7 @@ export class AgentSession {
|
|
|
4099
4346
|
if (sourceChanged) {
|
|
4100
4347
|
return await this._rejectCompaction(request, requestId, operationId, "stale-revision", false);
|
|
4101
4348
|
}
|
|
4102
|
-
if (this._wouldCompactionOverflow(pathEntries, compactionResult, fromExtension, model)) {
|
|
4349
|
+
if (await this._wouldCompactionOverflow(pathEntries, compactionResult, fromExtension, model)) {
|
|
4103
4350
|
return await this._rejectCompaction(request, requestId, operationId, "would-overflow", false);
|
|
4104
4351
|
}
|
|
4105
4352
|
const compactionEntryId = this.sessionManager.appendCompaction(compactionResult.summary, compactionResult.firstKeptEntryId, compactionResult.tokensBefore, compactionResult.details, fromExtension, compactionResult.usage);
|
|
@@ -4140,6 +4387,7 @@ export class AgentSession {
|
|
|
4140
4387
|
})) {
|
|
4141
4388
|
throw new CompactionCancelledError();
|
|
4142
4389
|
}
|
|
4390
|
+
this._delegatedCompactionKey = undefined;
|
|
4143
4391
|
if (request.owner === "compaction" && this._compactionAbortController === request.controller) {
|
|
4144
4392
|
this._compactionAbortController = undefined;
|
|
4145
4393
|
}
|
|
@@ -4190,7 +4438,7 @@ export class AgentSession {
|
|
|
4190
4438
|
finishCompactionWork();
|
|
4191
4439
|
}
|
|
4192
4440
|
}
|
|
4193
|
-
_wouldCompactionOverflow(pathEntries, compactionResult, fromExtension, model) {
|
|
4441
|
+
async _wouldCompactionOverflow(pathEntries, compactionResult, fromExtension, model) {
|
|
4194
4442
|
const currentLeaf = pathEntries[pathEntries.length - 1];
|
|
4195
4443
|
if (!currentLeaf)
|
|
4196
4444
|
return false;
|
|
@@ -4205,10 +4453,18 @@ export class AgentSession {
|
|
|
4205
4453
|
details: compactionResult.details,
|
|
4206
4454
|
fromHook: fromExtension,
|
|
4207
4455
|
};
|
|
4208
|
-
|
|
4456
|
+
let simulatedMessages = buildSessionContext([...pathEntries, simulatedCompactionEntry], simulatedCompactionEntry.id).messages;
|
|
4457
|
+
// Size the same retained context that will be admitted to Cursor. Persisted JSONL
|
|
4458
|
+
// remains verbatim, but the in-memory request representation is bounded first.
|
|
4459
|
+
if (model.provider === "cursor" || model.provider === "cursor-cli-oauth") {
|
|
4460
|
+
simulatedMessages = truncateToolResultBodies(simulatedMessages).messages ?? simulatedMessages;
|
|
4461
|
+
}
|
|
4209
4462
|
const contextTokens = estimateMessagesTokens(filterContextExcludedMessages(simulatedMessages));
|
|
4210
4463
|
const settings = this.settingsManager.getCompactionSettings();
|
|
4211
|
-
|
|
4464
|
+
const reserveTokens = settings.reserveScalingEnabled === false
|
|
4465
|
+
? settings.reserveTokens
|
|
4466
|
+
: resolveReserveTokens(model.contextWindow, settings.reserveTokens);
|
|
4467
|
+
return contextTokens > model.contextWindow - reserveTokens;
|
|
4212
4468
|
}
|
|
4213
4469
|
/**
|
|
4214
4470
|
* Replaces agent state with the canonical session context while keeping exact
|
|
@@ -4236,6 +4492,9 @@ export class AgentSession {
|
|
|
4236
4492
|
// also emitted with accepted:false so the compaction extension's circuit-breaker
|
|
4237
4493
|
// bookkeeping stops being dead code; other builtin session_compact handlers guard
|
|
4238
4494
|
// on event.accepted.
|
|
4495
|
+
if (rejectionCause === "external-owner" && this.model) {
|
|
4496
|
+
this._delegatedCompactionKey = { provider: this.model.provider, id: this.model.id };
|
|
4497
|
+
}
|
|
4239
4498
|
const trimmedExtensionReason = extensionReason?.trim();
|
|
4240
4499
|
const detailedMessage = trimmedExtensionReason
|
|
4241
4500
|
? `Compaction rejected: ${trimmedExtensionReason}`
|
|
@@ -4369,6 +4628,9 @@ export class AgentSession {
|
|
|
4369
4628
|
if (!model)
|
|
4370
4629
|
return;
|
|
4371
4630
|
const settings = this.settingsManager.getCompactionSettings();
|
|
4631
|
+
const reserveTokens = settings.reserveScalingEnabled === false
|
|
4632
|
+
? settings.reserveTokens
|
|
4633
|
+
: resolveReserveTokens(model.contextWindow, settings.reserveTokens);
|
|
4372
4634
|
const isOversized = () => {
|
|
4373
4635
|
const providerMessages = filterContextExcludedMessages([...this.agent.state.messages, ...messages]);
|
|
4374
4636
|
const estimate = estimateContextTokens(providerMessages);
|
|
@@ -4379,7 +4641,7 @@ export class AgentSession {
|
|
|
4379
4641
|
const contextTokens = usageMessage?.role === "assistant" && this._isAssistantFromBeforeLatestCompaction(usageMessage)
|
|
4380
4642
|
? estimateMessagesTokens(providerMessages)
|
|
4381
4643
|
: estimate.tokens;
|
|
4382
|
-
return contextTokens > model.contextWindow -
|
|
4644
|
+
return contextTokens > model.contextWindow - reserveTokens;
|
|
4383
4645
|
};
|
|
4384
4646
|
if (!settings.enabled || !isOversized())
|
|
4385
4647
|
return;
|
|
@@ -4572,15 +4834,15 @@ export class AgentSession {
|
|
|
4572
4834
|
return claimant !== undefined && !claimant.signal.aborted;
|
|
4573
4835
|
}
|
|
4574
4836
|
_isCompactionDelegated() {
|
|
4575
|
-
const state = this._compactionLifecycle.state;
|
|
4576
4837
|
const model = this.model;
|
|
4577
|
-
return (
|
|
4578
|
-
state.rejectionCause === "external-owner" &&
|
|
4579
|
-
state.model !== undefined &&
|
|
4838
|
+
return (this._delegatedCompactionKey !== undefined &&
|
|
4580
4839
|
model !== undefined &&
|
|
4581
|
-
|
|
4840
|
+
this._delegatedCompactionKey.provider === model.provider &&
|
|
4841
|
+
this._delegatedCompactionKey.id === model.id);
|
|
4582
4842
|
}
|
|
4583
4843
|
async _runPrePromptCompaction(lastAssistantMessage, skipAbortedCheck, reason = "pre_prompt", willRetry = false, allowSummaryOnly = false) {
|
|
4844
|
+
if (this._isCompactionDelegated())
|
|
4845
|
+
return false;
|
|
4584
4846
|
const controller = new AbortController();
|
|
4585
4847
|
const requestId = randomUUID();
|
|
4586
4848
|
this._claimCompactionController(controller, "compaction");
|
|
@@ -4753,6 +5015,8 @@ export class AgentSession {
|
|
|
4753
5015
|
* @returns Whether the post-run loop should call `agent.continue()`
|
|
4754
5016
|
*/
|
|
4755
5017
|
async _runAutoCompaction(reason, willRetry) {
|
|
5018
|
+
if (this._isCompactionDelegated())
|
|
5019
|
+
return false;
|
|
4756
5020
|
const finishCompactionWork = this._sessionWorkBarrier.begin();
|
|
4757
5021
|
const agentMessagesAtStart = this.agent.state.messages.slice();
|
|
4758
5022
|
const autoCompactionController = new AbortController();
|
|
@@ -4886,6 +5150,15 @@ export class AgentSession {
|
|
|
4886
5150
|
*/
|
|
4887
5151
|
setAutoCompactionEnabled(enabled) {
|
|
4888
5152
|
this.settingsManager.setCompactionEnabled(enabled);
|
|
5153
|
+
this._emitSessionSettingsChanged();
|
|
5154
|
+
}
|
|
5155
|
+
_emitSessionSettingsChanged() {
|
|
5156
|
+
this._emit({
|
|
5157
|
+
type: "session_settings_changed",
|
|
5158
|
+
steeringMode: this.steeringMode,
|
|
5159
|
+
followUpMode: this.followUpMode,
|
|
5160
|
+
autoCompactionEnabled: this.autoCompactionEnabled,
|
|
5161
|
+
});
|
|
4889
5162
|
}
|
|
4890
5163
|
/** Whether auto-compaction is enabled */
|
|
4891
5164
|
get autoCompactionEnabled() {
|
|
@@ -4983,6 +5256,7 @@ export class AgentSession {
|
|
|
4983
5256
|
: undefined;
|
|
4984
5257
|
}
|
|
4985
5258
|
_refreshCurrentModelFromRegistry() {
|
|
5259
|
+
this._delegatedCompactionKey = undefined;
|
|
4986
5260
|
const currentModel = this.model;
|
|
4987
5261
|
if (!currentModel) {
|
|
4988
5262
|
return;
|
|
@@ -5307,8 +5581,11 @@ export class AgentSession {
|
|
|
5307
5581
|
}),
|
|
5308
5582
|
})),
|
|
5309
5583
|
].filter((tool) => isAllowedTool(tool.definition.name));
|
|
5584
|
+
// Withheld tools stay in _baseToolDefinitions (and therefore in _toolRegistry, which
|
|
5585
|
+
// getRegisteredTool serves to the Cursor exec bridge) but are dropped from the model-facing
|
|
5586
|
+
// definitions so they never reach the prompt. See temporarilyDisabledToolNames.
|
|
5310
5587
|
const definitionRegistry = new Map(Array.from(this._baseToolDefinitions.entries())
|
|
5311
|
-
.filter(([name]) => isAllowedTool(name))
|
|
5588
|
+
.filter(([name]) => isAllowedTool(name) && !temporarilyDisabledToolNames.has(name))
|
|
5312
5589
|
.map(([name, definition]) => [
|
|
5313
5590
|
name,
|
|
5314
5591
|
{
|
|
@@ -5350,13 +5627,22 @@ export class AgentSession {
|
|
|
5350
5627
|
toolRegistry.set(tool.name, tool);
|
|
5351
5628
|
}
|
|
5352
5629
|
this._toolRegistry = toolRegistry;
|
|
5630
|
+
this._publishEvalOnlyToolHints();
|
|
5353
5631
|
const isDirectlyExposed = (name) => {
|
|
5354
5632
|
const entry = this._toolDefinitions.get(name);
|
|
5355
5633
|
return entry !== undefined && normalizeToolExposure(entry.definition).exposure === "direct";
|
|
5356
5634
|
};
|
|
5357
|
-
|
|
5635
|
+
// A withheld tool is dropped from the DEFAULT selection only. An explicit activeToolNames
|
|
5636
|
+
// request names the tool deliberately, and callers that do so (tests, SDK embedders,
|
|
5637
|
+
// filesystem-policy wiring) still expect it to activate.
|
|
5638
|
+
const hasExplicitActiveToolNames = options?.activeToolNames !== undefined;
|
|
5639
|
+
const nextActiveToolNames = (options?.activeToolNames
|
|
5640
|
+
? [...options.activeToolNames]
|
|
5641
|
+
: [...(this._requestedActiveToolNames ?? previousActiveToolNames)]).filter((name) => {
|
|
5358
5642
|
if (!isAllowedTool(name))
|
|
5359
5643
|
return false;
|
|
5644
|
+
if (!hasExplicitActiveToolNames && temporarilyDisabledToolNames.has(name))
|
|
5645
|
+
return false;
|
|
5360
5646
|
const previousRegistrationIds = options?.previousActiveToolRegistrationIds;
|
|
5361
5647
|
if (!previousRegistrationIds)
|
|
5362
5648
|
return true;
|
|
@@ -5387,6 +5673,7 @@ export class AgentSession {
|
|
|
5387
5673
|
this.setActiveToolsByName([...new Set(nextActiveToolNames)]);
|
|
5388
5674
|
}
|
|
5389
5675
|
_buildRuntime(options) {
|
|
5676
|
+
this._delegatedCompactionKey = undefined;
|
|
5390
5677
|
const autoResizeImages = this.settingsManager.getImageAutoResize();
|
|
5391
5678
|
const shellCommandPrefix = this.settingsManager.getShellCommandPrefix();
|
|
5392
5679
|
const shellPath = this.settingsManager.getShellPath();
|
|
@@ -5438,7 +5725,9 @@ export class AgentSession {
|
|
|
5438
5725
|
const oldExtensionIdentities = oldExtensionRunner.getExtensionIdentities();
|
|
5439
5726
|
const previousFlagValues = oldExtensionRunner.getFlagValues();
|
|
5440
5727
|
const previousActiveToolRegistrationIds = new Map();
|
|
5441
|
-
|
|
5728
|
+
// Cover withheld eval-only tools too: the rebuild drops any seeded name missing from this
|
|
5729
|
+
// map, which would strand shell tools when the policy disarms during this reload.
|
|
5730
|
+
for (const name of this._requestedActiveToolNames ?? this.getActiveToolNames()) {
|
|
5442
5731
|
const entry = this._toolDefinitions.get(name);
|
|
5443
5732
|
if (entry)
|
|
5444
5733
|
previousActiveToolRegistrationIds.set(name, deriveExtensionRegistrationId(entry.sourceInfo, name));
|
|
@@ -5449,6 +5738,12 @@ export class AgentSession {
|
|
|
5449
5738
|
});
|
|
5450
5739
|
time("shutdown", "reload");
|
|
5451
5740
|
await this.settingsManager.reload();
|
|
5741
|
+
this._delegatedCompactionKey = undefined;
|
|
5742
|
+
// Capture the unfiltered request BEFORE the rebuild reassigns it, so a policy that
|
|
5743
|
+
// disarms during this reload can still restore its withheld shell tools.
|
|
5744
|
+
const requestedActiveToolNamesBeforeRebuild = [...(this._requestedActiveToolNames ?? this.getActiveToolNames())];
|
|
5745
|
+
// A flag change must take effect on reload, matching documented settings hot-reload behavior.
|
|
5746
|
+
this._evalOnlyToolNames = this._resolveEvalOnlyToolNames();
|
|
5452
5747
|
this.syncQueueModesFromSettings();
|
|
5453
5748
|
resetApiProviders();
|
|
5454
5749
|
time("settings", "reload");
|
|
@@ -5473,7 +5768,7 @@ export class AgentSession {
|
|
|
5473
5768
|
time("resources", "reload");
|
|
5474
5769
|
try {
|
|
5475
5770
|
this._buildRuntime({
|
|
5476
|
-
activeToolNames:
|
|
5771
|
+
activeToolNames: requestedActiveToolNamesBeforeRebuild,
|
|
5477
5772
|
flagValues: previousFlagValues,
|
|
5478
5773
|
includeAllExtensionTools: true,
|
|
5479
5774
|
previousActiveToolRegistrationIds,
|
|
@@ -6178,12 +6473,13 @@ export class AgentSession {
|
|
|
6178
6473
|
try {
|
|
6179
6474
|
const result = await executeBashWithOperations(resolvedCommand, this.sessionManager.getCwd(), options?.operations ?? createLocalBashOperations({ shellPath }), {
|
|
6180
6475
|
onChunk: (delta) => {
|
|
6181
|
-
onChunk?.(delta);
|
|
6476
|
+
const callbackResult = onChunk?.(delta);
|
|
6182
6477
|
this._emit({
|
|
6183
6478
|
type: "bash_execution_update",
|
|
6184
6479
|
id: options?.id,
|
|
6185
6480
|
delta,
|
|
6186
6481
|
});
|
|
6482
|
+
return callbackResult;
|
|
6187
6483
|
},
|
|
6188
6484
|
signal: abortController.signal,
|
|
6189
6485
|
});
|
|
@@ -6231,6 +6527,10 @@ export class AgentSession {
|
|
|
6231
6527
|
abortController.abort();
|
|
6232
6528
|
}
|
|
6233
6529
|
}
|
|
6530
|
+
/** Remove a host-owned full-output spill after a remote observer failed. */
|
|
6531
|
+
async cleanupBashOutput(path) {
|
|
6532
|
+
await rm(path, { force: true });
|
|
6533
|
+
}
|
|
6234
6534
|
/** Whether a bash command is currently running */
|
|
6235
6535
|
get isBashRunning() {
|
|
6236
6536
|
return this._bashAbortControllers.size > 0;
|
|
@@ -6432,6 +6732,7 @@ export class AgentSession {
|
|
|
6432
6732
|
}
|
|
6433
6733
|
// Update agent state (preserving exact messages still awaiting persistence)
|
|
6434
6734
|
this._restoreAgentMessagesFromSession();
|
|
6735
|
+
this._delegatedCompactionKey = undefined;
|
|
6435
6736
|
this._incrementMessageRevision();
|
|
6436
6737
|
// Emit session_tree event
|
|
6437
6738
|
await this._extensionRunner.emit({
|