@astralyn/pi 0.85.3 → 0.86.1
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 +52 -0
- package/dist/bundle/chunks/anthropic-messages-R2LYJUDD.js +6 -0
- package/dist/bundle/chunks/azure-openai-responses-HS35BQV6.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +36 -32
- package/dist/bundle/chunks/{chunk-S2DJQQI2.js → chunk-2IO5GDBS.js} +10 -1
- package/dist/bundle/chunks/chunk-DAEM5JIZ.js +2 -0
- package/dist/bundle/chunks/{chunk-LB4P77SH.js → chunk-GTBMYBFG.js} +777 -762
- package/dist/bundle/chunks/{chunk-7LO5Z4WE.js → chunk-I5IVW2WS.js} +1 -1
- package/dist/bundle/chunks/chunk-JI4WGISU.js +2 -0
- package/dist/bundle/chunks/chunk-LPQCB2VJ.js +44 -0
- package/dist/bundle/chunks/chunk-NW5FIDD7.js +11 -0
- package/dist/bundle/chunks/chunk-PJVFYVHE.js +42 -0
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/google-generative-ai-NOVAJBFC.js +2 -0
- package/dist/bundle/chunks/google-vertex-4VHCZJV5.js +2 -0
- package/dist/bundle/chunks/https-proxy-agent-JOOPB4RE.js +16 -0
- package/dist/bundle/chunks/jiti-loader-BFSSLU7G.js +21 -0
- package/dist/bundle/chunks/jiti-static-loader-CLT3YR3B.js +2 -0
- package/dist/bundle/chunks/mistral-conversations-WC6A2WCJ.js +5 -0
- package/dist/bundle/chunks/{node-G4XOIDPH.js → node-CXWYTK2I.js} +1 -1
- package/dist/bundle/chunks/openai-codex-responses-XCDG75W2.js +10 -0
- package/dist/bundle/chunks/openai-completions-6SMWQWQN.js +7 -0
- package/dist/bundle/chunks/openai-responses-UT6XFKC7.js +2 -0
- package/dist/bundle/chunks/{pi-messages-PE6B42TG.js → pi-messages-MQMPIPNC.js} +1 -1
- package/dist/bundle/chunks/virtual-modules-OHUZ2T7X.js +2 -0
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -0
- package/dist/cli/args.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 +13 -11
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +56 -14
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +305 -176
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bug-report-upload.d.ts +12 -0
- package/dist/core/bug-report-upload.d.ts.map +1 -0
- package/dist/core/bug-report-upload.js +22 -0
- package/dist/core/bug-report-upload.js.map +1 -0
- package/dist/core/bug-report.d.ts +176 -0
- package/dist/core/bug-report.d.ts.map +1 -0
- package/dist/core/bug-report.js +292 -0
- package/dist/core/bug-report.js.map +1 -0
- package/dist/core/cache-stats.d.ts.map +1 -1
- package/dist/core/cache-stats.js +12 -1
- package/dist/core/cache-stats.js.map +1 -1
- package/dist/core/cache-warmer.d.ts +102 -0
- package/dist/core/cache-warmer.d.ts.map +1 -0
- package/dist/core/cache-warmer.js +333 -0
- package/dist/core/cache-warmer.js.map +1 -0
- package/dist/core/compaction/branch-summarization.js +2 -2
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +14 -9
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +30 -23
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/settings.d.ts +17 -20
- package/dist/core/compaction/settings.d.ts.map +1 -1
- package/dist/core/compaction/settings.js +19 -26
- package/dist/core/compaction/settings.js.map +1 -1
- package/dist/core/context-snapshot.d.ts +16 -5
- package/dist/core/context-snapshot.d.ts.map +1 -1
- package/dist/core/context-snapshot.js +20 -10
- package/dist/core/context-snapshot.js.map +1 -1
- package/dist/core/crash-log.d.ts +22 -0
- package/dist/core/crash-log.d.ts.map +1 -0
- package/dist/core/crash-log.js +71 -0
- package/dist/core/crash-log.js.map +1 -0
- package/dist/core/experimental.d.ts +0 -4
- package/dist/core/experimental.d.ts.map +1 -1
- package/dist/core/experimental.js +0 -4
- package/dist/core/experimental.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/jiti-loader.d.ts +2 -0
- package/dist/core/extensions/jiti-loader.d.ts.map +1 -0
- package/dist/core/extensions/jiti-loader.js +4 -0
- package/dist/core/extensions/jiti-loader.js.map +1 -0
- package/dist/core/extensions/jiti-static-loader.d.ts +2 -0
- package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -0
- package/dist/core/extensions/jiti-static-loader.js +4 -0
- package/dist/core/extensions/jiti-static-loader.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +38 -51
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +10 -7
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +85 -67
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +60 -50
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/virtual-modules.d.ts +3 -0
- package/dist/core/extensions/virtual-modules.d.ts.map +1 -0
- package/dist/core/extensions/virtual-modules.js +39 -0
- package/dist/core/extensions/virtual-modules.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +1 -20
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +1 -1
- package/dist/core/keybindings.js +1 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +1 -0
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-config.d.ts +101 -20
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +25 -18
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +8 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +2 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +5 -3
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/provider-composer.d.ts +3 -2
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +2 -0
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/radius.d.ts +3 -0
- package/dist/core/radius.d.ts.map +1 -1
- package/dist/core/radius.js +6 -0
- package/dist/core/radius.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +46 -18
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-export.d.ts +6 -2
- package/dist/core/session-export.d.ts.map +1 -1
- package/dist/core/session-export.js +14 -13
- package/dist/core/session-export.js.map +1 -1
- package/dist/core/session-manager.d.ts +29 -6
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +159 -96
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +31 -4
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +65 -8
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts +49 -6
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +121 -92
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +6 -3
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +1 -2
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -2
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/shell-execution.js +2 -2
- package/dist/core/tools/shell-execution.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +1 -2
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/usage-totals.d.ts +1 -1
- package/dist/core/usage-totals.d.ts.map +1 -1
- package/dist/core/usage-totals.js +4 -1
- package/dist/core/usage-totals.js.map +1 -1
- package/dist/extensions/background/schema.d.ts +1 -1
- package/dist/extensions/btw/agent.d.ts.map +1 -1
- package/dist/extensions/btw/agent.js +3 -2
- package/dist/extensions/btw/agent.js.map +1 -1
- package/dist/extensions/llama/client.d.ts +2 -0
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +7 -3
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +20 -5
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/provider/compat-fields.d.ts.map +1 -1
- package/dist/extensions/provider/compat-fields.js +5 -2
- package/dist/extensions/provider/compat-fields.js.map +1 -1
- package/dist/extensions/provider/ui/app.js +2 -2
- package/dist/extensions/provider/ui/app.js.map +1 -1
- package/dist/extensions/todo/schema.d.ts +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +13 -9
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +2 -2
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/bug-report.d.ts +16 -0
- package/dist/modes/interactive/bug-report.d.ts.map +1 -0
- package/dist/modes/interactive/bug-report.js +206 -0
- package/dist/modes/interactive/bug-report.js.map +1 -0
- package/dist/modes/interactive/chat-viewport.js +1 -1
- package/dist/modes/interactive/chat-viewport.js.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js +0 -5
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +0 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +2 -3
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +12 -5
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +12 -5
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts +6 -13
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +15 -51
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
- 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/extension-editor.d.ts +4 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +7 -2
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts +2 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +6 -0
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +1 -2
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +4 -2
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +5 -8
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +72 -95
- 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 +11 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +11 -4
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +2 -2
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +7 -7
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/tool-chrome.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-chrome.js +4 -1
- package/dist/modes/interactive/components/tool-chrome.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +4 -3
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +1 -10
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +4 -51
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +15 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +234 -91
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/session-share.d.ts +2 -0
- package/dist/modes/interactive/session-share.d.ts.map +1 -1
- package/dist/modes/interactive/session-share.js +8 -4
- package/dist/modes/interactive/session-share.js.map +1 -1
- package/dist/modes/interactive/tui-renderer.js +2 -2
- package/dist/modes/interactive/tui-renderer.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -2
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/clipboard-command.d.ts +7 -0
- package/dist/utils/clipboard-command.d.ts.map +1 -0
- package/dist/utils/clipboard-command.js +45 -0
- package/dist/utils/clipboard-command.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +53 -81
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +111 -121
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/wsl.d.ts +3 -0
- package/dist/utils/wsl.d.ts.map +1 -0
- package/dist/utils/wsl.js +15 -0
- package/dist/utils/wsl.js.map +1 -0
- package/dist/utils/zip.d.ts +7 -0
- package/dist/utils/zip.d.ts.map +1 -0
- package/dist/utils/zip.js +60 -0
- package/dist/utils/zip.js.map +1 -0
- package/docs/compaction.md +32 -11
- package/docs/custom-provider.md +19 -8
- package/docs/environment-variables.md +1 -0
- package/docs/extensions.md +50 -34
- package/docs/models.md +38 -3
- package/docs/providers.md +9 -1
- package/docs/sdk.md +4 -2
- package/docs/session-format.md +63 -24
- package/docs/sessions.md +28 -1
- package/docs/settings.md +58 -4
- package/docs/termux.md +0 -1
- package/docs/tui.md +2 -0
- package/docs/usage.md +1 -0
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +18 -12
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -2
- package/examples/extensions/prompt-customizer.ts +19 -67
- package/npm-shrinkwrap.json +275 -1028
- package/package.json +17 -23
- package/dist/bundle/chunks/anthropic-messages-IHRRITCV.js +0 -6
- package/dist/bundle/chunks/azure-openai-responses-QXBIDYXO.js +0 -2
- package/dist/bundle/chunks/chunk-JSJPY26N.js +0 -2
- package/dist/bundle/chunks/chunk-KI6LC764.js +0 -42
- package/dist/bundle/chunks/chunk-OWESLY5T.js +0 -11
- package/dist/bundle/chunks/chunk-RRBI7OUG.js +0 -50
- package/dist/bundle/chunks/chunk-YZJWMPUI.js +0 -2
- package/dist/bundle/chunks/google-generative-ai-NBOR3IQR.js +0 -2
- package/dist/bundle/chunks/google-vertex-VTHX3SUB.js +0 -2
- package/dist/bundle/chunks/https-proxy-agent-2VXB7436.js +0 -13
- package/dist/bundle/chunks/mistral-conversations-NO4ANAA5.js +0 -5
- package/dist/bundle/chunks/openai-codex-responses-5S3T3HMA.js +0 -10
- package/dist/bundle/chunks/openai-completions-CXRRTRWE.js +0 -7
- package/dist/bundle/chunks/openai-responses-CV3MH6VP.js +0 -2
- package/dist/utils/clipboard-native.d.ts +0 -11
- package/dist/utils/clipboard-native.d.ts.map +0 -1
- package/dist/utils/clipboard-native.js +0 -20
- package/dist/utils/clipboard-native.js.map +0 -1
- package/examples/extensions/kimi-deferred-tools.ts +0 -61
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { readFileSync } from "node:fs";
|
|
16
16
|
import { basename, dirname } from "node:path";
|
|
17
|
-
import { contentText } from "@earendil-works/pi-ai";
|
|
17
|
+
import { contentText, getCurrentSystemMessage, getSystemMessageText, retryDelayMs } from "@earendil-works/pi-ai";
|
|
18
18
|
import { clampThinkingLevel, cleanupSessionResources, getSupportedThinkingLevels, isContextOverflow, isRecoverableLength, isRetryableAssistantError, modelsAreEqual, resetApiProviders, streamSimple, } from "@earendil-works/pi-ai/compat";
|
|
19
19
|
import { getThemeByName, theme } from "../modes/interactive/theme/theme.js";
|
|
20
20
|
import { stripFrontmatter } from "../utils/frontmatter.js";
|
|
@@ -23,6 +23,7 @@ import { normalizeToolResultImages } from "../utils/tool-result-images.js";
|
|
|
23
23
|
import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
|
|
24
24
|
import { BackgroundSession } from "./background/session.js";
|
|
25
25
|
import { executeBashWithOperations } from "./bash-executor.js";
|
|
26
|
+
import { generateBugReportSummary } from "./bug-report.js";
|
|
26
27
|
import { calculateContextTokens, collectEntriesForBranchSummary, compact, estimateContextTokens, estimateTokens, generateBranchSummary, prepareCompaction, shouldCompact, } from "./compaction/index.js";
|
|
27
28
|
import { DEFAULT_THINKING_LEVEL, THINKING_LEVEL_OPTIONS } from "./defaults.js";
|
|
28
29
|
import { exportSessionToHtml } from "./export-html/index.js";
|
|
@@ -35,7 +36,7 @@ import { expandPromptTemplate } from "./prompt-templates.js";
|
|
|
35
36
|
import { exportSessionToJsonl } from "./session-export.js";
|
|
36
37
|
import { getLatestCompactionEntry } from "./session-manager.js";
|
|
37
38
|
import { createSyntheticSourceInfo } from "./source-info.js";
|
|
38
|
-
import { buildSystemPrompt } from "./system-prompt.js";
|
|
39
|
+
import { buildSystemPrompt, buildSystemPromptSections, diffSystemPromptSections, normalizeBuildSystemPromptOptions, } from "./system-prompt.js";
|
|
39
40
|
import { createLocalBashOperations } from "./tools/bash.js";
|
|
40
41
|
import { createAllToolDefinitions } from "./tools/index.js";
|
|
41
42
|
import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
|
|
@@ -71,15 +72,13 @@ function estimateMessagesTokens(messages) {
|
|
|
71
72
|
return tokens;
|
|
72
73
|
}
|
|
73
74
|
// ============================================================================
|
|
74
|
-
// Constants
|
|
75
|
-
// ============================================================================
|
|
76
|
-
// ============================================================================
|
|
77
75
|
// AgentSession Class
|
|
78
76
|
// ============================================================================
|
|
79
77
|
export class AgentSession {
|
|
80
78
|
constructor(config) {
|
|
81
79
|
this._eventListeners = [];
|
|
82
80
|
this._isAgentRunActive = false;
|
|
81
|
+
this._agentRunAbortRequested = false;
|
|
83
82
|
/** Tracks pending steering messages for UI display. Removed when delivered. */
|
|
84
83
|
this._steeringMessages = [];
|
|
85
84
|
/** Tracks pending follow-up messages for UI display. Removed when delivered. */
|
|
@@ -108,8 +107,6 @@ export class AgentSession {
|
|
|
108
107
|
this._toolDefinitions = new Map();
|
|
109
108
|
this._toolPromptSnippets = new Map();
|
|
110
109
|
this._toolPromptGuidelines = new Map();
|
|
111
|
-
// Base system prompt (without extension appends) - used to apply fresh appends each turn
|
|
112
|
-
this._baseSystemPrompt = "";
|
|
113
110
|
// Track last assistant message for auto-compaction check
|
|
114
111
|
this._lastAssistantMessage = undefined;
|
|
115
112
|
/** Internal handler for agent events - shared by subscribe and reconnect */
|
|
@@ -200,6 +197,10 @@ export class AgentSession {
|
|
|
200
197
|
this._cwd = config.cwd;
|
|
201
198
|
this._modelRuntime = config.modelRuntime;
|
|
202
199
|
this._captureModelContext = config.captureModelContext;
|
|
200
|
+
this._cacheWarmer = config.cacheWarmer;
|
|
201
|
+
if (this._cacheWarmer) {
|
|
202
|
+
this._cacheWarmer.onWarmed = (entry) => this._emit({ type: "entry_appended", entry });
|
|
203
|
+
}
|
|
203
204
|
this._extensionRunnerRef = config.extensionRunnerRef;
|
|
204
205
|
this._initialActiveToolNames = config.initialActiveToolNames;
|
|
205
206
|
this._allowedToolNames = config.allowedToolNames ? new Set(config.allowedToolNames) : undefined;
|
|
@@ -211,10 +212,13 @@ export class AgentSession {
|
|
|
211
212
|
this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
|
|
212
213
|
this._installAgentToolHooks();
|
|
213
214
|
this._installAgentNextTurnRefresh();
|
|
215
|
+
this._installAgentForcedPromptProjection();
|
|
214
216
|
this._buildRuntime({
|
|
215
217
|
activeToolNames: this._initialActiveToolNames,
|
|
216
218
|
includeAllExtensionTools: true,
|
|
217
219
|
});
|
|
220
|
+
if (this._initialActiveToolNames === undefined)
|
|
221
|
+
this._restoreToolsFromTranscript();
|
|
218
222
|
}
|
|
219
223
|
get background() {
|
|
220
224
|
return this._backgroundHost.service;
|
|
@@ -244,7 +248,6 @@ export class AgentSession {
|
|
|
244
248
|
leafId: this.sessionManager.getLeafId(),
|
|
245
249
|
model: structuredClone(model),
|
|
246
250
|
thinkingLevel: this.thinkingLevel,
|
|
247
|
-
systemPrompt: this.systemPrompt,
|
|
248
251
|
tools: this.agent.state.tools.map(({ name, description, parameters, constrainedSampling }) => ({
|
|
249
252
|
name,
|
|
250
253
|
description,
|
|
@@ -260,18 +263,26 @@ export class AgentSession {
|
|
|
260
263
|
onResponse: this.agent.onResponse,
|
|
261
264
|
}),
|
|
262
265
|
};
|
|
266
|
+
const currentSystemPrompt = this.systemPrompt;
|
|
263
267
|
const messages = structuredClone(this.agent.state.messages);
|
|
264
268
|
const convert = this.agent.convertToLlm;
|
|
265
269
|
const transform = this.agent.transformContext;
|
|
266
270
|
const prepared = this._captureModelContext
|
|
267
271
|
? await this._captureModelContext(messages)
|
|
268
272
|
: await convert(transform ? await transform(messages) : messages);
|
|
269
|
-
|
|
273
|
+
// The prepared transcript declares the prompt the provider received, including a forced
|
|
274
|
+
// prompt projected for the last request; before the first request there is none yet.
|
|
275
|
+
const declared = getCurrentSystemMessage(prepared);
|
|
276
|
+
return {
|
|
277
|
+
...snapshot,
|
|
278
|
+
systemPrompt: declared ? getSystemMessageText(declared) : currentSystemPrompt,
|
|
279
|
+
messages: structuredClone(prepared),
|
|
280
|
+
};
|
|
270
281
|
}
|
|
271
|
-
async _getRequiredRequestAuth(model) {
|
|
282
|
+
async _getRequiredRequestAuth(model, signal) {
|
|
272
283
|
let result;
|
|
273
284
|
try {
|
|
274
|
-
result = await this._modelRuntime.getAuth(model);
|
|
285
|
+
result = await this._modelRuntime.getAuth(model, { signal });
|
|
275
286
|
}
|
|
276
287
|
catch (error) {
|
|
277
288
|
const cause = error instanceof Error ? error.cause : undefined;
|
|
@@ -297,20 +308,12 @@ export class AgentSession {
|
|
|
297
308
|
}
|
|
298
309
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
299
310
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
* Callers that await this while the session stays live must capture
|
|
304
|
-
* `this.agent.streamFunction` first and pass it in: a model switch during the
|
|
305
|
-
* await would otherwise select auth for one stream function and generate the
|
|
306
|
-
* summary with another.
|
|
307
|
-
*/
|
|
308
|
-
async _getSummarizationRequestAuth(model, streamFunction) {
|
|
309
|
-
if (streamFunction === streamSimple) {
|
|
310
|
-
return this._getRequiredRequestAuth(model);
|
|
311
|
+
async _getSummarizationRequestAuth(model, signal) {
|
|
312
|
+
if (this.agent.streamFunction === streamSimple) {
|
|
313
|
+
return this._getRequiredRequestAuth(model, signal);
|
|
311
314
|
}
|
|
312
315
|
try {
|
|
313
|
-
const result = await this._modelRuntime.getAuth(model);
|
|
316
|
+
const result = await this._modelRuntime.getAuth(model, { signal });
|
|
314
317
|
if (!result)
|
|
315
318
|
return { model };
|
|
316
319
|
const requestModel = result.auth.baseUrl ? { ...model, baseUrl: result.auth.baseUrl } : model;
|
|
@@ -321,7 +324,9 @@ export class AgentSession {
|
|
|
321
324
|
env: result.env,
|
|
322
325
|
};
|
|
323
326
|
}
|
|
324
|
-
catch {
|
|
327
|
+
catch (error) {
|
|
328
|
+
if (signal?.aborted)
|
|
329
|
+
throw error;
|
|
325
330
|
return { model };
|
|
326
331
|
}
|
|
327
332
|
}
|
|
@@ -386,7 +391,7 @@ export class AgentSession {
|
|
|
386
391
|
}
|
|
387
392
|
async _compactBeforeNextAssistantResponse(context) {
|
|
388
393
|
const model = this.model;
|
|
389
|
-
const settings = this.settingsManager.getCompactionSettings();
|
|
394
|
+
const settings = this.settingsManager.getCompactionSettings(model);
|
|
390
395
|
if (!model ||
|
|
391
396
|
model.contextWindow <= 0 ||
|
|
392
397
|
!shouldCompact(estimateContextTokens(context.messages).tokens, model.contextWindow, settings)) {
|
|
@@ -407,13 +412,25 @@ export class AgentSession {
|
|
|
407
412
|
const context = await this._compactBeforeNextAssistantResponse(turn.context);
|
|
408
413
|
const previousSnapshot = await previousPrepareNextTurnWithContext?.({ ...turn, context }, signal);
|
|
409
414
|
const nextContext = previousSnapshot?.context ?? context;
|
|
415
|
+
const runOptions = this._runSystemPromptOptions ?? this._baseSystemPromptOptions;
|
|
416
|
+
const options = normalizeBuildSystemPromptOptions({
|
|
417
|
+
...runOptions,
|
|
418
|
+
selectedTools: this.getActiveToolNames(),
|
|
419
|
+
toolSnippets: { ...this._baseSystemPromptOptions.toolSnippets, ...runOptions.toolSnippets },
|
|
420
|
+
toolGuidelines: { ...this._baseSystemPromptOptions.toolGuidelines, ...runOptions.toolGuidelines },
|
|
421
|
+
});
|
|
422
|
+
const updateMessage = this._preparePromptAndToolLoadout(options, nextContext.messages);
|
|
423
|
+
// Keep session.systemPrompt and ctx.getSystemPrompt() in step with what the provider sees.
|
|
424
|
+
this._runSystemPromptOptions = options;
|
|
410
425
|
return {
|
|
411
426
|
...previousSnapshot,
|
|
412
427
|
context: {
|
|
413
428
|
...nextContext,
|
|
414
|
-
systemPrompt: this._systemPromptOverride ?? this._baseSystemPrompt,
|
|
415
429
|
tools: this.agent.state.tools.slice(),
|
|
416
430
|
},
|
|
431
|
+
messages: updateMessage
|
|
432
|
+
? [...(previousSnapshot?.messages ?? []), updateMessage]
|
|
433
|
+
: previousSnapshot?.messages,
|
|
417
434
|
model: this.agent.state.model,
|
|
418
435
|
thinkingLevel: this.agent.state.thinkingLevel,
|
|
419
436
|
};
|
|
@@ -458,6 +475,7 @@ export class AgentSession {
|
|
|
458
475
|
resolve();
|
|
459
476
|
}
|
|
460
477
|
async _emitAgentSettled() {
|
|
478
|
+
this._cacheWarmer?.onAgentSettled();
|
|
461
479
|
const resumeBackground = this.pauseBackgroundNotifications();
|
|
462
480
|
this._isAgentRunActive = false;
|
|
463
481
|
try {
|
|
@@ -477,7 +495,10 @@ export class AgentSession {
|
|
|
477
495
|
if (pendingIndex !== -1)
|
|
478
496
|
this._pendingNextTurnMessages.splice(pendingIndex, 1);
|
|
479
497
|
}
|
|
480
|
-
else if (message.role === "
|
|
498
|
+
else if (message.role === "system" ||
|
|
499
|
+
message.role === "user" ||
|
|
500
|
+
message.role === "assistant" ||
|
|
501
|
+
message.role === "toolResult") {
|
|
481
502
|
this.sessionManager.appendMessage(message);
|
|
482
503
|
}
|
|
483
504
|
else {
|
|
@@ -489,6 +510,8 @@ export class AgentSession {
|
|
|
489
510
|
return true;
|
|
490
511
|
}
|
|
491
512
|
_willRetryAfterAgentEnd(event) {
|
|
513
|
+
if (this._agentRunAbortRequested)
|
|
514
|
+
return false;
|
|
492
515
|
const settings = this.settingsManager.getRetrySettings();
|
|
493
516
|
if (!settings.enabled || this._retryAttempt >= settings.maxRetries) {
|
|
494
517
|
return false;
|
|
@@ -658,6 +681,10 @@ export class AgentSession {
|
|
|
658
681
|
this._extensionRunner.invalidate(STALE_EXTENSION_CONTEXT_MESSAGE);
|
|
659
682
|
this._disconnectFromAgent();
|
|
660
683
|
this._eventListeners = [];
|
|
684
|
+
if (this._cacheWarmer) {
|
|
685
|
+
this._cacheWarmer.onWarmed = undefined;
|
|
686
|
+
this._cacheWarmer.cancel();
|
|
687
|
+
}
|
|
661
688
|
cleanupSessionResources(this.sessionId);
|
|
662
689
|
}
|
|
663
690
|
// =========================================================================
|
|
@@ -667,6 +694,15 @@ export class AgentSession {
|
|
|
667
694
|
get state() {
|
|
668
695
|
return this.agent.state;
|
|
669
696
|
}
|
|
697
|
+
/** Current cache-warming state and the policy inputs that produced it. */
|
|
698
|
+
get cacheWarmingStatus() {
|
|
699
|
+
return this._cacheWarmer?.status;
|
|
700
|
+
}
|
|
701
|
+
/** Persist the cache-warming mode and immediately reconcile active warming. */
|
|
702
|
+
setCacheWarmingMode(mode) {
|
|
703
|
+
this.settingsManager.setCacheWarmingMode(mode);
|
|
704
|
+
this._cacheWarmer?.onModeChanged();
|
|
705
|
+
}
|
|
670
706
|
/** Current model (may be undefined if not yet selected) */
|
|
671
707
|
get model() {
|
|
672
708
|
return this.agent.state.model;
|
|
@@ -683,9 +719,9 @@ export class AgentSession {
|
|
|
683
719
|
get isIdle() {
|
|
684
720
|
return !this._isAgentRunActive && !this.isCompacting;
|
|
685
721
|
}
|
|
686
|
-
/** Current effective system prompt
|
|
722
|
+
/** Current effective system prompt, including changes not yet sent to the model. */
|
|
687
723
|
get systemPrompt() {
|
|
688
|
-
return this.
|
|
724
|
+
return buildSystemPrompt(this._runSystemPromptOptions ?? this._baseSystemPromptOptions);
|
|
689
725
|
}
|
|
690
726
|
/** Current retry attempt (0 if not retrying) */
|
|
691
727
|
get retryAttempt() {
|
|
@@ -730,9 +766,7 @@ export class AgentSession {
|
|
|
730
766
|
}
|
|
731
767
|
}
|
|
732
768
|
this.agent.state.tools = tools;
|
|
733
|
-
|
|
734
|
-
this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames);
|
|
735
|
-
this.agent.state.systemPrompt = this._systemPromptOverride ?? this._baseSystemPrompt;
|
|
769
|
+
this._rebuildSystemPrompt(validToolNames);
|
|
736
770
|
}
|
|
737
771
|
/** Whether compaction or branch summarization is currently running */
|
|
738
772
|
get isCompacting() {
|
|
@@ -801,23 +835,17 @@ export class AgentSession {
|
|
|
801
835
|
_rebuildSystemPrompt(toolNames) {
|
|
802
836
|
const validToolNames = toolNames.filter((name) => this._toolRegistry.has(name));
|
|
803
837
|
const toolSnippets = {};
|
|
804
|
-
const
|
|
805
|
-
for (const name of validToolNames) {
|
|
838
|
+
for (const name of this._toolRegistry.keys()) {
|
|
806
839
|
const snippet = this._toolPromptSnippets.get(name);
|
|
807
|
-
if (snippet)
|
|
840
|
+
if (snippet)
|
|
808
841
|
toolSnippets[name] = snippet;
|
|
809
|
-
}
|
|
810
|
-
const toolGuidelines = this._toolPromptGuidelines.get(name);
|
|
811
|
-
if (toolGuidelines) {
|
|
812
|
-
promptGuidelines.push(...toolGuidelines);
|
|
813
|
-
}
|
|
814
842
|
}
|
|
815
843
|
const loaderSystemPrompt = this._resourceLoader.getSystemPrompt();
|
|
816
844
|
const loaderAppendSystemPrompt = this._resourceLoader.getAppendSystemPrompt();
|
|
817
|
-
const appendSystemPrompt = loaderAppendSystemPrompt.length > 0 ? loaderAppendSystemPrompt.join("\n\n") :
|
|
845
|
+
const appendSystemPrompt = loaderAppendSystemPrompt.length > 0 ? loaderAppendSystemPrompt.join("\n\n") : "";
|
|
818
846
|
const loadedSkills = this._resourceLoader.getSkills().skills;
|
|
819
847
|
const loadedContextFiles = this._resourceLoader.getAgentsFiles().agentsFiles;
|
|
820
|
-
this._baseSystemPromptOptions = {
|
|
848
|
+
this._baseSystemPromptOptions = normalizeBuildSystemPromptOptions({
|
|
821
849
|
cwd: this._cwd,
|
|
822
850
|
skills: loadedSkills,
|
|
823
851
|
contextFiles: loadedContextFiles,
|
|
@@ -825,23 +853,87 @@ export class AgentSession {
|
|
|
825
853
|
appendSystemPrompt,
|
|
826
854
|
selectedTools: validToolNames,
|
|
827
855
|
toolSnippets,
|
|
828
|
-
|
|
856
|
+
toolGuidelines: Object.fromEntries(this._toolPromptGuidelines),
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Apply a prompt and tool loadout for the next request. Sets the executable tools and
|
|
861
|
+
* returns a system message patching the prompt sections the model currently has (replayed
|
|
862
|
+
* from `messages`), or undefined when the prompt is unchanged. Tool changes are declared by
|
|
863
|
+
* the agent loop before the request.
|
|
864
|
+
*
|
|
865
|
+
* A forced prompt does not affect the transcript: the structured sections are still diffed
|
|
866
|
+
* and persisted, and the forced text is projected onto the request by
|
|
867
|
+
* {@link _installAgentForcedPromptProjection}.
|
|
868
|
+
*/
|
|
869
|
+
_preparePromptAndToolLoadout(options, messages = this.agent.state.messages) {
|
|
870
|
+
options.selectedTools = [...new Set(options.selectedTools)].filter((name) => this._toolRegistry.has(name));
|
|
871
|
+
this.agent.state.tools = options.selectedTools.flatMap((name) => {
|
|
872
|
+
const tool = this._toolRegistry.get(name);
|
|
873
|
+
return tool ? [tool] : [];
|
|
874
|
+
});
|
|
875
|
+
const sections = diffSystemPromptSections(getCurrentSystemMessage(messages)?.sections ?? {}, buildSystemPromptSections(options));
|
|
876
|
+
return sections ? { role: "system", content: "", sections, timestamp: Date.now() } : undefined;
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Send a forced prompt as the provider's leading system prompt without recording it.
|
|
880
|
+
*
|
|
881
|
+
* A `before_agent_start` handler that returns `systemPrompt` needs that exact text at the
|
|
882
|
+
* head of the request; a mid-conversation system message would leave the original prompt
|
|
883
|
+
* in place. The forced text is a rendering of the current prompt, so the transcript keeps
|
|
884
|
+
* its structured sections and the request is projected instead: the system messages
|
|
885
|
+
* collapse into one head holding the forced text and the current tools. Runs after the
|
|
886
|
+
* `context` extension handlers.
|
|
887
|
+
*/
|
|
888
|
+
_installAgentForcedPromptProjection() {
|
|
889
|
+
const previousTransformContext = this.agent.transformContext;
|
|
890
|
+
this.agent.transformContext = async (messages, signal) => {
|
|
891
|
+
const transformed = previousTransformContext ? await previousTransformContext(messages, signal) : messages;
|
|
892
|
+
const forced = this._runSystemPromptOptions?.forceSystemPrompt;
|
|
893
|
+
if (forced === undefined)
|
|
894
|
+
return transformed;
|
|
895
|
+
const current = getCurrentSystemMessage(transformed);
|
|
896
|
+
const head = {
|
|
897
|
+
role: "system",
|
|
898
|
+
content: forced,
|
|
899
|
+
...(current?.toolsAdded ? { toolsAdded: current.toolsAdded } : {}),
|
|
900
|
+
timestamp: current?.timestamp ?? Date.now(),
|
|
901
|
+
};
|
|
902
|
+
return [head, ...transformed.filter((message) => message.role !== "system")];
|
|
829
903
|
};
|
|
830
|
-
|
|
904
|
+
}
|
|
905
|
+
/** Restore the active tool loadout declared by the session transcript, if it declares one. */
|
|
906
|
+
_restoreToolsFromTranscript() {
|
|
907
|
+
const current = getCurrentSystemMessage(this.sessionManager.buildSessionContext().messages);
|
|
908
|
+
if (!current)
|
|
909
|
+
return;
|
|
910
|
+
const toolNames = (current.toolsAdded ?? [])
|
|
911
|
+
.map((tool) => tool.name)
|
|
912
|
+
.filter((name) => this._toolRegistry.has(name));
|
|
913
|
+
this.agent.state.tools = toolNames.flatMap((name) => {
|
|
914
|
+
const registered = this._toolRegistry.get(name);
|
|
915
|
+
return registered ? [registered] : [];
|
|
916
|
+
});
|
|
917
|
+
this._rebuildSystemPrompt(toolNames);
|
|
831
918
|
}
|
|
832
919
|
// =========================================================================
|
|
833
920
|
// Prompting
|
|
834
921
|
// =========================================================================
|
|
835
922
|
async _runAgentPrompt(messages) {
|
|
923
|
+
this._agentRunAbortRequested = false;
|
|
836
924
|
this._isAgentRunActive = true;
|
|
837
925
|
try {
|
|
838
926
|
await this.agent.prompt(messages);
|
|
839
927
|
while (await this._handlePostAgentRun()) {
|
|
928
|
+
if (this._agentRunAbortRequested)
|
|
929
|
+
break;
|
|
840
930
|
await this.agent.continue();
|
|
841
931
|
}
|
|
842
932
|
}
|
|
843
933
|
finally {
|
|
844
|
-
this.
|
|
934
|
+
if (this._agentRunAbortRequested)
|
|
935
|
+
this._finishCancelledRetry();
|
|
936
|
+
this._runSystemPromptOptions = undefined;
|
|
845
937
|
this._flushPendingBashMessages();
|
|
846
938
|
this._flushPendingCustomMessages();
|
|
847
939
|
await this._emitAgentSettled();
|
|
@@ -850,11 +942,21 @@ export class AgentSession {
|
|
|
850
942
|
async _handlePostAgentRun() {
|
|
851
943
|
const msg = this._lastAssistantMessage;
|
|
852
944
|
this._lastAssistantMessage = undefined;
|
|
945
|
+
if (this._agentRunAbortRequested) {
|
|
946
|
+
this._finishCancelledRetry();
|
|
947
|
+
return false;
|
|
948
|
+
}
|
|
853
949
|
if (!msg) {
|
|
854
950
|
return false;
|
|
855
951
|
}
|
|
856
952
|
if (this._isRetryableError(msg) && (await this._prepareRetry(msg))) {
|
|
857
|
-
|
|
953
|
+
if (this._agentRunAbortRequested)
|
|
954
|
+
this._finishCancelledRetry();
|
|
955
|
+
return !this._agentRunAbortRequested;
|
|
956
|
+
}
|
|
957
|
+
if (this._agentRunAbortRequested) {
|
|
958
|
+
this._finishCancelledRetry();
|
|
959
|
+
return false;
|
|
858
960
|
}
|
|
859
961
|
if (msg.stopReason === "error" && this._retryAttempt > 0) {
|
|
860
962
|
this._emit({
|
|
@@ -866,11 +968,24 @@ export class AgentSession {
|
|
|
866
968
|
this._retryAttempt = 0;
|
|
867
969
|
}
|
|
868
970
|
if (await this._checkCompaction(msg)) {
|
|
869
|
-
return
|
|
971
|
+
return !this._agentRunAbortRequested;
|
|
870
972
|
}
|
|
871
973
|
// The agent loop drains both queues before emitting agent_end. Any messages
|
|
872
974
|
// here were queued by agent_end extension handlers and need a continuation.
|
|
873
|
-
return this.agent.hasQueuedMessages();
|
|
975
|
+
return !this._agentRunAbortRequested && this.agent.hasQueuedMessages();
|
|
976
|
+
}
|
|
977
|
+
async _runInputHandlers(text, images, source, streamingBehavior) {
|
|
978
|
+
if (!this._extensionRunner.hasHandlers("input")) {
|
|
979
|
+
return { text, images };
|
|
980
|
+
}
|
|
981
|
+
const inputResult = await this._extensionRunner.emitInput(text, images, source, streamingBehavior);
|
|
982
|
+
if (inputResult.action === "handled") {
|
|
983
|
+
return undefined;
|
|
984
|
+
}
|
|
985
|
+
if (inputResult.action === "transform") {
|
|
986
|
+
return { text: inputResult.text, images: inputResult.images ?? images };
|
|
987
|
+
}
|
|
988
|
+
return { text, images };
|
|
874
989
|
}
|
|
875
990
|
/**
|
|
876
991
|
* Send a prompt to the agent.
|
|
@@ -908,19 +1023,12 @@ export class AgentSession {
|
|
|
908
1023
|
throw new Error("Cannot submit a prompt while compaction is in progress. Wait for compaction to finish and retry.");
|
|
909
1024
|
}
|
|
910
1025
|
// Emit input event for extension interception (before skill/template expansion)
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
if (inputResult.action === "handled") {
|
|
916
|
-
preflightResult?.(true);
|
|
917
|
-
return;
|
|
918
|
-
}
|
|
919
|
-
if (inputResult.action === "transform") {
|
|
920
|
-
currentText = inputResult.text;
|
|
921
|
-
currentImages = inputResult.images ?? currentImages;
|
|
922
|
-
}
|
|
1026
|
+
const processedInput = await this._runInputHandlers(text, options?.images, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
|
|
1027
|
+
if (!processedInput) {
|
|
1028
|
+
preflightResult?.(true);
|
|
1029
|
+
return;
|
|
923
1030
|
}
|
|
1031
|
+
const { text: currentText, images: currentImages } = processedInput;
|
|
924
1032
|
// Expand skill commands (/skill:name args) and prompt templates (/template args)
|
|
925
1033
|
let expandedText = currentText;
|
|
926
1034
|
if (expandPromptTemplates) {
|
|
@@ -982,31 +1090,30 @@ export class AgentSession {
|
|
|
982
1090
|
messages.push(msg);
|
|
983
1091
|
}
|
|
984
1092
|
// Emit before_agent_start extension event
|
|
985
|
-
const
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
}
|
|
1005
|
-
else {
|
|
1006
|
-
// Ensure we're using the base prompt (in case previous turn had modifications)
|
|
1007
|
-
this._systemPromptOverride = undefined;
|
|
1008
|
-
this.agent.state.systemPrompt = this._baseSystemPrompt;
|
|
1093
|
+
const selectedToolsBefore = this._baseSystemPromptOptions.selectedTools;
|
|
1094
|
+
const result = await this._extensionRunner.emitBeforeAgentStart(expandedText, currentImages, this._baseSystemPromptOptions);
|
|
1095
|
+
// Handlers may edit event.systemPromptOptions.selectedTools or call setActiveTools(),
|
|
1096
|
+
// which updates the live loadout instead. An explicit edit wins; otherwise the live
|
|
1097
|
+
// loadout is authoritative, so a setActiveTools() call is not undone here.
|
|
1098
|
+
const handlerEditedTools = result.systemPromptOptions.selectedTools.length !== selectedToolsBefore.length ||
|
|
1099
|
+
result.systemPromptOptions.selectedTools.some((name, index) => name !== selectedToolsBefore[index]);
|
|
1100
|
+
if (!handlerEditedTools)
|
|
1101
|
+
result.systemPromptOptions.selectedTools = this.getActiveToolNames();
|
|
1102
|
+
for (const msg of result.messages) {
|
|
1103
|
+
messages.push({
|
|
1104
|
+
role: "custom",
|
|
1105
|
+
customType: msg.customType,
|
|
1106
|
+
// Untyped extensions can pass null/missing content; normalize at ingestion.
|
|
1107
|
+
content: msg.content ?? [],
|
|
1108
|
+
display: msg.display,
|
|
1109
|
+
details: msg.details,
|
|
1110
|
+
timestamp: Date.now(),
|
|
1111
|
+
});
|
|
1009
1112
|
}
|
|
1113
|
+
const updateMessage = this._preparePromptAndToolLoadout(result.systemPromptOptions);
|
|
1114
|
+
this._runSystemPromptOptions = result.systemPromptOptions;
|
|
1115
|
+
if (updateMessage)
|
|
1116
|
+
messages.unshift(updateMessage);
|
|
1010
1117
|
}
|
|
1011
1118
|
catch (error) {
|
|
1012
1119
|
preflightResult?.(false);
|
|
@@ -1079,40 +1186,44 @@ export class AgentSession {
|
|
|
1079
1186
|
return text; // Return original on error
|
|
1080
1187
|
}
|
|
1081
1188
|
}
|
|
1189
|
+
async _queueUserInput(text, images, behavior, source) {
|
|
1190
|
+
if (text.startsWith("/")) {
|
|
1191
|
+
this._throwIfExtensionCommand(text);
|
|
1192
|
+
}
|
|
1193
|
+
const processedInput = await this._runInputHandlers(text, images, source, this.isStreaming ? behavior : undefined);
|
|
1194
|
+
if (!processedInput)
|
|
1195
|
+
return;
|
|
1196
|
+
let expandedText = this._expandSkillCommand(processedInput.text);
|
|
1197
|
+
expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
|
|
1198
|
+
if (behavior === "steer") {
|
|
1199
|
+
await this._queueSteer(expandedText, processedInput.images);
|
|
1200
|
+
}
|
|
1201
|
+
else {
|
|
1202
|
+
await this._queueFollowUp(expandedText, processedInput.images);
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1082
1205
|
/**
|
|
1083
1206
|
* Queue a steering message while the agent is running.
|
|
1084
1207
|
* Delivered after the current assistant turn finishes executing its tool calls,
|
|
1085
1208
|
* before the next LLM call.
|
|
1086
1209
|
* Expands skill commands and prompt templates. Errors on extension commands.
|
|
1087
1210
|
* @param images Optional image attachments to include with the message
|
|
1211
|
+
* @param options Input source; defaults to interactive
|
|
1088
1212
|
* @throws Error if text is an extension command
|
|
1089
1213
|
*/
|
|
1090
|
-
async steer(text, images) {
|
|
1091
|
-
|
|
1092
|
-
if (text.startsWith("/")) {
|
|
1093
|
-
this._throwIfExtensionCommand(text);
|
|
1094
|
-
}
|
|
1095
|
-
// Expand skill commands and prompt templates
|
|
1096
|
-
let expandedText = this._expandSkillCommand(text);
|
|
1097
|
-
expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
|
|
1098
|
-
await this._queueSteer(expandedText, images);
|
|
1214
|
+
async steer(text, images, options) {
|
|
1215
|
+
await this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
|
|
1099
1216
|
}
|
|
1100
1217
|
/**
|
|
1101
1218
|
* Queue a follow-up message to be processed after the agent finishes.
|
|
1102
1219
|
* Delivered only when agent has no more tool calls or steering messages.
|
|
1103
1220
|
* Expands skill commands and prompt templates. Errors on extension commands.
|
|
1104
1221
|
* @param images Optional image attachments to include with the message
|
|
1222
|
+
* @param options Input source; defaults to interactive
|
|
1105
1223
|
* @throws Error if text is an extension command
|
|
1106
1224
|
*/
|
|
1107
|
-
async followUp(text, images) {
|
|
1108
|
-
|
|
1109
|
-
if (text.startsWith("/")) {
|
|
1110
|
-
this._throwIfExtensionCommand(text);
|
|
1111
|
-
}
|
|
1112
|
-
// Expand skill commands and prompt templates
|
|
1113
|
-
let expandedText = this._expandSkillCommand(text);
|
|
1114
|
-
expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
|
|
1115
|
-
await this._queueFollowUp(expandedText, images);
|
|
1225
|
+
async followUp(text, images, options) {
|
|
1226
|
+
await this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
|
|
1116
1227
|
}
|
|
1117
1228
|
/**
|
|
1118
1229
|
* Internal: Queue a steering message (already expanded, no extension command check).
|
|
@@ -1295,6 +1406,9 @@ export class AgentSession {
|
|
|
1295
1406
|
* Abort current operation and wait for agent to become idle.
|
|
1296
1407
|
*/
|
|
1297
1408
|
async abort() {
|
|
1409
|
+
if (this._isAgentRunActive) {
|
|
1410
|
+
this._agentRunAbortRequested = true;
|
|
1411
|
+
}
|
|
1298
1412
|
this.abortRetry();
|
|
1299
1413
|
this.abortCompaction();
|
|
1300
1414
|
this.abortBranchSummary();
|
|
@@ -1524,8 +1638,8 @@ export class AgentSession {
|
|
|
1524
1638
|
// Compaction
|
|
1525
1639
|
// =========================================================================
|
|
1526
1640
|
/** Generate Pi's built-in compaction summary for manual and automatic compaction. */
|
|
1527
|
-
async _runDefaultCompaction(preparation, requestModel, apiKey, headers, customInstructions, signal, env, reason
|
|
1528
|
-
return compact(preparation, requestModel, apiKey, headers, customInstructions, signal, this.thinkingLevel, streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }), undefined);
|
|
1641
|
+
async _runDefaultCompaction(preparation, requestModel, apiKey, headers, customInstructions, signal, env, reason) {
|
|
1642
|
+
return compact(preparation, requestModel, apiKey, headers, customInstructions, signal, this.thinkingLevel, this.agent.streamFunction, env, this.settingsManager.getRetrySettings(), this._summarizationRetryCallbacks({ source: "compaction", reason }), undefined);
|
|
1529
1643
|
}
|
|
1530
1644
|
_clearManualCompactionState() {
|
|
1531
1645
|
this._compactionAbortController = undefined;
|
|
@@ -1553,15 +1667,16 @@ export class AgentSession {
|
|
|
1553
1667
|
this._compactionAbortController = new AbortController();
|
|
1554
1668
|
this._emit({ type: "compaction_start", reason: "manual" });
|
|
1555
1669
|
let fromExtension = false;
|
|
1670
|
+
let cancelledByExtension = false;
|
|
1556
1671
|
try {
|
|
1557
|
-
|
|
1672
|
+
const model = this.model;
|
|
1673
|
+
if (!model) {
|
|
1558
1674
|
throw new Error(formatNoModelSelectedMessage());
|
|
1559
1675
|
}
|
|
1560
|
-
const
|
|
1561
|
-
const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(
|
|
1676
|
+
const settings = this.settingsManager.getCompactionSettings(model);
|
|
1677
|
+
const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
|
|
1562
1678
|
const pathEntries = this.sessionManager.getBranch();
|
|
1563
|
-
const
|
|
1564
|
-
const preparation = prepareCompaction(pathEntries, settings, requestModel.contextWindow);
|
|
1679
|
+
const preparation = prepareCompaction(pathEntries, settings);
|
|
1565
1680
|
if (!preparation) {
|
|
1566
1681
|
// Check why we can't compact
|
|
1567
1682
|
const lastEntry = pathEntries[pathEntries.length - 1];
|
|
@@ -1582,6 +1697,7 @@ export class AgentSession {
|
|
|
1582
1697
|
signal: this._compactionAbortController.signal,
|
|
1583
1698
|
}));
|
|
1584
1699
|
if (result?.cancel) {
|
|
1700
|
+
cancelledByExtension = true;
|
|
1585
1701
|
throw new Error("Compaction cancelled");
|
|
1586
1702
|
}
|
|
1587
1703
|
if (result?.compaction) {
|
|
@@ -1604,7 +1720,7 @@ export class AgentSession {
|
|
|
1604
1720
|
}
|
|
1605
1721
|
else {
|
|
1606
1722
|
// Shared default summary generator, also used by automatic compaction.
|
|
1607
|
-
const result = await this._runDefaultCompaction(preparation, requestModel, apiKey, headers, customInstructions, this._compactionAbortController.signal, env, "manual"
|
|
1723
|
+
const result = await this._runDefaultCompaction(preparation, requestModel, apiKey, headers, customInstructions, this._compactionAbortController.signal, env, "manual");
|
|
1608
1724
|
summary = result.summary;
|
|
1609
1725
|
firstKeptEntryId = result.firstKeptEntryId;
|
|
1610
1726
|
tokensBefore = result.tokensBefore;
|
|
@@ -1651,7 +1767,7 @@ export class AgentSession {
|
|
|
1651
1767
|
}
|
|
1652
1768
|
catch (error) {
|
|
1653
1769
|
const message = error instanceof Error ? error.message : String(error);
|
|
1654
|
-
const aborted =
|
|
1770
|
+
const aborted = this._compactionAbortController?.signal.aborted === true || cancelledByExtension;
|
|
1655
1771
|
const errorMessage = aborted ? undefined : `Compaction failed: ${message}`;
|
|
1656
1772
|
this._clearManualCompactionState();
|
|
1657
1773
|
this._emit({
|
|
@@ -1714,7 +1830,7 @@ export class AgentSession {
|
|
|
1714
1830
|
* @returns Whether the post-run loop should call `agent.continue()` for overflow recovery or queued messages
|
|
1715
1831
|
*/
|
|
1716
1832
|
async _checkCompaction(assistantMessage, skipAbortedCheck = true) {
|
|
1717
|
-
const settings = this.settingsManager.getCompactionSettings();
|
|
1833
|
+
const settings = this.settingsManager.getCompactionSettings(this.model);
|
|
1718
1834
|
if (!settings.enabled)
|
|
1719
1835
|
return false;
|
|
1720
1836
|
// Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
|
|
@@ -1821,25 +1937,28 @@ export class AgentSession {
|
|
|
1821
1937
|
async _runAutoCompaction(reason, willRetry) {
|
|
1822
1938
|
const resumeBackground = this.pauseBackgroundNotifications();
|
|
1823
1939
|
try {
|
|
1824
|
-
const
|
|
1940
|
+
const model = this.model;
|
|
1941
|
+
const settings = this.settingsManager.getCompactionSettings(model);
|
|
1942
|
+
let abortController;
|
|
1825
1943
|
let started = false;
|
|
1826
1944
|
let fromExtension = false;
|
|
1945
|
+
let cancelledByExtension = false;
|
|
1827
1946
|
try {
|
|
1828
|
-
if (!
|
|
1947
|
+
if (!model) {
|
|
1829
1948
|
return false;
|
|
1830
1949
|
}
|
|
1831
|
-
// Capture before awaiting auth: a model switch during the await would leave the
|
|
1832
|
-
// resolved auth and the summary generator disagreeing about the stream function.
|
|
1833
|
-
const streamFunction = this.agent.streamFunction;
|
|
1834
|
-
const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(this.model, streamFunction);
|
|
1835
1950
|
const pathEntries = this.sessionManager.getBranch();
|
|
1836
|
-
const preparation = prepareCompaction(pathEntries, settings
|
|
1951
|
+
const preparation = prepareCompaction(pathEntries, settings);
|
|
1837
1952
|
if (!preparation) {
|
|
1838
1953
|
return false;
|
|
1839
1954
|
}
|
|
1840
|
-
|
|
1841
|
-
this._autoCompactionAbortController =
|
|
1955
|
+
abortController = new AbortController();
|
|
1956
|
+
this._autoCompactionAbortController = abortController;
|
|
1842
1957
|
started = true;
|
|
1958
|
+
this._emit({ type: "compaction_start", reason });
|
|
1959
|
+
abortController.signal.throwIfAborted();
|
|
1960
|
+
const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, abortController.signal);
|
|
1961
|
+
abortController.signal.throwIfAborted();
|
|
1843
1962
|
let extensionCompaction;
|
|
1844
1963
|
if (this._extensionRunner.hasHandlers("session_before_compact")) {
|
|
1845
1964
|
const extensionResult = (await this._extensionRunner.emit({
|
|
@@ -1849,29 +1968,18 @@ export class AgentSession {
|
|
|
1849
1968
|
customInstructions: undefined,
|
|
1850
1969
|
reason,
|
|
1851
1970
|
willRetry,
|
|
1852
|
-
signal:
|
|
1971
|
+
signal: abortController.signal,
|
|
1853
1972
|
}));
|
|
1854
1973
|
if (extensionResult?.cancel) {
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
reason,
|
|
1858
|
-
result: undefined,
|
|
1859
|
-
aborted: true,
|
|
1860
|
-
willRetry: false,
|
|
1861
|
-
});
|
|
1862
|
-
await this._emitSessionCompactFailed({
|
|
1863
|
-
reason,
|
|
1864
|
-
aborted: true,
|
|
1865
|
-
willRetry: false,
|
|
1866
|
-
fromExtension: false,
|
|
1867
|
-
});
|
|
1868
|
-
return false;
|
|
1974
|
+
cancelledByExtension = true;
|
|
1975
|
+
throw new Error("Compaction cancelled");
|
|
1869
1976
|
}
|
|
1870
1977
|
if (extensionResult?.compaction) {
|
|
1871
1978
|
extensionCompaction = extensionResult.compaction;
|
|
1872
1979
|
fromExtension = true;
|
|
1873
1980
|
}
|
|
1874
1981
|
}
|
|
1982
|
+
abortController.signal.throwIfAborted();
|
|
1875
1983
|
let summary;
|
|
1876
1984
|
let firstKeptEntryId;
|
|
1877
1985
|
let tokensBefore;
|
|
@@ -1887,29 +1995,14 @@ export class AgentSession {
|
|
|
1887
1995
|
}
|
|
1888
1996
|
else {
|
|
1889
1997
|
// Shared default summary generator, also used by manual compaction.
|
|
1890
|
-
const compactResult = await this._runDefaultCompaction(preparation, requestModel, apiKey, headers, undefined,
|
|
1998
|
+
const compactResult = await this._runDefaultCompaction(preparation, requestModel, apiKey, headers, undefined, abortController.signal, env, reason);
|
|
1891
1999
|
summary = compactResult.summary;
|
|
1892
2000
|
firstKeptEntryId = compactResult.firstKeptEntryId;
|
|
1893
2001
|
tokensBefore = compactResult.tokensBefore;
|
|
1894
2002
|
usage = compactResult.usage;
|
|
1895
2003
|
details = compactResult.details;
|
|
1896
2004
|
}
|
|
1897
|
-
|
|
1898
|
-
this._emit({
|
|
1899
|
-
type: "compaction_end",
|
|
1900
|
-
reason,
|
|
1901
|
-
result: undefined,
|
|
1902
|
-
aborted: true,
|
|
1903
|
-
willRetry: false,
|
|
1904
|
-
});
|
|
1905
|
-
await this._emitSessionCompactFailed({
|
|
1906
|
-
reason,
|
|
1907
|
-
aborted: true,
|
|
1908
|
-
willRetry: false,
|
|
1909
|
-
fromExtension,
|
|
1910
|
-
});
|
|
1911
|
-
return false;
|
|
1912
|
-
}
|
|
2005
|
+
abortController.signal.throwIfAborted();
|
|
1913
2006
|
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension, usage);
|
|
1914
2007
|
const newEntries = this.sessionManager.getEntries();
|
|
1915
2008
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
@@ -1953,23 +2046,26 @@ export class AgentSession {
|
|
|
1953
2046
|
return this.agent.hasQueuedMessages();
|
|
1954
2047
|
}
|
|
1955
2048
|
catch (error) {
|
|
1956
|
-
const
|
|
2049
|
+
const message = error instanceof Error ? error.message : "compaction failed";
|
|
2050
|
+
const aborted = abortController?.signal.aborted === true || cancelledByExtension;
|
|
1957
2051
|
if (started) {
|
|
1958
|
-
const
|
|
1959
|
-
?
|
|
1960
|
-
:
|
|
2052
|
+
const errorMessage = aborted
|
|
2053
|
+
? undefined
|
|
2054
|
+
: reason === "overflow"
|
|
2055
|
+
? `Context overflow recovery failed: ${message}`
|
|
2056
|
+
: `Auto-compaction failed: ${message}`;
|
|
1961
2057
|
this._emit({
|
|
1962
2058
|
type: "compaction_end",
|
|
1963
2059
|
reason,
|
|
1964
2060
|
result: undefined,
|
|
1965
|
-
aborted
|
|
2061
|
+
aborted,
|
|
1966
2062
|
willRetry: false,
|
|
1967
|
-
errorMessage
|
|
2063
|
+
errorMessage,
|
|
1968
2064
|
});
|
|
1969
2065
|
await this._emitSessionCompactFailed({
|
|
1970
2066
|
reason,
|
|
1971
|
-
errorMessage
|
|
1972
|
-
aborted
|
|
2067
|
+
errorMessage,
|
|
2068
|
+
aborted,
|
|
1973
2069
|
willRetry: false,
|
|
1974
2070
|
fromExtension,
|
|
1975
2071
|
});
|
|
@@ -1977,7 +2073,9 @@ export class AgentSession {
|
|
|
1977
2073
|
return false;
|
|
1978
2074
|
}
|
|
1979
2075
|
finally {
|
|
1980
|
-
this._autoCompactionAbortController
|
|
2076
|
+
if (this._autoCompactionAbortController === abortController) {
|
|
2077
|
+
this._autoCompactionAbortController = undefined;
|
|
2078
|
+
}
|
|
1981
2079
|
this._resolveIdleWaitIfIdle();
|
|
1982
2080
|
}
|
|
1983
2081
|
}
|
|
@@ -2041,8 +2139,7 @@ export class AgentSession {
|
|
|
2041
2139
|
themePaths: this.buildExtensionResourcePaths(themePaths),
|
|
2042
2140
|
};
|
|
2043
2141
|
this._resourceLoader.extendResources(extensionPaths);
|
|
2044
|
-
this.
|
|
2045
|
-
this.agent.state.systemPrompt = this._baseSystemPrompt;
|
|
2142
|
+
this._rebuildSystemPrompt(this.getActiveToolNames());
|
|
2046
2143
|
}
|
|
2047
2144
|
buildExtensionResourcePaths(entries) {
|
|
2048
2145
|
return entries.map((entry) => {
|
|
@@ -2392,6 +2489,18 @@ export class AgentSession {
|
|
|
2392
2489
|
},
|
|
2393
2490
|
};
|
|
2394
2491
|
}
|
|
2492
|
+
_finishCancelledRetry() {
|
|
2493
|
+
if (this._retryAttempt === 0)
|
|
2494
|
+
return;
|
|
2495
|
+
const attempt = this._retryAttempt;
|
|
2496
|
+
this._retryAttempt = 0;
|
|
2497
|
+
this._emit({
|
|
2498
|
+
type: "auto_retry_end",
|
|
2499
|
+
success: false,
|
|
2500
|
+
attempt,
|
|
2501
|
+
finalError: "Retry cancelled",
|
|
2502
|
+
});
|
|
2503
|
+
}
|
|
2395
2504
|
/**
|
|
2396
2505
|
* Prepare a retryable error for continuation with exponential backoff.
|
|
2397
2506
|
* @returns true if the caller should continue the agent, false otherwise
|
|
@@ -2407,7 +2516,7 @@ export class AgentSession {
|
|
|
2407
2516
|
this._retryAttempt--;
|
|
2408
2517
|
return false;
|
|
2409
2518
|
}
|
|
2410
|
-
const delayMs = settings
|
|
2519
|
+
const delayMs = retryDelayMs(settings, this._retryAttempt);
|
|
2411
2520
|
this._emit({
|
|
2412
2521
|
type: "auto_retry_start",
|
|
2413
2522
|
attempt: this._retryAttempt,
|
|
@@ -2427,14 +2536,7 @@ export class AgentSession {
|
|
|
2427
2536
|
}
|
|
2428
2537
|
catch {
|
|
2429
2538
|
// Aborted during sleep - emit end event so UI can clean up
|
|
2430
|
-
|
|
2431
|
-
this._retryAttempt = 0;
|
|
2432
|
-
this._emit({
|
|
2433
|
-
type: "auto_retry_end",
|
|
2434
|
-
success: false,
|
|
2435
|
-
attempt,
|
|
2436
|
-
finalError: "Retry cancelled",
|
|
2437
|
-
});
|
|
2539
|
+
this._finishCancelledRetry();
|
|
2438
2540
|
return false;
|
|
2439
2541
|
}
|
|
2440
2542
|
finally {
|
|
@@ -2585,6 +2687,9 @@ export class AgentSession {
|
|
|
2585
2687
|
if (this.isStreaming) {
|
|
2586
2688
|
throw new Error("Wait for the current response to finish before navigating the session tree.");
|
|
2587
2689
|
}
|
|
2690
|
+
if (this.isCompacting) {
|
|
2691
|
+
throw new Error("Wait for the current compaction or tree navigation to finish before navigating the session tree.");
|
|
2692
|
+
}
|
|
2588
2693
|
const oldLeafId = this.sessionManager.getLeafId();
|
|
2589
2694
|
// No-op if already at target
|
|
2590
2695
|
if (targetId === oldLeafId) {
|
|
@@ -2651,8 +2756,7 @@ export class AgentSession {
|
|
|
2651
2756
|
let summaryUsage;
|
|
2652
2757
|
if (options.summarize && entriesToSummarize.length > 0 && !extensionSummary) {
|
|
2653
2758
|
const model = this.model;
|
|
2654
|
-
const
|
|
2655
|
-
const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, streamFunction);
|
|
2759
|
+
const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
|
|
2656
2760
|
const branchSummarySettings = this.settingsManager.getBranchSummarySettings();
|
|
2657
2761
|
const result = await generateBranchSummary(entriesToSummarize, {
|
|
2658
2762
|
model: requestModel,
|
|
@@ -2663,7 +2767,7 @@ export class AgentSession {
|
|
|
2663
2767
|
customInstructions,
|
|
2664
2768
|
replaceInstructions,
|
|
2665
2769
|
reserveTokens: branchSummarySettings.reserveTokens,
|
|
2666
|
-
streamFn: streamFunction,
|
|
2770
|
+
streamFn: this.agent.streamFunction,
|
|
2667
2771
|
retry: this.settingsManager.getRetrySettings(),
|
|
2668
2772
|
callbacks: this._summarizationRetryCallbacks({ source: "branchSummary" }),
|
|
2669
2773
|
});
|
|
@@ -2731,6 +2835,7 @@ export class AgentSession {
|
|
|
2731
2835
|
// Update agent state
|
|
2732
2836
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
2733
2837
|
this.agent.state.messages = sessionContext.messages;
|
|
2838
|
+
this._restoreToolsFromTranscript();
|
|
2734
2839
|
// Emit session_tree event
|
|
2735
2840
|
await this._extensionRunner.emit({
|
|
2736
2841
|
type: "session_tree",
|
|
@@ -2889,6 +2994,30 @@ export class AgentSession {
|
|
|
2889
2994
|
exportToJsonl(outputPath) {
|
|
2890
2995
|
return exportSessionToJsonl(this.sessionManager, outputPath);
|
|
2891
2996
|
}
|
|
2997
|
+
/**
|
|
2998
|
+
* Ask the current model to describe what went wrong in this session for a bug report.
|
|
2999
|
+
* Used when the user declines to share the transcript itself.
|
|
3000
|
+
*/
|
|
3001
|
+
async summarizeForBugReport(options) {
|
|
3002
|
+
const model = this.model;
|
|
3003
|
+
if (!model) {
|
|
3004
|
+
throw new Error("No model selected");
|
|
3005
|
+
}
|
|
3006
|
+
const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, options.signal);
|
|
3007
|
+
return generateBugReportSummary({
|
|
3008
|
+
messages: this.messages,
|
|
3009
|
+
hint: options.hint,
|
|
3010
|
+
model: requestModel,
|
|
3011
|
+
apiKey,
|
|
3012
|
+
headers,
|
|
3013
|
+
env,
|
|
3014
|
+
signal: options.signal,
|
|
3015
|
+
thinkingLevel: this.thinkingLevel,
|
|
3016
|
+
streamFn: this.agent.streamFunction,
|
|
3017
|
+
retry: this.settingsManager.getRetrySettings(),
|
|
3018
|
+
sessionId: this.sessionId,
|
|
3019
|
+
});
|
|
3020
|
+
}
|
|
2892
3021
|
// =========================================================================
|
|
2893
3022
|
// Utilities
|
|
2894
3023
|
// =========================================================================
|