@sheason/pi-coding-agent 0.74.1-sheason.0 → 0.78.0-sheason.0.6.0-alpha.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 +256 -4
- package/README.md +16 -8
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js.map +1 -1
- package/dist/cli/args.d.ts +7 -2
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +49 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts +2 -2
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +2 -3
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.d.ts +1 -1
- package/dist/cli/initial-message.d.ts.map +1 -1
- package/dist/cli/initial-message.js.map +1 -1
- package/dist/cli/list-models.d.ts +1 -1
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/session-picker.d.ts +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -6
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +61 -32
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-proxy.d.ts +268 -0
- package/dist/core/agent-session-proxy.d.ts.map +1 -0
- package/dist/core/agent-session-proxy.js +2 -0
- package/dist/core/agent-session-proxy.js.map +1 -0
- package/dist/core/agent-session-runtime.d.ts +10 -10
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +14 -14
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +8 -7
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +4 -2
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +60 -27
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +303 -177
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -2
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +3 -3
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +5 -5
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +41 -37
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/index.d.ts +3 -3
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/index.d.ts +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +8 -6
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.js +23 -6
- package/dist/core/export-html/tool-renderer.d.ts +2 -2
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +8 -8
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +2 -2
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +17 -34
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +12 -7
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +36 -2
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +26 -24
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts +2 -2
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +3 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +4 -0
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts +21 -0
- package/dist/core/http-dispatcher.d.ts.map +1 -0
- package/dist/core/http-dispatcher.js +48 -0
- package/dist/core/http-dispatcher.js.map +1 -0
- package/dist/core/index.d.ts +8 -8
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/local-agent-session-proxy.d.ts +82 -0
- package/dist/core/local-agent-session-proxy.d.ts.map +1 -0
- package/dist/core/local-agent-session-proxy.js +531 -0
- package/dist/core/local-agent-session-proxy.js.map +1 -0
- package/dist/core/messages.d.ts +0 -9
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +0 -10
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts +4 -4
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +72 -16
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/output-guard.d.ts +1 -0
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js +52 -22
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/package-manager.d.ts +7 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +129 -64
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +1 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +12 -24
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +0 -1
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts +9 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +134 -11
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +13 -10
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +41 -33
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +15 -13
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +24 -17
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +20 -10
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +201 -106
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +5 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +31 -13
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +2 -2
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +10 -27
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/source-info.d.ts +1 -1
- package/dist/core/source-info.d.ts.map +1 -1
- package/dist/core/source-info.js.map +1 -1
- package/dist/core/system-prompt.d.ts +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +16 -9
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/telemetry.d.ts +1 -1
- package/dist/core/telemetry.d.ts.map +1 -1
- package/dist/core/telemetry.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -2
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +55 -54
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +3 -1
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +8 -1
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +5 -3
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +51 -91
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js +27 -12
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts +2 -2
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +2 -3
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +2 -2
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +3 -3
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +17 -17
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +2 -2
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +10 -12
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +3 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +9 -3
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/path-utils.d.ts +2 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js +39 -21
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/read.d.ts +2 -2
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +15 -15
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +5 -2
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +17 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/truncate.d.ts.map +1 -1
- package/dist/core/tools/truncate.js +12 -2
- package/dist/core/tools/truncate.js.map +1 -1
- package/dist/core/tools/write.d.ts +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +25 -41
- package/dist/core/tools/write.js.map +1 -1
- package/dist/d-pi-worker.d.ts +12 -0
- package/dist/d-pi-worker.d.ts.map +1 -0
- package/dist/d-pi-worker.js +9 -0
- package/dist/d-pi-worker.js.map +1 -0
- package/dist/index.d.ts +30 -28
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +100 -39
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +118 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/connect/auth-headers.d.ts +2 -0
- package/dist/modes/connect/auth-headers.d.ts.map +1 -0
- package/dist/modes/connect/auth-headers.js +2 -0
- package/dist/modes/connect/auth-headers.js.map +1 -0
- package/dist/modes/connect/client-extension-sync.d.ts +13 -0
- package/dist/modes/connect/client-extension-sync.d.ts.map +1 -0
- package/dist/modes/connect/client-extension-sync.js +51 -0
- package/dist/modes/connect/client-extension-sync.js.map +1 -0
- package/dist/modes/connect/connect-mode.d.ts +6 -0
- package/dist/modes/connect/connect-mode.d.ts.map +1 -0
- package/dist/modes/connect/connect-mode.js +29 -0
- package/dist/modes/connect/connect-mode.js.map +1 -0
- package/dist/modes/connect/remote-agent-session-proxy.d.ts +81 -0
- package/dist/modes/connect/remote-agent-session-proxy.d.ts.map +1 -0
- package/dist/modes/connect/remote-agent-session-proxy.js +326 -0
- package/dist/modes/connect/remote-agent-session-proxy.js.map +1 -0
- package/dist/modes/connect/sse-client.d.ts +18 -0
- package/dist/modes/connect/sse-client.d.ts.map +1 -0
- package/dist/modes/connect/sse-client.js +90 -0
- package/dist/modes/connect/sse-client.js.map +1 -0
- package/dist/modes/index.d.ts +5 -5
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +4 -4
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +8 -5
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts +2 -2
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +2 -2
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +2 -2
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +0 -1
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
- package/dist/modes/interactive/components/daxnuts.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +1 -1
- package/dist/modes/interactive/components/earendil-announcement.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +14 -6
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +15 -4
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +126 -8
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +31 -31
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +7 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +28 -5
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +2 -2
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +3 -3
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +15 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +53 -7
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1247 -205
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +5 -4
- package/dist/modes/interactive/theme/light.json +5 -4
- package/dist/modes/interactive/theme/theme.d.ts +22 -3
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +130 -69
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +8 -5
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +65 -8
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +2 -2
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +18 -4
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +5 -4
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/serve/api-handlers.d.ts +4 -0
- package/dist/modes/serve/api-handlers.d.ts.map +1 -0
- package/dist/modes/serve/api-handlers.js +324 -0
- package/dist/modes/serve/api-handlers.js.map +1 -0
- package/dist/modes/serve/http-server.d.ts +14 -0
- package/dist/modes/serve/http-server.d.ts.map +1 -0
- package/dist/modes/serve/http-server.js +94 -0
- package/dist/modes/serve/http-server.js.map +1 -0
- package/dist/modes/serve/serve-mode.d.ts +10 -0
- package/dist/modes/serve/serve-mode.d.ts.map +1 -0
- package/dist/modes/serve/serve-mode.js +217 -0
- package/dist/modes/serve/serve-mode.js.map +1 -0
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +62 -7
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js +47 -72
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/changelog.d.ts +1 -1
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/child-process.d.ts +5 -2
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js +9 -7
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +3 -1
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js +14 -8
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/deprecation.d.ts +4 -0
- package/dist/utils/deprecation.d.ts.map +1 -0
- package/dist/utils/deprecation.js +13 -0
- package/dist/utils/deprecation.js.map +1 -0
- package/dist/utils/exif-orientation.d.ts +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/html.d.ts +7 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +40 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts +30 -0
- package/dist/utils/image-resize-core.d.ts.map +1 -0
- package/dist/utils/image-resize-core.js +124 -0
- package/dist/utils/image-resize-core.js.map +1 -0
- package/dist/utils/image-resize-worker.d.ts +2 -0
- package/dist/utils/image-resize-worker.d.ts.map +1 -0
- package/dist/utils/image-resize-worker.js +31 -0
- package/dist/utils/image-resize-worker.js.map +1 -0
- package/dist/utils/image-resize.d.ts +7 -27
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +75 -131
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/json.d.ts +3 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +7 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/paths.d.ts +16 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +49 -7
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +6 -1
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts +12 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -0
- package/dist/utils/syntax-highlight.js +118 -0
- package/dist/utils/syntax-highlight.js.map +1 -0
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +4 -1
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts +2 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +9 -4
- package/dist/utils/version-check.js.map +1 -1
- package/dist/utils/windows-self-update.d.ts +3 -0
- package/dist/utils/windows-self-update.d.ts.map +1 -0
- package/dist/utils/windows-self-update.js +77 -0
- package/dist/utils/windows-self-update.js.map +1 -0
- package/docs/custom-provider.md +111 -21
- package/docs/development.md +1 -1
- package/docs/extensions.md +13 -7
- package/docs/index.md +13 -3
- package/docs/models.md +32 -13
- package/docs/packages.md +9 -6
- package/docs/providers.md +13 -5
- package/docs/quickstart.md +24 -1
- package/docs/rpc.md +2 -1
- package/docs/sdk.md +8 -0
- package/docs/session-format.md +1 -1
- package/docs/sessions.md +8 -0
- package/docs/settings.md +8 -6
- package/docs/skills.md +3 -4
- package/docs/terminal-setup.md +8 -0
- package/docs/termux.md +3 -3
- package/docs/tui.md +2 -2
- package/docs/usage.md +13 -2
- package/examples/extensions/README.md +1 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +2 -2
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +54 -3
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +1 -1
- package/examples/extensions/doom-overlay/doom-component.ts +2 -2
- package/examples/extensions/doom-overlay/index.ts +3 -3
- package/examples/extensions/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/overlay-qa-tests.ts +97 -66
- package/examples/extensions/overlay-test.ts +7 -4
- package/examples/extensions/plan-mode/index.ts +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +2 -2
- package/examples/extensions/subagent/README.md +3 -0
- package/examples/extensions/subagent/index.ts +42 -20
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +3 -3
- package/npm-shrinkwrap.json +1790 -0
- package/package.json +39 -32
- package/dist/utils/uuid.d.ts +0 -2
- package/dist/utils/uuid.d.ts.map +0 -1
- package/dist/utils/uuid.js +0 -40
- package/dist/utils/uuid.js.map +0 -1
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
* Modes use this class and add their own I/O layer on top.
|
|
14
14
|
*/
|
|
15
15
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
16
|
-
import { basename, dirname
|
|
17
|
-
import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, modelsAreEqual, resetApiProviders, } from "@sheason/pi-ai";
|
|
16
|
+
import { basename, dirname } from "node:path";
|
|
17
|
+
import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, modelsAreEqual, resetApiProviders, streamSimple, } from "@sheason/pi-ai";
|
|
18
18
|
import { theme } from "../modes/interactive/theme/theme.js";
|
|
19
19
|
import { stripFrontmatter } from "../utils/frontmatter.js";
|
|
20
|
+
import { resolvePath } from "../utils/paths.js";
|
|
20
21
|
import { sleep } from "../utils/sleep.js";
|
|
21
22
|
import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
|
|
22
23
|
import { executeBashWithOperations } from "./bash-executor.js";
|
|
@@ -64,7 +65,6 @@ export class AgentSession {
|
|
|
64
65
|
// Event subscription state
|
|
65
66
|
_unsubscribeAgent;
|
|
66
67
|
_eventListeners = [];
|
|
67
|
-
_agentEventQueue = Promise.resolve();
|
|
68
68
|
/** Tracks pending steering messages for UI display. Removed when delivered. */
|
|
69
69
|
_steeringMessages = [];
|
|
70
70
|
/** Tracks pending follow-up messages for UI display. Removed when delivered. */
|
|
@@ -80,14 +80,14 @@ export class AgentSession {
|
|
|
80
80
|
// Retry state
|
|
81
81
|
_retryAbortController = undefined;
|
|
82
82
|
_retryAttempt = 0;
|
|
83
|
-
_retryPromise = undefined;
|
|
84
|
-
_retryResolve = undefined;
|
|
85
83
|
// Bash execution state
|
|
86
84
|
_bashAbortController = undefined;
|
|
87
85
|
_pendingBashMessages = [];
|
|
88
86
|
// Extension system
|
|
89
87
|
_extensionRunner;
|
|
90
88
|
_turnIndex = 0;
|
|
89
|
+
/** Timestamp when the current agent run started, for per-turn TPS calculation */
|
|
90
|
+
_agentStartTime = undefined;
|
|
91
91
|
_resourceLoader;
|
|
92
92
|
_customTools;
|
|
93
93
|
_baseToolDefinitions = new Map();
|
|
@@ -95,10 +95,12 @@ export class AgentSession {
|
|
|
95
95
|
_extensionRunnerRef;
|
|
96
96
|
_initialActiveToolNames;
|
|
97
97
|
_allowedToolNames;
|
|
98
|
+
_excludedToolNames;
|
|
98
99
|
_baseToolsOverride;
|
|
99
100
|
_sessionStartEvent;
|
|
100
101
|
_extensionUIContext;
|
|
101
102
|
_extensionCommandContextActions;
|
|
103
|
+
_extensionAbortHandler;
|
|
102
104
|
_extensionShutdownHandler;
|
|
103
105
|
_extensionErrorListener;
|
|
104
106
|
_extensionErrorUnsubscriber;
|
|
@@ -124,6 +126,7 @@ export class AgentSession {
|
|
|
124
126
|
this._extensionRunnerRef = config.extensionRunnerRef;
|
|
125
127
|
this._initialActiveToolNames = config.initialActiveToolNames;
|
|
126
128
|
this._allowedToolNames = config.allowedToolNames ? new Set(config.allowedToolNames) : undefined;
|
|
129
|
+
this._excludedToolNames = config.excludedToolNames ? new Set(config.excludedToolNames) : undefined;
|
|
127
130
|
this._baseToolsOverride = config.baseToolsOverride;
|
|
128
131
|
this._sessionStartEvent = config.sessionStartEvent ?? { type: "session_start", reason: "startup" };
|
|
129
132
|
// Always subscribe to agent events for internal handling
|
|
@@ -158,6 +161,13 @@ export class AgentSession {
|
|
|
158
161
|
}
|
|
159
162
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
160
163
|
}
|
|
164
|
+
async _getCompactionRequestAuth(model) {
|
|
165
|
+
if (this.agent.streamFn === streamSimple) {
|
|
166
|
+
return this._getRequiredRequestAuth(model);
|
|
167
|
+
}
|
|
168
|
+
const result = await this._modelRegistry.getApiKeyAndHeaders(model);
|
|
169
|
+
return result.ok ? { apiKey: result.apiKey, headers: result.headers } : {};
|
|
170
|
+
}
|
|
161
171
|
/**
|
|
162
172
|
* Install tool hooks once on the Agent instance.
|
|
163
173
|
*
|
|
@@ -172,7 +182,6 @@ export class AgentSession {
|
|
|
172
182
|
if (!runner.hasHandlers("tool_call")) {
|
|
173
183
|
return undefined;
|
|
174
184
|
}
|
|
175
|
-
await this._agentEventQueue;
|
|
176
185
|
try {
|
|
177
186
|
return await runner.emitToolCall({
|
|
178
187
|
type: "tool_call",
|
|
@@ -228,72 +237,81 @@ export class AgentSession {
|
|
|
228
237
|
followUp: [...this._followUpMessages],
|
|
229
238
|
});
|
|
230
239
|
}
|
|
240
|
+
/** Emit a state_update event with the current token/context/model snapshot */
|
|
241
|
+
_emitStateUpdate() {
|
|
242
|
+
const model = this.model;
|
|
243
|
+
const state = this.state;
|
|
244
|
+
// Compute cumulative token usage
|
|
245
|
+
let totalInput = 0;
|
|
246
|
+
let totalOutput = 0;
|
|
247
|
+
let totalCacheRead = 0;
|
|
248
|
+
let totalCacheWrite = 0;
|
|
249
|
+
let totalCost = 0;
|
|
250
|
+
for (const entry of this.sessionManager.getEntries()) {
|
|
251
|
+
if (entry.type === "message" && entry.message.role === "assistant") {
|
|
252
|
+
totalInput += entry.message.usage.input;
|
|
253
|
+
totalOutput += entry.message.usage.output;
|
|
254
|
+
totalCacheRead += entry.message.usage.cacheRead;
|
|
255
|
+
totalCacheWrite += entry.message.usage.cacheWrite;
|
|
256
|
+
totalCost += entry.message.usage.cost.total;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const usingSubscription = model ? this.modelRegistry.isUsingOAuth(model) : false;
|
|
260
|
+
const rawContextUsage = this.getContextUsage();
|
|
261
|
+
const snapshot = {
|
|
262
|
+
model: model?.id ?? "",
|
|
263
|
+
thinkingLevel: state.thinkingLevel,
|
|
264
|
+
// Note: isStreaming and isCompacting are NOT included here.
|
|
265
|
+
// They are managed by agent_start/agent_end and compaction_start/compaction_end events
|
|
266
|
+
// to avoid race conditions where a late state_update overwrites the correct state.
|
|
267
|
+
tokenUsage: {
|
|
268
|
+
input: totalInput,
|
|
269
|
+
output: totalOutput,
|
|
270
|
+
cacheRead: totalCacheRead,
|
|
271
|
+
cacheWrite: totalCacheWrite,
|
|
272
|
+
cost: totalCost,
|
|
273
|
+
usingSubscription,
|
|
274
|
+
},
|
|
275
|
+
contextUsage: rawContextUsage
|
|
276
|
+
? {
|
|
277
|
+
tokens: rawContextUsage.tokens,
|
|
278
|
+
contextWindow: rawContextUsage.contextWindow,
|
|
279
|
+
percent: rawContextUsage.percent,
|
|
280
|
+
}
|
|
281
|
+
: { tokens: null, contextWindow: model?.contextWindow ?? 0, percent: null },
|
|
282
|
+
modelInfo: model
|
|
283
|
+
? { id: model.id, provider: model.provider, reasoning: model.reasoning, contextWindow: model.contextWindow }
|
|
284
|
+
: { id: "", provider: "", reasoning: false, contextWindow: 0 },
|
|
285
|
+
autoCompactEnabled: this.autoCompactionEnabled,
|
|
286
|
+
cwd: this.sessionManager.getCwd(),
|
|
287
|
+
availableProviderCount: this.modelRegistry.getAvailable().length,
|
|
288
|
+
};
|
|
289
|
+
this._emit({ type: "state_update", snapshot });
|
|
290
|
+
}
|
|
231
291
|
// Track last assistant message for auto-compaction check
|
|
232
292
|
_lastAssistantMessage = undefined;
|
|
233
293
|
/** Internal handler for agent events - shared by subscribe and reconnect */
|
|
234
|
-
_handleAgentEvent = (event) => {
|
|
235
|
-
//
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
this._agentEventQueue.catch(() => { });
|
|
244
|
-
};
|
|
245
|
-
_createRetryPromiseForAgentEnd(event) {
|
|
246
|
-
if (event.type !== "agent_end" || this._retryPromise) {
|
|
247
|
-
return;
|
|
248
|
-
}
|
|
249
|
-
const settings = this.settingsManager.getRetrySettings();
|
|
250
|
-
if (!settings.enabled) {
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
const lastAssistant = this._findLastAssistantInMessages(event.messages);
|
|
254
|
-
if (!lastAssistant || !this._isRetryableError(lastAssistant)) {
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
this._retryPromise = new Promise((resolve) => {
|
|
258
|
-
this._retryResolve = resolve;
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
_findLastAssistantInMessages(messages) {
|
|
262
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
263
|
-
const message = messages[i];
|
|
264
|
-
if (message.role === "assistant") {
|
|
265
|
-
return message;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
return undefined;
|
|
269
|
-
}
|
|
270
|
-
async _processAgentEvent(event) {
|
|
271
|
-
// When a user message starts, check if it's from either queue and remove it BEFORE emitting
|
|
272
|
-
// This ensures the UI sees the updated queue state
|
|
273
|
-
if (event.type === "message_start" && event.message.role === "user") {
|
|
274
|
-
this._overflowRecoveryAttempted = false;
|
|
275
|
-
const messageText = this._getUserMessageText(event.message);
|
|
294
|
+
_handleAgentEvent = async (event) => {
|
|
295
|
+
// When a queued message starts, remove it BEFORE emitting so the UI sees the updated queue state.
|
|
296
|
+
if (event.type === "message_start" && (event.message.role === "user" || event.message.role === "custom")) {
|
|
297
|
+
if (event.message.role === "user") {
|
|
298
|
+
this._overflowRecoveryAttempted = false;
|
|
299
|
+
}
|
|
300
|
+
const messageText = event.message.role === "user"
|
|
301
|
+
? this._getUserMessageText(event.message)
|
|
302
|
+
: this._getCustomMessageText(event.message);
|
|
276
303
|
if (messageText) {
|
|
277
|
-
|
|
278
|
-
const steeringIndex = this._steeringMessages.indexOf(messageText);
|
|
279
|
-
if (steeringIndex !== -1) {
|
|
280
|
-
this._steeringMessages.splice(steeringIndex, 1);
|
|
281
|
-
this._emitQueueUpdate();
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
// Check follow-up queue
|
|
285
|
-
const followUpIndex = this._followUpMessages.indexOf(messageText);
|
|
286
|
-
if (followUpIndex !== -1) {
|
|
287
|
-
this._followUpMessages.splice(followUpIndex, 1);
|
|
288
|
-
this._emitQueueUpdate();
|
|
289
|
-
}
|
|
290
|
-
}
|
|
304
|
+
this._removeQueuedMessageText(messageText);
|
|
291
305
|
}
|
|
292
306
|
}
|
|
307
|
+
// Track agent start time for per-turn TPS calculation
|
|
308
|
+
if (event.type === "agent_start") {
|
|
309
|
+
this._agentStartTime = Date.now();
|
|
310
|
+
}
|
|
293
311
|
// Emit to extensions first
|
|
294
312
|
await this._emitExtensionEvent(event);
|
|
295
313
|
// Notify all listeners
|
|
296
|
-
this._emit(event);
|
|
314
|
+
this._emit(event.type === "agent_end" ? { ...event, willRetry: this._willRetryAfterAgentEnd(event) } : event);
|
|
297
315
|
// Handle session persistence
|
|
298
316
|
if (event.type === "message_end") {
|
|
299
317
|
// Check if this is a custom message from extensions
|
|
@@ -325,40 +343,87 @@ export class AgentSession {
|
|
|
325
343
|
});
|
|
326
344
|
this._retryAttempt = 0;
|
|
327
345
|
}
|
|
346
|
+
// Push state update (token usage changed)
|
|
347
|
+
this._emitStateUpdate();
|
|
328
348
|
}
|
|
329
349
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
350
|
+
else if (event.type === "agent_end") {
|
|
351
|
+
// Push state update (streaming ended)
|
|
352
|
+
this._emitStateUpdate();
|
|
353
|
+
// Emit per-turn stats
|
|
354
|
+
if (this._agentStartTime !== undefined) {
|
|
355
|
+
const duration = (Date.now() - this._agentStartTime) / 1000;
|
|
356
|
+
this._agentStartTime = undefined;
|
|
357
|
+
// Sum token usage from all assistant messages in this agent run
|
|
358
|
+
let turnInput = 0;
|
|
359
|
+
let turnOutput = 0;
|
|
360
|
+
let turnCacheRead = 0;
|
|
361
|
+
let turnCacheWrite = 0;
|
|
362
|
+
for (const msg of event.messages) {
|
|
363
|
+
if (msg.role === "assistant") {
|
|
364
|
+
const usage = msg.usage;
|
|
365
|
+
turnInput += usage.input;
|
|
366
|
+
turnOutput += usage.output;
|
|
367
|
+
turnCacheRead += usage.cacheRead;
|
|
368
|
+
turnCacheWrite += usage.cacheWrite;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
const total = turnInput + turnOutput + turnCacheRead + turnCacheWrite;
|
|
372
|
+
const tps = duration > 0 ? turnOutput / duration : 0;
|
|
373
|
+
this._emit({
|
|
374
|
+
type: "turn_stats",
|
|
375
|
+
tps,
|
|
376
|
+
output: turnOutput,
|
|
377
|
+
input: turnInput,
|
|
378
|
+
cacheRead: turnCacheRead,
|
|
379
|
+
cacheWrite: turnCacheWrite,
|
|
380
|
+
total,
|
|
381
|
+
duration,
|
|
382
|
+
});
|
|
339
383
|
}
|
|
340
|
-
this._resolveRetry();
|
|
341
|
-
await this._checkCompaction(msg);
|
|
342
384
|
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if (this.
|
|
347
|
-
|
|
348
|
-
this._retryResolve = undefined;
|
|
349
|
-
this._retryPromise = undefined;
|
|
385
|
+
};
|
|
386
|
+
_willRetryAfterAgentEnd(event) {
|
|
387
|
+
const settings = this.settingsManager.getRetrySettings();
|
|
388
|
+
if (!settings.enabled || this._retryAttempt >= settings.maxRetries) {
|
|
389
|
+
return false;
|
|
350
390
|
}
|
|
391
|
+
for (let i = event.messages.length - 1; i >= 0; i--) {
|
|
392
|
+
const message = event.messages[i];
|
|
393
|
+
if (message.role === "assistant") {
|
|
394
|
+
return this._isRetryableError(message);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return false;
|
|
351
398
|
}
|
|
352
399
|
/** Extract text content from a message */
|
|
353
400
|
_getUserMessageText(message) {
|
|
354
401
|
if (message.role !== "user")
|
|
355
402
|
return "";
|
|
356
|
-
|
|
403
|
+
return this._getContentText(message.content);
|
|
404
|
+
}
|
|
405
|
+
_getCustomMessageText(message) {
|
|
406
|
+
return this._getContentText(message.content);
|
|
407
|
+
}
|
|
408
|
+
_getContentText(content) {
|
|
357
409
|
if (typeof content === "string")
|
|
358
410
|
return content;
|
|
359
411
|
const textBlocks = content.filter((c) => c.type === "text");
|
|
360
412
|
return textBlocks.map((c) => c.text).join("");
|
|
361
413
|
}
|
|
414
|
+
_removeQueuedMessageText(messageText) {
|
|
415
|
+
const steeringIndex = this._steeringMessages.indexOf(messageText);
|
|
416
|
+
if (steeringIndex !== -1) {
|
|
417
|
+
this._steeringMessages.splice(steeringIndex, 1);
|
|
418
|
+
this._emitQueueUpdate();
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
const followUpIndex = this._followUpMessages.indexOf(messageText);
|
|
422
|
+
if (followUpIndex !== -1) {
|
|
423
|
+
this._followUpMessages.splice(followUpIndex, 1);
|
|
424
|
+
this._emitQueueUpdate();
|
|
425
|
+
}
|
|
426
|
+
}
|
|
362
427
|
/** Find the last assistant message in agent state (including aborted ones) */
|
|
363
428
|
_findLastAssistantMessage() {
|
|
364
429
|
const messages = this.agent.state.messages;
|
|
@@ -372,7 +437,7 @@ export class AgentSession {
|
|
|
372
437
|
}
|
|
373
438
|
_replaceMessageInPlace(target, replacement) {
|
|
374
439
|
// Agent-core stores the finalized message object in its state before emitting message_end.
|
|
375
|
-
// SessionManager persistence happens later in
|
|
440
|
+
// SessionManager persistence happens later in _handleAgentEvent() with event.message.
|
|
376
441
|
// Mutating this object in place keeps agent state, later turn/agent events, listeners,
|
|
377
442
|
// and the eventual SessionManager.appendMessage(event.message) persistence in sync.
|
|
378
443
|
if (target === replacement) {
|
|
@@ -506,6 +571,16 @@ export class AgentSession {
|
|
|
506
571
|
* Call this when completely done with the session.
|
|
507
572
|
*/
|
|
508
573
|
dispose() {
|
|
574
|
+
try {
|
|
575
|
+
this.abortRetry();
|
|
576
|
+
this.abortCompaction();
|
|
577
|
+
this.abortBranchSummary();
|
|
578
|
+
this.abortBash();
|
|
579
|
+
this.agent.abort();
|
|
580
|
+
}
|
|
581
|
+
catch {
|
|
582
|
+
// Dispose must succeed even if an abort hook throws.
|
|
583
|
+
}
|
|
509
584
|
this._extensionRunner.invalidate("This extension ctx is stale after session replacement or reload. Do not use a captured pi or command ctx after ctx.newSession(), ctx.fork(), ctx.switchSession(), or ctx.reload(). For newSession, fork, and switchSession, move post-replacement work into withSession and use the ctx passed to withSession. For reload, do not use the old ctx after await ctx.reload().");
|
|
510
585
|
this._disconnectFromAgent();
|
|
511
586
|
this._eventListeners = [];
|
|
@@ -546,13 +621,14 @@ export class AgentSession {
|
|
|
546
621
|
return this.agent.state.tools.map((t) => t.name);
|
|
547
622
|
}
|
|
548
623
|
/**
|
|
549
|
-
* Get all configured tools with name, description, parameter schema, and source metadata.
|
|
624
|
+
* Get all configured tools with name, description, parameter schema, prompt guidelines, and source metadata.
|
|
550
625
|
*/
|
|
551
626
|
getAllTools() {
|
|
552
627
|
return Array.from(this._toolDefinitions.values()).map(({ definition, sourceInfo }) => ({
|
|
553
628
|
name: definition.name,
|
|
554
629
|
description: definition.description,
|
|
555
630
|
parameters: definition.parameters,
|
|
631
|
+
promptGuidelines: definition.promptGuidelines,
|
|
556
632
|
sourceInfo,
|
|
557
633
|
}));
|
|
558
634
|
}
|
|
@@ -678,6 +754,42 @@ export class AgentSession {
|
|
|
678
754
|
// =========================================================================
|
|
679
755
|
// Prompting
|
|
680
756
|
// =========================================================================
|
|
757
|
+
async _runAgentPrompt(messages) {
|
|
758
|
+
try {
|
|
759
|
+
await this.agent.prompt(messages);
|
|
760
|
+
while (await this._handlePostAgentRun()) {
|
|
761
|
+
await this.agent.continue();
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
finally {
|
|
765
|
+
this._flushPendingBashMessages();
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
async _handlePostAgentRun() {
|
|
769
|
+
const msg = this._lastAssistantMessage;
|
|
770
|
+
this._lastAssistantMessage = undefined;
|
|
771
|
+
if (!msg) {
|
|
772
|
+
return false;
|
|
773
|
+
}
|
|
774
|
+
if (this._isRetryableError(msg) && (await this._prepareRetry(msg))) {
|
|
775
|
+
return true;
|
|
776
|
+
}
|
|
777
|
+
if (msg.stopReason === "error" && this._retryAttempt > 0) {
|
|
778
|
+
this._emit({
|
|
779
|
+
type: "auto_retry_end",
|
|
780
|
+
success: false,
|
|
781
|
+
attempt: this._retryAttempt,
|
|
782
|
+
finalError: msg.errorMessage,
|
|
783
|
+
});
|
|
784
|
+
this._retryAttempt = 0;
|
|
785
|
+
}
|
|
786
|
+
if (await this._checkCompaction(msg)) {
|
|
787
|
+
return true;
|
|
788
|
+
}
|
|
789
|
+
// The agent loop drains both queues before emitting agent_end. Any messages
|
|
790
|
+
// here were queued by agent_end extension handlers and need a continuation.
|
|
791
|
+
return this.agent.hasQueuedMessages();
|
|
792
|
+
}
|
|
681
793
|
/**
|
|
682
794
|
* Send a prompt to the agent.
|
|
683
795
|
* - Handles extension commands (registered via pi.registerCommand) immediately, even during streaming
|
|
@@ -706,7 +818,7 @@ export class AgentSession {
|
|
|
706
818
|
let currentText = text;
|
|
707
819
|
let currentImages = options?.images;
|
|
708
820
|
if (this._extensionRunner.hasHandlers("input")) {
|
|
709
|
-
const inputResult = await this._extensionRunner.emitInput(currentText, currentImages, options?.source ?? "interactive");
|
|
821
|
+
const inputResult = await this._extensionRunner.emitInput(currentText, currentImages, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
|
|
710
822
|
if (inputResult.action === "handled") {
|
|
711
823
|
preflightResult?.(true);
|
|
712
824
|
return;
|
|
@@ -753,8 +865,16 @@ export class AgentSession {
|
|
|
753
865
|
}
|
|
754
866
|
// Check if we need to compact before sending (catches aborted responses)
|
|
755
867
|
const lastAssistant = this._findLastAssistantMessage();
|
|
756
|
-
if (lastAssistant) {
|
|
757
|
-
|
|
868
|
+
if (lastAssistant && (await this._checkCompaction(lastAssistant, false))) {
|
|
869
|
+
try {
|
|
870
|
+
await this.agent.continue();
|
|
871
|
+
while (await this._handlePostAgentRun()) {
|
|
872
|
+
await this.agent.continue();
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
finally {
|
|
876
|
+
this._flushPendingBashMessages();
|
|
877
|
+
}
|
|
758
878
|
}
|
|
759
879
|
// Build messages array (custom message if any, then user message)
|
|
760
880
|
messages = [];
|
|
@@ -805,8 +925,7 @@ export class AgentSession {
|
|
|
805
925
|
return;
|
|
806
926
|
}
|
|
807
927
|
preflightResult?.(true);
|
|
808
|
-
await this.
|
|
809
|
-
await this.waitForRetry();
|
|
928
|
+
await this._runAgentPrompt(messages);
|
|
810
929
|
}
|
|
811
930
|
/**
|
|
812
931
|
* Try to execute an extension command. Returns true if command was found and executed.
|
|
@@ -968,15 +1087,20 @@ export class AgentSession {
|
|
|
968
1087
|
this._pendingNextTurnMessages.push(appMessage);
|
|
969
1088
|
}
|
|
970
1089
|
else if (this.isStreaming) {
|
|
1090
|
+
const queuedText = this._getCustomMessageText(appMessage);
|
|
971
1091
|
if (options?.deliverAs === "followUp") {
|
|
1092
|
+
this._followUpMessages.push(queuedText);
|
|
1093
|
+
this._emitQueueUpdate();
|
|
972
1094
|
this.agent.followUp(appMessage);
|
|
973
1095
|
}
|
|
974
1096
|
else {
|
|
1097
|
+
this._steeringMessages.push(queuedText);
|
|
1098
|
+
this._emitQueueUpdate();
|
|
975
1099
|
this.agent.steer(appMessage);
|
|
976
1100
|
}
|
|
977
1101
|
}
|
|
978
1102
|
else if (options?.triggerTurn) {
|
|
979
|
-
await this.
|
|
1103
|
+
await this._runAgentPrompt(appMessage);
|
|
980
1104
|
}
|
|
981
1105
|
else {
|
|
982
1106
|
this.agent.state.messages.push(appMessage);
|
|
@@ -1077,7 +1201,7 @@ export class AgentSession {
|
|
|
1077
1201
|
* Validates that auth is configured, saves to session and settings.
|
|
1078
1202
|
* @throws Error if no auth is configured for the model
|
|
1079
1203
|
*/
|
|
1080
|
-
async setModel(model
|
|
1204
|
+
async setModel(model) {
|
|
1081
1205
|
if (!this._modelRegistry.hasConfiguredAuth(model)) {
|
|
1082
1206
|
throw new Error(`No API key for ${model.provider}/${model.id}`);
|
|
1083
1207
|
}
|
|
@@ -1085,12 +1209,11 @@ export class AgentSession {
|
|
|
1085
1209
|
const thinkingLevel = this._getThinkingLevelForModelSwitch();
|
|
1086
1210
|
this.agent.state.model = model;
|
|
1087
1211
|
this.sessionManager.appendModelChange(model.provider, model.id);
|
|
1088
|
-
|
|
1089
|
-
this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
|
|
1090
|
-
}
|
|
1212
|
+
this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
|
|
1091
1213
|
// Re-clamp thinking level for new model's capabilities
|
|
1092
1214
|
this.setThinkingLevel(thinkingLevel);
|
|
1093
1215
|
await this._emitModelSelect(model, previousModel, "set");
|
|
1216
|
+
this._emitStateUpdate();
|
|
1094
1217
|
}
|
|
1095
1218
|
/**
|
|
1096
1219
|
* Cycle to next/previous model.
|
|
@@ -1126,6 +1249,7 @@ export class AgentSession {
|
|
|
1126
1249
|
// setThinkingLevel clamps to model capabilities.
|
|
1127
1250
|
this.setThinkingLevel(thinkingLevel);
|
|
1128
1251
|
await this._emitModelSelect(next.model, currentModel, "cycle");
|
|
1252
|
+
this._emitStateUpdate();
|
|
1129
1253
|
return { model: next.model, thinkingLevel: this.thinkingLevel, isScoped: true };
|
|
1130
1254
|
}
|
|
1131
1255
|
async _cycleAvailableModel(direction) {
|
|
@@ -1146,6 +1270,7 @@ export class AgentSession {
|
|
|
1146
1270
|
// Re-clamp thinking level for new model's capabilities
|
|
1147
1271
|
this.setThinkingLevel(thinkingLevel);
|
|
1148
1272
|
await this._emitModelSelect(nextModel, currentModel, "cycle");
|
|
1273
|
+
this._emitStateUpdate();
|
|
1149
1274
|
return { model: nextModel, thinkingLevel: this.thinkingLevel, isScoped: false };
|
|
1150
1275
|
}
|
|
1151
1276
|
// =========================================================================
|
|
@@ -1174,6 +1299,7 @@ export class AgentSession {
|
|
|
1174
1299
|
level: effectiveLevel,
|
|
1175
1300
|
previousLevel,
|
|
1176
1301
|
});
|
|
1302
|
+
this._emitStateUpdate();
|
|
1177
1303
|
}
|
|
1178
1304
|
}
|
|
1179
1305
|
/**
|
|
@@ -1227,6 +1353,7 @@ export class AgentSession {
|
|
|
1227
1353
|
setSteeringMode(mode) {
|
|
1228
1354
|
this.agent.steeringMode = mode;
|
|
1229
1355
|
this.settingsManager.setSteeringMode(mode);
|
|
1356
|
+
this._emitStateUpdate();
|
|
1230
1357
|
}
|
|
1231
1358
|
/**
|
|
1232
1359
|
* Set follow-up message mode.
|
|
@@ -1235,6 +1362,7 @@ export class AgentSession {
|
|
|
1235
1362
|
setFollowUpMode(mode) {
|
|
1236
1363
|
this.agent.followUpMode = mode;
|
|
1237
1364
|
this.settingsManager.setFollowUpMode(mode);
|
|
1365
|
+
this._emitStateUpdate();
|
|
1238
1366
|
}
|
|
1239
1367
|
// =========================================================================
|
|
1240
1368
|
// Compaction
|
|
@@ -1253,7 +1381,7 @@ export class AgentSession {
|
|
|
1253
1381
|
if (!this.model) {
|
|
1254
1382
|
throw new Error(formatNoModelSelectedMessage());
|
|
1255
1383
|
}
|
|
1256
|
-
const { apiKey, headers } = await this.
|
|
1384
|
+
const { apiKey, headers } = await this._getCompactionRequestAuth(this.model);
|
|
1257
1385
|
const pathEntries = this.sessionManager.getBranch();
|
|
1258
1386
|
const settings = this.settingsManager.getCompactionSettings();
|
|
1259
1387
|
const preparation = prepareCompaction(pathEntries, settings);
|
|
@@ -1296,7 +1424,7 @@ export class AgentSession {
|
|
|
1296
1424
|
}
|
|
1297
1425
|
else {
|
|
1298
1426
|
// Generate compaction result
|
|
1299
|
-
const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel);
|
|
1427
|
+
const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel, this.agent.streamFn);
|
|
1300
1428
|
summary = result.summary;
|
|
1301
1429
|
firstKeptEntryId = result.firstKeptEntryId;
|
|
1302
1430
|
tokensBefore = result.tokensBefore;
|
|
@@ -1309,6 +1437,8 @@ export class AgentSession {
|
|
|
1309
1437
|
const newEntries = this.sessionManager.getEntries();
|
|
1310
1438
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1311
1439
|
this.agent.state.messages = sessionContext.messages;
|
|
1440
|
+
// Prune old entries from memory and disk to prevent unbounded growth
|
|
1441
|
+
this.sessionManager.pruneAfterCompaction();
|
|
1312
1442
|
// Get the saved compaction entry for the extension event
|
|
1313
1443
|
const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
|
|
1314
1444
|
if (this._extensionRunner && savedCompactionEntry) {
|
|
@@ -1331,6 +1461,7 @@ export class AgentSession {
|
|
|
1331
1461
|
aborted: false,
|
|
1332
1462
|
willRetry: false,
|
|
1333
1463
|
});
|
|
1464
|
+
this._emitStateUpdate();
|
|
1334
1465
|
return compactionResult;
|
|
1335
1466
|
}
|
|
1336
1467
|
catch (error) {
|
|
@@ -1344,6 +1475,7 @@ export class AgentSession {
|
|
|
1344
1475
|
willRetry: false,
|
|
1345
1476
|
errorMessage: aborted ? undefined : `Compaction failed: ${message}`,
|
|
1346
1477
|
});
|
|
1478
|
+
this._emitStateUpdate();
|
|
1347
1479
|
throw error;
|
|
1348
1480
|
}
|
|
1349
1481
|
finally {
|
|
@@ -1378,10 +1510,10 @@ export class AgentSession {
|
|
|
1378
1510
|
async _checkCompaction(assistantMessage, skipAbortedCheck = true) {
|
|
1379
1511
|
const settings = this.settingsManager.getCompactionSettings();
|
|
1380
1512
|
if (!settings.enabled)
|
|
1381
|
-
return;
|
|
1513
|
+
return false;
|
|
1382
1514
|
// Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
|
|
1383
1515
|
if (skipAbortedCheck && assistantMessage.stopReason === "aborted")
|
|
1384
|
-
return;
|
|
1516
|
+
return false;
|
|
1385
1517
|
const contextWindow = this.model?.contextWindow ?? 0;
|
|
1386
1518
|
// Skip overflow check if the message came from a different model.
|
|
1387
1519
|
// This handles the case where user switched from a smaller-context model (e.g. opus)
|
|
@@ -1394,7 +1526,7 @@ export class AgentSession {
|
|
|
1394
1526
|
const compactionEntry = getLatestCompactionEntry(this.sessionManager.getBranch());
|
|
1395
1527
|
const assistantIsFromBeforeCompaction = compactionEntry !== null && assistantMessage.timestamp <= new Date(compactionEntry.timestamp).getTime();
|
|
1396
1528
|
if (assistantIsFromBeforeCompaction) {
|
|
1397
|
-
return;
|
|
1529
|
+
return false;
|
|
1398
1530
|
}
|
|
1399
1531
|
// Case 1: Overflow - LLM returned context overflow error
|
|
1400
1532
|
if (sameModel && isContextOverflow(assistantMessage, contextWindow)) {
|
|
@@ -1407,7 +1539,8 @@ export class AgentSession {
|
|
|
1407
1539
|
willRetry: false,
|
|
1408
1540
|
errorMessage: "Context overflow recovery failed after one compact-and-retry attempt. Try reducing context or switching to a larger-context model.",
|
|
1409
1541
|
});
|
|
1410
|
-
|
|
1542
|
+
this._emitStateUpdate();
|
|
1543
|
+
return false;
|
|
1411
1544
|
}
|
|
1412
1545
|
this._overflowRecoveryAttempted = true;
|
|
1413
1546
|
// Remove the error message from agent state (it IS saved to session for history,
|
|
@@ -1416,8 +1549,7 @@ export class AgentSession {
|
|
|
1416
1549
|
if (messages.length > 0 && messages[messages.length - 1].role === "assistant") {
|
|
1417
1550
|
this.agent.state.messages = messages.slice(0, -1);
|
|
1418
1551
|
}
|
|
1419
|
-
await this._runAutoCompaction("overflow", true);
|
|
1420
|
-
return;
|
|
1552
|
+
return await this._runAutoCompaction("overflow", true);
|
|
1421
1553
|
}
|
|
1422
1554
|
// Case 2: Threshold - context is getting large
|
|
1423
1555
|
// For error messages (no usage data), estimate from last successful response.
|
|
@@ -1427,7 +1559,7 @@ export class AgentSession {
|
|
|
1427
1559
|
const messages = this.agent.state.messages;
|
|
1428
1560
|
const estimate = estimateContextTokens(messages);
|
|
1429
1561
|
if (estimate.lastUsageIndex === null)
|
|
1430
|
-
return; // No usage data at all
|
|
1562
|
+
return false; // No usage data at all
|
|
1431
1563
|
// Verify the usage source is post-compaction. Kept pre-compaction messages
|
|
1432
1564
|
// have stale usage reflecting the old (larger) context and would falsely
|
|
1433
1565
|
// trigger compaction right after one just finished.
|
|
@@ -1435,7 +1567,7 @@ export class AgentSession {
|
|
|
1435
1567
|
if (compactionEntry &&
|
|
1436
1568
|
usageMsg.role === "assistant" &&
|
|
1437
1569
|
usageMsg.timestamp <= new Date(compactionEntry.timestamp).getTime()) {
|
|
1438
|
-
return;
|
|
1570
|
+
return false;
|
|
1439
1571
|
}
|
|
1440
1572
|
contextTokens = estimate.tokens;
|
|
1441
1573
|
}
|
|
@@ -1443,8 +1575,9 @@ export class AgentSession {
|
|
|
1443
1575
|
contextTokens = calculateContextTokens(assistantMessage.usage);
|
|
1444
1576
|
}
|
|
1445
1577
|
if (shouldCompact(contextTokens, contextWindow, settings)) {
|
|
1446
|
-
await this._runAutoCompaction("threshold", false);
|
|
1578
|
+
return await this._runAutoCompaction("threshold", false);
|
|
1447
1579
|
}
|
|
1580
|
+
return false;
|
|
1448
1581
|
}
|
|
1449
1582
|
/**
|
|
1450
1583
|
* Internal: Run auto-compaction with events.
|
|
@@ -1462,20 +1595,30 @@ export class AgentSession {
|
|
|
1462
1595
|
aborted: false,
|
|
1463
1596
|
willRetry: false,
|
|
1464
1597
|
});
|
|
1465
|
-
|
|
1598
|
+
this._emitStateUpdate();
|
|
1599
|
+
return false;
|
|
1466
1600
|
}
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1601
|
+
let apiKey;
|
|
1602
|
+
let headers;
|
|
1603
|
+
if (this.agent.streamFn === streamSimple) {
|
|
1604
|
+
const authResult = await this._modelRegistry.getApiKeyAndHeaders(this.model);
|
|
1605
|
+
if (!authResult.ok || !authResult.apiKey) {
|
|
1606
|
+
this._emit({
|
|
1607
|
+
type: "compaction_end",
|
|
1608
|
+
reason,
|
|
1609
|
+
result: undefined,
|
|
1610
|
+
aborted: false,
|
|
1611
|
+
willRetry: false,
|
|
1612
|
+
});
|
|
1613
|
+
this._emitStateUpdate();
|
|
1614
|
+
return false;
|
|
1615
|
+
}
|
|
1616
|
+
apiKey = authResult.apiKey;
|
|
1617
|
+
headers = authResult.headers;
|
|
1618
|
+
}
|
|
1619
|
+
else {
|
|
1620
|
+
({ apiKey, headers } = await this._getCompactionRequestAuth(this.model));
|
|
1477
1621
|
}
|
|
1478
|
-
const { apiKey, headers } = authResult;
|
|
1479
1622
|
const pathEntries = this.sessionManager.getBranch();
|
|
1480
1623
|
const preparation = prepareCompaction(pathEntries, settings);
|
|
1481
1624
|
if (!preparation) {
|
|
@@ -1486,7 +1629,8 @@ export class AgentSession {
|
|
|
1486
1629
|
aborted: false,
|
|
1487
1630
|
willRetry: false,
|
|
1488
1631
|
});
|
|
1489
|
-
|
|
1632
|
+
this._emitStateUpdate();
|
|
1633
|
+
return false;
|
|
1490
1634
|
}
|
|
1491
1635
|
let extensionCompaction;
|
|
1492
1636
|
let fromExtension = false;
|
|
@@ -1506,7 +1650,8 @@ export class AgentSession {
|
|
|
1506
1650
|
aborted: true,
|
|
1507
1651
|
willRetry: false,
|
|
1508
1652
|
});
|
|
1509
|
-
|
|
1653
|
+
this._emitStateUpdate();
|
|
1654
|
+
return false;
|
|
1510
1655
|
}
|
|
1511
1656
|
if (extensionResult?.compaction) {
|
|
1512
1657
|
extensionCompaction = extensionResult.compaction;
|
|
@@ -1526,7 +1671,7 @@ export class AgentSession {
|
|
|
1526
1671
|
}
|
|
1527
1672
|
else {
|
|
1528
1673
|
// Generate compaction result
|
|
1529
|
-
const compactResult = await compact(preparation, this.model, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel);
|
|
1674
|
+
const compactResult = await compact(preparation, this.model, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel, this.agent.streamFn);
|
|
1530
1675
|
summary = compactResult.summary;
|
|
1531
1676
|
firstKeptEntryId = compactResult.firstKeptEntryId;
|
|
1532
1677
|
tokensBefore = compactResult.tokensBefore;
|
|
@@ -1540,12 +1685,14 @@ export class AgentSession {
|
|
|
1540
1685
|
aborted: true,
|
|
1541
1686
|
willRetry: false,
|
|
1542
1687
|
});
|
|
1543
|
-
return;
|
|
1688
|
+
return false;
|
|
1544
1689
|
}
|
|
1545
1690
|
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension);
|
|
1546
1691
|
const newEntries = this.sessionManager.getEntries();
|
|
1547
1692
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1548
1693
|
this.agent.state.messages = sessionContext.messages;
|
|
1694
|
+
// Prune old entries from memory and disk to prevent unbounded growth
|
|
1695
|
+
this.sessionManager.pruneAfterCompaction();
|
|
1549
1696
|
// Get the saved compaction entry for the extension event
|
|
1550
1697
|
const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
|
|
1551
1698
|
if (this._extensionRunner && savedCompactionEntry) {
|
|
@@ -1562,23 +1709,18 @@ export class AgentSession {
|
|
|
1562
1709
|
details,
|
|
1563
1710
|
};
|
|
1564
1711
|
this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
|
|
1712
|
+
this._emitStateUpdate();
|
|
1565
1713
|
if (willRetry) {
|
|
1566
1714
|
const messages = this.agent.state.messages;
|
|
1567
1715
|
const lastMsg = messages[messages.length - 1];
|
|
1568
1716
|
if (lastMsg?.role === "assistant" && lastMsg.stopReason === "error") {
|
|
1569
1717
|
this.agent.state.messages = messages.slice(0, -1);
|
|
1570
1718
|
}
|
|
1571
|
-
|
|
1572
|
-
this.agent.continue().catch(() => { });
|
|
1573
|
-
}, 100);
|
|
1574
|
-
}
|
|
1575
|
-
else if (this.agent.hasQueuedMessages()) {
|
|
1576
|
-
// Auto-compaction can complete while follow-up/steering/custom messages are waiting.
|
|
1577
|
-
// Kick the loop so queued messages are actually delivered.
|
|
1578
|
-
setTimeout(() => {
|
|
1579
|
-
this.agent.continue().catch(() => { });
|
|
1580
|
-
}, 100);
|
|
1719
|
+
return true;
|
|
1581
1720
|
}
|
|
1721
|
+
// Auto-compaction can complete while follow-up/steering/custom messages are waiting.
|
|
1722
|
+
// Continue once so queued messages are delivered.
|
|
1723
|
+
return this.agent.hasQueuedMessages();
|
|
1582
1724
|
}
|
|
1583
1725
|
catch (error) {
|
|
1584
1726
|
const errorMessage = error instanceof Error ? error.message : "compaction failed";
|
|
@@ -1592,6 +1734,8 @@ export class AgentSession {
|
|
|
1592
1734
|
? `Context overflow recovery failed: ${errorMessage}`
|
|
1593
1735
|
: `Auto-compaction failed: ${errorMessage}`,
|
|
1594
1736
|
});
|
|
1737
|
+
this._emitStateUpdate();
|
|
1738
|
+
return false;
|
|
1595
1739
|
}
|
|
1596
1740
|
finally {
|
|
1597
1741
|
this._autoCompactionAbortController = undefined;
|
|
@@ -1602,6 +1746,7 @@ export class AgentSession {
|
|
|
1602
1746
|
*/
|
|
1603
1747
|
setAutoCompactionEnabled(enabled) {
|
|
1604
1748
|
this.settingsManager.setCompactionEnabled(enabled);
|
|
1749
|
+
this._emitStateUpdate();
|
|
1605
1750
|
}
|
|
1606
1751
|
/** Whether auto-compaction is enabled */
|
|
1607
1752
|
get autoCompactionEnabled() {
|
|
@@ -1614,6 +1759,9 @@ export class AgentSession {
|
|
|
1614
1759
|
if (bindings.commandContextActions !== undefined) {
|
|
1615
1760
|
this._extensionCommandContextActions = bindings.commandContextActions;
|
|
1616
1761
|
}
|
|
1762
|
+
if (bindings.abortHandler !== undefined) {
|
|
1763
|
+
this._extensionAbortHandler = bindings.abortHandler;
|
|
1764
|
+
}
|
|
1617
1765
|
if (bindings.shutdownHandler !== undefined) {
|
|
1618
1766
|
this._extensionShutdownHandler = bindings.shutdownHandler;
|
|
1619
1767
|
}
|
|
@@ -1753,7 +1901,13 @@ export class AgentSession {
|
|
|
1753
1901
|
getModel: () => this.model,
|
|
1754
1902
|
isIdle: () => !this.isStreaming,
|
|
1755
1903
|
getSignal: () => this.agent.signal,
|
|
1756
|
-
abort: () =>
|
|
1904
|
+
abort: () => {
|
|
1905
|
+
if (this._extensionAbortHandler) {
|
|
1906
|
+
this._extensionAbortHandler();
|
|
1907
|
+
return;
|
|
1908
|
+
}
|
|
1909
|
+
void this.abort();
|
|
1910
|
+
},
|
|
1757
1911
|
hasPendingMessages: () => this.pendingMessageCount > 0,
|
|
1758
1912
|
shutdown: () => {
|
|
1759
1913
|
this._extensionShutdownHandler?.();
|
|
@@ -1787,7 +1941,8 @@ export class AgentSession {
|
|
|
1787
1941
|
const previousRegistryNames = new Set(this._toolRegistry.keys());
|
|
1788
1942
|
const previousActiveToolNames = this.getActiveToolNames();
|
|
1789
1943
|
const allowedToolNames = this._allowedToolNames;
|
|
1790
|
-
const
|
|
1944
|
+
const excludedToolNames = this._excludedToolNames;
|
|
1945
|
+
const isAllowedTool = (name) => (!allowedToolNames || allowedToolNames.has(name)) && !excludedToolNames?.has(name);
|
|
1791
1946
|
const registeredTools = this._extensionRunner.getAllRegisteredTools();
|
|
1792
1947
|
const allCustomTools = [
|
|
1793
1948
|
...registeredTools,
|
|
@@ -1917,6 +2072,9 @@ export class AgentSession {
|
|
|
1917
2072
|
// =========================================================================
|
|
1918
2073
|
// Auto-Retry
|
|
1919
2074
|
// =========================================================================
|
|
2075
|
+
_isNonRetryableProviderLimitError(errorMessage) {
|
|
2076
|
+
return /GoUsageLimitError|FreeUsageLimitError|Monthly usage limit reached|available balance|insufficient_quota|out of budget|quota exceeded|billing/i.test(errorMessage);
|
|
2077
|
+
}
|
|
1920
2078
|
/**
|
|
1921
2079
|
* Check if an error is retryable (overloaded, rate limit, server errors).
|
|
1922
2080
|
* Context overflow errors are NOT retryable (handled by compaction instead).
|
|
@@ -1929,37 +2087,24 @@ export class AgentSession {
|
|
|
1929
2087
|
if (isContextOverflow(message, contextWindow))
|
|
1930
2088
|
return false;
|
|
1931
2089
|
const err = message.errorMessage;
|
|
2090
|
+
if (this._isNonRetryableProviderLimitError(err))
|
|
2091
|
+
return false;
|
|
1932
2092
|
// Match: overloaded_error, provider returned error, rate limit, 429, 500, 502, 503, 504, service unavailable, network/connection errors (including connection lost), WebSocket transport closes/errors, fetch failed, premature stream endings, HTTP/2 closed before response, terminated, retry delay exceeded
|
|
1933
2093
|
return /overloaded|provider.?returned.?error|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|network.?error|connection.?error|connection.?refused|connection.?lost|websocket.?closed|websocket.?error|other side closed|fetch failed|upstream.?connect|reset before headers|socket hang up|ended without|stream ended before message_stop|http2 request did not get a response|timed? out|timeout|terminated|retry delay/i.test(err);
|
|
1934
2094
|
}
|
|
1935
2095
|
/**
|
|
1936
|
-
*
|
|
1937
|
-
* @returns true if
|
|
2096
|
+
* Prepare a retryable error for continuation with exponential backoff.
|
|
2097
|
+
* @returns true if the caller should continue the agent, false otherwise
|
|
1938
2098
|
*/
|
|
1939
|
-
async
|
|
2099
|
+
async _prepareRetry(message) {
|
|
1940
2100
|
const settings = this.settingsManager.getRetrySettings();
|
|
1941
2101
|
if (!settings.enabled) {
|
|
1942
|
-
this._resolveRetry();
|
|
1943
2102
|
return false;
|
|
1944
2103
|
}
|
|
1945
|
-
// Retry promise is created synchronously in _handleAgentEvent for agent_end.
|
|
1946
|
-
// Keep a defensive fallback here in case a future refactor bypasses that path.
|
|
1947
|
-
if (!this._retryPromise) {
|
|
1948
|
-
this._retryPromise = new Promise((resolve) => {
|
|
1949
|
-
this._retryResolve = resolve;
|
|
1950
|
-
});
|
|
1951
|
-
}
|
|
1952
2104
|
this._retryAttempt++;
|
|
1953
2105
|
if (this._retryAttempt > settings.maxRetries) {
|
|
1954
|
-
//
|
|
1955
|
-
this.
|
|
1956
|
-
type: "auto_retry_end",
|
|
1957
|
-
success: false,
|
|
1958
|
-
attempt: this._retryAttempt - 1,
|
|
1959
|
-
finalError: message.errorMessage,
|
|
1960
|
-
});
|
|
1961
|
-
this._retryAttempt = 0;
|
|
1962
|
-
this._resolveRetry(); // Resolve so waitForRetry() completes
|
|
2106
|
+
// Preserve the completed attempt count so post-run handling can emit the final failure.
|
|
2107
|
+
this._retryAttempt--;
|
|
1963
2108
|
return false;
|
|
1964
2109
|
}
|
|
1965
2110
|
const delayMs = settings.baseDelayMs * 2 ** (this._retryAttempt - 1);
|
|
@@ -1984,23 +2129,17 @@ export class AgentSession {
|
|
|
1984
2129
|
// Aborted during sleep - emit end event so UI can clean up
|
|
1985
2130
|
const attempt = this._retryAttempt;
|
|
1986
2131
|
this._retryAttempt = 0;
|
|
1987
|
-
this._retryAbortController = undefined;
|
|
1988
2132
|
this._emit({
|
|
1989
2133
|
type: "auto_retry_end",
|
|
1990
2134
|
success: false,
|
|
1991
2135
|
attempt,
|
|
1992
2136
|
finalError: "Retry cancelled",
|
|
1993
2137
|
});
|
|
1994
|
-
this._resolveRetry();
|
|
1995
2138
|
return false;
|
|
1996
2139
|
}
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
this.agent.continue().catch(() => {
|
|
2001
|
-
// Retry failed - will be caught by next agent_end
|
|
2002
|
-
});
|
|
2003
|
-
}, 0);
|
|
2140
|
+
finally {
|
|
2141
|
+
this._retryAbortController = undefined;
|
|
2142
|
+
}
|
|
2004
2143
|
return true;
|
|
2005
2144
|
}
|
|
2006
2145
|
/**
|
|
@@ -2008,23 +2147,10 @@ export class AgentSession {
|
|
|
2008
2147
|
*/
|
|
2009
2148
|
abortRetry() {
|
|
2010
2149
|
this._retryAbortController?.abort();
|
|
2011
|
-
// Note: _retryAttempt is reset in the catch block of _autoRetry
|
|
2012
|
-
this._resolveRetry();
|
|
2013
|
-
}
|
|
2014
|
-
/**
|
|
2015
|
-
* Wait for any in-progress retry to complete.
|
|
2016
|
-
* Returns immediately if no retry is in progress.
|
|
2017
|
-
*/
|
|
2018
|
-
async waitForRetry() {
|
|
2019
|
-
if (!this._retryPromise) {
|
|
2020
|
-
return;
|
|
2021
|
-
}
|
|
2022
|
-
await this._retryPromise;
|
|
2023
|
-
await this.agent.waitForIdle();
|
|
2024
2150
|
}
|
|
2025
2151
|
/** Whether auto-retry is currently in progress */
|
|
2026
2152
|
get isRetrying() {
|
|
2027
|
-
return this.
|
|
2153
|
+
return this._retryAbortController !== undefined;
|
|
2028
2154
|
}
|
|
2029
2155
|
/** Whether auto-retry is enabled */
|
|
2030
2156
|
get autoRetryEnabled() {
|
|
@@ -2443,7 +2569,7 @@ export class AgentSession {
|
|
|
2443
2569
|
* @returns The resolved output file path.
|
|
2444
2570
|
*/
|
|
2445
2571
|
exportToJsonl(outputPath) {
|
|
2446
|
-
const filePath =
|
|
2572
|
+
const filePath = resolvePath(outputPath ?? `session-${new Date().toISOString().replace(/[:.]/g, "-")}.jsonl`, process.cwd());
|
|
2447
2573
|
const dir = dirname(filePath);
|
|
2448
2574
|
if (!existsSync(dir)) {
|
|
2449
2575
|
mkdirSync(dir, { recursive: true });
|