@mariozechner/pi-coding-agent 0.49.2 → 0.50.0
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 +126 -1
- package/README.md +310 -1229
- package/dist/cli/args.d.ts +5 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +57 -22
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts +14 -0
- package/dist/cli/config-selector.d.ts.map +1 -0
- package/dist/cli/config-selector.js +31 -0
- package/dist/cli/config-selector.js.map +1 -0
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +53 -34
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +262 -67
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +8 -18
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +39 -55
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +2 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/diagnostics.d.ts +15 -0
- package/dist/core/diagnostics.d.ts.map +1 -0
- package/dist/core/diagnostics.js +2 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/export-html/template.css +9 -0
- package/dist/core/export-html/template.js +6 -4
- 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/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +10 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +9 -3
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +39 -12
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +112 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +9 -2
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +13 -0
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/model-registry.d.ts +42 -2
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +154 -44
- 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 +3 -2
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +129 -0
- package/dist/core/package-manager.d.ts.map +1 -0
- package/dist/core/package-manager.js +1148 -0
- package/dist/core/package-manager.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +6 -0
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +114 -54
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/resource-loader.d.ts +160 -0
- package/dist/core/resource-loader.d.ts.map +1 -0
- package/dist/core/resource-loader.js +604 -0
- package/dist/core/resource-loader.js.map +1 -0
- package/dist/core/sdk.d.ts +14 -105
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +52 -304
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +45 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +39 -16
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +107 -25
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +18 -10
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +126 -93
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts +3 -27
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +16 -103
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +2 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +4 -4
- package/dist/core/tools/read.js.map +1 -1
- package/dist/index.d.ts +12 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -6
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +209 -97
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +3 -2
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +5 -3
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts +5 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +29 -9
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +3 -2
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +4 -2
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +3 -2
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +4 -2
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +71 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/config-selector.js +468 -0
- package/dist/modes/interactive/components/config-selector.js.map +1 -0
- package/dist/modes/interactive/components/custom-message.d.ts +3 -2
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +4 -2
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +9 -0
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +3 -4
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +18 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +195 -87
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +12 -5
- 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 -2
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +2 -2
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +2 -2
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +47 -2
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +566 -211
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +1 -1
- package/dist/modes/interactive/theme/light.json +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +8 -1
- package/dist/modes/interactive/theme/theme.d.ts +8 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +79 -28
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +25 -89
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +32 -92
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/git.d.ts +2 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +6 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/shell.d.ts +1 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +16 -2
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/sleep.d.ts +5 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +17 -0
- package/dist/utils/sleep.js.map +1 -0
- package/docs/compaction.md +23 -21
- package/docs/custom-provider.md +538 -0
- package/docs/development.md +69 -0
- package/docs/extensions.md +180 -118
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/json.md +79 -0
- package/docs/keybindings.md +162 -0
- package/docs/models.md +193 -0
- package/docs/packages.md +163 -0
- package/docs/prompt-templates.md +67 -0
- package/docs/providers.md +147 -0
- package/docs/sdk.md +111 -178
- package/docs/session.md +167 -16
- package/docs/settings.md +216 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +111 -202
- package/docs/terminal-setup.md +65 -0
- package/docs/themes.md +295 -0
- package/docs/tui.md +36 -5
- package/docs/windows.md +17 -0
- package/examples/README.md +1 -0
- package/examples/extensions/README.md +24 -2
- package/examples/extensions/antigravity-image-gen.ts +413 -0
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/doom-overlay/doom/build.sh +1 -1
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/space-invaders.ts +560 -0
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/02-custom-model.ts +3 -3
- package/examples/sdk/03-custom-prompt.ts +20 -9
- package/examples/sdk/04-skills.ts +26 -27
- package/examples/sdk/06-extensions.ts +15 -6
- package/examples/sdk/07-context-files.ts +22 -18
- package/examples/sdk/08-prompt-templates.ts +19 -14
- package/examples/sdk/09-api-keys-and-oauth.ts +5 -12
- package/examples/sdk/10-settings.ts +3 -3
- package/examples/sdk/12-full-control.ts +16 -7
- package/examples/sdk/README.md +24 -30
- package/package.json +4 -4
- package/docs/theme.md +0 -617
- package/examples/extensions/chalk-logger.ts +0 -26
|
@@ -13,15 +13,35 @@
|
|
|
13
13
|
* Modes use this class and add their own I/O layer on top.
|
|
14
14
|
*/
|
|
15
15
|
import { readFileSync } from "node:fs";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { isContextOverflow, modelsAreEqual, resetApiProviders, supportsXhigh } from "@mariozechner/pi-ai";
|
|
18
|
+
import { getDocsPath } from "../config.js";
|
|
18
19
|
import { theme } from "../modes/interactive/theme/theme.js";
|
|
19
20
|
import { stripFrontmatter } from "../utils/frontmatter.js";
|
|
21
|
+
import { sleep } from "../utils/sleep.js";
|
|
20
22
|
import { executeBash as executeBashCommand, executeBashWithOperations } from "./bash-executor.js";
|
|
21
23
|
import { calculateContextTokens, collectEntriesForBranchSummary, compact, estimateContextTokens, generateBranchSummary, prepareCompaction, shouldCompact, } from "./compaction/index.js";
|
|
22
24
|
import { exportSessionToHtml } from "./export-html/index.js";
|
|
23
25
|
import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
|
|
26
|
+
import { ExtensionRunner, wrapRegisteredTools, wrapToolsWithExtensions, } from "./extensions/index.js";
|
|
24
27
|
import { expandPromptTemplate } from "./prompt-templates.js";
|
|
28
|
+
import { buildSystemPrompt } from "./system-prompt.js";
|
|
29
|
+
import { createAllTools } from "./tools/index.js";
|
|
30
|
+
/**
|
|
31
|
+
* Parse a skill block from message text.
|
|
32
|
+
* Returns null if the text doesn't contain a skill block.
|
|
33
|
+
*/
|
|
34
|
+
export function parseSkillBlock(text) {
|
|
35
|
+
const match = text.match(/^<skill name="([^"]+)" location="([^"]+)">\n([\s\S]*?)\n<\/skill>(?:\n\n([\s\S]+))?$/);
|
|
36
|
+
if (!match)
|
|
37
|
+
return null;
|
|
38
|
+
return {
|
|
39
|
+
name: match[1],
|
|
40
|
+
location: match[2],
|
|
41
|
+
content: match[3],
|
|
42
|
+
userMessage: match[4]?.trim() || undefined,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
25
45
|
// ============================================================================
|
|
26
46
|
// Constants
|
|
27
47
|
// ============================================================================
|
|
@@ -37,7 +57,6 @@ export class AgentSession {
|
|
|
37
57
|
sessionManager;
|
|
38
58
|
settingsManager;
|
|
39
59
|
_scopedModels;
|
|
40
|
-
_promptTemplates;
|
|
41
60
|
// Event subscription state
|
|
42
61
|
_unsubscribeAgent;
|
|
43
62
|
_eventListeners = [];
|
|
@@ -63,34 +82,43 @@ export class AgentSession {
|
|
|
63
82
|
// Extension system
|
|
64
83
|
_extensionRunner = undefined;
|
|
65
84
|
_turnIndex = 0;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
85
|
+
_resourceLoader;
|
|
86
|
+
_customTools;
|
|
87
|
+
_baseToolRegistry = new Map();
|
|
88
|
+
_cwd;
|
|
89
|
+
_extensionRunnerRef;
|
|
90
|
+
_initialActiveToolNames;
|
|
91
|
+
_baseToolsOverride;
|
|
92
|
+
_extensionUIContext;
|
|
93
|
+
_extensionCommandContextActions;
|
|
94
|
+
_extensionShutdownHandler;
|
|
95
|
+
_extensionErrorListener;
|
|
96
|
+
_extensionErrorUnsubscriber;
|
|
69
97
|
// Model registry for API key resolution
|
|
70
98
|
_modelRegistry;
|
|
71
99
|
// Tool registry for extension getTools/setTools
|
|
72
|
-
_toolRegistry;
|
|
73
|
-
// Function to rebuild system prompt when tools change
|
|
74
|
-
_rebuildSystemPrompt;
|
|
100
|
+
_toolRegistry = new Map();
|
|
75
101
|
// Base system prompt (without extension appends) - used to apply fresh appends each turn
|
|
76
|
-
_baseSystemPrompt;
|
|
102
|
+
_baseSystemPrompt = "";
|
|
77
103
|
constructor(config) {
|
|
78
104
|
this.agent = config.agent;
|
|
79
105
|
this.sessionManager = config.sessionManager;
|
|
80
106
|
this.settingsManager = config.settingsManager;
|
|
81
107
|
this._scopedModels = config.scopedModels ?? [];
|
|
82
|
-
this.
|
|
83
|
-
this.
|
|
84
|
-
this.
|
|
85
|
-
this._skillWarnings = config.skillWarnings ?? [];
|
|
86
|
-
this._skillsSettings = config.skillsSettings;
|
|
108
|
+
this._resourceLoader = config.resourceLoader;
|
|
109
|
+
this._customTools = config.customTools ?? [];
|
|
110
|
+
this._cwd = config.cwd;
|
|
87
111
|
this._modelRegistry = config.modelRegistry;
|
|
88
|
-
this.
|
|
89
|
-
this.
|
|
90
|
-
this.
|
|
112
|
+
this._extensionRunnerRef = config.extensionRunnerRef;
|
|
113
|
+
this._initialActiveToolNames = config.initialActiveToolNames;
|
|
114
|
+
this._baseToolsOverride = config.baseToolsOverride;
|
|
91
115
|
// Always subscribe to agent events for internal handling
|
|
92
116
|
// (session persistence, extensions, auto-compaction, retry logic)
|
|
93
117
|
this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
|
|
118
|
+
this._buildRuntime({
|
|
119
|
+
activeToolNames: this._initialActiveToolNames,
|
|
120
|
+
includeAllExtensionTools: true,
|
|
121
|
+
});
|
|
94
122
|
}
|
|
95
123
|
/** Model registry for API key resolution and model discovery */
|
|
96
124
|
get modelRegistry() {
|
|
@@ -334,10 +362,8 @@ export class AgentSession {
|
|
|
334
362
|
}
|
|
335
363
|
this.agent.setTools(tools);
|
|
336
364
|
// Rebuild base system prompt with new tool set
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
this.agent.setSystemPrompt(this._baseSystemPrompt);
|
|
340
|
-
}
|
|
365
|
+
this._baseSystemPrompt = this._rebuildSystemPrompt(validToolNames);
|
|
366
|
+
this.agent.setSystemPrompt(this._baseSystemPrompt);
|
|
341
367
|
}
|
|
342
368
|
/** Whether auto-compaction is currently running */
|
|
343
369
|
get isCompacting() {
|
|
@@ -373,7 +399,23 @@ export class AgentSession {
|
|
|
373
399
|
}
|
|
374
400
|
/** File-based prompt templates */
|
|
375
401
|
get promptTemplates() {
|
|
376
|
-
return this.
|
|
402
|
+
return this._resourceLoader.getPrompts().prompts;
|
|
403
|
+
}
|
|
404
|
+
_rebuildSystemPrompt(toolNames) {
|
|
405
|
+
const validToolNames = toolNames.filter((name) => this._baseToolRegistry.has(name));
|
|
406
|
+
const loaderSystemPrompt = this._resourceLoader.getSystemPrompt();
|
|
407
|
+
const loaderAppendSystemPrompt = this._resourceLoader.getAppendSystemPrompt();
|
|
408
|
+
const appendSystemPrompt = loaderAppendSystemPrompt.length > 0 ? loaderAppendSystemPrompt.join("\n\n") : undefined;
|
|
409
|
+
const loadedSkills = this._resourceLoader.getSkills().skills;
|
|
410
|
+
const loadedContextFiles = this._resourceLoader.getAgentsFiles().agentsFiles;
|
|
411
|
+
return buildSystemPrompt({
|
|
412
|
+
cwd: this._cwd,
|
|
413
|
+
skills: loadedSkills,
|
|
414
|
+
contextFiles: loadedContextFiles,
|
|
415
|
+
customPrompt: loaderSystemPrompt,
|
|
416
|
+
appendSystemPrompt,
|
|
417
|
+
selectedTools: validToolNames,
|
|
418
|
+
});
|
|
377
419
|
}
|
|
378
420
|
// =========================================================================
|
|
379
421
|
// Prompting
|
|
@@ -415,7 +457,7 @@ export class AgentSession {
|
|
|
415
457
|
let expandedText = currentText;
|
|
416
458
|
if (expandPromptTemplates) {
|
|
417
459
|
expandedText = this._expandSkillCommand(expandedText);
|
|
418
|
-
expandedText = expandPromptTemplate(expandedText, [...this.
|
|
460
|
+
expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
|
|
419
461
|
}
|
|
420
462
|
// If streaming, queue via steer() or followUp() based on option
|
|
421
463
|
if (this.isStreaming) {
|
|
@@ -435,7 +477,7 @@ export class AgentSession {
|
|
|
435
477
|
// Validate model
|
|
436
478
|
if (!this.model) {
|
|
437
479
|
throw new Error("No model selected.\n\n" +
|
|
438
|
-
`Use /login
|
|
480
|
+
`Use /login or set an API key environment variable. See ${join(getDocsPath(), "authentication.md")}\n\n` +
|
|
439
481
|
"Then use /model to select a model.");
|
|
440
482
|
}
|
|
441
483
|
// Validate API key
|
|
@@ -448,7 +490,7 @@ export class AgentSession {
|
|
|
448
490
|
`Run '/login ${this.model.provider}' to re-authenticate.`);
|
|
449
491
|
}
|
|
450
492
|
throw new Error(`No API key found for ${this.model.provider}.\n\n` +
|
|
451
|
-
`Use /login
|
|
493
|
+
`Use /login or set an API key environment variable. See ${join(getDocsPath(), "authentication.md")}`);
|
|
452
494
|
}
|
|
453
495
|
// Check if we need to compact before sending (catches aborted responses)
|
|
454
496
|
const lastAssistant = this._findLastAssistantMessage();
|
|
@@ -540,15 +582,14 @@ export class AgentSession {
|
|
|
540
582
|
const spaceIndex = text.indexOf(" ");
|
|
541
583
|
const skillName = spaceIndex === -1 ? text.slice(7) : text.slice(7, spaceIndex);
|
|
542
584
|
const args = spaceIndex === -1 ? "" : text.slice(spaceIndex + 1).trim();
|
|
543
|
-
const skill = this.
|
|
585
|
+
const skill = this.resourceLoader.getSkills().skills.find((s) => s.name === skillName);
|
|
544
586
|
if (!skill)
|
|
545
587
|
return text; // Unknown skill, pass through
|
|
546
588
|
try {
|
|
547
589
|
const content = readFileSync(skill.filePath, "utf-8");
|
|
548
590
|
const body = stripFrontmatter(content).trim();
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
return args ? `${skillMessage}\n\n---\n\nUser: ${args}` : skillMessage;
|
|
591
|
+
const skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">\nReferences are relative to ${skill.baseDir}.\n\n${body}\n</skill>`;
|
|
592
|
+
return args ? `${skillBlock}\n\n${args}` : skillBlock;
|
|
552
593
|
}
|
|
553
594
|
catch (err) {
|
|
554
595
|
// Emit error like extension commands do
|
|
@@ -573,7 +614,7 @@ export class AgentSession {
|
|
|
573
614
|
}
|
|
574
615
|
// Expand skill commands and prompt templates
|
|
575
616
|
let expandedText = this._expandSkillCommand(text);
|
|
576
|
-
expandedText = expandPromptTemplate(expandedText, [...this.
|
|
617
|
+
expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
|
|
577
618
|
await this._queueSteer(expandedText);
|
|
578
619
|
}
|
|
579
620
|
/**
|
|
@@ -589,7 +630,7 @@ export class AgentSession {
|
|
|
589
630
|
}
|
|
590
631
|
// Expand skill commands and prompt templates
|
|
591
632
|
let expandedText = this._expandSkillCommand(text);
|
|
592
|
-
expandedText = expandPromptTemplate(expandedText, [...this.
|
|
633
|
+
expandedText = expandPromptTemplate(expandedText, [...this.promptTemplates]);
|
|
593
634
|
await this._queueFollowUp(expandedText);
|
|
594
635
|
}
|
|
595
636
|
/**
|
|
@@ -665,6 +706,8 @@ export class AgentSession {
|
|
|
665
706
|
else {
|
|
666
707
|
this.agent.appendMessage(appMessage);
|
|
667
708
|
this.sessionManager.appendCustomMessageEntry(message.customType, message.content, message.display, message.details);
|
|
709
|
+
this._emit({ type: "message_start", message: appMessage });
|
|
710
|
+
this._emit({ type: "message_end", message: appMessage });
|
|
668
711
|
}
|
|
669
712
|
}
|
|
670
713
|
/**
|
|
@@ -729,16 +772,8 @@ export class AgentSession {
|
|
|
729
772
|
getFollowUpMessages() {
|
|
730
773
|
return this._followUpMessages;
|
|
731
774
|
}
|
|
732
|
-
get
|
|
733
|
-
return this.
|
|
734
|
-
}
|
|
735
|
-
/** Skills loaded by SDK (empty if --no-skills or skills: [] was passed) */
|
|
736
|
-
get skills() {
|
|
737
|
-
return this._skills;
|
|
738
|
-
}
|
|
739
|
-
/** Skill loading warnings captured by SDK */
|
|
740
|
-
get skillWarnings() {
|
|
741
|
-
return this._skillWarnings;
|
|
775
|
+
get resourceLoader() {
|
|
776
|
+
return this._resourceLoader;
|
|
742
777
|
}
|
|
743
778
|
/**
|
|
744
779
|
* Abort current operation and wait for agent to become idle.
|
|
@@ -879,12 +914,6 @@ export class AgentSession {
|
|
|
879
914
|
await this._emitModelSelect(nextModel, currentModel, "cycle");
|
|
880
915
|
return { model: nextModel, thinkingLevel: this.thinkingLevel, isScoped: false };
|
|
881
916
|
}
|
|
882
|
-
/**
|
|
883
|
-
* Get all available models with valid API keys.
|
|
884
|
-
*/
|
|
885
|
-
async getAvailableModels() {
|
|
886
|
-
return this._modelRegistry.getAvailable();
|
|
887
|
-
}
|
|
888
917
|
// =========================================================================
|
|
889
918
|
// Thinking Level Management
|
|
890
919
|
// =========================================================================
|
|
@@ -1255,6 +1284,188 @@ export class AgentSession {
|
|
|
1255
1284
|
get autoCompactionEnabled() {
|
|
1256
1285
|
return this.settingsManager.getCompactionEnabled();
|
|
1257
1286
|
}
|
|
1287
|
+
async bindExtensions(bindings) {
|
|
1288
|
+
if (bindings.uiContext !== undefined) {
|
|
1289
|
+
this._extensionUIContext = bindings.uiContext;
|
|
1290
|
+
}
|
|
1291
|
+
if (bindings.commandContextActions !== undefined) {
|
|
1292
|
+
this._extensionCommandContextActions = bindings.commandContextActions;
|
|
1293
|
+
}
|
|
1294
|
+
if (bindings.shutdownHandler !== undefined) {
|
|
1295
|
+
this._extensionShutdownHandler = bindings.shutdownHandler;
|
|
1296
|
+
}
|
|
1297
|
+
if (bindings.onError !== undefined) {
|
|
1298
|
+
this._extensionErrorListener = bindings.onError;
|
|
1299
|
+
}
|
|
1300
|
+
if (this._extensionRunner) {
|
|
1301
|
+
this._applyExtensionBindings(this._extensionRunner);
|
|
1302
|
+
await this._extensionRunner.emit({ type: "session_start" });
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
_applyExtensionBindings(runner) {
|
|
1306
|
+
runner.setUIContext(this._extensionUIContext);
|
|
1307
|
+
runner.bindCommandContext(this._extensionCommandContextActions);
|
|
1308
|
+
this._extensionErrorUnsubscriber?.();
|
|
1309
|
+
this._extensionErrorUnsubscriber = this._extensionErrorListener
|
|
1310
|
+
? runner.onError(this._extensionErrorListener)
|
|
1311
|
+
: undefined;
|
|
1312
|
+
}
|
|
1313
|
+
_bindExtensionCore(runner) {
|
|
1314
|
+
runner.bindCore({
|
|
1315
|
+
sendMessage: (message, options) => {
|
|
1316
|
+
this.sendCustomMessage(message, options).catch((err) => {
|
|
1317
|
+
runner.emitError({
|
|
1318
|
+
extensionPath: "<runtime>",
|
|
1319
|
+
event: "send_message",
|
|
1320
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1321
|
+
});
|
|
1322
|
+
});
|
|
1323
|
+
},
|
|
1324
|
+
sendUserMessage: (content, options) => {
|
|
1325
|
+
this.sendUserMessage(content, options).catch((err) => {
|
|
1326
|
+
runner.emitError({
|
|
1327
|
+
extensionPath: "<runtime>",
|
|
1328
|
+
event: "send_user_message",
|
|
1329
|
+
error: err instanceof Error ? err.message : String(err),
|
|
1330
|
+
});
|
|
1331
|
+
});
|
|
1332
|
+
},
|
|
1333
|
+
appendEntry: (customType, data) => {
|
|
1334
|
+
this.sessionManager.appendCustomEntry(customType, data);
|
|
1335
|
+
},
|
|
1336
|
+
setSessionName: (name) => {
|
|
1337
|
+
this.sessionManager.appendSessionInfo(name);
|
|
1338
|
+
},
|
|
1339
|
+
getSessionName: () => {
|
|
1340
|
+
return this.sessionManager.getSessionName();
|
|
1341
|
+
},
|
|
1342
|
+
setLabel: (entryId, label) => {
|
|
1343
|
+
this.sessionManager.appendLabelChange(entryId, label);
|
|
1344
|
+
},
|
|
1345
|
+
getActiveTools: () => this.getActiveToolNames(),
|
|
1346
|
+
getAllTools: () => this.getAllTools(),
|
|
1347
|
+
setActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),
|
|
1348
|
+
setModel: async (model) => {
|
|
1349
|
+
const key = await this.modelRegistry.getApiKey(model);
|
|
1350
|
+
if (!key)
|
|
1351
|
+
return false;
|
|
1352
|
+
await this.setModel(model);
|
|
1353
|
+
return true;
|
|
1354
|
+
},
|
|
1355
|
+
getThinkingLevel: () => this.thinkingLevel,
|
|
1356
|
+
setThinkingLevel: (level) => this.setThinkingLevel(level),
|
|
1357
|
+
}, {
|
|
1358
|
+
getModel: () => this.model,
|
|
1359
|
+
isIdle: () => !this.isStreaming,
|
|
1360
|
+
abort: () => this.abort(),
|
|
1361
|
+
hasPendingMessages: () => this.pendingMessageCount > 0,
|
|
1362
|
+
shutdown: () => {
|
|
1363
|
+
this._extensionShutdownHandler?.();
|
|
1364
|
+
},
|
|
1365
|
+
getContextUsage: () => this.getContextUsage(),
|
|
1366
|
+
compact: (options) => {
|
|
1367
|
+
void (async () => {
|
|
1368
|
+
try {
|
|
1369
|
+
const result = await this.compact(options?.customInstructions);
|
|
1370
|
+
options?.onComplete?.(result);
|
|
1371
|
+
}
|
|
1372
|
+
catch (error) {
|
|
1373
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
1374
|
+
options?.onError?.(err);
|
|
1375
|
+
}
|
|
1376
|
+
})();
|
|
1377
|
+
},
|
|
1378
|
+
});
|
|
1379
|
+
}
|
|
1380
|
+
_buildRuntime(options) {
|
|
1381
|
+
const autoResizeImages = this.settingsManager.getImageAutoResize();
|
|
1382
|
+
const shellCommandPrefix = this.settingsManager.getShellCommandPrefix();
|
|
1383
|
+
const baseTools = this._baseToolsOverride
|
|
1384
|
+
? this._baseToolsOverride
|
|
1385
|
+
: createAllTools(this._cwd, {
|
|
1386
|
+
read: { autoResizeImages },
|
|
1387
|
+
bash: { commandPrefix: shellCommandPrefix },
|
|
1388
|
+
});
|
|
1389
|
+
this._baseToolRegistry = new Map(Object.entries(baseTools).map(([name, tool]) => [name, tool]));
|
|
1390
|
+
const extensionsResult = this._resourceLoader.getExtensions();
|
|
1391
|
+
if (options.flagValues) {
|
|
1392
|
+
for (const [name, value] of options.flagValues) {
|
|
1393
|
+
extensionsResult.runtime.flagValues.set(name, value);
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
const hasExtensions = extensionsResult.extensions.length > 0;
|
|
1397
|
+
const hasCustomTools = this._customTools.length > 0;
|
|
1398
|
+
this._extensionRunner =
|
|
1399
|
+
hasExtensions || hasCustomTools
|
|
1400
|
+
? new ExtensionRunner(extensionsResult.extensions, extensionsResult.runtime, this._cwd, this.sessionManager, this._modelRegistry)
|
|
1401
|
+
: undefined;
|
|
1402
|
+
if (this._extensionRunnerRef) {
|
|
1403
|
+
this._extensionRunnerRef.current = this._extensionRunner;
|
|
1404
|
+
}
|
|
1405
|
+
if (this._extensionRunner) {
|
|
1406
|
+
this._bindExtensionCore(this._extensionRunner);
|
|
1407
|
+
this._applyExtensionBindings(this._extensionRunner);
|
|
1408
|
+
}
|
|
1409
|
+
const registeredTools = this._extensionRunner?.getAllRegisteredTools() ?? [];
|
|
1410
|
+
const allCustomTools = [
|
|
1411
|
+
...registeredTools,
|
|
1412
|
+
...this._customTools.map((def) => ({ definition: def, extensionPath: "<sdk>" })),
|
|
1413
|
+
];
|
|
1414
|
+
const wrappedExtensionTools = this._extensionRunner
|
|
1415
|
+
? wrapRegisteredTools(allCustomTools, this._extensionRunner)
|
|
1416
|
+
: [];
|
|
1417
|
+
const toolRegistry = new Map(this._baseToolRegistry);
|
|
1418
|
+
for (const tool of wrappedExtensionTools) {
|
|
1419
|
+
toolRegistry.set(tool.name, tool);
|
|
1420
|
+
}
|
|
1421
|
+
const defaultActiveToolNames = this._baseToolsOverride
|
|
1422
|
+
? Object.keys(this._baseToolsOverride)
|
|
1423
|
+
: ["read", "bash", "edit", "write"];
|
|
1424
|
+
const baseActiveToolNames = options.activeToolNames ?? defaultActiveToolNames;
|
|
1425
|
+
const activeToolNameSet = new Set(baseActiveToolNames);
|
|
1426
|
+
if (options.includeAllExtensionTools) {
|
|
1427
|
+
for (const tool of wrappedExtensionTools) {
|
|
1428
|
+
activeToolNameSet.add(tool.name);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
const extensionToolNames = new Set(wrappedExtensionTools.map((tool) => tool.name));
|
|
1432
|
+
const activeBaseTools = Array.from(activeToolNameSet)
|
|
1433
|
+
.filter((name) => this._baseToolRegistry.has(name) && !extensionToolNames.has(name))
|
|
1434
|
+
.map((name) => this._baseToolRegistry.get(name));
|
|
1435
|
+
const activeExtensionTools = wrappedExtensionTools.filter((tool) => activeToolNameSet.has(tool.name));
|
|
1436
|
+
const activeToolsArray = [...activeBaseTools, ...activeExtensionTools];
|
|
1437
|
+
if (this._extensionRunner) {
|
|
1438
|
+
const wrappedActiveTools = wrapToolsWithExtensions(activeToolsArray, this._extensionRunner);
|
|
1439
|
+
this.agent.setTools(wrappedActiveTools);
|
|
1440
|
+
const wrappedAllTools = wrapToolsWithExtensions(Array.from(toolRegistry.values()), this._extensionRunner);
|
|
1441
|
+
this._toolRegistry = new Map(wrappedAllTools.map((tool) => [tool.name, tool]));
|
|
1442
|
+
}
|
|
1443
|
+
else {
|
|
1444
|
+
this.agent.setTools(activeToolsArray);
|
|
1445
|
+
this._toolRegistry = toolRegistry;
|
|
1446
|
+
}
|
|
1447
|
+
const systemPromptToolNames = Array.from(activeToolNameSet).filter((name) => this._baseToolRegistry.has(name));
|
|
1448
|
+
this._baseSystemPrompt = this._rebuildSystemPrompt(systemPromptToolNames);
|
|
1449
|
+
this.agent.setSystemPrompt(this._baseSystemPrompt);
|
|
1450
|
+
}
|
|
1451
|
+
async reload() {
|
|
1452
|
+
const previousFlagValues = this._extensionRunner?.getFlagValues();
|
|
1453
|
+
await this._extensionRunner?.emit({ type: "session_shutdown" });
|
|
1454
|
+
resetApiProviders();
|
|
1455
|
+
await this._resourceLoader.reload();
|
|
1456
|
+
this._buildRuntime({
|
|
1457
|
+
activeToolNames: this.getActiveToolNames(),
|
|
1458
|
+
flagValues: previousFlagValues,
|
|
1459
|
+
includeAllExtensionTools: true,
|
|
1460
|
+
});
|
|
1461
|
+
const hasBindings = this._extensionUIContext ||
|
|
1462
|
+
this._extensionCommandContextActions ||
|
|
1463
|
+
this._extensionShutdownHandler ||
|
|
1464
|
+
this._extensionErrorListener;
|
|
1465
|
+
if (this._extensionRunner && hasBindings) {
|
|
1466
|
+
await this._extensionRunner.emit({ type: "session_start" });
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1258
1469
|
// =========================================================================
|
|
1259
1470
|
// Auto-Retry
|
|
1260
1471
|
// =========================================================================
|
|
@@ -1270,8 +1481,8 @@ export class AgentSession {
|
|
|
1270
1481
|
if (isContextOverflow(message, contextWindow))
|
|
1271
1482
|
return false;
|
|
1272
1483
|
const err = message.errorMessage;
|
|
1273
|
-
// Match: overloaded_error, rate limit, 429, 500, 502, 503, 504, service unavailable, connection errors, fetch failed
|
|
1274
|
-
return /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers/i.test(err);
|
|
1484
|
+
// Match: overloaded_error, rate limit, 429, 500, 502, 503, 504, service unavailable, connection errors, fetch failed, terminated
|
|
1485
|
+
return /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated/i.test(err);
|
|
1275
1486
|
}
|
|
1276
1487
|
/**
|
|
1277
1488
|
* Handle retryable errors with exponential backoff.
|
|
@@ -1316,7 +1527,7 @@ export class AgentSession {
|
|
|
1316
1527
|
// Wait with exponential backoff (abortable)
|
|
1317
1528
|
this._retryAbortController = new AbortController();
|
|
1318
1529
|
try {
|
|
1319
|
-
await
|
|
1530
|
+
await sleep(delayMs, this._retryAbortController.signal);
|
|
1320
1531
|
}
|
|
1321
1532
|
catch {
|
|
1322
1533
|
// Aborted during sleep - emit end event so UI can clean up
|
|
@@ -1341,22 +1552,6 @@ export class AgentSession {
|
|
|
1341
1552
|
}, 0);
|
|
1342
1553
|
return true;
|
|
1343
1554
|
}
|
|
1344
|
-
/**
|
|
1345
|
-
* Sleep helper that respects abort signal.
|
|
1346
|
-
*/
|
|
1347
|
-
_sleep(ms, signal) {
|
|
1348
|
-
return new Promise((resolve, reject) => {
|
|
1349
|
-
if (signal?.aborted) {
|
|
1350
|
-
reject(new Error("Aborted"));
|
|
1351
|
-
return;
|
|
1352
|
-
}
|
|
1353
|
-
const timeout = setTimeout(resolve, ms);
|
|
1354
|
-
signal?.addEventListener("abort", () => {
|
|
1355
|
-
clearTimeout(timeout);
|
|
1356
|
-
reject(new Error("Aborted"));
|
|
1357
|
-
});
|
|
1358
|
-
});
|
|
1359
|
-
}
|
|
1360
1555
|
/**
|
|
1361
1556
|
* Cancel in-progress retry.
|
|
1362
1557
|
*/
|