@mariozechner/pi-coding-agent 0.64.0 → 0.65.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 +12 -6
- package/dist/cli/args.d.ts +7 -4
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +37 -15
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +83 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -0
- package/dist/core/agent-session-runtime.js +236 -0
- package/dist/core/agent-session-runtime.js.map +1 -0
- package/dist/core/agent-session-services.d.ts +86 -0
- package/dist/core/agent-session-services.d.ts.map +1 -0
- package/dist/core/agent-session-services.js +116 -0
- package/dist/core/agent-session-services.js.map +1 -0
- package/dist/core/agent-session.d.ts +5 -42
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +46 -237
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +19 -7
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts +2 -0
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +2 -2
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/types.d.ts +16 -28
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +10 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +5 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +70 -8
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +14 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +13 -14
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/package-manager.d.ts +20 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +55 -9
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +25 -3
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +4 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +4 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-cwd.d.ts +19 -0
- package/dist/core/session-cwd.d.ts.map +1 -0
- package/dist/core/session-cwd.js +38 -0
- package/dist/core/session-cwd.js.map +1 -0
- package/dist/core/session-manager.d.ts +5 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +16 -8
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +2 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +19 -9
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +245 -426
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +20 -0
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -0
- 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/tree-selector.d.ts +4 -2
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +48 -15
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +10 -4
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +160 -94
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +15 -11
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts +2 -2
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +41 -36
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +1 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +2 -2
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +92 -64
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts +4 -0
- package/dist/package-manager-cli.d.ts.map +1 -0
- package/dist/package-manager-cli.js +234 -0
- package/dist/package-manager-cli.js.map +1 -0
- package/dist/utils/paths.d.ts +7 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +19 -0
- package/dist/utils/paths.js.map +1 -0
- package/docs/extensions.md +72 -40
- package/docs/keybindings.md +2 -0
- package/docs/sdk.md +227 -74
- package/docs/settings.md +1 -1
- package/docs/tree.md +6 -3
- 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/package.json +1 -1
- package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
- package/examples/extensions/doom-overlay/doom/build.sh +2 -2
- package/examples/extensions/hello.ts +18 -17
- package/examples/extensions/hidden-thinking-label.ts +0 -4
- package/examples/extensions/rpc-demo.ts +3 -9
- package/examples/extensions/status-line.ts +0 -8
- package/examples/extensions/todo.ts +0 -2
- package/examples/extensions/tools.ts +0 -5
- package/examples/extensions/widget-placement.ts +4 -12
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/13-session-runtime.ts +67 -0
- package/examples/sdk/README.md +4 -1
- package/package.json +4 -4
|
@@ -15,6 +15,7 @@ import { KeybindingsManager } from "../../core/keybindings.js";
|
|
|
15
15
|
import { createCompactionSummaryMessage } from "../../core/messages.js";
|
|
16
16
|
import { findExactModelReferenceMatch, resolveModelScope } from "../../core/model-resolver.js";
|
|
17
17
|
import { DefaultPackageManager } from "../../core/package-manager.js";
|
|
18
|
+
import { formatMissingSessionCwdPrompt, MissingSessionCwdError } from "../../core/session-cwd.js";
|
|
18
19
|
import { SessionManager } from "../../core/session-manager.js";
|
|
19
20
|
import { BUILTIN_SLASH_COMMANDS } from "../../core/slash-commands.js";
|
|
20
21
|
import { getChangelogPath, getNewEntries, parseChangelog } from "../../utils/changelog.js";
|
|
@@ -48,13 +49,13 @@ import { ToolExecutionComponent } from "./components/tool-execution.js";
|
|
|
48
49
|
import { TreeSelectorComponent } from "./components/tree-selector.js";
|
|
49
50
|
import { UserMessageComponent } from "./components/user-message.js";
|
|
50
51
|
import { UserMessageSelectorComponent } from "./components/user-message-selector.js";
|
|
51
|
-
import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, initTheme, onThemeChange, setRegisteredThemes, setTheme, setThemeInstance, Theme, theme, } from "./theme/theme.js";
|
|
52
|
+
import { getAvailableThemes, getAvailableThemesWithPaths, getEditorTheme, getMarkdownTheme, getThemeByName, initTheme, onThemeChange, setRegisteredThemes, setTheme, setThemeInstance, stopThemeWatcher, Theme, theme, } from "./theme/theme.js";
|
|
52
53
|
function isExpandable(obj) {
|
|
53
54
|
return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
|
|
54
55
|
}
|
|
55
56
|
export class InteractiveMode {
|
|
56
57
|
options;
|
|
57
|
-
|
|
58
|
+
runtimeHost;
|
|
58
59
|
ui;
|
|
59
60
|
chatContainer;
|
|
60
61
|
pendingMessagesContainer;
|
|
@@ -130,6 +131,9 @@ export class InteractiveMode {
|
|
|
130
131
|
// Custom header from extension (undefined = use built-in header)
|
|
131
132
|
customHeader = undefined;
|
|
132
133
|
// Convenience accessors
|
|
134
|
+
get session() {
|
|
135
|
+
return this.runtimeHost.session;
|
|
136
|
+
}
|
|
133
137
|
get agent() {
|
|
134
138
|
return this.session.agent;
|
|
135
139
|
}
|
|
@@ -139,9 +143,9 @@ export class InteractiveMode {
|
|
|
139
143
|
get settingsManager() {
|
|
140
144
|
return this.session.settingsManager;
|
|
141
145
|
}
|
|
142
|
-
constructor(
|
|
146
|
+
constructor(runtimeHost, options = {}) {
|
|
143
147
|
this.options = options;
|
|
144
|
-
this.
|
|
148
|
+
this.runtimeHost = runtimeHost;
|
|
145
149
|
this.version = VERSION;
|
|
146
150
|
this.ui = new TUI(new ProcessTerminal(), this.settingsManager.getShowHardwareCursor());
|
|
147
151
|
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
|
@@ -162,9 +166,9 @@ export class InteractiveMode {
|
|
|
162
166
|
this.editor = this.defaultEditor;
|
|
163
167
|
this.editorContainer = new Container();
|
|
164
168
|
this.editorContainer.addChild(this.editor);
|
|
165
|
-
this.footerDataProvider = new FooterDataProvider();
|
|
166
|
-
this.footer = new FooterComponent(session, this.footerDataProvider);
|
|
167
|
-
this.footer.setAutoCompactEnabled(session.autoCompactionEnabled);
|
|
169
|
+
this.footerDataProvider = new FooterDataProvider(this.sessionManager.getCwd());
|
|
170
|
+
this.footer = new FooterComponent(this.session, this.footerDataProvider);
|
|
171
|
+
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
168
172
|
// Load hide thinking block setting
|
|
169
173
|
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
|
170
174
|
// Register themes from resource loader and initialize
|
|
@@ -271,7 +275,7 @@ export class InteractiveMode {
|
|
|
271
275
|
}
|
|
272
276
|
}
|
|
273
277
|
// Setup autocomplete
|
|
274
|
-
this.autocompleteProvider = new CombinedAutocompleteProvider([...slashCommands, ...templateCommands, ...extensionCommands, ...skillCommandList],
|
|
278
|
+
this.autocompleteProvider = new CombinedAutocompleteProvider([...slashCommands, ...templateCommands, ...extensionCommands, ...skillCommandList], this.sessionManager.getCwd(), fdPath);
|
|
275
279
|
this.defaultEditor.setAutocompleteProvider(this.autocompleteProvider);
|
|
276
280
|
if (this.editor !== this.defaultEditor) {
|
|
277
281
|
this.editor.setAutocompleteProvider?.(this.autocompleteProvider);
|
|
@@ -366,7 +370,7 @@ export class InteractiveMode {
|
|
|
366
370
|
this.ui.start();
|
|
367
371
|
this.isInitialized = true;
|
|
368
372
|
// Initialize extensions first so resources are shown before messages
|
|
369
|
-
await this.
|
|
373
|
+
await this.bindCurrentSessionExtensions();
|
|
370
374
|
// Render initial messages AFTER showing loaded resources
|
|
371
375
|
this.renderInitialMessages();
|
|
372
376
|
// Set terminal title
|
|
@@ -390,7 +394,7 @@ export class InteractiveMode {
|
|
|
390
394
|
* Update terminal title with session name and cwd.
|
|
391
395
|
*/
|
|
392
396
|
updateTerminalTitle() {
|
|
393
|
-
const cwdBasename = path.basename(
|
|
397
|
+
const cwdBasename = path.basename(this.sessionManager.getCwd());
|
|
394
398
|
const sessionName = this.sessionManager.getSessionName();
|
|
395
399
|
if (sessionName) {
|
|
396
400
|
this.ui.terminal.setTitle(`π - ${sessionName} - ${cwdBasename}`);
|
|
@@ -497,7 +501,7 @@ export class InteractiveMode {
|
|
|
497
501
|
}
|
|
498
502
|
try {
|
|
499
503
|
const packageManager = new DefaultPackageManager({
|
|
500
|
-
cwd:
|
|
504
|
+
cwd: this.sessionManager.getCwd(),
|
|
501
505
|
agentDir: getAgentDir(),
|
|
502
506
|
settingsManager: this.settingsManager,
|
|
503
507
|
});
|
|
@@ -885,7 +889,7 @@ export class InteractiveMode {
|
|
|
885
889
|
/**
|
|
886
890
|
* Initialize the extension system with TUI-based UI context.
|
|
887
891
|
*/
|
|
888
|
-
async
|
|
892
|
+
async bindCurrentSessionExtensions() {
|
|
889
893
|
const uiContext = this.createExtensionUIContext();
|
|
890
894
|
await this.session.bindExtensions({
|
|
891
895
|
uiContext,
|
|
@@ -897,33 +901,33 @@ export class InteractiveMode {
|
|
|
897
901
|
this.loadingAnimation = undefined;
|
|
898
902
|
}
|
|
899
903
|
this.statusContainer.clear();
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
+
try {
|
|
905
|
+
const result = await this.runtimeHost.newSession(options);
|
|
906
|
+
if (!result.cancelled) {
|
|
907
|
+
await this.handleRuntimeSessionChange();
|
|
908
|
+
this.renderCurrentSessionState();
|
|
909
|
+
this.ui.requestRender();
|
|
910
|
+
}
|
|
911
|
+
return result;
|
|
912
|
+
}
|
|
913
|
+
catch (error) {
|
|
914
|
+
return this.handleFatalRuntimeError("Failed to create session", error);
|
|
904
915
|
}
|
|
905
|
-
// Clear UI state
|
|
906
|
-
this.chatContainer.clear();
|
|
907
|
-
this.pendingMessagesContainer.clear();
|
|
908
|
-
this.compactionQueuedMessages = [];
|
|
909
|
-
this.streamingComponent = undefined;
|
|
910
|
-
this.streamingMessage = undefined;
|
|
911
|
-
this.pendingTools.clear();
|
|
912
|
-
// Render any messages added via setup, or show empty session
|
|
913
|
-
this.renderInitialMessages();
|
|
914
|
-
this.ui.requestRender();
|
|
915
|
-
return { cancelled: false };
|
|
916
916
|
},
|
|
917
917
|
fork: async (entryId) => {
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
918
|
+
try {
|
|
919
|
+
const result = await this.runtimeHost.fork(entryId);
|
|
920
|
+
if (!result.cancelled) {
|
|
921
|
+
await this.handleRuntimeSessionChange();
|
|
922
|
+
this.renderCurrentSessionState();
|
|
923
|
+
this.editor.setText(result.selectedText ?? "");
|
|
924
|
+
this.showStatus("Forked to new session");
|
|
925
|
+
}
|
|
926
|
+
return { cancelled: result.cancelled };
|
|
927
|
+
}
|
|
928
|
+
catch (error) {
|
|
929
|
+
return this.handleFatalRuntimeError("Failed to fork session", error);
|
|
921
930
|
}
|
|
922
|
-
this.chatContainer.clear();
|
|
923
|
-
this.renderInitialMessages();
|
|
924
|
-
this.editor.setText(result.selectedText);
|
|
925
|
-
this.showStatus("Forked to new session");
|
|
926
|
-
return { cancelled: false };
|
|
927
931
|
},
|
|
928
932
|
navigateTree: async (targetId, options) => {
|
|
929
933
|
const result = await this.session.navigateTree(targetId, {
|
|
@@ -971,6 +975,49 @@ export class InteractiveMode {
|
|
|
971
975
|
this.setupExtensionShortcuts(extensionRunner);
|
|
972
976
|
this.showLoadedResources({ force: false });
|
|
973
977
|
}
|
|
978
|
+
applyRuntimeSettings() {
|
|
979
|
+
this.footer.setSession(this.session);
|
|
980
|
+
this.footer.setAutoCompactEnabled(this.session.autoCompactionEnabled);
|
|
981
|
+
this.footerDataProvider.setCwd(this.sessionManager.getCwd());
|
|
982
|
+
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
|
983
|
+
this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
|
|
984
|
+
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
|
985
|
+
const editorPaddingX = this.settingsManager.getEditorPaddingX();
|
|
986
|
+
const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
|
|
987
|
+
this.defaultEditor.setPaddingX(editorPaddingX);
|
|
988
|
+
this.defaultEditor.setAutocompleteMaxVisible(autocompleteMaxVisible);
|
|
989
|
+
if (this.editor !== this.defaultEditor) {
|
|
990
|
+
this.editor.setPaddingX?.(editorPaddingX);
|
|
991
|
+
this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
async handleRuntimeSessionChange() {
|
|
995
|
+
this.resetExtensionUI();
|
|
996
|
+
this.unsubscribe?.();
|
|
997
|
+
this.unsubscribe = undefined;
|
|
998
|
+
this.applyRuntimeSettings();
|
|
999
|
+
await this.bindCurrentSessionExtensions();
|
|
1000
|
+
this.subscribeToAgent();
|
|
1001
|
+
await this.updateAvailableProviderCount();
|
|
1002
|
+
this.updateEditorBorderColor();
|
|
1003
|
+
this.updateTerminalTitle();
|
|
1004
|
+
}
|
|
1005
|
+
async handleFatalRuntimeError(prefix, error) {
|
|
1006
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1007
|
+
this.showError(`${prefix}: ${message}`);
|
|
1008
|
+
stopThemeWatcher();
|
|
1009
|
+
this.stop();
|
|
1010
|
+
process.exit(1);
|
|
1011
|
+
}
|
|
1012
|
+
renderCurrentSessionState() {
|
|
1013
|
+
this.chatContainer.clear();
|
|
1014
|
+
this.pendingMessagesContainer.clear();
|
|
1015
|
+
this.compactionQueuedMessages = [];
|
|
1016
|
+
this.streamingComponent = undefined;
|
|
1017
|
+
this.streamingMessage = undefined;
|
|
1018
|
+
this.pendingTools.clear();
|
|
1019
|
+
this.renderInitialMessages();
|
|
1020
|
+
}
|
|
974
1021
|
/**
|
|
975
1022
|
* Get a registered tool definition by name (for custom rendering).
|
|
976
1023
|
*/
|
|
@@ -988,7 +1035,7 @@ export class InteractiveMode {
|
|
|
988
1035
|
const createContext = () => ({
|
|
989
1036
|
ui: this.createExtensionUIContext(),
|
|
990
1037
|
hasUI: true,
|
|
991
|
-
cwd:
|
|
1038
|
+
cwd: this.sessionManager.getCwd(),
|
|
992
1039
|
sessionManager: this.sessionManager,
|
|
993
1040
|
modelRegistry: this.session.modelRegistry,
|
|
994
1041
|
model: this.session.model,
|
|
@@ -1331,6 +1378,10 @@ export class InteractiveMode {
|
|
|
1331
1378
|
const result = await this.showExtensionSelector(`${title}\n${message}`, ["Yes", "No"], opts);
|
|
1332
1379
|
return result === "Yes";
|
|
1333
1380
|
}
|
|
1381
|
+
async promptForMissingSessionCwd(error) {
|
|
1382
|
+
const confirmed = await this.showExtensionConfirm("Session cwd not found", formatMissingSessionCwdPrompt(error.issue));
|
|
1383
|
+
return confirmed ? error.issue.fallbackCwd : undefined;
|
|
1384
|
+
}
|
|
1334
1385
|
/**
|
|
1335
1386
|
* Show a text input for extensions.
|
|
1336
1387
|
*/
|
|
@@ -1884,7 +1935,7 @@ export class InteractiveMode {
|
|
|
1884
1935
|
if (!this.pendingTools.has(content.id)) {
|
|
1885
1936
|
const component = new ToolExecutionComponent(content.name, content.id, content.arguments, {
|
|
1886
1937
|
showImages: this.settingsManager.getShowImages(),
|
|
1887
|
-
}, this.getRegisteredToolDefinition(content.name), this.ui);
|
|
1938
|
+
}, this.getRegisteredToolDefinition(content.name), this.ui, this.sessionManager.getCwd());
|
|
1888
1939
|
component.setExpanded(this.toolOutputExpanded);
|
|
1889
1940
|
this.chatContainer.addChild(component);
|
|
1890
1941
|
this.pendingTools.set(content.id, component);
|
|
@@ -1944,7 +1995,7 @@ export class InteractiveMode {
|
|
|
1944
1995
|
if (!component) {
|
|
1945
1996
|
component = new ToolExecutionComponent(event.toolName, event.toolCallId, event.args, {
|
|
1946
1997
|
showImages: this.settingsManager.getShowImages(),
|
|
1947
|
-
}, this.getRegisteredToolDefinition(event.toolName), this.ui);
|
|
1998
|
+
}, this.getRegisteredToolDefinition(event.toolName), this.ui, this.sessionManager.getCwd());
|
|
1948
1999
|
component.setExpanded(this.toolOutputExpanded);
|
|
1949
2000
|
this.chatContainer.addChild(component);
|
|
1950
2001
|
this.pendingTools.set(event.toolCallId, component);
|
|
@@ -2198,7 +2249,7 @@ export class InteractiveMode {
|
|
|
2198
2249
|
// Render tool call components
|
|
2199
2250
|
for (const content of message.content) {
|
|
2200
2251
|
if (content.type === "toolCall") {
|
|
2201
|
-
const component = new ToolExecutionComponent(content.name, content.id, content.arguments, { showImages: this.settingsManager.getShowImages() }, this.getRegisteredToolDefinition(content.name), this.ui);
|
|
2252
|
+
const component = new ToolExecutionComponent(content.name, content.id, content.arguments, { showImages: this.settingsManager.getShowImages() }, this.getRegisteredToolDefinition(content.name), this.ui, this.sessionManager.getCwd());
|
|
2202
2253
|
component.setExpanded(this.toolOutputExpanded);
|
|
2203
2254
|
this.chatContainer.addChild(component);
|
|
2204
2255
|
if (message.stopReason === "aborted" || message.stopReason === "error") {
|
|
@@ -2291,13 +2342,7 @@ export class InteractiveMode {
|
|
|
2291
2342
|
if (this.isShuttingDown)
|
|
2292
2343
|
return;
|
|
2293
2344
|
this.isShuttingDown = true;
|
|
2294
|
-
|
|
2295
|
-
const extensionRunner = this.session.extensionRunner;
|
|
2296
|
-
if (extensionRunner?.hasHandlers("session_shutdown")) {
|
|
2297
|
-
await extensionRunner.emit({
|
|
2298
|
-
type: "session_shutdown",
|
|
2299
|
-
});
|
|
2300
|
-
}
|
|
2345
|
+
await this.runtimeHost.dispose();
|
|
2301
2346
|
// Wait for any pending renders to complete
|
|
2302
2347
|
// requestRender() uses process.nextTick(), so we wait one tick
|
|
2303
2348
|
await new Promise((resolve) => process.nextTick(resolve));
|
|
@@ -2767,7 +2812,7 @@ export class InteractiveMode {
|
|
|
2767
2812
|
},
|
|
2768
2813
|
onTransportChange: (transport) => {
|
|
2769
2814
|
this.settingsManager.setTransport(transport);
|
|
2770
|
-
this.session.agent.
|
|
2815
|
+
this.session.agent.transport = transport;
|
|
2771
2816
|
},
|
|
2772
2817
|
onThinkingLevelChange: (level) => {
|
|
2773
2818
|
this.session.setThinkingLevel(level);
|
|
@@ -3023,16 +3068,15 @@ export class InteractiveMode {
|
|
|
3023
3068
|
}
|
|
3024
3069
|
this.showSelector((done) => {
|
|
3025
3070
|
const selector = new UserMessageSelectorComponent(userMessages.map((m) => ({ id: m.entryId, text: m.text })), async (entryId) => {
|
|
3026
|
-
const result = await this.
|
|
3071
|
+
const result = await this.runtimeHost.fork(entryId);
|
|
3027
3072
|
if (result.cancelled) {
|
|
3028
|
-
// Extension cancelled the fork
|
|
3029
3073
|
done();
|
|
3030
3074
|
this.ui.requestRender();
|
|
3031
3075
|
return;
|
|
3032
3076
|
}
|
|
3033
|
-
this.
|
|
3034
|
-
this.
|
|
3035
|
-
this.editor.setText(result.selectedText);
|
|
3077
|
+
await this.handleRuntimeSessionChange();
|
|
3078
|
+
this.renderCurrentSessionState();
|
|
3079
|
+
this.editor.setText(result.selectedText ?? "");
|
|
3036
3080
|
done();
|
|
3037
3081
|
this.showStatus("Branched to new session");
|
|
3038
3082
|
}, () => {
|
|
@@ -3168,24 +3212,38 @@ export class InteractiveMode {
|
|
|
3168
3212
|
});
|
|
3169
3213
|
}
|
|
3170
3214
|
async handleResumeSession(sessionPath) {
|
|
3171
|
-
// Stop loading animation
|
|
3172
3215
|
if (this.loadingAnimation) {
|
|
3173
3216
|
this.loadingAnimation.stop();
|
|
3174
3217
|
this.loadingAnimation = undefined;
|
|
3175
3218
|
}
|
|
3176
3219
|
this.statusContainer.clear();
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3220
|
+
try {
|
|
3221
|
+
const result = await this.runtimeHost.switchSession(sessionPath);
|
|
3222
|
+
if (result.cancelled) {
|
|
3223
|
+
return;
|
|
3224
|
+
}
|
|
3225
|
+
await this.handleRuntimeSessionChange();
|
|
3226
|
+
this.renderCurrentSessionState();
|
|
3227
|
+
this.showStatus("Resumed session");
|
|
3228
|
+
}
|
|
3229
|
+
catch (error) {
|
|
3230
|
+
if (error instanceof MissingSessionCwdError) {
|
|
3231
|
+
const selectedCwd = await this.promptForMissingSessionCwd(error);
|
|
3232
|
+
if (!selectedCwd) {
|
|
3233
|
+
this.showStatus("Resume cancelled");
|
|
3234
|
+
return;
|
|
3235
|
+
}
|
|
3236
|
+
const result = await this.runtimeHost.switchSession(sessionPath, selectedCwd);
|
|
3237
|
+
if (result.cancelled) {
|
|
3238
|
+
return;
|
|
3239
|
+
}
|
|
3240
|
+
await this.handleRuntimeSessionChange();
|
|
3241
|
+
this.renderCurrentSessionState();
|
|
3242
|
+
this.showStatus("Resumed session in current cwd");
|
|
3243
|
+
return;
|
|
3244
|
+
}
|
|
3245
|
+
await this.handleFatalRuntimeError("Failed to resume session", error);
|
|
3246
|
+
}
|
|
3189
3247
|
}
|
|
3190
3248
|
async showOAuthSelector(mode) {
|
|
3191
3249
|
if (mode === "logout") {
|
|
@@ -3403,30 +3461,38 @@ export class InteractiveMode {
|
|
|
3403
3461
|
return;
|
|
3404
3462
|
}
|
|
3405
3463
|
try {
|
|
3406
|
-
// Stop loading animation
|
|
3407
3464
|
if (this.loadingAnimation) {
|
|
3408
3465
|
this.loadingAnimation.stop();
|
|
3409
3466
|
this.loadingAnimation = undefined;
|
|
3410
3467
|
}
|
|
3411
3468
|
this.statusContainer.clear();
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
this.streamingComponent = undefined;
|
|
3416
|
-
this.streamingMessage = undefined;
|
|
3417
|
-
this.pendingTools.clear();
|
|
3418
|
-
const success = await this.session.importFromJsonl(inputPath);
|
|
3419
|
-
if (!success) {
|
|
3420
|
-
this.showWarning("Import cancelled");
|
|
3469
|
+
const result = await this.runtimeHost.importFromJsonl(inputPath);
|
|
3470
|
+
if (result.cancelled) {
|
|
3471
|
+
this.showStatus("Import cancelled");
|
|
3421
3472
|
return;
|
|
3422
3473
|
}
|
|
3423
|
-
|
|
3424
|
-
this.
|
|
3425
|
-
this.renderInitialMessages();
|
|
3474
|
+
await this.handleRuntimeSessionChange();
|
|
3475
|
+
this.renderCurrentSessionState();
|
|
3426
3476
|
this.showStatus(`Session imported from: ${inputPath}`);
|
|
3427
3477
|
}
|
|
3428
3478
|
catch (error) {
|
|
3429
|
-
|
|
3479
|
+
if (error instanceof MissingSessionCwdError) {
|
|
3480
|
+
const selectedCwd = await this.promptForMissingSessionCwd(error);
|
|
3481
|
+
if (!selectedCwd) {
|
|
3482
|
+
this.showStatus("Import cancelled");
|
|
3483
|
+
return;
|
|
3484
|
+
}
|
|
3485
|
+
const result = await this.runtimeHost.importFromJsonl(inputPath, selectedCwd);
|
|
3486
|
+
if (result.cancelled) {
|
|
3487
|
+
this.showStatus("Import cancelled");
|
|
3488
|
+
return;
|
|
3489
|
+
}
|
|
3490
|
+
await this.handleRuntimeSessionChange();
|
|
3491
|
+
this.renderCurrentSessionState();
|
|
3492
|
+
this.showStatus(`Session imported from: ${inputPath}`);
|
|
3493
|
+
return;
|
|
3494
|
+
}
|
|
3495
|
+
await this.handleFatalRuntimeError("Failed to import session", error);
|
|
3430
3496
|
}
|
|
3431
3497
|
}
|
|
3432
3498
|
async handleShareCommand() {
|
|
@@ -3736,25 +3802,25 @@ export class InteractiveMode {
|
|
|
3736
3802
|
this.ui.requestRender();
|
|
3737
3803
|
}
|
|
3738
3804
|
async handleClearCommand() {
|
|
3739
|
-
// Stop loading animation
|
|
3740
3805
|
if (this.loadingAnimation) {
|
|
3741
3806
|
this.loadingAnimation.stop();
|
|
3742
3807
|
this.loadingAnimation = undefined;
|
|
3743
3808
|
}
|
|
3744
3809
|
this.statusContainer.clear();
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3810
|
+
try {
|
|
3811
|
+
const result = await this.runtimeHost.newSession();
|
|
3812
|
+
if (result.cancelled) {
|
|
3813
|
+
return;
|
|
3814
|
+
}
|
|
3815
|
+
await this.handleRuntimeSessionChange();
|
|
3816
|
+
this.renderCurrentSessionState();
|
|
3817
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
3818
|
+
this.chatContainer.addChild(new Text(`${theme.fg("accent", "✓ New session started")}`, 1, 1));
|
|
3819
|
+
this.ui.requestRender();
|
|
3820
|
+
}
|
|
3821
|
+
catch (error) {
|
|
3822
|
+
await this.handleFatalRuntimeError("Failed to create session", error);
|
|
3823
|
+
}
|
|
3758
3824
|
}
|
|
3759
3825
|
handleDebugCommand() {
|
|
3760
3826
|
const width = this.ui.terminal.columns;
|
|
@@ -3806,7 +3872,7 @@ export class InteractiveMode {
|
|
|
3806
3872
|
type: "user_bash",
|
|
3807
3873
|
command,
|
|
3808
3874
|
excludeFromContext,
|
|
3809
|
-
cwd:
|
|
3875
|
+
cwd: this.sessionManager.getCwd(),
|
|
3810
3876
|
})
|
|
3811
3877
|
: undefined;
|
|
3812
3878
|
// If extension returned a full result, use it directly
|