@codex-infinity/pi-infinity 0.60.1 → 0.61.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 +45 -0
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js +1 -0
- package/dist/bun/cli.js.map +1 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.js.map +1 -1
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +2 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +14 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +107 -72
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.js +4 -8
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/event-bus.js.map +1 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +7 -3
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/ansi-to-html.js.map +1 -1
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.css +43 -13
- package/dist/core/export-html/template.html +1 -0
- package/dist/core/export-html/template.js +107 -0
- package/dist/core/export-html/tool-renderer.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/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +4 -4
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +62 -56
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +4 -3
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.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 +92 -20
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +268 -51
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +220 -143
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-registry.d.ts +1 -0
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +29 -21
- 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 +4 -4
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.js +0 -6
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.js +0 -37
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +2 -2
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +4 -4
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +5 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +8 -12
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.js +7 -16
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +2 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +12 -10
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +3 -2
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts +6 -0
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -0
- package/dist/core/tools/file-mutation-queue.js +37 -0
- package/dist/core/tools/file-mutation-queue.js.map +1 -0
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/truncate.js.map +1 -1
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +6 -3
- package/dist/core/tools/write.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +10 -5
- package/dist/main.js.map +1 -1
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/armin.js +6 -10
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +0 -4
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +8 -14
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +1 -4
- package/dist/modes/interactive/components/bordered-loader.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 +3 -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 +3 -5
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +14 -23
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +0 -5
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +7 -14
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -6
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/daxnuts.js +6 -8
- package/dist/modes/interactive/components/daxnuts.js.map +1 -1
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +0 -1
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +10 -15
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +7 -13
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +9 -16
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.js +1 -3
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts +3 -36
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +5 -44
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +9 -15
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +20 -28
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +8 -13
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +13 -17
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +65 -93
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +0 -2
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +0 -1
- package/dist/modes/interactive/components/show-images-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 +3 -5
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +0 -2
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +0 -1
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +7 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +57 -28
- 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 +32 -46
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +9 -12
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +210 -170
- 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 +49 -42
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/jsonl.js.map +1 -1
- package/dist/modes/rpc/rpc-client.js +6 -7
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +4 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/child-process.d.ts +11 -0
- package/dist/utils/child-process.d.ts.map +1 -0
- package/dist/utils/child-process.js +78 -0
- package/dist/utils/child-process.js.map +1 -0
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +1 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +11 -1
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/photon.js.map +1 -1
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/sleep.js.map +1 -1
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/extensions.md +42 -5
- package/docs/keybindings.md +101 -112
- package/examples/extensions/antigravity-image-gen.ts +5 -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/subagent/index.ts +7 -5
- package/examples/extensions/tool-override.ts +9 -7
- package/examples/extensions/truncated-tool.ts +6 -3
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +4 -4
|
@@ -6,7 +6,7 @@ import * as crypto from "node:crypto";
|
|
|
6
6
|
import * as fs from "node:fs";
|
|
7
7
|
import * as os from "node:os";
|
|
8
8
|
import * as path from "node:path";
|
|
9
|
-
import { CombinedAutocompleteProvider, Container, fuzzyFilter, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, Text, TruncatedText, TUI, visibleWidth, } from "@mariozechner/pi-tui";
|
|
9
|
+
import { CombinedAutocompleteProvider, Container, fuzzyFilter, Loader, Markdown, matchesKey, ProcessTerminal, Spacer, setKeybindings, Text, TruncatedText, TUI, visibleWidth, } from "@mariozechner/pi-tui";
|
|
10
10
|
import { spawn, spawnSync } from "child_process";
|
|
11
11
|
import { APP_NAME, getAgentDir, getAuthPath, getDebugLogPath, getShareViewerUrl, getUpdateInstruction, VERSION, } from "../../config.js";
|
|
12
12
|
import { parseSkillBlock } from "../../core/agent-session.js";
|
|
@@ -35,7 +35,7 @@ import { ExtensionEditorComponent } from "./components/extension-editor.js";
|
|
|
35
35
|
import { ExtensionInputComponent } from "./components/extension-input.js";
|
|
36
36
|
import { ExtensionSelectorComponent } from "./components/extension-selector.js";
|
|
37
37
|
import { FooterComponent } from "./components/footer.js";
|
|
38
|
-
import {
|
|
38
|
+
import { keyHint, keyText, rawKeyHint } from "./components/keybinding-hints.js";
|
|
39
39
|
import { LoginDialogComponent } from "./components/login-dialog.js";
|
|
40
40
|
import { ModelSelectorComponent } from "./components/model-selector.js";
|
|
41
41
|
import { OAuthSelectorComponent } from "./components/oauth-selector.js";
|
|
@@ -52,79 +52,6 @@ function isExpandable(obj) {
|
|
|
52
52
|
return typeof obj === "object" && obj !== null && "setExpanded" in obj && typeof obj.setExpanded === "function";
|
|
53
53
|
}
|
|
54
54
|
export class InteractiveMode {
|
|
55
|
-
options;
|
|
56
|
-
session;
|
|
57
|
-
ui;
|
|
58
|
-
chatContainer;
|
|
59
|
-
pendingMessagesContainer;
|
|
60
|
-
statusContainer;
|
|
61
|
-
defaultEditor;
|
|
62
|
-
editor;
|
|
63
|
-
autocompleteProvider;
|
|
64
|
-
fdPath;
|
|
65
|
-
editorContainer;
|
|
66
|
-
footer;
|
|
67
|
-
footerDataProvider;
|
|
68
|
-
keybindings;
|
|
69
|
-
version;
|
|
70
|
-
isInitialized = false;
|
|
71
|
-
onInputCallback;
|
|
72
|
-
loadingAnimation = undefined;
|
|
73
|
-
pendingWorkingMessage = undefined;
|
|
74
|
-
defaultWorkingMessage = "Working...";
|
|
75
|
-
lastSigintTime = 0;
|
|
76
|
-
lastEscapeTime = 0;
|
|
77
|
-
changelogMarkdown = undefined;
|
|
78
|
-
// Status line tracking (for mutating immediately-sequential status updates)
|
|
79
|
-
lastStatusSpacer = undefined;
|
|
80
|
-
lastStatusText = undefined;
|
|
81
|
-
// Streaming message tracking
|
|
82
|
-
streamingComponent = undefined;
|
|
83
|
-
streamingMessage = undefined;
|
|
84
|
-
// Tool execution tracking: toolCallId -> component
|
|
85
|
-
pendingTools = new Map();
|
|
86
|
-
// Tool output expansion state
|
|
87
|
-
toolOutputExpanded = false;
|
|
88
|
-
// Thinking block visibility state
|
|
89
|
-
hideThinkingBlock = false;
|
|
90
|
-
// Skill commands: command name -> skill file path
|
|
91
|
-
skillCommands = new Map();
|
|
92
|
-
// Agent subscription unsubscribe function
|
|
93
|
-
unsubscribe;
|
|
94
|
-
// Track if editor is in bash mode (text starts with !)
|
|
95
|
-
isBashMode = false;
|
|
96
|
-
// Track current bash execution component
|
|
97
|
-
bashComponent = undefined;
|
|
98
|
-
// Track pending bash components (shown in pending area, moved to chat on submit)
|
|
99
|
-
pendingBashComponents = [];
|
|
100
|
-
// Auto-compaction state
|
|
101
|
-
autoCompactionLoader = undefined;
|
|
102
|
-
autoCompactionEscapeHandler;
|
|
103
|
-
// Auto-retry state
|
|
104
|
-
retryLoader = undefined;
|
|
105
|
-
retryEscapeHandler;
|
|
106
|
-
// Messages queued while compaction is running
|
|
107
|
-
compactionQueuedMessages = [];
|
|
108
|
-
// Shutdown state
|
|
109
|
-
shutdownRequested = false;
|
|
110
|
-
// Extension UI state
|
|
111
|
-
extensionSelector = undefined;
|
|
112
|
-
extensionInput = undefined;
|
|
113
|
-
extensionEditor = undefined;
|
|
114
|
-
extensionTerminalInputUnsubscribers = new Set();
|
|
115
|
-
// Extension widgets (components rendered above/below the editor)
|
|
116
|
-
extensionWidgetsAbove = new Map();
|
|
117
|
-
extensionWidgetsBelow = new Map();
|
|
118
|
-
widgetContainerAbove;
|
|
119
|
-
widgetContainerBelow;
|
|
120
|
-
// Custom footer from extension (undefined = use built-in footer)
|
|
121
|
-
customFooter = undefined;
|
|
122
|
-
// Header container that holds the built-in or custom header
|
|
123
|
-
headerContainer;
|
|
124
|
-
// Built-in header (logo + keybinding hints + changelog)
|
|
125
|
-
builtInHeader = undefined;
|
|
126
|
-
// Custom header from extension (undefined = use built-in header)
|
|
127
|
-
customHeader = undefined;
|
|
128
55
|
// Convenience accessors
|
|
129
56
|
get agent() {
|
|
130
57
|
return this.session.agent;
|
|
@@ -137,6 +64,60 @@ export class InteractiveMode {
|
|
|
137
64
|
}
|
|
138
65
|
constructor(session, options = {}) {
|
|
139
66
|
this.options = options;
|
|
67
|
+
this.isInitialized = false;
|
|
68
|
+
this.loadingAnimation = undefined;
|
|
69
|
+
this.pendingWorkingMessage = undefined;
|
|
70
|
+
this.defaultWorkingMessage = "Working...";
|
|
71
|
+
this.lastSigintTime = 0;
|
|
72
|
+
this.lastEscapeTime = 0;
|
|
73
|
+
this.changelogMarkdown = undefined;
|
|
74
|
+
// Status line tracking (for mutating immediately-sequential status updates)
|
|
75
|
+
this.lastStatusSpacer = undefined;
|
|
76
|
+
this.lastStatusText = undefined;
|
|
77
|
+
// Streaming message tracking
|
|
78
|
+
this.streamingComponent = undefined;
|
|
79
|
+
this.streamingMessage = undefined;
|
|
80
|
+
// Tool execution tracking: toolCallId -> component
|
|
81
|
+
this.pendingTools = new Map();
|
|
82
|
+
// Tool output expansion state
|
|
83
|
+
this.toolOutputExpanded = false;
|
|
84
|
+
// Thinking block visibility state
|
|
85
|
+
this.hideThinkingBlock = false;
|
|
86
|
+
// Skill commands: command name -> skill file path
|
|
87
|
+
this.skillCommands = new Map();
|
|
88
|
+
// Track if editor is in bash mode (text starts with !)
|
|
89
|
+
this.isBashMode = false;
|
|
90
|
+
// Track current bash execution component
|
|
91
|
+
this.bashComponent = undefined;
|
|
92
|
+
// Track pending bash components (shown in pending area, moved to chat on submit)
|
|
93
|
+
this.pendingBashComponents = [];
|
|
94
|
+
// Auto-compaction state
|
|
95
|
+
this.autoCompactionLoader = undefined;
|
|
96
|
+
// Auto-retry state
|
|
97
|
+
this.retryLoader = undefined;
|
|
98
|
+
// Messages queued while compaction is running
|
|
99
|
+
this.compactionQueuedMessages = [];
|
|
100
|
+
// Shutdown state
|
|
101
|
+
this.shutdownRequested = false;
|
|
102
|
+
// Extension UI state
|
|
103
|
+
this.extensionSelector = undefined;
|
|
104
|
+
this.extensionInput = undefined;
|
|
105
|
+
this.extensionEditor = undefined;
|
|
106
|
+
this.extensionTerminalInputUnsubscribers = new Set();
|
|
107
|
+
// Extension widgets (components rendered above/below the editor)
|
|
108
|
+
this.extensionWidgetsAbove = new Map();
|
|
109
|
+
this.extensionWidgetsBelow = new Map();
|
|
110
|
+
// Custom footer from extension (undefined = use built-in footer)
|
|
111
|
+
this.customFooter = undefined;
|
|
112
|
+
// Built-in header (logo + keybinding hints + changelog)
|
|
113
|
+
this.builtInHeader = undefined;
|
|
114
|
+
// Custom header from extension (undefined = use built-in header)
|
|
115
|
+
this.customHeader = undefined;
|
|
116
|
+
/**
|
|
117
|
+
* Gracefully shutdown the agent.
|
|
118
|
+
* Emits shutdown event to extensions, then exits.
|
|
119
|
+
*/
|
|
120
|
+
this.isShuttingDown = false;
|
|
140
121
|
this.session = session;
|
|
141
122
|
this.version = VERSION;
|
|
142
123
|
this.ui = new TUI(new ProcessTerminal(), this.settingsManager.getShowHardwareCursor());
|
|
@@ -148,6 +129,7 @@ export class InteractiveMode {
|
|
|
148
129
|
this.widgetContainerAbove = new Container();
|
|
149
130
|
this.widgetContainerBelow = new Container();
|
|
150
131
|
this.keybindings = KeybindingsManager.create();
|
|
132
|
+
setKeybindings(this.keybindings);
|
|
151
133
|
const editorPaddingX = this.settingsManager.getEditorPaddingX();
|
|
152
134
|
const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
|
|
153
135
|
this.defaultEditor = new CustomEditor(this.ui, getEditorTheme(), this.keybindings, {
|
|
@@ -242,27 +224,26 @@ export class InteractiveMode {
|
|
|
242
224
|
if (this.options.verbose || !this.settingsManager.getQuietStartup()) {
|
|
243
225
|
const logo = theme.bold(theme.fg("accent", APP_NAME)) + theme.fg("dim", ` v${this.version}`);
|
|
244
226
|
// Build startup instructions using keybinding hint helpers
|
|
245
|
-
const
|
|
246
|
-
const hint = (action, desc) => appKeyHint(kb, action, desc);
|
|
227
|
+
const hint = (keybinding, description) => keyHint(keybinding, description);
|
|
247
228
|
const instructions = [
|
|
248
|
-
hint("interrupt", "to interrupt"),
|
|
249
|
-
hint("clear", "to clear"),
|
|
250
|
-
rawKeyHint(`${
|
|
251
|
-
hint("exit", "to exit (empty)"),
|
|
252
|
-
hint("suspend", "to suspend"),
|
|
253
|
-
keyHint("deleteToLineEnd", "to delete to end"),
|
|
254
|
-
hint("
|
|
255
|
-
rawKeyHint(`${
|
|
256
|
-
hint("
|
|
257
|
-
hint("
|
|
258
|
-
hint("
|
|
259
|
-
hint("
|
|
229
|
+
hint("app.interrupt", "to interrupt"),
|
|
230
|
+
hint("app.clear", "to clear"),
|
|
231
|
+
rawKeyHint(`${keyText("app.clear")} twice`, "to exit"),
|
|
232
|
+
hint("app.exit", "to exit (empty)"),
|
|
233
|
+
hint("app.suspend", "to suspend"),
|
|
234
|
+
keyHint("tui.editor.deleteToLineEnd", "to delete to end"),
|
|
235
|
+
hint("app.thinking.cycle", "to cycle thinking level"),
|
|
236
|
+
rawKeyHint(`${keyText("app.model.cycleForward")}/${keyText("app.model.cycleBackward")}`, "to cycle models"),
|
|
237
|
+
hint("app.model.select", "to select model"),
|
|
238
|
+
hint("app.tools.expand", "to expand tools"),
|
|
239
|
+
hint("app.thinking.toggle", "to expand thinking"),
|
|
240
|
+
hint("app.editor.external", "for external editor"),
|
|
260
241
|
rawKeyHint("/", "for commands"),
|
|
261
242
|
rawKeyHint("!", "to run bash"),
|
|
262
243
|
rawKeyHint("!!", "to run bash (no context)"),
|
|
263
|
-
hint("followUp", "to queue follow-up"),
|
|
264
|
-
hint("dequeue", "to edit all queued messages"),
|
|
265
|
-
hint("pasteImage", "to paste image"),
|
|
244
|
+
hint("app.message.followUp", "to queue follow-up"),
|
|
245
|
+
hint("app.message.dequeue", "to edit all queued messages"),
|
|
246
|
+
hint("app.clipboard.pasteImage", "to paste image"),
|
|
266
247
|
rawKeyHint("drop files", "to attach"),
|
|
267
248
|
].join("\n");
|
|
268
249
|
this.builtInHeader = new Text(`${logo}\n${instructions}`, 1, 0);
|
|
@@ -1049,11 +1030,11 @@ export class InteractiveMode {
|
|
|
1049
1030
|
this.defaultEditor.onExtensionShortcut = undefined;
|
|
1050
1031
|
this.updateTerminalTitle();
|
|
1051
1032
|
if (this.loadingAnimation) {
|
|
1052
|
-
this.loadingAnimation.setMessage(`${this.defaultWorkingMessage} (${
|
|
1033
|
+
this.loadingAnimation.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`);
|
|
1053
1034
|
}
|
|
1054
1035
|
}
|
|
1055
1036
|
// Maximum total widget lines to prevent viewport overflow
|
|
1056
|
-
static MAX_WIDGET_LINES = 10;
|
|
1037
|
+
static { this.MAX_WIDGET_LINES = 10; }
|
|
1057
1038
|
/**
|
|
1058
1039
|
* Render all extension widgets to the widget container.
|
|
1059
1040
|
*/
|
|
@@ -1172,7 +1153,7 @@ export class InteractiveMode {
|
|
|
1172
1153
|
this.loadingAnimation.setMessage(message);
|
|
1173
1154
|
}
|
|
1174
1155
|
else {
|
|
1175
|
-
this.loadingAnimation.setMessage(`${this.defaultWorkingMessage} (${
|
|
1156
|
+
this.loadingAnimation.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`);
|
|
1176
1157
|
}
|
|
1177
1158
|
}
|
|
1178
1159
|
else {
|
|
@@ -1530,24 +1511,24 @@ export class InteractiveMode {
|
|
|
1530
1511
|
}
|
|
1531
1512
|
};
|
|
1532
1513
|
// Register app action handlers
|
|
1533
|
-
this.defaultEditor.onAction("clear", () => this.handleCtrlC());
|
|
1514
|
+
this.defaultEditor.onAction("app.clear", () => this.handleCtrlC());
|
|
1534
1515
|
this.defaultEditor.onCtrlD = () => this.handleCtrlD();
|
|
1535
|
-
this.defaultEditor.onAction("suspend", () => this.handleCtrlZ());
|
|
1536
|
-
this.defaultEditor.onAction("
|
|
1537
|
-
this.defaultEditor.onAction("
|
|
1538
|
-
this.defaultEditor.onAction("
|
|
1516
|
+
this.defaultEditor.onAction("app.suspend", () => this.handleCtrlZ());
|
|
1517
|
+
this.defaultEditor.onAction("app.thinking.cycle", () => this.cycleThinkingLevel());
|
|
1518
|
+
this.defaultEditor.onAction("app.model.cycleForward", () => this.cycleModel("forward"));
|
|
1519
|
+
this.defaultEditor.onAction("app.model.cycleBackward", () => this.cycleModel("backward"));
|
|
1539
1520
|
// Global debug handler on TUI (works regardless of focus)
|
|
1540
1521
|
this.ui.onDebug = () => this.handleDebugCommand();
|
|
1541
|
-
this.defaultEditor.onAction("
|
|
1542
|
-
this.defaultEditor.onAction("
|
|
1543
|
-
this.defaultEditor.onAction("
|
|
1544
|
-
this.defaultEditor.onAction("
|
|
1545
|
-
this.defaultEditor.onAction("followUp", () => this.handleFollowUp());
|
|
1546
|
-
this.defaultEditor.onAction("dequeue", () => this.handleDequeue());
|
|
1547
|
-
this.defaultEditor.onAction("
|
|
1548
|
-
this.defaultEditor.onAction("tree", () => this.showTreeSelector());
|
|
1549
|
-
this.defaultEditor.onAction("fork", () => this.showUserMessageSelector());
|
|
1550
|
-
this.defaultEditor.onAction("resume", () => this.showSessionSelector());
|
|
1522
|
+
this.defaultEditor.onAction("app.model.select", () => this.showModelSelector());
|
|
1523
|
+
this.defaultEditor.onAction("app.tools.expand", () => this.toggleToolOutputExpansion());
|
|
1524
|
+
this.defaultEditor.onAction("app.thinking.toggle", () => this.toggleThinkingBlockVisibility());
|
|
1525
|
+
this.defaultEditor.onAction("app.editor.external", () => this.openExternalEditor());
|
|
1526
|
+
this.defaultEditor.onAction("app.message.followUp", () => this.handleFollowUp());
|
|
1527
|
+
this.defaultEditor.onAction("app.message.dequeue", () => this.handleDequeue());
|
|
1528
|
+
this.defaultEditor.onAction("app.session.new", () => this.handleClearCommand());
|
|
1529
|
+
this.defaultEditor.onAction("app.session.tree", () => this.showTreeSelector());
|
|
1530
|
+
this.defaultEditor.onAction("app.session.fork", () => this.showUserMessageSelector());
|
|
1531
|
+
this.defaultEditor.onAction("app.session.resume", () => this.showSessionSelector());
|
|
1551
1532
|
this.defaultEditor.onChange = (text) => {
|
|
1552
1533
|
const wasBashMode = this.isBashMode;
|
|
1553
1534
|
this.isBashMode = text.trimStart().startsWith("!");
|
|
@@ -1607,13 +1588,18 @@ export class InteractiveMode {
|
|
|
1607
1588
|
this.editor.setText("");
|
|
1608
1589
|
return;
|
|
1609
1590
|
}
|
|
1591
|
+
if (text.startsWith("/import")) {
|
|
1592
|
+
await this.handleImportCommand(text);
|
|
1593
|
+
this.editor.setText("");
|
|
1594
|
+
return;
|
|
1595
|
+
}
|
|
1610
1596
|
if (text === "/share") {
|
|
1611
1597
|
await this.handleShareCommand();
|
|
1612
1598
|
this.editor.setText("");
|
|
1613
1599
|
return;
|
|
1614
1600
|
}
|
|
1615
1601
|
if (text === "/copy") {
|
|
1616
|
-
this.handleCopyCommand();
|
|
1602
|
+
await this.handleCopyCommand();
|
|
1617
1603
|
this.editor.setText("");
|
|
1618
1604
|
return;
|
|
1619
1605
|
}
|
|
@@ -1861,15 +1847,17 @@ export class InteractiveMode {
|
|
|
1861
1847
|
this.ui.requestRender();
|
|
1862
1848
|
break;
|
|
1863
1849
|
case "tool_execution_start": {
|
|
1864
|
-
|
|
1865
|
-
|
|
1850
|
+
let component = this.pendingTools.get(event.toolCallId);
|
|
1851
|
+
if (!component) {
|
|
1852
|
+
component = new ToolExecutionComponent(event.toolName, event.args, {
|
|
1866
1853
|
showImages: this.settingsManager.getShowImages(),
|
|
1867
1854
|
}, this.getRegisteredToolDefinition(event.toolName), this.ui);
|
|
1868
1855
|
component.setExpanded(this.toolOutputExpanded);
|
|
1869
1856
|
this.chatContainer.addChild(component);
|
|
1870
1857
|
this.pendingTools.set(event.toolCallId, component);
|
|
1871
|
-
this.ui.requestRender();
|
|
1872
1858
|
}
|
|
1859
|
+
component.markExecutionStarted();
|
|
1860
|
+
this.ui.requestRender();
|
|
1873
1861
|
break;
|
|
1874
1862
|
}
|
|
1875
1863
|
case "tool_execution_update": {
|
|
@@ -1914,7 +1902,7 @@ export class InteractiveMode {
|
|
|
1914
1902
|
// Show compacting indicator with reason
|
|
1915
1903
|
this.statusContainer.clear();
|
|
1916
1904
|
const reasonText = event.reason === "overflow" ? "Context overflow detected, " : "";
|
|
1917
|
-
this.autoCompactionLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), `${reasonText}Auto-compacting... (${
|
|
1905
|
+
this.autoCompactionLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), `${reasonText}Auto-compacting... (${keyText("app.interrupt")} to cancel)`);
|
|
1918
1906
|
this.statusContainer.addChild(this.autoCompactionLoader);
|
|
1919
1907
|
this.ui.requestRender();
|
|
1920
1908
|
break;
|
|
@@ -1966,7 +1954,7 @@ export class InteractiveMode {
|
|
|
1966
1954
|
// Show retry indicator
|
|
1967
1955
|
this.statusContainer.clear();
|
|
1968
1956
|
const delaySeconds = Math.round(event.delayMs / 1000);
|
|
1969
|
-
this.retryLoader = new Loader(this.ui, (spinner) => theme.fg("warning", spinner), (text) => theme.fg("muted", text), `Retrying (${event.attempt}/${event.maxAttempts}) in ${delaySeconds}s... (${
|
|
1957
|
+
this.retryLoader = new Loader(this.ui, (spinner) => theme.fg("warning", spinner), (text) => theme.fg("muted", text), `Retrying (${event.attempt}/${event.maxAttempts}) in ${delaySeconds}s... (${keyText("app.interrupt")} to cancel)`);
|
|
1970
1958
|
this.statusContainer.addChild(this.retryLoader);
|
|
1971
1959
|
this.ui.requestRender();
|
|
1972
1960
|
break;
|
|
@@ -2201,11 +2189,6 @@ export class InteractiveMode {
|
|
|
2201
2189
|
// Only called when editor is empty (enforced by CustomEditor)
|
|
2202
2190
|
void this.shutdown();
|
|
2203
2191
|
}
|
|
2204
|
-
/**
|
|
2205
|
-
* Gracefully shutdown the agent.
|
|
2206
|
-
* Emits shutdown event to extensions, then exits.
|
|
2207
|
-
*/
|
|
2208
|
-
isShuttingDown = false;
|
|
2209
2192
|
async shutdown() {
|
|
2210
2193
|
if (this.isShuttingDown)
|
|
2211
2194
|
return;
|
|
@@ -2235,20 +2218,32 @@ export class InteractiveMode {
|
|
|
2235
2218
|
await this.shutdown();
|
|
2236
2219
|
}
|
|
2237
2220
|
handleCtrlZ() {
|
|
2221
|
+
// Keep the event loop alive while suspended. Without this, stopping the TUI
|
|
2222
|
+
// can leave Node with no ref'ed handles, causing the process to exit on fg
|
|
2223
|
+
// before the SIGCONT handler gets a chance to restore the terminal.
|
|
2224
|
+
const suspendKeepAlive = setInterval(() => { }, 2 ** 30);
|
|
2238
2225
|
// Ignore SIGINT while suspended so Ctrl+C in the terminal does not
|
|
2239
2226
|
// kill the backgrounded process. The handler is removed on resume.
|
|
2240
2227
|
const ignoreSigint = () => { };
|
|
2241
2228
|
process.on("SIGINT", ignoreSigint);
|
|
2242
2229
|
// Set up handler to restore TUI when resumed
|
|
2243
2230
|
process.once("SIGCONT", () => {
|
|
2231
|
+
clearInterval(suspendKeepAlive);
|
|
2244
2232
|
process.removeListener("SIGINT", ignoreSigint);
|
|
2245
2233
|
this.ui.start();
|
|
2246
2234
|
this.ui.requestRender(true);
|
|
2247
2235
|
});
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2236
|
+
try {
|
|
2237
|
+
// Stop the TUI (restore terminal to normal mode)
|
|
2238
|
+
this.ui.stop();
|
|
2239
|
+
// Send SIGTSTP to process group (pid=0 means all processes in group)
|
|
2240
|
+
process.kill(0, "SIGTSTP");
|
|
2241
|
+
}
|
|
2242
|
+
catch (error) {
|
|
2243
|
+
clearInterval(suspendKeepAlive);
|
|
2244
|
+
process.removeListener("SIGINT", ignoreSigint);
|
|
2245
|
+
throw error;
|
|
2246
|
+
}
|
|
2252
2247
|
}
|
|
2253
2248
|
async handleFollowUp() {
|
|
2254
2249
|
const text = (this.editor.getExpandedText?.() ?? this.editor.getText()).trim();
|
|
@@ -2481,7 +2476,7 @@ export class InteractiveMode {
|
|
|
2481
2476
|
const text = theme.fg("dim", `Follow-up: ${message}`);
|
|
2482
2477
|
this.pendingMessagesContainer.addChild(new TruncatedText(text, 1, 0));
|
|
2483
2478
|
}
|
|
2484
|
-
const dequeueHint = this.getAppKeyDisplay("dequeue");
|
|
2479
|
+
const dequeueHint = this.getAppKeyDisplay("app.message.dequeue");
|
|
2485
2480
|
const hintText = theme.fg("dim", `↳ ${dequeueHint} to edit all queued messages`);
|
|
2486
2481
|
this.pendingMessagesContainer.addChild(new TruncatedText(hintText, 1, 0));
|
|
2487
2482
|
}
|
|
@@ -3003,7 +2998,7 @@ export class InteractiveMode {
|
|
|
3003
2998
|
this.session.abortBranchSummary();
|
|
3004
2999
|
};
|
|
3005
3000
|
this.chatContainer.addChild(new Spacer(1));
|
|
3006
|
-
summaryLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), `Summarizing branch... (${
|
|
3001
|
+
summaryLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), `Summarizing branch... (${keyText("app.interrupt")} to cancel)`);
|
|
3007
3002
|
this.statusContainer.addChild(summaryLoader);
|
|
3008
3003
|
this.ui.requestRender();
|
|
3009
3004
|
}
|
|
@@ -3285,13 +3280,58 @@ export class InteractiveMode {
|
|
|
3285
3280
|
const parts = text.split(/\s+/);
|
|
3286
3281
|
const outputPath = parts.length > 1 ? parts[1] : undefined;
|
|
3287
3282
|
try {
|
|
3288
|
-
|
|
3289
|
-
|
|
3283
|
+
if (outputPath?.endsWith(".jsonl")) {
|
|
3284
|
+
const filePath = this.session.exportToJsonl(outputPath);
|
|
3285
|
+
this.showStatus(`Session exported to: ${filePath}`);
|
|
3286
|
+
}
|
|
3287
|
+
else {
|
|
3288
|
+
const filePath = await this.session.exportToHtml(outputPath);
|
|
3289
|
+
this.showStatus(`Session exported to: ${filePath}`);
|
|
3290
|
+
}
|
|
3290
3291
|
}
|
|
3291
3292
|
catch (error) {
|
|
3292
3293
|
this.showError(`Failed to export session: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3293
3294
|
}
|
|
3294
3295
|
}
|
|
3296
|
+
async handleImportCommand(text) {
|
|
3297
|
+
const parts = text.split(/\s+/);
|
|
3298
|
+
if (parts.length < 2 || !parts[1]) {
|
|
3299
|
+
this.showError("Usage: /import <path.jsonl>");
|
|
3300
|
+
return;
|
|
3301
|
+
}
|
|
3302
|
+
const inputPath = parts[1];
|
|
3303
|
+
const confirmed = await this.showExtensionConfirm("Import session", `Replace current session with ${inputPath}?`);
|
|
3304
|
+
if (!confirmed) {
|
|
3305
|
+
this.showStatus("Import cancelled");
|
|
3306
|
+
return;
|
|
3307
|
+
}
|
|
3308
|
+
try {
|
|
3309
|
+
// Stop loading animation
|
|
3310
|
+
if (this.loadingAnimation) {
|
|
3311
|
+
this.loadingAnimation.stop();
|
|
3312
|
+
this.loadingAnimation = undefined;
|
|
3313
|
+
}
|
|
3314
|
+
this.statusContainer.clear();
|
|
3315
|
+
// Clear UI state
|
|
3316
|
+
this.pendingMessagesContainer.clear();
|
|
3317
|
+
this.compactionQueuedMessages = [];
|
|
3318
|
+
this.streamingComponent = undefined;
|
|
3319
|
+
this.streamingMessage = undefined;
|
|
3320
|
+
this.pendingTools.clear();
|
|
3321
|
+
const success = await this.session.importFromJsonl(inputPath);
|
|
3322
|
+
if (!success) {
|
|
3323
|
+
this.showWarning("Import cancelled");
|
|
3324
|
+
return;
|
|
3325
|
+
}
|
|
3326
|
+
// Clear and re-render the chat
|
|
3327
|
+
this.chatContainer.clear();
|
|
3328
|
+
this.renderInitialMessages();
|
|
3329
|
+
this.showStatus(`Session imported from: ${inputPath}`);
|
|
3330
|
+
}
|
|
3331
|
+
catch (error) {
|
|
3332
|
+
this.showError(`Failed to import session: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3295
3335
|
async handleShareCommand() {
|
|
3296
3336
|
// Check if gh is available and logged in
|
|
3297
3337
|
try {
|
|
@@ -3379,14 +3419,14 @@ export class InteractiveMode {
|
|
|
3379
3419
|
}
|
|
3380
3420
|
}
|
|
3381
3421
|
}
|
|
3382
|
-
handleCopyCommand() {
|
|
3422
|
+
async handleCopyCommand() {
|
|
3383
3423
|
const text = this.session.getLastAssistantText();
|
|
3384
3424
|
if (!text) {
|
|
3385
3425
|
this.showError("No agent messages to copy yet.");
|
|
3386
3426
|
return;
|
|
3387
3427
|
}
|
|
3388
3428
|
try {
|
|
3389
|
-
copyToClipboard(text);
|
|
3429
|
+
await copyToClipboard(text);
|
|
3390
3430
|
this.showStatus("Copied last agent message to clipboard");
|
|
3391
3431
|
}
|
|
3392
3432
|
catch (error) {
|
|
@@ -3479,54 +3519,54 @@ export class InteractiveMode {
|
|
|
3479
3519
|
* Get capitalized display string for an app keybinding action.
|
|
3480
3520
|
*/
|
|
3481
3521
|
getAppKeyDisplay(action) {
|
|
3482
|
-
return this.capitalizeKey(
|
|
3522
|
+
return this.capitalizeKey(keyText(action));
|
|
3483
3523
|
}
|
|
3484
3524
|
/**
|
|
3485
3525
|
* Get capitalized display string for an editor keybinding action.
|
|
3486
3526
|
*/
|
|
3487
3527
|
getEditorKeyDisplay(action) {
|
|
3488
|
-
return this.capitalizeKey(
|
|
3528
|
+
return this.capitalizeKey(keyText(action));
|
|
3489
3529
|
}
|
|
3490
3530
|
handleHotkeysCommand() {
|
|
3491
3531
|
// Navigation keybindings
|
|
3492
|
-
const cursorUp = this.getEditorKeyDisplay("cursorUp");
|
|
3493
|
-
const cursorDown = this.getEditorKeyDisplay("cursorDown");
|
|
3494
|
-
const cursorLeft = this.getEditorKeyDisplay("cursorLeft");
|
|
3495
|
-
const cursorRight = this.getEditorKeyDisplay("cursorRight");
|
|
3496
|
-
const cursorWordLeft = this.getEditorKeyDisplay("cursorWordLeft");
|
|
3497
|
-
const cursorWordRight = this.getEditorKeyDisplay("cursorWordRight");
|
|
3498
|
-
const cursorLineStart = this.getEditorKeyDisplay("cursorLineStart");
|
|
3499
|
-
const cursorLineEnd = this.getEditorKeyDisplay("cursorLineEnd");
|
|
3500
|
-
const jumpForward = this.getEditorKeyDisplay("jumpForward");
|
|
3501
|
-
const jumpBackward = this.getEditorKeyDisplay("jumpBackward");
|
|
3502
|
-
const pageUp = this.getEditorKeyDisplay("pageUp");
|
|
3503
|
-
const pageDown = this.getEditorKeyDisplay("pageDown");
|
|
3532
|
+
const cursorUp = this.getEditorKeyDisplay("tui.editor.cursorUp");
|
|
3533
|
+
const cursorDown = this.getEditorKeyDisplay("tui.editor.cursorDown");
|
|
3534
|
+
const cursorLeft = this.getEditorKeyDisplay("tui.editor.cursorLeft");
|
|
3535
|
+
const cursorRight = this.getEditorKeyDisplay("tui.editor.cursorRight");
|
|
3536
|
+
const cursorWordLeft = this.getEditorKeyDisplay("tui.editor.cursorWordLeft");
|
|
3537
|
+
const cursorWordRight = this.getEditorKeyDisplay("tui.editor.cursorWordRight");
|
|
3538
|
+
const cursorLineStart = this.getEditorKeyDisplay("tui.editor.cursorLineStart");
|
|
3539
|
+
const cursorLineEnd = this.getEditorKeyDisplay("tui.editor.cursorLineEnd");
|
|
3540
|
+
const jumpForward = this.getEditorKeyDisplay("tui.editor.jumpForward");
|
|
3541
|
+
const jumpBackward = this.getEditorKeyDisplay("tui.editor.jumpBackward");
|
|
3542
|
+
const pageUp = this.getEditorKeyDisplay("tui.editor.pageUp");
|
|
3543
|
+
const pageDown = this.getEditorKeyDisplay("tui.editor.pageDown");
|
|
3504
3544
|
// Editing keybindings
|
|
3505
|
-
const submit = this.getEditorKeyDisplay("submit");
|
|
3506
|
-
const newLine = this.getEditorKeyDisplay("newLine");
|
|
3507
|
-
const deleteWordBackward = this.getEditorKeyDisplay("deleteWordBackward");
|
|
3508
|
-
const deleteWordForward = this.getEditorKeyDisplay("deleteWordForward");
|
|
3509
|
-
const deleteToLineStart = this.getEditorKeyDisplay("deleteToLineStart");
|
|
3510
|
-
const deleteToLineEnd = this.getEditorKeyDisplay("deleteToLineEnd");
|
|
3511
|
-
const yank = this.getEditorKeyDisplay("yank");
|
|
3512
|
-
const yankPop = this.getEditorKeyDisplay("yankPop");
|
|
3513
|
-
const undo = this.getEditorKeyDisplay("undo");
|
|
3514
|
-
const tab = this.getEditorKeyDisplay("tab");
|
|
3545
|
+
const submit = this.getEditorKeyDisplay("tui.input.submit");
|
|
3546
|
+
const newLine = this.getEditorKeyDisplay("tui.input.newLine");
|
|
3547
|
+
const deleteWordBackward = this.getEditorKeyDisplay("tui.editor.deleteWordBackward");
|
|
3548
|
+
const deleteWordForward = this.getEditorKeyDisplay("tui.editor.deleteWordForward");
|
|
3549
|
+
const deleteToLineStart = this.getEditorKeyDisplay("tui.editor.deleteToLineStart");
|
|
3550
|
+
const deleteToLineEnd = this.getEditorKeyDisplay("tui.editor.deleteToLineEnd");
|
|
3551
|
+
const yank = this.getEditorKeyDisplay("tui.editor.yank");
|
|
3552
|
+
const yankPop = this.getEditorKeyDisplay("tui.editor.yankPop");
|
|
3553
|
+
const undo = this.getEditorKeyDisplay("tui.editor.undo");
|
|
3554
|
+
const tab = this.getEditorKeyDisplay("tui.input.tab");
|
|
3515
3555
|
// App keybindings
|
|
3516
|
-
const interrupt = this.getAppKeyDisplay("interrupt");
|
|
3517
|
-
const clear = this.getAppKeyDisplay("clear");
|
|
3518
|
-
const exit = this.getAppKeyDisplay("exit");
|
|
3519
|
-
const suspend = this.getAppKeyDisplay("suspend");
|
|
3520
|
-
const cycleThinkingLevel = this.getAppKeyDisplay("
|
|
3521
|
-
const cycleModelForward = this.getAppKeyDisplay("
|
|
3522
|
-
const selectModel = this.getAppKeyDisplay("
|
|
3523
|
-
const expandTools = this.getAppKeyDisplay("
|
|
3524
|
-
const toggleThinking = this.getAppKeyDisplay("
|
|
3525
|
-
const externalEditor = this.getAppKeyDisplay("
|
|
3526
|
-
const cycleModelBackward = this.getAppKeyDisplay("
|
|
3527
|
-
const followUp = this.getAppKeyDisplay("followUp");
|
|
3528
|
-
const dequeue = this.getAppKeyDisplay("dequeue");
|
|
3529
|
-
const pasteImage = this.getAppKeyDisplay("pasteImage");
|
|
3556
|
+
const interrupt = this.getAppKeyDisplay("app.interrupt");
|
|
3557
|
+
const clear = this.getAppKeyDisplay("app.clear");
|
|
3558
|
+
const exit = this.getAppKeyDisplay("app.exit");
|
|
3559
|
+
const suspend = this.getAppKeyDisplay("app.suspend");
|
|
3560
|
+
const cycleThinkingLevel = this.getAppKeyDisplay("app.thinking.cycle");
|
|
3561
|
+
const cycleModelForward = this.getAppKeyDisplay("app.model.cycleForward");
|
|
3562
|
+
const selectModel = this.getAppKeyDisplay("app.model.select");
|
|
3563
|
+
const expandTools = this.getAppKeyDisplay("app.tools.expand");
|
|
3564
|
+
const toggleThinking = this.getAppKeyDisplay("app.thinking.toggle");
|
|
3565
|
+
const externalEditor = this.getAppKeyDisplay("app.editor.external");
|
|
3566
|
+
const cycleModelBackward = this.getAppKeyDisplay("app.model.cycleBackward");
|
|
3567
|
+
const followUp = this.getAppKeyDisplay("app.message.followUp");
|
|
3568
|
+
const dequeue = this.getAppKeyDisplay("app.message.dequeue");
|
|
3569
|
+
const pasteImage = this.getAppKeyDisplay("app.clipboard.pasteImage");
|
|
3530
3570
|
let hotkeys = `
|
|
3531
3571
|
**Navigation**
|
|
3532
3572
|
| Key | Action |
|
|
@@ -3751,7 +3791,7 @@ export class InteractiveMode {
|
|
|
3751
3791
|
};
|
|
3752
3792
|
// Show compacting status
|
|
3753
3793
|
this.chatContainer.addChild(new Spacer(1));
|
|
3754
|
-
const cancelHint = `(${
|
|
3794
|
+
const cancelHint = `(${keyText("app.interrupt")} to cancel)`;
|
|
3755
3795
|
const label = isAuto ? `Auto-compacting context... ${cancelHint}` : `Compacting context... ${cancelHint}`;
|
|
3756
3796
|
const compactingLoader = new Loader(this.ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), label);
|
|
3757
3797
|
this.statusContainer.addChild(compactingLoader);
|