pi-namespace-patch 0.85.1 → 0.86.1-namespace.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 +110 -0
- package/README.md +26 -705
- package/dist/bundle/chunks/anthropic-messages-MYU5ZMRF.js +6 -0
- package/dist/bundle/chunks/azure-openai-responses-HUSQ3GP2.js +2 -0
- package/dist/bundle/chunks/bedrock-converse-stream.js +47 -38
- package/dist/bundle/chunks/chunk-4YJERF5N.js +2 -0
- package/dist/bundle/chunks/chunk-A3JYRWB6.js +2 -0
- package/dist/bundle/chunks/chunk-CVPNLAPW.js +1562 -0
- package/dist/bundle/chunks/chunk-DTD7JQ7Y.js +42 -0
- package/dist/bundle/chunks/chunk-FUXEF6JQ.js +44 -0
- package/dist/bundle/chunks/{chunk-IDDQWTHI.js → chunk-RCZIEVGO.js} +10 -1
- package/dist/bundle/chunks/chunk-S7SZN6Z3.js +2 -0
- package/dist/bundle/chunks/chunk-WIUZI2CJ.js +11 -0
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/google-generative-ai-IMS5EK2Y.js +2 -0
- package/dist/bundle/chunks/google-vertex-O4YJEQUW.js +2 -0
- package/dist/bundle/chunks/jiti-loader-C3NU2SDH.js +21 -0
- package/dist/bundle/chunks/jiti-static-loader-E6ANQD5T.js +2 -0
- package/dist/bundle/chunks/meta.js +2 -0
- package/dist/bundle/chunks/mistral-conversations-NOSQHBEY.js +5 -0
- package/dist/bundle/chunks/{node-KG362ECQ.js → node-O3RIBJRH.js} +1 -1
- package/dist/bundle/chunks/openai-codex-responses-QDSOTBBO.js +10 -0
- package/dist/bundle/chunks/openai-completions-CYGM3XXP.js +7 -0
- package/dist/bundle/chunks/openai-responses-HWEUZ6WZ.js +2 -0
- package/dist/bundle/chunks/{pi-messages-PML4SPVJ.js → pi-messages-GFKBWJHZ.js} +1 -1
- package/dist/bundle/chunks/virtual-modules-R7YYFUSE.js +2 -0
- package/dist/bundle/cli-runtime.js +3 -0
- package/dist/bundle/cli.js +4 -2
- 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.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +56 -6
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +294 -157
- 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 +342 -0
- package/dist/core/cache-warmer.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- 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 +2 -2
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +11 -12
- package/dist/core/compaction/compaction.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 +38 -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.d.ts.map +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 +60 -38
- 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 +20 -4
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +43 -7
- 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 +10 -4
- 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/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js +9 -1
- package/dist/core/tools/renderers/bash.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 +5 -1
- package/dist/core/usage-totals.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/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.d.ts.map +1 -1
- package/dist/modes/interactive/chat-viewport.js +1 -1
- package/dist/modes/interactive/chat-viewport.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/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 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +4 -0
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +4 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +5 -5
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +74 -48
- 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-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +18 -9
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +2 -0
- 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 +227 -84
- 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.d.ts.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.d.ts.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/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +11 -4
- package/dist/utils/version-check.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 +39 -13
- package/docs/custom-provider.md +22 -13
- package/docs/development.md +4 -4
- package/docs/docs.json +4 -0
- package/docs/environment-variables.md +1 -0
- package/docs/extensions.md +57 -43
- package/docs/json.md +4 -4
- package/docs/models.md +33 -2
- package/docs/providers.md +10 -2
- package/docs/sdk.md +4 -2
- package/docs/security.md +1 -1
- package/docs/session-format.md +82 -40
- package/docs/sessions.md +27 -0
- package/docs/settings.md +60 -1
- package/docs/termux.md +0 -1
- package/docs/tui.md +2 -2
- 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-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -2
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/prompt-customizer.ts +19 -67
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +435 -762
- package/package.json +17 -23
- package/dist/bundle/chunks/anthropic-messages-VWZZOSJQ.js +0 -6
- package/dist/bundle/chunks/azure-openai-responses-BJLAM6CD.js +0 -2
- package/dist/bundle/chunks/chunk-AXIIZGTV.js +0 -2
- package/dist/bundle/chunks/chunk-CLNPYIDP.js +0 -42
- package/dist/bundle/chunks/chunk-GMWCTUPB.js +0 -2
- package/dist/bundle/chunks/chunk-JJ2YFCJF.js +0 -1547
- package/dist/bundle/chunks/chunk-OUXLLA64.js +0 -11
- package/dist/bundle/chunks/chunk-U6ZMQKGD.js +0 -50
- package/dist/bundle/chunks/chunk-UAQELI3K.js +0 -2
- package/dist/bundle/chunks/google-generative-ai-Q2K7FBDI.js +0 -2
- package/dist/bundle/chunks/google-vertex-7UJBF4S7.js +0 -2
- package/dist/bundle/chunks/mistral-conversations-4M6BZBX6.js +0 -5
- package/dist/bundle/chunks/openai-codex-responses-R6VYZTVY.js +0 -10
- package/dist/bundle/chunks/openai-completions-EKZT2IH2.js +0 -7
- package/dist/bundle/chunks/openai-responses-TFDINO6W.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, 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";
|
|
@@ -22,6 +22,7 @@ import { sleep } from "../utils/sleep.js";
|
|
|
22
22
|
import { normalizeToolResultImages } from "../utils/tool-result-images.js";
|
|
23
23
|
import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
|
|
24
24
|
import { executeBashWithOperations } from "./bash-executor.js";
|
|
25
|
+
import { generateBugReportSummary } from "./bug-report.js";
|
|
25
26
|
import { calculateContextTokens, collectEntriesForBranchSummary, compact, estimateContextTokens, estimateTokens, generateBranchSummary, prepareCompaction, shouldCompact, } from "./compaction/index.js";
|
|
26
27
|
import { DEFAULT_THINKING_LEVEL, THINKING_LEVEL_OPTIONS } from "./defaults.js";
|
|
27
28
|
import { exportSessionToHtml } from "./export-html/index.js";
|
|
@@ -34,7 +35,7 @@ import { exportSessionToJsonl } from "./session-export.js";
|
|
|
34
35
|
import { getLatestCompactionEntry } from "./session-manager.js";
|
|
35
36
|
import { findSkillByInvocationName, resolveBareNamespaceSkill } from "./skills.js";
|
|
36
37
|
import { createSyntheticSourceInfo } from "./source-info.js";
|
|
37
|
-
import { buildSystemPrompt } from "./system-prompt.js";
|
|
38
|
+
import { buildSystemPrompt, buildSystemPromptSections, diffSystemPromptSections, normalizeBuildSystemPromptOptions, } from "./system-prompt.js";
|
|
38
39
|
import { createLocalBashOperations } from "./tools/bash.js";
|
|
39
40
|
import { createAllToolDefinitions } from "./tools/index.js";
|
|
40
41
|
import { createToolDefinitionFromAgentTool } from "./tools/tool-definition-wrapper.js";
|
|
@@ -70,9 +71,6 @@ function estimateMessagesTokens(messages) {
|
|
|
70
71
|
return tokens;
|
|
71
72
|
}
|
|
72
73
|
// ============================================================================
|
|
73
|
-
// Constants
|
|
74
|
-
// ============================================================================
|
|
75
|
-
// ============================================================================
|
|
76
74
|
// AgentSession Class
|
|
77
75
|
// ============================================================================
|
|
78
76
|
export class AgentSession {
|
|
@@ -84,6 +82,7 @@ export class AgentSession {
|
|
|
84
82
|
_unsubscribeAgent;
|
|
85
83
|
_eventListeners = [];
|
|
86
84
|
_isAgentRunActive = false;
|
|
85
|
+
_agentRunAbortRequested = false;
|
|
87
86
|
_idleWaitPromise;
|
|
88
87
|
_resolveIdleWait;
|
|
89
88
|
/** Tracks pending steering messages for UI display. Removed when delivered. */
|
|
@@ -127,15 +126,15 @@ export class AgentSession {
|
|
|
127
126
|
_extensionErrorListener;
|
|
128
127
|
_extensionErrorUnsubscriber;
|
|
129
128
|
_modelRuntime;
|
|
129
|
+
_cacheWarmer;
|
|
130
130
|
// Tool registry for extension getTools/setTools
|
|
131
131
|
_toolRegistry = new Map();
|
|
132
132
|
_toolDefinitions = new Map();
|
|
133
133
|
_toolPromptSnippets = new Map();
|
|
134
134
|
_toolPromptGuidelines = new Map();
|
|
135
|
-
// Base system prompt (without extension appends) - used to apply fresh appends each turn
|
|
136
|
-
_baseSystemPrompt = "";
|
|
137
135
|
_baseSystemPromptOptions;
|
|
138
|
-
|
|
136
|
+
/** Prompt options after before_agent_start mutations for the active run. */
|
|
137
|
+
_runSystemPromptOptions;
|
|
139
138
|
constructor(config) {
|
|
140
139
|
this.agent = config.agent;
|
|
141
140
|
this.sessionManager = config.sessionManager;
|
|
@@ -145,6 +144,10 @@ export class AgentSession {
|
|
|
145
144
|
this._customTools = config.customTools ?? [];
|
|
146
145
|
this._cwd = config.cwd;
|
|
147
146
|
this._modelRuntime = config.modelRuntime;
|
|
147
|
+
this._cacheWarmer = config.cacheWarmer;
|
|
148
|
+
if (this._cacheWarmer) {
|
|
149
|
+
this._cacheWarmer.onWarmed = (entry) => this._emit({ type: "entry_appended", entry });
|
|
150
|
+
}
|
|
148
151
|
this._extensionRunnerRef = config.extensionRunnerRef;
|
|
149
152
|
this._initialActiveToolNames = config.initialActiveToolNames;
|
|
150
153
|
this._allowedToolNames = config.allowedToolNames ? new Set(config.allowedToolNames) : undefined;
|
|
@@ -156,18 +159,21 @@ export class AgentSession {
|
|
|
156
159
|
this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
|
|
157
160
|
this._installAgentToolHooks();
|
|
158
161
|
this._installAgentNextTurnRefresh();
|
|
162
|
+
this._installAgentForcedPromptProjection();
|
|
159
163
|
this._buildRuntime({
|
|
160
164
|
activeToolNames: this._initialActiveToolNames,
|
|
161
165
|
includeAllExtensionTools: true,
|
|
162
166
|
});
|
|
167
|
+
if (this._initialActiveToolNames === undefined)
|
|
168
|
+
this._restoreToolsFromTranscript();
|
|
163
169
|
}
|
|
164
170
|
get modelRuntime() {
|
|
165
171
|
return this._modelRuntime;
|
|
166
172
|
}
|
|
167
|
-
async _getRequiredRequestAuth(model) {
|
|
173
|
+
async _getRequiredRequestAuth(model, signal) {
|
|
168
174
|
let result;
|
|
169
175
|
try {
|
|
170
|
-
result = await this._modelRuntime.getAuth(model);
|
|
176
|
+
result = await this._modelRuntime.getAuth(model, { signal });
|
|
171
177
|
}
|
|
172
178
|
catch (error) {
|
|
173
179
|
const cause = error instanceof Error ? error.cause : undefined;
|
|
@@ -193,12 +199,12 @@ export class AgentSession {
|
|
|
193
199
|
}
|
|
194
200
|
throw new Error(formatNoApiKeyFoundMessage(model.provider));
|
|
195
201
|
}
|
|
196
|
-
async _getSummarizationRequestAuth(model) {
|
|
202
|
+
async _getSummarizationRequestAuth(model, signal) {
|
|
197
203
|
if (this.agent.streamFunction === streamSimple) {
|
|
198
|
-
return this._getRequiredRequestAuth(model);
|
|
204
|
+
return this._getRequiredRequestAuth(model, signal);
|
|
199
205
|
}
|
|
200
206
|
try {
|
|
201
|
-
const result = await this._modelRuntime.getAuth(model);
|
|
207
|
+
const result = await this._modelRuntime.getAuth(model, { signal });
|
|
202
208
|
if (!result)
|
|
203
209
|
return { model };
|
|
204
210
|
const requestModel = result.auth.baseUrl ? { ...model, baseUrl: result.auth.baseUrl } : model;
|
|
@@ -209,7 +215,9 @@ export class AgentSession {
|
|
|
209
215
|
env: result.env,
|
|
210
216
|
};
|
|
211
217
|
}
|
|
212
|
-
catch {
|
|
218
|
+
catch (error) {
|
|
219
|
+
if (signal?.aborted)
|
|
220
|
+
throw error;
|
|
213
221
|
return { model };
|
|
214
222
|
}
|
|
215
223
|
}
|
|
@@ -274,7 +282,7 @@ export class AgentSession {
|
|
|
274
282
|
}
|
|
275
283
|
async _compactBeforeNextAssistantResponse(context) {
|
|
276
284
|
const model = this.model;
|
|
277
|
-
const settings = this.settingsManager.getCompactionSettings();
|
|
285
|
+
const settings = this.settingsManager.getCompactionSettings(model);
|
|
278
286
|
if (!model ||
|
|
279
287
|
model.contextWindow <= 0 ||
|
|
280
288
|
!shouldCompact(estimateContextTokens(context.messages).tokens, model.contextWindow, settings)) {
|
|
@@ -295,13 +303,25 @@ export class AgentSession {
|
|
|
295
303
|
const context = await this._compactBeforeNextAssistantResponse(turn.context);
|
|
296
304
|
const previousSnapshot = await previousPrepareNextTurnWithContext?.({ ...turn, context }, signal);
|
|
297
305
|
const nextContext = previousSnapshot?.context ?? context;
|
|
306
|
+
const runOptions = this._runSystemPromptOptions ?? this._baseSystemPromptOptions;
|
|
307
|
+
const options = normalizeBuildSystemPromptOptions({
|
|
308
|
+
...runOptions,
|
|
309
|
+
selectedTools: this.getActiveToolNames(),
|
|
310
|
+
toolSnippets: { ...this._baseSystemPromptOptions.toolSnippets, ...runOptions.toolSnippets },
|
|
311
|
+
toolGuidelines: { ...this._baseSystemPromptOptions.toolGuidelines, ...runOptions.toolGuidelines },
|
|
312
|
+
});
|
|
313
|
+
const updateMessage = this._preparePromptAndToolLoadout(options, nextContext.messages);
|
|
314
|
+
// Keep session.systemPrompt and ctx.getSystemPrompt() in step with what the provider sees.
|
|
315
|
+
this._runSystemPromptOptions = options;
|
|
298
316
|
return {
|
|
299
317
|
...previousSnapshot,
|
|
300
318
|
context: {
|
|
301
319
|
...nextContext,
|
|
302
|
-
systemPrompt: this._systemPromptOverride ?? this._baseSystemPrompt,
|
|
303
320
|
tools: this.agent.state.tools.slice(),
|
|
304
321
|
},
|
|
322
|
+
messages: updateMessage
|
|
323
|
+
? [...(previousSnapshot?.messages ?? []), updateMessage]
|
|
324
|
+
: previousSnapshot?.messages,
|
|
305
325
|
model: this.agent.state.model,
|
|
306
326
|
thinkingLevel: this.agent.state.thinkingLevel,
|
|
307
327
|
};
|
|
@@ -346,6 +366,7 @@ export class AgentSession {
|
|
|
346
366
|
resolve();
|
|
347
367
|
}
|
|
348
368
|
async _emitAgentSettled() {
|
|
369
|
+
this._cacheWarmer?.onAgentSettled();
|
|
349
370
|
this._isAgentRunActive = false;
|
|
350
371
|
try {
|
|
351
372
|
await this._extensionRunner.emit({ type: "agent_settled" });
|
|
@@ -392,7 +413,8 @@ export class AgentSession {
|
|
|
392
413
|
// Persist as CustomMessageEntry
|
|
393
414
|
this.sessionManager.appendCustomMessageEntry(event.message.customType, event.message.content, event.message.display, event.message.details);
|
|
394
415
|
}
|
|
395
|
-
else if (event.message.role === "
|
|
416
|
+
else if (event.message.role === "system" ||
|
|
417
|
+
event.message.role === "user" ||
|
|
396
418
|
event.message.role === "assistant" ||
|
|
397
419
|
event.message.role === "toolResult") {
|
|
398
420
|
// Regular LLM message - persist as SessionMessageEntry
|
|
@@ -428,6 +450,8 @@ export class AgentSession {
|
|
|
428
450
|
}
|
|
429
451
|
};
|
|
430
452
|
_willRetryAfterAgentEnd(event) {
|
|
453
|
+
if (this._agentRunAbortRequested)
|
|
454
|
+
return false;
|
|
431
455
|
const settings = this.settingsManager.getRetrySettings();
|
|
432
456
|
if (!settings.enabled || this._retryAttempt >= settings.maxRetries) {
|
|
433
457
|
return false;
|
|
@@ -596,6 +620,10 @@ export class AgentSession {
|
|
|
596
620
|
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().");
|
|
597
621
|
this._disconnectFromAgent();
|
|
598
622
|
this._eventListeners = [];
|
|
623
|
+
if (this._cacheWarmer) {
|
|
624
|
+
this._cacheWarmer.onWarmed = undefined;
|
|
625
|
+
this._cacheWarmer.cancel();
|
|
626
|
+
}
|
|
599
627
|
cleanupSessionResources(this.sessionId);
|
|
600
628
|
}
|
|
601
629
|
// =========================================================================
|
|
@@ -605,6 +633,15 @@ export class AgentSession {
|
|
|
605
633
|
get state() {
|
|
606
634
|
return this.agent.state;
|
|
607
635
|
}
|
|
636
|
+
/** Current cache-warming state and the policy inputs that produced it. */
|
|
637
|
+
get cacheWarmingStatus() {
|
|
638
|
+
return this._cacheWarmer?.status;
|
|
639
|
+
}
|
|
640
|
+
/** Persist the cache-warming mode and immediately reconcile active warming. */
|
|
641
|
+
setCacheWarmingMode(mode) {
|
|
642
|
+
this.settingsManager.setCacheWarmingMode(mode);
|
|
643
|
+
this._cacheWarmer?.onModeChanged();
|
|
644
|
+
}
|
|
608
645
|
/** Current model (may be undefined if not yet selected) */
|
|
609
646
|
get model() {
|
|
610
647
|
return this.agent.state.model;
|
|
@@ -621,9 +658,9 @@ export class AgentSession {
|
|
|
621
658
|
get isIdle() {
|
|
622
659
|
return !this._isAgentRunActive && !this.isCompacting;
|
|
623
660
|
}
|
|
624
|
-
/** Current effective system prompt
|
|
661
|
+
/** Current effective system prompt, including changes not yet sent to the model. */
|
|
625
662
|
get systemPrompt() {
|
|
626
|
-
return this.
|
|
663
|
+
return buildSystemPrompt(this._runSystemPromptOptions ?? this._baseSystemPromptOptions);
|
|
627
664
|
}
|
|
628
665
|
/** Current retry attempt (0 if not retrying) */
|
|
629
666
|
get retryAttempt() {
|
|
@@ -668,9 +705,7 @@ export class AgentSession {
|
|
|
668
705
|
}
|
|
669
706
|
}
|
|
670
707
|
this.agent.state.tools = tools;
|
|
671
|
-
|
|
672
|
-
this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames);
|
|
673
|
-
this.agent.state.systemPrompt = this._systemPromptOverride ?? this._baseSystemPrompt;
|
|
708
|
+
this._rebuildSystemPrompt(validToolNames);
|
|
674
709
|
}
|
|
675
710
|
/** Whether compaction or branch summarization is currently running */
|
|
676
711
|
get isCompacting() {
|
|
@@ -739,23 +774,17 @@ export class AgentSession {
|
|
|
739
774
|
_rebuildSystemPrompt(toolNames) {
|
|
740
775
|
const validToolNames = toolNames.filter((name) => this._toolRegistry.has(name));
|
|
741
776
|
const toolSnippets = {};
|
|
742
|
-
const
|
|
743
|
-
for (const name of validToolNames) {
|
|
777
|
+
for (const name of this._toolRegistry.keys()) {
|
|
744
778
|
const snippet = this._toolPromptSnippets.get(name);
|
|
745
|
-
if (snippet)
|
|
779
|
+
if (snippet)
|
|
746
780
|
toolSnippets[name] = snippet;
|
|
747
|
-
}
|
|
748
|
-
const toolGuidelines = this._toolPromptGuidelines.get(name);
|
|
749
|
-
if (toolGuidelines) {
|
|
750
|
-
promptGuidelines.push(...toolGuidelines);
|
|
751
|
-
}
|
|
752
781
|
}
|
|
753
782
|
const loaderSystemPrompt = this._resourceLoader.getSystemPrompt();
|
|
754
783
|
const loaderAppendSystemPrompt = this._resourceLoader.getAppendSystemPrompt();
|
|
755
|
-
const appendSystemPrompt = loaderAppendSystemPrompt.length > 0 ? loaderAppendSystemPrompt.join("\n\n") :
|
|
784
|
+
const appendSystemPrompt = loaderAppendSystemPrompt.length > 0 ? loaderAppendSystemPrompt.join("\n\n") : "";
|
|
756
785
|
const loadedSkills = this._resourceLoader.getSkills().skills;
|
|
757
786
|
const loadedContextFiles = this._resourceLoader.getAgentsFiles().agentsFiles;
|
|
758
|
-
this._baseSystemPromptOptions = {
|
|
787
|
+
this._baseSystemPromptOptions = normalizeBuildSystemPromptOptions({
|
|
759
788
|
cwd: this._cwd,
|
|
760
789
|
skills: loadedSkills,
|
|
761
790
|
contextFiles: loadedContextFiles,
|
|
@@ -763,23 +792,87 @@ export class AgentSession {
|
|
|
763
792
|
appendSystemPrompt,
|
|
764
793
|
selectedTools: validToolNames,
|
|
765
794
|
toolSnippets,
|
|
766
|
-
|
|
795
|
+
toolGuidelines: Object.fromEntries(this._toolPromptGuidelines),
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* Apply a prompt and tool loadout for the next request. Sets the executable tools and
|
|
800
|
+
* returns a system message patching the prompt sections the model currently has (replayed
|
|
801
|
+
* from `messages`), or undefined when the prompt is unchanged. Tool changes are declared by
|
|
802
|
+
* the agent loop before the request.
|
|
803
|
+
*
|
|
804
|
+
* A forced prompt does not affect the transcript: the structured sections are still diffed
|
|
805
|
+
* and persisted, and the forced text is projected onto the request by
|
|
806
|
+
* {@link _installAgentForcedPromptProjection}.
|
|
807
|
+
*/
|
|
808
|
+
_preparePromptAndToolLoadout(options, messages = this.agent.state.messages) {
|
|
809
|
+
options.selectedTools = [...new Set(options.selectedTools)].filter((name) => this._toolRegistry.has(name));
|
|
810
|
+
this.agent.state.tools = options.selectedTools.flatMap((name) => {
|
|
811
|
+
const tool = this._toolRegistry.get(name);
|
|
812
|
+
return tool ? [tool] : [];
|
|
813
|
+
});
|
|
814
|
+
const sections = diffSystemPromptSections(getCurrentSystemMessage(messages)?.sections ?? {}, buildSystemPromptSections(options));
|
|
815
|
+
return sections ? { role: "system", content: "", sections, timestamp: Date.now() } : undefined;
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Send a forced prompt as the provider's leading system prompt without recording it.
|
|
819
|
+
*
|
|
820
|
+
* A `before_agent_start` handler that returns `systemPrompt` needs that exact text at the
|
|
821
|
+
* head of the request; a mid-conversation system message would leave the original prompt
|
|
822
|
+
* in place. The forced text is a rendering of the current prompt, so the transcript keeps
|
|
823
|
+
* its structured sections and the request is projected instead: the system messages
|
|
824
|
+
* collapse into one head holding the forced text and the current tools. Runs after the
|
|
825
|
+
* `context` extension handlers.
|
|
826
|
+
*/
|
|
827
|
+
_installAgentForcedPromptProjection() {
|
|
828
|
+
const previousTransformContext = this.agent.transformContext;
|
|
829
|
+
this.agent.transformContext = async (messages, signal) => {
|
|
830
|
+
const transformed = previousTransformContext ? await previousTransformContext(messages, signal) : messages;
|
|
831
|
+
const forced = this._runSystemPromptOptions?.forceSystemPrompt;
|
|
832
|
+
if (forced === undefined)
|
|
833
|
+
return transformed;
|
|
834
|
+
const current = getCurrentSystemMessage(transformed);
|
|
835
|
+
const head = {
|
|
836
|
+
role: "system",
|
|
837
|
+
content: forced,
|
|
838
|
+
...(current?.toolsAdded ? { toolsAdded: current.toolsAdded } : {}),
|
|
839
|
+
timestamp: current?.timestamp ?? Date.now(),
|
|
840
|
+
};
|
|
841
|
+
return [head, ...transformed.filter((message) => message.role !== "system")];
|
|
767
842
|
};
|
|
768
|
-
|
|
843
|
+
}
|
|
844
|
+
/** Restore the active tool loadout declared by the session transcript, if it declares one. */
|
|
845
|
+
_restoreToolsFromTranscript() {
|
|
846
|
+
const current = getCurrentSystemMessage(this.sessionManager.buildSessionContext().messages);
|
|
847
|
+
if (!current)
|
|
848
|
+
return;
|
|
849
|
+
const toolNames = (current.toolsAdded ?? [])
|
|
850
|
+
.map((tool) => tool.name)
|
|
851
|
+
.filter((name) => this._toolRegistry.has(name));
|
|
852
|
+
this.agent.state.tools = toolNames.flatMap((name) => {
|
|
853
|
+
const registered = this._toolRegistry.get(name);
|
|
854
|
+
return registered ? [registered] : [];
|
|
855
|
+
});
|
|
856
|
+
this._rebuildSystemPrompt(toolNames);
|
|
769
857
|
}
|
|
770
858
|
// =========================================================================
|
|
771
859
|
// Prompting
|
|
772
860
|
// =========================================================================
|
|
773
861
|
async _runAgentPrompt(messages) {
|
|
862
|
+
this._agentRunAbortRequested = false;
|
|
774
863
|
this._isAgentRunActive = true;
|
|
775
864
|
try {
|
|
776
865
|
await this.agent.prompt(messages);
|
|
777
866
|
while (await this._handlePostAgentRun()) {
|
|
867
|
+
if (this._agentRunAbortRequested)
|
|
868
|
+
break;
|
|
778
869
|
await this.agent.continue();
|
|
779
870
|
}
|
|
780
871
|
}
|
|
781
872
|
finally {
|
|
782
|
-
this.
|
|
873
|
+
if (this._agentRunAbortRequested)
|
|
874
|
+
this._finishCancelledRetry();
|
|
875
|
+
this._runSystemPromptOptions = undefined;
|
|
783
876
|
this._flushPendingBashMessages();
|
|
784
877
|
this._flushPendingCustomMessages();
|
|
785
878
|
await this._emitAgentSettled();
|
|
@@ -788,11 +881,21 @@ export class AgentSession {
|
|
|
788
881
|
async _handlePostAgentRun() {
|
|
789
882
|
const msg = this._lastAssistantMessage;
|
|
790
883
|
this._lastAssistantMessage = undefined;
|
|
884
|
+
if (this._agentRunAbortRequested) {
|
|
885
|
+
this._finishCancelledRetry();
|
|
886
|
+
return false;
|
|
887
|
+
}
|
|
791
888
|
if (!msg) {
|
|
792
889
|
return false;
|
|
793
890
|
}
|
|
794
891
|
if (this._isRetryableError(msg) && (await this._prepareRetry(msg))) {
|
|
795
|
-
|
|
892
|
+
if (this._agentRunAbortRequested)
|
|
893
|
+
this._finishCancelledRetry();
|
|
894
|
+
return !this._agentRunAbortRequested;
|
|
895
|
+
}
|
|
896
|
+
if (this._agentRunAbortRequested) {
|
|
897
|
+
this._finishCancelledRetry();
|
|
898
|
+
return false;
|
|
796
899
|
}
|
|
797
900
|
if (msg.stopReason === "error" && this._retryAttempt > 0) {
|
|
798
901
|
this._emit({
|
|
@@ -804,11 +907,24 @@ export class AgentSession {
|
|
|
804
907
|
this._retryAttempt = 0;
|
|
805
908
|
}
|
|
806
909
|
if (await this._checkCompaction(msg)) {
|
|
807
|
-
return
|
|
910
|
+
return !this._agentRunAbortRequested;
|
|
808
911
|
}
|
|
809
912
|
// The agent loop drains both queues before emitting agent_end. Any messages
|
|
810
913
|
// here were queued by agent_end extension handlers and need a continuation.
|
|
811
|
-
return this.agent.hasQueuedMessages();
|
|
914
|
+
return !this._agentRunAbortRequested && this.agent.hasQueuedMessages();
|
|
915
|
+
}
|
|
916
|
+
async _runInputHandlers(text, images, source, streamingBehavior) {
|
|
917
|
+
if (!this._extensionRunner.hasHandlers("input")) {
|
|
918
|
+
return { text, images };
|
|
919
|
+
}
|
|
920
|
+
const inputResult = await this._extensionRunner.emitInput(text, images, source, streamingBehavior);
|
|
921
|
+
if (inputResult.action === "handled") {
|
|
922
|
+
return undefined;
|
|
923
|
+
}
|
|
924
|
+
if (inputResult.action === "transform") {
|
|
925
|
+
return { text: inputResult.text, images: inputResult.images ?? images };
|
|
926
|
+
}
|
|
927
|
+
return { text, images };
|
|
812
928
|
}
|
|
813
929
|
/**
|
|
814
930
|
* Send a prompt to the agent.
|
|
@@ -838,19 +954,12 @@ export class AgentSession {
|
|
|
838
954
|
throw new Error("Cannot submit a prompt while compaction is in progress. Wait for compaction to finish and retry.");
|
|
839
955
|
}
|
|
840
956
|
// Emit input event for extension interception (before skill/template expansion)
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
if (inputResult.action === "handled") {
|
|
846
|
-
preflightResult?.(true);
|
|
847
|
-
return;
|
|
848
|
-
}
|
|
849
|
-
if (inputResult.action === "transform") {
|
|
850
|
-
currentText = inputResult.text;
|
|
851
|
-
currentImages = inputResult.images ?? currentImages;
|
|
852
|
-
}
|
|
957
|
+
const processedInput = await this._runInputHandlers(text, options?.images, options?.source ?? "interactive", this.isStreaming ? options?.streamingBehavior : undefined);
|
|
958
|
+
if (!processedInput) {
|
|
959
|
+
preflightResult?.(true);
|
|
960
|
+
return;
|
|
853
961
|
}
|
|
962
|
+
const { text: currentText, images: currentImages } = processedInput;
|
|
854
963
|
// Expand skill commands (/skill:name args) and prompt templates (/template args)
|
|
855
964
|
let expandedText = currentText;
|
|
856
965
|
if (expandPromptTemplates) {
|
|
@@ -914,31 +1023,30 @@ export class AgentSession {
|
|
|
914
1023
|
}
|
|
915
1024
|
this._pendingNextTurnMessages = [];
|
|
916
1025
|
// Emit before_agent_start extension event
|
|
917
|
-
const
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
}
|
|
937
|
-
else {
|
|
938
|
-
// Ensure we're using the base prompt (in case previous turn had modifications)
|
|
939
|
-
this._systemPromptOverride = undefined;
|
|
940
|
-
this.agent.state.systemPrompt = this._baseSystemPrompt;
|
|
1026
|
+
const selectedToolsBefore = this._baseSystemPromptOptions.selectedTools;
|
|
1027
|
+
const result = await this._extensionRunner.emitBeforeAgentStart(expandedText, currentImages, this._baseSystemPromptOptions);
|
|
1028
|
+
// Handlers may edit event.systemPromptOptions.selectedTools or call setActiveTools(),
|
|
1029
|
+
// which updates the live loadout instead. An explicit edit wins; otherwise the live
|
|
1030
|
+
// loadout is authoritative, so a setActiveTools() call is not undone here.
|
|
1031
|
+
const handlerEditedTools = result.systemPromptOptions.selectedTools.length !== selectedToolsBefore.length ||
|
|
1032
|
+
result.systemPromptOptions.selectedTools.some((name, index) => name !== selectedToolsBefore[index]);
|
|
1033
|
+
if (!handlerEditedTools)
|
|
1034
|
+
result.systemPromptOptions.selectedTools = this.getActiveToolNames();
|
|
1035
|
+
for (const msg of result.messages) {
|
|
1036
|
+
messages.push({
|
|
1037
|
+
role: "custom",
|
|
1038
|
+
customType: msg.customType,
|
|
1039
|
+
// Untyped extensions can pass null/missing content; normalize at ingestion.
|
|
1040
|
+
content: msg.content ?? [],
|
|
1041
|
+
display: msg.display,
|
|
1042
|
+
details: msg.details,
|
|
1043
|
+
timestamp: Date.now(),
|
|
1044
|
+
});
|
|
941
1045
|
}
|
|
1046
|
+
const updateMessage = this._preparePromptAndToolLoadout(result.systemPromptOptions);
|
|
1047
|
+
this._runSystemPromptOptions = result.systemPromptOptions;
|
|
1048
|
+
if (updateMessage)
|
|
1049
|
+
messages.unshift(updateMessage);
|
|
942
1050
|
}
|
|
943
1051
|
catch (error) {
|
|
944
1052
|
preflightResult?.(false);
|
|
@@ -1027,42 +1135,45 @@ export class AgentSession {
|
|
|
1027
1135
|
return text; // Return original on error
|
|
1028
1136
|
}
|
|
1029
1137
|
}
|
|
1138
|
+
async _queueUserInput(text, images, behavior, source) {
|
|
1139
|
+
if (text.startsWith("/")) {
|
|
1140
|
+
this._throwIfExtensionCommand(text);
|
|
1141
|
+
}
|
|
1142
|
+
const processedInput = await this._runInputHandlers(text, images, source, this.isStreaming ? behavior : undefined);
|
|
1143
|
+
if (!processedInput)
|
|
1144
|
+
return;
|
|
1145
|
+
let expandedText = this._expandSkillCommand(processedInput.text);
|
|
1146
|
+
expandedText = this._expandBareNamespaceSkillCommand(expandedText);
|
|
1147
|
+
expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
|
|
1148
|
+
if (behavior === "steer") {
|
|
1149
|
+
await this._queueSteer(expandedText, processedInput.images);
|
|
1150
|
+
}
|
|
1151
|
+
else {
|
|
1152
|
+
await this._queueFollowUp(expandedText, processedInput.images);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1030
1155
|
/**
|
|
1031
1156
|
* Queue a steering message while the agent is running.
|
|
1032
1157
|
* Delivered after the current assistant turn finishes executing its tool calls,
|
|
1033
1158
|
* before the next LLM call.
|
|
1034
1159
|
* Expands skill commands and prompt templates. Errors on extension commands.
|
|
1035
1160
|
* @param images Optional image attachments to include with the message
|
|
1161
|
+
* @param options Input source; defaults to interactive
|
|
1036
1162
|
* @throws Error if text is an extension command
|
|
1037
1163
|
*/
|
|
1038
|
-
async steer(text, images) {
|
|
1039
|
-
|
|
1040
|
-
if (text.startsWith("/")) {
|
|
1041
|
-
this._throwIfExtensionCommand(text);
|
|
1042
|
-
}
|
|
1043
|
-
// Expand skill commands and prompt templates
|
|
1044
|
-
let expandedText = this._expandSkillCommand(text);
|
|
1045
|
-
expandedText = this._expandBareNamespaceSkillCommand(expandedText);
|
|
1046
|
-
expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
|
|
1047
|
-
await this._queueSteer(expandedText, images);
|
|
1164
|
+
async steer(text, images, options) {
|
|
1165
|
+
await this._queueUserInput(text, images, "steer", options?.source ?? "interactive");
|
|
1048
1166
|
}
|
|
1049
1167
|
/**
|
|
1050
1168
|
* Queue a follow-up message to be processed after the agent finishes.
|
|
1051
1169
|
* Delivered only when agent has no more tool calls or steering messages.
|
|
1052
1170
|
* Expands skill commands and prompt templates. Errors on extension commands.
|
|
1053
1171
|
* @param images Optional image attachments to include with the message
|
|
1172
|
+
* @param options Input source; defaults to interactive
|
|
1054
1173
|
* @throws Error if text is an extension command
|
|
1055
1174
|
*/
|
|
1056
|
-
async followUp(text, images) {
|
|
1057
|
-
|
|
1058
|
-
if (text.startsWith("/")) {
|
|
1059
|
-
this._throwIfExtensionCommand(text);
|
|
1060
|
-
}
|
|
1061
|
-
// Expand skill commands and prompt templates
|
|
1062
|
-
let expandedText = this._expandSkillCommand(text);
|
|
1063
|
-
expandedText = this._expandBareNamespaceSkillCommand(expandedText);
|
|
1064
|
-
expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
|
|
1065
|
-
await this._queueFollowUp(expandedText, images);
|
|
1175
|
+
async followUp(text, images, options) {
|
|
1176
|
+
await this._queueUserInput(text, images, "followUp", options?.source ?? "interactive");
|
|
1066
1177
|
}
|
|
1067
1178
|
/**
|
|
1068
1179
|
* Internal: Queue a steering message (already expanded, no extension command check).
|
|
@@ -1244,6 +1355,9 @@ export class AgentSession {
|
|
|
1244
1355
|
* Abort current operation and wait for agent to become idle.
|
|
1245
1356
|
*/
|
|
1246
1357
|
async abort() {
|
|
1358
|
+
if (this._isAgentRunActive) {
|
|
1359
|
+
this._agentRunAbortRequested = true;
|
|
1360
|
+
}
|
|
1247
1361
|
this.abortRetry();
|
|
1248
1362
|
this.abortCompaction();
|
|
1249
1363
|
this.abortBranchSummary();
|
|
@@ -1500,13 +1614,15 @@ export class AgentSession {
|
|
|
1500
1614
|
this._compactionAbortController = new AbortController();
|
|
1501
1615
|
this._emit({ type: "compaction_start", reason: "manual" });
|
|
1502
1616
|
let fromExtension = false;
|
|
1617
|
+
let cancelledByExtension = false;
|
|
1503
1618
|
try {
|
|
1504
|
-
|
|
1619
|
+
const model = this.model;
|
|
1620
|
+
if (!model) {
|
|
1505
1621
|
throw new Error(formatNoModelSelectedMessage());
|
|
1506
1622
|
}
|
|
1507
|
-
const
|
|
1623
|
+
const settings = this.settingsManager.getCompactionSettings(model);
|
|
1624
|
+
const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, this._compactionAbortController.signal);
|
|
1508
1625
|
const pathEntries = this.sessionManager.getBranch();
|
|
1509
|
-
const settings = this.settingsManager.getCompactionSettings();
|
|
1510
1626
|
const preparation = prepareCompaction(pathEntries, settings);
|
|
1511
1627
|
if (!preparation) {
|
|
1512
1628
|
// Check why we can't compact
|
|
@@ -1528,6 +1644,7 @@ export class AgentSession {
|
|
|
1528
1644
|
signal: this._compactionAbortController.signal,
|
|
1529
1645
|
}));
|
|
1530
1646
|
if (result?.cancel) {
|
|
1647
|
+
cancelledByExtension = true;
|
|
1531
1648
|
throw new Error("Compaction cancelled");
|
|
1532
1649
|
}
|
|
1533
1650
|
if (result?.compaction) {
|
|
@@ -1597,7 +1714,7 @@ export class AgentSession {
|
|
|
1597
1714
|
}
|
|
1598
1715
|
catch (error) {
|
|
1599
1716
|
const message = error instanceof Error ? error.message : String(error);
|
|
1600
|
-
const aborted =
|
|
1717
|
+
const aborted = this._compactionAbortController.signal.aborted || cancelledByExtension;
|
|
1601
1718
|
const errorMessage = aborted ? undefined : `Compaction failed: ${message}`;
|
|
1602
1719
|
this._clearManualCompactionState();
|
|
1603
1720
|
this._emit({
|
|
@@ -1656,7 +1773,7 @@ export class AgentSession {
|
|
|
1656
1773
|
* @returns Whether the post-run loop should call `agent.continue()` for overflow recovery or queued messages
|
|
1657
1774
|
*/
|
|
1658
1775
|
async _checkCompaction(assistantMessage, skipAbortedCheck = true) {
|
|
1659
|
-
const settings = this.settingsManager.getCompactionSettings();
|
|
1776
|
+
const settings = this.settingsManager.getCompactionSettings(this.model);
|
|
1660
1777
|
if (!settings.enabled)
|
|
1661
1778
|
return false;
|
|
1662
1779
|
// Skip if message was aborted (user cancelled) - unless skipAbortedCheck is false
|
|
@@ -1761,22 +1878,28 @@ export class AgentSession {
|
|
|
1761
1878
|
* @returns Whether the post-run loop should call `agent.continue()`
|
|
1762
1879
|
*/
|
|
1763
1880
|
async _runAutoCompaction(reason, willRetry) {
|
|
1764
|
-
const
|
|
1881
|
+
const model = this.model;
|
|
1882
|
+
const settings = this.settingsManager.getCompactionSettings(model);
|
|
1883
|
+
let abortController;
|
|
1765
1884
|
let started = false;
|
|
1766
1885
|
let fromExtension = false;
|
|
1886
|
+
let cancelledByExtension = false;
|
|
1767
1887
|
try {
|
|
1768
|
-
if (!
|
|
1888
|
+
if (!model) {
|
|
1769
1889
|
return false;
|
|
1770
1890
|
}
|
|
1771
|
-
const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(this.model);
|
|
1772
1891
|
const pathEntries = this.sessionManager.getBranch();
|
|
1773
1892
|
const preparation = prepareCompaction(pathEntries, settings);
|
|
1774
1893
|
if (!preparation) {
|
|
1775
1894
|
return false;
|
|
1776
1895
|
}
|
|
1777
|
-
|
|
1778
|
-
this._autoCompactionAbortController =
|
|
1896
|
+
abortController = new AbortController();
|
|
1897
|
+
this._autoCompactionAbortController = abortController;
|
|
1779
1898
|
started = true;
|
|
1899
|
+
this._emit({ type: "compaction_start", reason });
|
|
1900
|
+
abortController.signal.throwIfAborted();
|
|
1901
|
+
const { model: requestModel, apiKey, headers, env, } = await this._getSummarizationRequestAuth(model, abortController.signal);
|
|
1902
|
+
abortController.signal.throwIfAborted();
|
|
1780
1903
|
let extensionCompaction;
|
|
1781
1904
|
if (this._extensionRunner.hasHandlers("session_before_compact")) {
|
|
1782
1905
|
const extensionResult = (await this._extensionRunner.emit({
|
|
@@ -1786,29 +1909,18 @@ export class AgentSession {
|
|
|
1786
1909
|
customInstructions: undefined,
|
|
1787
1910
|
reason,
|
|
1788
1911
|
willRetry,
|
|
1789
|
-
signal:
|
|
1912
|
+
signal: abortController.signal,
|
|
1790
1913
|
}));
|
|
1791
1914
|
if (extensionResult?.cancel) {
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
reason,
|
|
1795
|
-
result: undefined,
|
|
1796
|
-
aborted: true,
|
|
1797
|
-
willRetry: false,
|
|
1798
|
-
});
|
|
1799
|
-
await this._emitSessionCompactFailed({
|
|
1800
|
-
reason,
|
|
1801
|
-
aborted: true,
|
|
1802
|
-
willRetry: false,
|
|
1803
|
-
fromExtension: false,
|
|
1804
|
-
});
|
|
1805
|
-
return false;
|
|
1915
|
+
cancelledByExtension = true;
|
|
1916
|
+
throw new Error("Compaction cancelled");
|
|
1806
1917
|
}
|
|
1807
1918
|
if (extensionResult?.compaction) {
|
|
1808
1919
|
extensionCompaction = extensionResult.compaction;
|
|
1809
1920
|
fromExtension = true;
|
|
1810
1921
|
}
|
|
1811
1922
|
}
|
|
1923
|
+
abortController.signal.throwIfAborted();
|
|
1812
1924
|
let summary;
|
|
1813
1925
|
let firstKeptEntryId;
|
|
1814
1926
|
let tokensBefore;
|
|
@@ -1824,29 +1936,14 @@ export class AgentSession {
|
|
|
1824
1936
|
}
|
|
1825
1937
|
else {
|
|
1826
1938
|
// Shared default summary generator, also used by manual compaction.
|
|
1827
|
-
const compactResult = await this._runDefaultCompaction(preparation, requestModel, apiKey, headers, undefined,
|
|
1939
|
+
const compactResult = await this._runDefaultCompaction(preparation, requestModel, apiKey, headers, undefined, abortController.signal, env, reason);
|
|
1828
1940
|
summary = compactResult.summary;
|
|
1829
1941
|
firstKeptEntryId = compactResult.firstKeptEntryId;
|
|
1830
1942
|
tokensBefore = compactResult.tokensBefore;
|
|
1831
1943
|
usage = compactResult.usage;
|
|
1832
1944
|
details = compactResult.details;
|
|
1833
1945
|
}
|
|
1834
|
-
|
|
1835
|
-
this._emit({
|
|
1836
|
-
type: "compaction_end",
|
|
1837
|
-
reason,
|
|
1838
|
-
result: undefined,
|
|
1839
|
-
aborted: true,
|
|
1840
|
-
willRetry: false,
|
|
1841
|
-
});
|
|
1842
|
-
await this._emitSessionCompactFailed({
|
|
1843
|
-
reason,
|
|
1844
|
-
aborted: true,
|
|
1845
|
-
willRetry: false,
|
|
1846
|
-
fromExtension,
|
|
1847
|
-
});
|
|
1848
|
-
return false;
|
|
1849
|
-
}
|
|
1946
|
+
abortController.signal.throwIfAborted();
|
|
1850
1947
|
this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension, usage);
|
|
1851
1948
|
const newEntries = this.sessionManager.getEntries();
|
|
1852
1949
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
@@ -1889,23 +1986,26 @@ export class AgentSession {
|
|
|
1889
1986
|
return this.agent.hasQueuedMessages();
|
|
1890
1987
|
}
|
|
1891
1988
|
catch (error) {
|
|
1892
|
-
const
|
|
1989
|
+
const message = error instanceof Error ? error.message : "compaction failed";
|
|
1990
|
+
const aborted = abortController?.signal.aborted === true || cancelledByExtension;
|
|
1893
1991
|
if (started) {
|
|
1894
|
-
const
|
|
1895
|
-
?
|
|
1896
|
-
:
|
|
1992
|
+
const errorMessage = aborted
|
|
1993
|
+
? undefined
|
|
1994
|
+
: reason === "overflow"
|
|
1995
|
+
? `Context overflow recovery failed: ${message}`
|
|
1996
|
+
: `Auto-compaction failed: ${message}`;
|
|
1897
1997
|
this._emit({
|
|
1898
1998
|
type: "compaction_end",
|
|
1899
1999
|
reason,
|
|
1900
2000
|
result: undefined,
|
|
1901
|
-
aborted
|
|
2001
|
+
aborted,
|
|
1902
2002
|
willRetry: false,
|
|
1903
|
-
errorMessage
|
|
2003
|
+
errorMessage,
|
|
1904
2004
|
});
|
|
1905
2005
|
await this._emitSessionCompactFailed({
|
|
1906
2006
|
reason,
|
|
1907
|
-
errorMessage
|
|
1908
|
-
aborted
|
|
2007
|
+
errorMessage,
|
|
2008
|
+
aborted,
|
|
1909
2009
|
willRetry: false,
|
|
1910
2010
|
fromExtension,
|
|
1911
2011
|
});
|
|
@@ -1913,7 +2013,9 @@ export class AgentSession {
|
|
|
1913
2013
|
return false;
|
|
1914
2014
|
}
|
|
1915
2015
|
finally {
|
|
1916
|
-
this._autoCompactionAbortController
|
|
2016
|
+
if (this._autoCompactionAbortController === abortController) {
|
|
2017
|
+
this._autoCompactionAbortController = undefined;
|
|
2018
|
+
}
|
|
1917
2019
|
this._resolveIdleWaitIfIdle();
|
|
1918
2020
|
}
|
|
1919
2021
|
}
|
|
@@ -1964,8 +2066,7 @@ export class AgentSession {
|
|
|
1964
2066
|
themePaths: this.buildExtensionResourcePaths(themePaths),
|
|
1965
2067
|
};
|
|
1966
2068
|
this._resourceLoader.extendResources(extensionPaths);
|
|
1967
|
-
this.
|
|
1968
|
-
this.agent.state.systemPrompt = this._baseSystemPrompt;
|
|
2069
|
+
this._rebuildSystemPrompt(this.getActiveToolNames());
|
|
1969
2070
|
}
|
|
1970
2071
|
buildExtensionResourcePaths(entries) {
|
|
1971
2072
|
return entries.map((entry) => {
|
|
@@ -2303,6 +2404,18 @@ export class AgentSession {
|
|
|
2303
2404
|
},
|
|
2304
2405
|
};
|
|
2305
2406
|
}
|
|
2407
|
+
_finishCancelledRetry() {
|
|
2408
|
+
if (this._retryAttempt === 0)
|
|
2409
|
+
return;
|
|
2410
|
+
const attempt = this._retryAttempt;
|
|
2411
|
+
this._retryAttempt = 0;
|
|
2412
|
+
this._emit({
|
|
2413
|
+
type: "auto_retry_end",
|
|
2414
|
+
success: false,
|
|
2415
|
+
attempt,
|
|
2416
|
+
finalError: "Retry cancelled",
|
|
2417
|
+
});
|
|
2418
|
+
}
|
|
2306
2419
|
/**
|
|
2307
2420
|
* Prepare a retryable error for continuation with exponential backoff.
|
|
2308
2421
|
* @returns true if the caller should continue the agent, false otherwise
|
|
@@ -2318,7 +2431,7 @@ export class AgentSession {
|
|
|
2318
2431
|
this._retryAttempt--;
|
|
2319
2432
|
return false;
|
|
2320
2433
|
}
|
|
2321
|
-
const delayMs = settings
|
|
2434
|
+
const delayMs = retryDelayMs(settings, this._retryAttempt);
|
|
2322
2435
|
this._emit({
|
|
2323
2436
|
type: "auto_retry_start",
|
|
2324
2437
|
attempt: this._retryAttempt,
|
|
@@ -2338,14 +2451,7 @@ export class AgentSession {
|
|
|
2338
2451
|
}
|
|
2339
2452
|
catch {
|
|
2340
2453
|
// Aborted during sleep - emit end event so UI can clean up
|
|
2341
|
-
|
|
2342
|
-
this._retryAttempt = 0;
|
|
2343
|
-
this._emit({
|
|
2344
|
-
type: "auto_retry_end",
|
|
2345
|
-
success: false,
|
|
2346
|
-
attempt,
|
|
2347
|
-
finalError: "Retry cancelled",
|
|
2348
|
-
});
|
|
2454
|
+
this._finishCancelledRetry();
|
|
2349
2455
|
return false;
|
|
2350
2456
|
}
|
|
2351
2457
|
finally {
|
|
@@ -2496,6 +2602,9 @@ export class AgentSession {
|
|
|
2496
2602
|
if (this.isStreaming) {
|
|
2497
2603
|
throw new Error("Wait for the current response to finish before navigating the session tree.");
|
|
2498
2604
|
}
|
|
2605
|
+
if (this.isCompacting) {
|
|
2606
|
+
throw new Error("Wait for the current compaction or tree navigation to finish before navigating the session tree.");
|
|
2607
|
+
}
|
|
2499
2608
|
const oldLeafId = this.sessionManager.getLeafId();
|
|
2500
2609
|
// No-op if already at target
|
|
2501
2610
|
if (targetId === oldLeafId) {
|
|
@@ -2638,6 +2747,7 @@ export class AgentSession {
|
|
|
2638
2747
|
// Update agent state
|
|
2639
2748
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
2640
2749
|
this.agent.state.messages = sessionContext.messages;
|
|
2750
|
+
this._restoreToolsFromTranscript();
|
|
2641
2751
|
// Emit session_tree event
|
|
2642
2752
|
await this._extensionRunner.emit({
|
|
2643
2753
|
type: "session_tree",
|
|
@@ -2685,7 +2795,10 @@ export class AgentSession {
|
|
|
2685
2795
|
let toolCalls = 0;
|
|
2686
2796
|
const usageTotals = createUsageTotals();
|
|
2687
2797
|
for (const entry of this.sessionManager.getEntries()) {
|
|
2688
|
-
if (
|
|
2798
|
+
if (entry.type === "usage") {
|
|
2799
|
+
addUsageToTotals(usageTotals, entry.usage);
|
|
2800
|
+
}
|
|
2801
|
+
else if ((entry.type === "branch_summary" || entry.type === "compaction") && entry.usage) {
|
|
2689
2802
|
addUsageToTotals(usageTotals, entry.usage);
|
|
2690
2803
|
}
|
|
2691
2804
|
if (entry.type !== "message")
|
|
@@ -2799,6 +2912,30 @@ export class AgentSession {
|
|
|
2799
2912
|
exportToJsonl(outputPath) {
|
|
2800
2913
|
return exportSessionToJsonl(this.sessionManager, outputPath);
|
|
2801
2914
|
}
|
|
2915
|
+
/**
|
|
2916
|
+
* Ask the current model to describe what went wrong in this session for a bug report.
|
|
2917
|
+
* Used when the user declines to share the transcript itself.
|
|
2918
|
+
*/
|
|
2919
|
+
async summarizeForBugReport(options) {
|
|
2920
|
+
const model = this.model;
|
|
2921
|
+
if (!model) {
|
|
2922
|
+
throw new Error("No model selected");
|
|
2923
|
+
}
|
|
2924
|
+
const { model: requestModel, apiKey, headers, env } = await this._getSummarizationRequestAuth(model);
|
|
2925
|
+
return generateBugReportSummary({
|
|
2926
|
+
messages: this.messages,
|
|
2927
|
+
hint: options.hint,
|
|
2928
|
+
model: requestModel,
|
|
2929
|
+
apiKey,
|
|
2930
|
+
headers,
|
|
2931
|
+
env,
|
|
2932
|
+
signal: options.signal,
|
|
2933
|
+
thinkingLevel: this.thinkingLevel,
|
|
2934
|
+
streamFn: this.agent.streamFunction,
|
|
2935
|
+
retry: this.settingsManager.getRetrySettings(),
|
|
2936
|
+
sessionId: this.sessionId,
|
|
2937
|
+
});
|
|
2938
|
+
}
|
|
2802
2939
|
// =========================================================================
|
|
2803
2940
|
// Utilities
|
|
2804
2941
|
// =========================================================================
|