pi-ui-extend 0.1.13 → 0.1.17
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/README.md +1 -1
- package/dist/app/app.d.ts +7 -0
- package/dist/app/app.js +102 -17
- package/dist/app/commands/command-controller.js +2 -0
- package/dist/app/commands/command-host.d.ts +5 -0
- package/dist/app/commands/command-model-actions.d.ts +2 -0
- package/dist/app/commands/command-model-actions.js +40 -4
- package/dist/app/commands/command-navigation-actions.d.ts +9 -0
- package/dist/app/commands/command-navigation-actions.js +62 -0
- package/dist/app/commands/command-registry.d.ts +2 -0
- package/dist/app/commands/command-registry.js +16 -0
- package/dist/app/constants.d.ts +0 -1
- package/dist/app/constants.js +0 -1
- package/dist/app/extensions/extension-ui-controller.d.ts +16 -5
- package/dist/app/extensions/extension-ui-controller.js +99 -61
- package/dist/app/icons.d.ts +1 -0
- package/dist/app/icons.js +2 -0
- package/dist/app/input/input-action-controller.d.ts +2 -0
- package/dist/app/input/input-action-controller.js +8 -1
- package/dist/app/logger.d.ts +25 -0
- package/dist/app/logger.js +90 -0
- package/dist/app/model/model-usage-status.js +30 -15
- package/dist/app/popup/menu-items-controller.d.ts +4 -0
- package/dist/app/popup/menu-items-controller.js +68 -6
- package/dist/app/popup/popup-action-controller.d.ts +2 -1
- package/dist/app/popup/popup-action-controller.js +7 -4
- package/dist/app/popup/popup-menu-controller.d.ts +36 -23
- package/dist/app/popup/popup-menu-controller.js +97 -326
- package/dist/app/rendering/conversation-entry-renderer.js +3 -3
- package/dist/app/rendering/conversation-viewport.d.ts +10 -2
- package/dist/app/rendering/conversation-viewport.js +157 -16
- package/dist/app/rendering/editor-panels.js +22 -9
- package/dist/app/rendering/popup-menu-renderer.d.ts +62 -0
- package/dist/app/rendering/popup-menu-renderer.js +405 -0
- package/dist/app/rendering/render-controller.js +30 -28
- package/dist/app/rendering/render-text.js +5 -2
- package/dist/app/rendering/status-line-renderer.d.ts +8 -1
- package/dist/app/rendering/status-line-renderer.js +217 -117
- package/dist/app/rendering/toast-controller.d.ts +12 -3
- package/dist/app/rendering/toast-controller.js +70 -12
- package/dist/app/runtime.d.ts +2 -1
- package/dist/app/runtime.js +20 -10
- package/dist/app/screen/mouse-controller.d.ts +2 -2
- package/dist/app/screen/mouse-controller.js +27 -48
- package/dist/app/screen/screen-styler.d.ts +1 -1
- package/dist/app/screen/screen-styler.js +9 -7
- package/dist/app/screen/scroll-controller.d.ts +12 -9
- package/dist/app/screen/scroll-controller.js +56 -45
- package/dist/app/screen/status-controller.js +2 -1
- package/dist/app/session/lazy-session-manager.d.ts +11 -0
- package/dist/app/session/lazy-session-manager.js +539 -0
- package/dist/app/session/pix-system-message.d.ts +16 -0
- package/dist/app/session/pix-system-message.js +64 -0
- package/dist/app/session/request-history.d.ts +4 -0
- package/dist/app/session/request-history.js +11 -0
- package/dist/app/session/session-event-controller.d.ts +11 -0
- package/dist/app/session/session-event-controller.js +58 -2
- package/dist/app/session/session-history.d.ts +18 -0
- package/dist/app/session/session-history.js +72 -3
- package/dist/app/session/session-lifecycle-controller.d.ts +6 -2
- package/dist/app/session/session-lifecycle-controller.js +7 -2
- package/dist/app/session/session-search.js +10 -0
- package/dist/app/session/tabs-controller.d.ts +17 -5
- package/dist/app/session/tabs-controller.js +308 -29
- package/dist/app/todo/todo-model.d.ts +4 -2
- package/dist/app/todo/todo-model.js +23 -13
- package/dist/app/types.d.ts +17 -6
- package/dist/app/workspace/workspace-actions-controller.d.ts +2 -0
- package/dist/app/workspace/workspace-actions-controller.js +12 -0
- package/dist/config.d.ts +6 -1
- package/dist/config.js +82 -25
- package/dist/default-pix-config.js +4 -0
- package/dist/fuzzy.d.ts +2 -0
- package/dist/fuzzy.js +27 -7
- package/dist/input-editor.d.ts +9 -0
- package/dist/input-editor.js +52 -0
- package/dist/schemas/pi-tools-suite-schema.d.ts +1 -0
- package/dist/schemas/pi-tools-suite-schema.js +1 -0
- package/dist/schemas/pix-schema.d.ts +3 -1
- package/dist/schemas/pix-schema.js +6 -4
- package/dist/terminal-width.d.ts +2 -0
- package/dist/terminal-width.js +64 -3
- package/dist/theme.js +6 -6
- package/dist/ui.d.ts +8 -0
- package/external/pi-tools-suite/README.md +3 -2
- package/external/pi-tools-suite/src/antigravity-auth/auth-store.ts +52 -8
- package/external/pi-tools-suite/src/antigravity-auth/commands.ts +3 -41
- package/external/pi-tools-suite/src/antigravity-auth/constants.ts +0 -2
- package/external/pi-tools-suite/src/antigravity-auth/index.ts +11 -18
- package/external/pi-tools-suite/src/antigravity-auth/oauth.ts +129 -61
- package/external/pi-tools-suite/src/antigravity-auth/status.ts +82 -3
- package/external/pi-tools-suite/src/antigravity-auth/stream.ts +20 -7
- package/external/pi-tools-suite/src/antigravity-auth/types.ts +21 -0
- package/external/pi-tools-suite/src/config.ts +8 -0
- package/external/pi-tools-suite/src/dcp/index.ts +16 -1
- package/external/pi-tools-suite/src/dcp/state.ts +35 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +3 -0
- package/external/pi-tools-suite/src/todo/index.ts +123 -14
- package/external/pi-tools-suite/src/todo/state/persistence.ts +0 -1
- package/external/pi-tools-suite/src/todo/state/state-reducer.ts +26 -43
- package/external/pi-tools-suite/src/todo/todo.ts +12 -23
- package/external/pi-tools-suite/src/todo/tool/response-envelope.ts +34 -16
- package/external/pi-tools-suite/src/todo/tool/types.ts +7 -28
- package/external/pi-tools-suite/src/todo/view/format.ts +2 -3
- package/external/pi-tools-suite/src/tool-descriptions.ts +6 -4
- package/external/pi-tools-suite/src/usage/index.ts +5 -2
- package/external/pi-tools-suite/src/usage/lib/google.ts +53 -40
- package/external/pi-tools-suite/src/usage/lib/types.ts +12 -2
- package/package.json +1 -1
- package/schemas/pi-tools-suite.json +4 -0
- package/schemas/pix.json +11 -2
package/README.md
CHANGED
|
@@ -215,7 +215,7 @@ Type `/` in the prompt to open the command picker. Commands that accept argument
|
|
|
215
215
|
| `/settings` | — | Show current session, model, theme, and key settings. |
|
|
216
216
|
| `/model` | `[provider/model[:thinking]]` | Select the active model. Without arguments, opens the model picker. With a reference like `anthropic/claude-sonnet-4-20250514:medium`, sets the model and optional thinking level directly. |
|
|
217
217
|
| `/scoped-models` | `[refs…\|reset]` | Show or set the models used by the model selector and cycling. Pass one or more `provider/model[:thinking]` references separated by spaces or commas. Use `reset` to restore the default favorites. |
|
|
218
|
-
| `/thinking` | `[level]` | Select the thinking level. Without arguments, opens the thinking picker. Accepts an explicit level (`off`, `minimal`, `low`, `medium`, `high`, `xhigh`). |
|
|
218
|
+
| `/thinking` | `[level\|auto]` | Select the thinking level. Without arguments, opens the thinking picker. Accepts an explicit level (`off`, `minimal`, `low`, `medium`, `high`, `xhigh`) or `auto`, which chooses a supported level per prompt. |
|
|
219
219
|
| `/enhance` | — | Improve the current prompt draft using the prompt enhancer model. |
|
|
220
220
|
| `/export` | `[path]` | Export the session. Defaults to HTML. Pass a `.jsonl` path to export as JSONL. |
|
|
221
221
|
| `/import` | `<path.jsonl>` | Import and resume a session from a JSONL file. |
|
package/dist/app/app.d.ts
CHANGED
|
@@ -44,6 +44,7 @@ export declare class PiUiExtendApp {
|
|
|
44
44
|
private readonly extensionShutdownHandler;
|
|
45
45
|
private runtime;
|
|
46
46
|
private readonly inputEditor;
|
|
47
|
+
private lastInputEditorContentVersion;
|
|
47
48
|
private readonly requestHistory;
|
|
48
49
|
/** Shortcut: get/set the editor text as a plain string. */
|
|
49
50
|
private get input();
|
|
@@ -58,6 +59,7 @@ export declare class PiUiExtendApp {
|
|
|
58
59
|
private resumeSessions;
|
|
59
60
|
private resumeLoading;
|
|
60
61
|
constructor(options: AppOptions);
|
|
62
|
+
private createRuntime;
|
|
61
63
|
start(): Promise<void>;
|
|
62
64
|
private checkPixUpdateOnStartup;
|
|
63
65
|
private bindCurrentSession;
|
|
@@ -67,6 +69,7 @@ export declare class PiUiExtendApp {
|
|
|
67
69
|
private afterSessionReplacement;
|
|
68
70
|
private requireRuntime;
|
|
69
71
|
private restoreSessionStatus;
|
|
72
|
+
private activeExtensionUiScope;
|
|
70
73
|
private setInput;
|
|
71
74
|
private resetInputAfterProgrammaticEdit;
|
|
72
75
|
private restoreTabInputState;
|
|
@@ -77,6 +80,8 @@ export declare class PiUiExtendApp {
|
|
|
77
80
|
private resetSessionView;
|
|
78
81
|
private loadSessionHistory;
|
|
79
82
|
private openSearchResultInNewTab;
|
|
83
|
+
private scrollToUserMessageJumpTarget;
|
|
84
|
+
private findUserEntryBySessionEntryId;
|
|
80
85
|
private loadSessionHistoryAsync;
|
|
81
86
|
private handleSessionEvent;
|
|
82
87
|
private findEntry;
|
|
@@ -93,9 +98,11 @@ export declare class PiUiExtendApp {
|
|
|
93
98
|
private toggleTerminalBellSound;
|
|
94
99
|
private refreshModelUsageStatusFromClick;
|
|
95
100
|
private showToast;
|
|
101
|
+
private toastNotifierForScope;
|
|
96
102
|
private clearToastTimers;
|
|
97
103
|
private render;
|
|
98
104
|
private scheduleRender;
|
|
105
|
+
private syncScrollAfterInputEditorChange;
|
|
99
106
|
private renderStatusLine;
|
|
100
107
|
private terminalColumns;
|
|
101
108
|
private terminalRows;
|
package/dist/app/app.js
CHANGED
|
@@ -16,6 +16,7 @@ import { createId } from "./id.js";
|
|
|
16
16
|
import { NerdFontController } from "./terminal/nerd-font-controller.js";
|
|
17
17
|
import { AppPopupActionController } from "./popup/popup-action-controller.js";
|
|
18
18
|
import { AppPopupMenuController } from "./popup/popup-menu-controller.js";
|
|
19
|
+
import { PopupMenuRenderer } from "./rendering/popup-menu-renderer.js";
|
|
19
20
|
import { AppPromptEnhancerController } from "./input/prompt-enhancer-controller.js";
|
|
20
21
|
import { AppAutocompleteController } from "./input/autocomplete-controller.js";
|
|
21
22
|
import { AppQueuedMessageController } from "./session/queued-message-controller.js";
|
|
@@ -109,6 +110,7 @@ export class PiUiExtendApp {
|
|
|
109
110
|
extensionShutdownHandler = () => { };
|
|
110
111
|
runtime;
|
|
111
112
|
inputEditor = new InputEditor();
|
|
113
|
+
lastInputEditorContentVersion = this.inputEditor.contentVersion;
|
|
112
114
|
requestHistory;
|
|
113
115
|
/** Shortcut: get/set the editor text as a plain string. */
|
|
114
116
|
get input() { return this.inputEditor.text; }
|
|
@@ -125,6 +127,8 @@ export class PiUiExtendApp {
|
|
|
125
127
|
constructor(options) {
|
|
126
128
|
this.options = options;
|
|
127
129
|
this.theme = THEMES[options.themeName];
|
|
130
|
+
this.pixConfig = loadPixConfig(this.options.cwd);
|
|
131
|
+
setAppIconTheme(this.pixConfig.iconTheme.name);
|
|
128
132
|
const app = this;
|
|
129
133
|
this.blinkController = new AppBlinkController({
|
|
130
134
|
render: () => this.render(),
|
|
@@ -136,6 +140,7 @@ export class PiUiExtendApp {
|
|
|
136
140
|
get mouseSelection() { return app.mouseController.mouseSelection; },
|
|
137
141
|
});
|
|
138
142
|
this.toastController = new AppToastController({
|
|
143
|
+
activeScope: () => this.activeExtensionUiScope(),
|
|
139
144
|
render: () => this.render(),
|
|
140
145
|
});
|
|
141
146
|
this.nerdFontController = new NerdFontController({
|
|
@@ -155,14 +160,15 @@ export class PiUiExtendApp {
|
|
|
155
160
|
});
|
|
156
161
|
this.tabsController = new AppTabsController({
|
|
157
162
|
options: this.options,
|
|
163
|
+
maxProjectSessions: this.pixConfig.maxProjectSessions,
|
|
158
164
|
blinkController: this.blinkController,
|
|
159
165
|
runtime: () => this.runtime,
|
|
160
|
-
createRuntimeForNewSession: () =>
|
|
161
|
-
createRuntimeForSession: (sessionPath) =>
|
|
166
|
+
createRuntimeForNewSession: () => this.createRuntime(newTabRuntimeOptions(this.options)),
|
|
167
|
+
createRuntimeForSession: (sessionPath) => this.createRuntime({
|
|
162
168
|
...this.options,
|
|
163
169
|
noSession: false,
|
|
164
170
|
sessionPath,
|
|
165
|
-
}
|
|
171
|
+
}),
|
|
166
172
|
activateRuntime: (runtime) => this.activateRuntime(runtime),
|
|
167
173
|
disposeRuntime: (runtime) => this.terminalController.disposeRuntime(runtime),
|
|
168
174
|
isRunning: () => this.running,
|
|
@@ -173,16 +179,15 @@ export class PiUiExtendApp {
|
|
|
173
179
|
loadSessionHistory: () => this.loadSessionHistory(),
|
|
174
180
|
loadSessionHistoryAsync: (options) => this.loadSessionHistoryAsync(options),
|
|
175
181
|
syncUserSessionEntryMetadata: () => this.workspaceActions.syncUserSessionEntryMetadata(),
|
|
176
|
-
captureInputState: () =>
|
|
177
|
-
restoreInputState: (state) => this.restoreTabInputState(state
|
|
182
|
+
captureInputState: () => this.inputEditor.draftState,
|
|
183
|
+
restoreInputState: (state) => this.restoreTabInputState(state),
|
|
184
|
+
closeMenusForTabSwitch: () => this.popupMenus.closeMenusForTabSwitch(),
|
|
178
185
|
captureDeferredUserMessages: () => this.queuedMessages.captureDeferredUserMessages(),
|
|
179
186
|
restoreDeferredUserMessages: (messages) => this.queuedMessages.restoreDeferredUserMessages(messages),
|
|
180
187
|
addEntry: (entry) => this.addEntry(entry),
|
|
181
188
|
showToast: (message, kind) => this.showToast(message, kind),
|
|
182
189
|
render: () => this.render(),
|
|
183
190
|
});
|
|
184
|
-
this.pixConfig = loadPixConfig();
|
|
185
|
-
setAppIconTheme(this.pixConfig.iconTheme.name);
|
|
186
191
|
this.terminalBellSoundController = new TerminalBellSoundController();
|
|
187
192
|
this.promptEnhancer = new AppPromptEnhancerController({
|
|
188
193
|
runtime: () => this.runtime,
|
|
@@ -218,9 +223,17 @@ export class PiUiExtendApp {
|
|
|
218
223
|
getEntries: () => this.entries,
|
|
219
224
|
getResumeSessions: () => this.resumeSessions,
|
|
220
225
|
});
|
|
221
|
-
|
|
226
|
+
const popupMenuRenderer = new PopupMenuRenderer({
|
|
222
227
|
theme: this.theme,
|
|
223
228
|
screenStyler: this.screenStyler,
|
|
229
|
+
modelColors: this.pixConfig.modelColors,
|
|
230
|
+
get entries() { return app.entries; },
|
|
231
|
+
get session() { return app.runtime?.session; },
|
|
232
|
+
get resumeLoading() { return app.resumeLoading; },
|
|
233
|
+
get resumeSessionCount() { return app.resumeSessions.length; },
|
|
234
|
+
get userMessageJumpLoading() { return app.menuItems.isUserMessageJumpLoading(); },
|
|
235
|
+
});
|
|
236
|
+
this.popupMenus = new AppPopupMenuController({
|
|
224
237
|
get entries() { return app.entries; },
|
|
225
238
|
get session() { return app.runtime?.session; },
|
|
226
239
|
get resumeLoading() { return app.resumeLoading; },
|
|
@@ -241,7 +254,7 @@ export class PiUiExtendApp {
|
|
|
241
254
|
setStatus: (status) => this.setStatus(status),
|
|
242
255
|
restoreSessionStatus: () => this.restoreSessionStatus(),
|
|
243
256
|
render: () => this.render(),
|
|
244
|
-
});
|
|
257
|
+
}, popupMenuRenderer);
|
|
245
258
|
this.statusLineRenderer = new StatusLineRenderer({
|
|
246
259
|
theme: this.theme,
|
|
247
260
|
screenStyler: this.screenStyler,
|
|
@@ -277,10 +290,12 @@ export class PiUiExtendApp {
|
|
|
277
290
|
});
|
|
278
291
|
this.extensionUiController = new ExtensionUiController({
|
|
279
292
|
theme: this.theme,
|
|
293
|
+
activeExtensionUiScope: () => this.activeExtensionUiScope(),
|
|
280
294
|
isRunning: () => this.running,
|
|
281
295
|
render: () => this.render(),
|
|
282
|
-
showToast: (message, kind) => this.showToast(message, kind),
|
|
296
|
+
showToast: (message, kind, options) => this.showToast(message, kind, options),
|
|
283
297
|
toastNotifier: this.toastNotifier,
|
|
298
|
+
toastNotifierForScope: (scopeKey) => this.toastNotifierForScope(scopeKey),
|
|
284
299
|
menuController: this.popupMenus.menuController,
|
|
285
300
|
setStatus: (status) => this.setStatus(status),
|
|
286
301
|
restoreSessionStatus: () => this.restoreSessionStatus(),
|
|
@@ -328,11 +343,14 @@ export class PiUiExtendApp {
|
|
|
328
343
|
showToast: (message, kind) => this.showToast(message, kind),
|
|
329
344
|
render: () => this.render(),
|
|
330
345
|
isRunning: () => this.running,
|
|
346
|
+
forkSessionEntryInNewTab: (sessionEntryId) => this.tabsController.forkSessionEntryInNewTab(sessionEntryId),
|
|
331
347
|
});
|
|
332
348
|
this.sessionEvents = new AppSessionEventController({
|
|
333
349
|
entries: this.entries,
|
|
334
350
|
runtime: () => this.runtime,
|
|
335
351
|
conversationViewport: () => this.conversationViewport,
|
|
352
|
+
conversationViewportColumns: () => this.terminalColumns(),
|
|
353
|
+
onHistoryWindowPruned: (edge, lineCount) => this.scrollController.adjustForHistoryWindowPrune(edge, lineCount),
|
|
336
354
|
isRunning: () => this.running,
|
|
337
355
|
render: () => this.render(),
|
|
338
356
|
scheduleRender: () => this.scheduleRender(),
|
|
@@ -408,11 +426,15 @@ export class PiUiExtendApp {
|
|
|
408
426
|
terminalColumns: () => this.terminalColumns(),
|
|
409
427
|
terminalRows: () => this.terminalRows(),
|
|
410
428
|
tabPanelRows: (terminalRows) => this.tabsController.tabPanelRows(terminalRows),
|
|
429
|
+
hasOlderSessionHistory: () => this.sessionEvents.hasOlderSessionHistory(),
|
|
430
|
+
isLoadingOlderSessionHistory: () => this.sessionEvents.isLoadingOlderSessionHistory(),
|
|
431
|
+
loadOlderSessionHistory: (options) => this.sessionEvents.loadOlderSessionHistory(options),
|
|
411
432
|
render: () => this.render(),
|
|
412
433
|
});
|
|
413
434
|
this.commandController = new AppCommandController({
|
|
414
435
|
options: this.options,
|
|
415
436
|
runtime: () => this.runtime,
|
|
437
|
+
requestHistory: () => this.requestHistory,
|
|
416
438
|
getInput: () => this.input,
|
|
417
439
|
setInput: (value) => this.setInput(value),
|
|
418
440
|
promptEnhancerModelRef: () => this.pixConfig.promptEnhancer.modelRef,
|
|
@@ -421,6 +443,10 @@ export class PiUiExtendApp {
|
|
|
421
443
|
this.pixConfig.autocomplete.modelRef = modelRef;
|
|
422
444
|
this.autocompleteController.dispose();
|
|
423
445
|
},
|
|
446
|
+
ignoreContextFiles: () => this.pixConfig.ignoreContextFiles,
|
|
447
|
+
setIgnoreContextFiles: (ignoreContextFiles) => {
|
|
448
|
+
this.pixConfig.ignoreContextFiles = ignoreContextFiles;
|
|
449
|
+
},
|
|
424
450
|
enhancePrompt: () => this.promptEnhancer.enhancePrompt(),
|
|
425
451
|
isRunning: () => this.running,
|
|
426
452
|
stop: () => this.stop(),
|
|
@@ -452,6 +478,7 @@ export class PiUiExtendApp {
|
|
|
452
478
|
setDirectPopupMenuQuery: (query) => {
|
|
453
479
|
this.popupMenus.setDirectQuery(query);
|
|
454
480
|
},
|
|
481
|
+
refreshUserMessageJumpMenuItems: () => this.menuItems.refreshUserMessageJumpMenuItems(),
|
|
455
482
|
getResumeLoading: () => this.resumeLoading,
|
|
456
483
|
getResumeSessions: () => this.resumeSessions,
|
|
457
484
|
setResumeLoading: (loading) => {
|
|
@@ -481,6 +508,7 @@ export class PiUiExtendApp {
|
|
|
481
508
|
bindCurrentSession: () => this.bindCurrentSession(),
|
|
482
509
|
loadSessionHistory: () => this.loadSessionHistory(),
|
|
483
510
|
scrollToConversationEntry: (entryId) => this.scrollController.scrollToConversationEntry(entryId),
|
|
511
|
+
scrollToUserMessageJumpTarget: (target) => this.scrollToUserMessageJumpTarget(target),
|
|
484
512
|
}, this.popupMenus, this.commandController, this.menuItems, this.queuedMessages, this.workspaceActions);
|
|
485
513
|
this.mouseController = new AppMouseController({
|
|
486
514
|
terminalColumns: () => this.terminalColumns(),
|
|
@@ -519,10 +547,11 @@ export class PiUiExtendApp {
|
|
|
519
547
|
closeTab: (tabId) => {
|
|
520
548
|
void this.tabsController.closeTab(tabId);
|
|
521
549
|
},
|
|
522
|
-
toastEntry: (toastId) => this.toastController.
|
|
550
|
+
toastEntry: (toastId) => this.toastController.entry(toastId),
|
|
523
551
|
showToast: (message, kind, options) => this.showToast(message, kind, options),
|
|
524
552
|
dismissToast: (toastId) => this.toastController.dismissToast(toastId),
|
|
525
553
|
refreshModelUsageStatus: () => this.refreshModelUsageStatusFromClick(),
|
|
554
|
+
refreshUserMessageJumpMenuItems: () => this.menuItems.refreshUserMessageJumpMenuItems(),
|
|
526
555
|
queueInputFromStatus: () => {
|
|
527
556
|
void this.inputActions.queueInputFromEditor().catch((error) => {
|
|
528
557
|
this.addEntry({ id: createId("error"), kind: "error", text: `Queue input failed: ${error instanceof Error ? error.message : String(error)}` });
|
|
@@ -590,6 +619,7 @@ export class PiUiExtendApp {
|
|
|
590
619
|
addEntry: (entry) => this.addEntry(entry),
|
|
591
620
|
addSessionAbortedEntry: () => this.sessionEvents.addSessionAbortedEntry(),
|
|
592
621
|
showToast: (message, kind) => this.showToast(message, kind),
|
|
622
|
+
dismissActiveDialog: () => this.toastController.dismissActiveDialog(),
|
|
593
623
|
stopVoiceInput: () => this.voiceController.stopRecording(),
|
|
594
624
|
isShellCommandRunning: () => this.shellController.isRunning(),
|
|
595
625
|
runChatShellCommand: (command) => this.shellController.run(command),
|
|
@@ -653,7 +683,7 @@ export class PiUiExtendApp {
|
|
|
653
683
|
});
|
|
654
684
|
this.sessionLifecycle = new AppSessionLifecycleController({
|
|
655
685
|
options: this.options,
|
|
656
|
-
createRuntime: () =>
|
|
686
|
+
createRuntime: () => this.createRuntime(this.options),
|
|
657
687
|
entries: this.entries,
|
|
658
688
|
runtime: () => this.runtime,
|
|
659
689
|
setRuntime: (runtime) => {
|
|
@@ -671,8 +701,8 @@ export class PiUiExtendApp {
|
|
|
671
701
|
loadRequestHistory: () => this.requestHistory.load(),
|
|
672
702
|
startSubagentsPolling: () => this.subagentsWidgetController.startPolling(),
|
|
673
703
|
closeSdkMenuForBind: () => this.popupMenus.closeSdkMenu(undefined, { render: false, restoreStatus: false }),
|
|
674
|
-
clearExtensionWidgets: () => this.extensionUiController.clearWidgets(),
|
|
675
|
-
createExtensionUIContext: () => this.extensionUiController.createExtensionUIContext(),
|
|
704
|
+
clearExtensionWidgets: (scopeKey, options) => this.extensionUiController.clearWidgets(scopeKey, options),
|
|
705
|
+
createExtensionUIContext: (scopeKey) => this.extensionUiController.createExtensionUIContext(scopeKey),
|
|
676
706
|
extensionShutdownHandler: () => this.extensionShutdownHandler,
|
|
677
707
|
createExtensionCommandContextActions: (runtime) => this.extensionActions.createCommandContextActions(runtime),
|
|
678
708
|
handleExtensionError: (error) => this.extensionActions.handleExtensionError(error),
|
|
@@ -715,6 +745,11 @@ export class PiUiExtendApp {
|
|
|
715
745
|
});
|
|
716
746
|
this.slashCommands = this.commandController.slashCommands;
|
|
717
747
|
}
|
|
748
|
+
createRuntime(options) {
|
|
749
|
+
return createPixRuntime(options, {
|
|
750
|
+
eventBus: this.createExtensionEventBus(),
|
|
751
|
+
});
|
|
752
|
+
}
|
|
718
753
|
async start() {
|
|
719
754
|
await this.sessionLifecycle.start();
|
|
720
755
|
this.modelUsageController.startPolling();
|
|
@@ -766,6 +801,12 @@ export class PiUiExtendApp {
|
|
|
766
801
|
if (this.runtime)
|
|
767
802
|
this.setSessionStatus(this.runtime.session);
|
|
768
803
|
}
|
|
804
|
+
activeExtensionUiScope() {
|
|
805
|
+
const session = this.runtime?.session;
|
|
806
|
+
if (!session)
|
|
807
|
+
return undefined;
|
|
808
|
+
return session.sessionFile ?? session.sessionId;
|
|
809
|
+
}
|
|
769
810
|
setInput(value) {
|
|
770
811
|
if (value !== this.input) {
|
|
771
812
|
this.requestHistory.resetNavigation();
|
|
@@ -779,10 +820,10 @@ export class PiUiExtendApp {
|
|
|
779
820
|
this.popupMenus.resetInputMenuDismissals();
|
|
780
821
|
this.autocompleteController.dispose();
|
|
781
822
|
}
|
|
782
|
-
restoreTabInputState(
|
|
823
|
+
restoreTabInputState(state) {
|
|
783
824
|
this.requestHistory.resetNavigation();
|
|
784
825
|
this.popupMenus.resetInputMenuDismissals();
|
|
785
|
-
this.inputEditor.
|
|
826
|
+
this.inputEditor.setDraftState(state);
|
|
786
827
|
this.autocompleteController.dispose();
|
|
787
828
|
}
|
|
788
829
|
async clearPersistedInputDraft() {
|
|
@@ -818,7 +859,11 @@ export class PiUiExtendApp {
|
|
|
818
859
|
this.sessionLifecycle.resetSessionView();
|
|
819
860
|
}
|
|
820
861
|
loadSessionHistory() {
|
|
821
|
-
this.
|
|
862
|
+
void this.sessionEvents.loadSessionHistoryAsync({
|
|
863
|
+
isCancelled: () => !this.running,
|
|
864
|
+
render: () => this.render(),
|
|
865
|
+
lazyOlderHistory: true,
|
|
866
|
+
});
|
|
822
867
|
}
|
|
823
868
|
async openSearchResultInNewTab(result) {
|
|
824
869
|
const opened = await this.tabsController.openSessionInNewTab(result.session.path);
|
|
@@ -838,6 +883,23 @@ export class PiUiExtendApp {
|
|
|
838
883
|
this.showToast("Opened search result", "success");
|
|
839
884
|
this.setSessionStatus(this.runtime?.session);
|
|
840
885
|
}
|
|
886
|
+
async scrollToUserMessageJumpTarget(target) {
|
|
887
|
+
if (target.entryId && this.scrollController.scrollToConversationEntry(target.entryId))
|
|
888
|
+
return true;
|
|
889
|
+
if (!target.sessionEntryId)
|
|
890
|
+
return false;
|
|
891
|
+
let entry = this.findUserEntryBySessionEntryId(target.sessionEntryId);
|
|
892
|
+
while (!entry && this.sessionEvents.hasOlderSessionHistory() && !this.sessionEvents.isLoadingOlderSessionHistory()) {
|
|
893
|
+
const loaded = await this.sessionEvents.loadOlderSessionHistory({ render: false });
|
|
894
|
+
if (!loaded)
|
|
895
|
+
break;
|
|
896
|
+
entry = this.findUserEntryBySessionEntryId(target.sessionEntryId);
|
|
897
|
+
}
|
|
898
|
+
return entry ? this.scrollController.scrollToConversationEntry(entry.id) : false;
|
|
899
|
+
}
|
|
900
|
+
findUserEntryBySessionEntryId(sessionEntryId) {
|
|
901
|
+
return this.entries.find((entry) => entry.kind === "user" && entry.sessionEntryId === sessionEntryId);
|
|
902
|
+
}
|
|
841
903
|
async loadSessionHistoryAsync(options) {
|
|
842
904
|
return this.sessionEvents.loadSessionHistoryAsync(options);
|
|
843
905
|
}
|
|
@@ -928,6 +990,20 @@ export class PiUiExtendApp {
|
|
|
928
990
|
showToast(message, kind = "info", options) {
|
|
929
991
|
this.toastController.showToast(message, kind, options);
|
|
930
992
|
}
|
|
993
|
+
toastNotifierForScope(scopeKey) {
|
|
994
|
+
const options = () => {
|
|
995
|
+
if (scopeKey === undefined)
|
|
996
|
+
return {};
|
|
997
|
+
return { scopeKey };
|
|
998
|
+
};
|
|
999
|
+
return {
|
|
1000
|
+
show: (message, kind = "info") => this.showToast(message, kind, options()),
|
|
1001
|
+
success: (message) => this.showToast(message, "success", options()),
|
|
1002
|
+
error: (message) => this.showToast(message, "error", options()),
|
|
1003
|
+
warning: (message) => this.showToast(message, "warning", options()),
|
|
1004
|
+
info: (message) => this.showToast(message, "info", options()),
|
|
1005
|
+
};
|
|
1006
|
+
}
|
|
931
1007
|
clearToastTimers() {
|
|
932
1008
|
this.toastController.clearToastTimers();
|
|
933
1009
|
}
|
|
@@ -937,6 +1013,7 @@ export class PiUiExtendApp {
|
|
|
937
1013
|
this.scheduledRenderTimer = undefined;
|
|
938
1014
|
}
|
|
939
1015
|
this.autocompleteController.observeInput();
|
|
1016
|
+
this.syncScrollAfterInputEditorChange();
|
|
940
1017
|
this.renderController.render();
|
|
941
1018
|
}
|
|
942
1019
|
scheduleRender() {
|
|
@@ -944,10 +1021,18 @@ export class PiUiExtendApp {
|
|
|
944
1021
|
return;
|
|
945
1022
|
this.scheduledRenderTimer = setTimeout(() => {
|
|
946
1023
|
this.scheduledRenderTimer = undefined;
|
|
1024
|
+
this.syncScrollAfterInputEditorChange();
|
|
947
1025
|
this.renderController.render();
|
|
948
1026
|
}, COALESCED_RENDER_DELAY_MS);
|
|
949
1027
|
this.scheduledRenderTimer.unref?.();
|
|
950
1028
|
}
|
|
1029
|
+
syncScrollAfterInputEditorChange() {
|
|
1030
|
+
const contentVersion = this.inputEditor.contentVersion;
|
|
1031
|
+
if (contentVersion === this.lastInputEditorContentVersion)
|
|
1032
|
+
return;
|
|
1033
|
+
this.lastInputEditorContentVersion = contentVersion;
|
|
1034
|
+
this.scrollController.scrollToBottom();
|
|
1035
|
+
}
|
|
951
1036
|
renderStatusLine() {
|
|
952
1037
|
this.renderController.renderStatusLine();
|
|
953
1038
|
}
|
|
@@ -30,6 +30,7 @@ export class AppCommandController {
|
|
|
30
30
|
runModelSlashCommand: (argumentsText) => this.modelActions.runModelSlashCommand(argumentsText),
|
|
31
31
|
runDefaultModelSlashCommand: (argumentsText) => this.modelActions.runDefaultModelSlashCommand(argumentsText),
|
|
32
32
|
runAutocompleteSlashCommand: (argumentsText) => this.modelActions.runAutocompleteSlashCommand(argumentsText),
|
|
33
|
+
runNoContextFilesSlashCommand: (argumentsText) => this.modelActions.runNoContextFilesSlashCommand(argumentsText),
|
|
33
34
|
runScopedModelsCommand: (argumentsText) => this.modelActions.runScopedModelsCommand(argumentsText),
|
|
34
35
|
runThinkingSlashCommand: (argumentsText) => this.modelActions.runThinkingSlashCommand(argumentsText),
|
|
35
36
|
runDefaultThinkingSlashCommand: (argumentsText) => this.modelActions.runDefaultThinkingSlashCommand(argumentsText),
|
|
@@ -53,6 +54,7 @@ export class AppCommandController {
|
|
|
53
54
|
runCloneCommand: () => this.navigationActions.runCloneCommand(),
|
|
54
55
|
runTreeCommand: (argumentsText) => this.navigationActions.runTreeCommand(argumentsText),
|
|
55
56
|
runJumpCommand: (argumentsText) => this.navigationActions.runJumpCommand(argumentsText),
|
|
57
|
+
runHistoryCommand: (argumentsText) => this.navigationActions.runHistoryCommand(argumentsText),
|
|
56
58
|
runSearchCommand: (argumentsText) => this.navigationActions.runSearchCommand(argumentsText),
|
|
57
59
|
runUnsupportedBuiltinCommand: (commandName, message) => this.navigationActions.runUnsupportedBuiltinCommand(commandName, message),
|
|
58
60
|
runResumePathCommand: (sessionPath) => this.navigationActions.runResumePathCommand(sessionPath),
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import type { AgentSession, AgentSessionRuntime, SessionInfo } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import type { SessionSearchResult } from "../session/session-search.js";
|
|
3
|
+
import type { AppRequestHistory } from "../session/request-history.js";
|
|
3
4
|
import type { ActivePopupMenu, AppOptions, Entry, ModelMenuValue, PixMenuItem, PixMenuOptions, PopupMenuPlacement, ScopedSessionModel, SessionModel, ThinkingMenuValue } from "../types.js";
|
|
4
5
|
import type { ToastNotifier } from "../../ui.js";
|
|
5
6
|
export type DirectPopupMenu = Exclude<ActivePopupMenu, "slash">;
|
|
6
7
|
export type CommandControllerHost = {
|
|
7
8
|
readonly options: AppOptions;
|
|
8
9
|
runtime(): AgentSessionRuntime | undefined;
|
|
10
|
+
requestHistory(): AppRequestHistory;
|
|
9
11
|
getInput(): string;
|
|
10
12
|
setInput(value: string): void;
|
|
11
13
|
promptEnhancerModelRef(): string;
|
|
12
14
|
autocompleteModelRef(): string;
|
|
13
15
|
setAutocompleteModelRef(modelRef: string): void;
|
|
16
|
+
ignoreContextFiles(): boolean;
|
|
17
|
+
setIgnoreContextFiles(ignoreContextFiles: boolean): void;
|
|
14
18
|
enhancePrompt(): Promise<void>;
|
|
15
19
|
isRunning(): boolean;
|
|
16
20
|
stop(): void | Promise<void>;
|
|
@@ -37,6 +41,7 @@ export type CommandControllerHost = {
|
|
|
37
41
|
setDirectPopupMenuPreserveStatus(preserveStatus: boolean): void;
|
|
38
42
|
getDirectPopupMenuQuery(): string;
|
|
39
43
|
setDirectPopupMenuQuery(query: string): void;
|
|
44
|
+
refreshUserMessageJumpMenuItems(): Promise<void>;
|
|
40
45
|
getResumeLoading(): boolean;
|
|
41
46
|
getResumeSessions(): readonly SessionInfo[];
|
|
42
47
|
setResumeLoading(loading: boolean): void;
|
|
@@ -7,11 +7,13 @@ export declare class ModelCommandActions {
|
|
|
7
7
|
runModelSlashCommand(argumentsText: string): Promise<void>;
|
|
8
8
|
runDefaultModelSlashCommand(argumentsText: string): Promise<void>;
|
|
9
9
|
runAutocompleteSlashCommand(argumentsText: string): Promise<void>;
|
|
10
|
+
runNoContextFilesSlashCommand(argumentsText: string): Promise<void>;
|
|
10
11
|
runScopedModelsCommand(argumentsText: string): Promise<void>;
|
|
11
12
|
runThinkingSlashCommand(argumentsText: string): Promise<void>;
|
|
12
13
|
runDefaultThinkingSlashCommand(argumentsText: string): Promise<void>;
|
|
13
14
|
runModelCommand(model: SessionModel): Promise<void>;
|
|
14
15
|
runThinkingCommand(level: ThinkingLevel): Promise<void>;
|
|
16
|
+
private addPersistentSystemEntry;
|
|
15
17
|
private saveDefaultModel;
|
|
16
18
|
private saveDefaultThinking;
|
|
17
19
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { getIdleRuntime, getRuntime } from "./command-runtime.js";
|
|
2
|
-
import { savePixAutocompleteModel, savePixDefaultModel, savePixDefaultThinking } from "../../config.js";
|
|
2
|
+
import { getProjectPixConfigPath, savePixAutocompleteModel, savePixDefaultModel, savePixDefaultThinking, saveProjectPixIgnoreContextFiles } from "../../config.js";
|
|
3
3
|
import { createId } from "../id.js";
|
|
4
4
|
import { isThinkingLevel, parseScopedModelRef } from "../model/model-ref.js";
|
|
5
|
+
import { appendPixSystemDisplayEntry } from "../session/pix-system-message.js";
|
|
5
6
|
export class ModelCommandActions {
|
|
6
7
|
host;
|
|
7
8
|
constructor(host) {
|
|
@@ -24,6 +25,7 @@ export class ModelCommandActions {
|
|
|
24
25
|
`model: ${currentModel}`,
|
|
25
26
|
`prompt enhancer model: ${this.host.promptEnhancerModelRef()}`,
|
|
26
27
|
`autocomplete model: ${this.host.autocompleteModelRef() || "disabled"}`,
|
|
28
|
+
`context files: ${this.host.ignoreContextFiles() ? "disabled" : "enabled"}`,
|
|
27
29
|
`thinking: ${runtime.session.thinkingLevel}`,
|
|
28
30
|
`theme: ${settings.getTheme() ?? this.host.options.themeName}`,
|
|
29
31
|
`skill commands: ${settings.getEnableSkillCommands() ? "enabled" : "disabled"}`,
|
|
@@ -33,7 +35,7 @@ export class ModelCommandActions {
|
|
|
33
35
|
"scoped models:",
|
|
34
36
|
scopedModelText,
|
|
35
37
|
"",
|
|
36
|
-
"Use /model, /thinking, /scoped-models, /export, /import, /reload for editable settings in pix.",
|
|
38
|
+
"Use /model, /thinking, /no-context-files, /scoped-models, /export, /import, /reload for editable settings in pix.",
|
|
37
39
|
].join("\n");
|
|
38
40
|
this.host.addEntry({ id: createId("system"), kind: "system", text });
|
|
39
41
|
this.host.setSessionStatus(runtime.session);
|
|
@@ -68,7 +70,7 @@ export class ModelCommandActions {
|
|
|
68
70
|
await this.runModelCommand(model);
|
|
69
71
|
if (parsed.thinkingLevel !== undefined) {
|
|
70
72
|
runtime.session.setThinkingLevel(parsed.thinkingLevel);
|
|
71
|
-
this.
|
|
73
|
+
this.addPersistentSystemEntry(runtime.session, `Selected thinking level ${runtime.session.thinkingLevel}`);
|
|
72
74
|
this.host.setSessionStatus(runtime.session);
|
|
73
75
|
}
|
|
74
76
|
}
|
|
@@ -125,6 +127,36 @@ export class ModelCommandActions {
|
|
|
125
127
|
this.host.addEntry({ id: createId("system"), kind: "system", text: `Autocomplete model set to ${saved.modelRef}.` });
|
|
126
128
|
this.host.setSessionStatus(runtime.session);
|
|
127
129
|
}
|
|
130
|
+
async runNoContextFilesSlashCommand(argumentsText) {
|
|
131
|
+
const value = argumentsText.trim().toLowerCase();
|
|
132
|
+
if (!value) {
|
|
133
|
+
this.host.addEntry({
|
|
134
|
+
id: createId("system"),
|
|
135
|
+
kind: "system",
|
|
136
|
+
text: [
|
|
137
|
+
`Context file loading is currently ${this.host.ignoreContextFiles() ? "disabled" : "enabled"} for this project.`,
|
|
138
|
+
"Usage: /no-context-files <on|off>",
|
|
139
|
+
].join("\n"),
|
|
140
|
+
});
|
|
141
|
+
this.host.setSessionStatus(this.host.runtime()?.session);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (value !== "on" && value !== "off")
|
|
145
|
+
throw new Error("Usage: /no-context-files <on|off>");
|
|
146
|
+
const ignoreContextFiles = value === "on";
|
|
147
|
+
const saved = saveProjectPixIgnoreContextFiles(this.host.options.cwd, ignoreContextFiles);
|
|
148
|
+
this.host.setIgnoreContextFiles(saved);
|
|
149
|
+
this.host.addEntry({
|
|
150
|
+
id: createId("system"),
|
|
151
|
+
kind: "system",
|
|
152
|
+
text: [
|
|
153
|
+
`Context file loading ${saved ? "disabled" : "enabled"} for this project.`,
|
|
154
|
+
`Saved ignoreContextFiles=${saved ? "true" : "false"} to ${getProjectPixConfigPath(this.host.options.cwd)}.`,
|
|
155
|
+
"Start a new session or restart Pix for the change to affect loaded AGENTS.md/CLAUDE.md context.",
|
|
156
|
+
].join("\n"),
|
|
157
|
+
});
|
|
158
|
+
this.host.setSessionStatus(this.host.runtime()?.session);
|
|
159
|
+
}
|
|
128
160
|
async runScopedModelsCommand(argumentsText) {
|
|
129
161
|
const runtime = getIdleRuntime(this.host, "scoped-models");
|
|
130
162
|
if (!runtime)
|
|
@@ -246,9 +278,13 @@ export class ModelCommandActions {
|
|
|
246
278
|
this.host.setStatus(`selecting thinking ${level}`);
|
|
247
279
|
this.host.render();
|
|
248
280
|
runtime.session.setThinkingLevel(level);
|
|
249
|
-
this.
|
|
281
|
+
this.addPersistentSystemEntry(runtime.session, `Selected thinking level ${runtime.session.thinkingLevel}`);
|
|
250
282
|
this.host.setSessionStatus(runtime.session);
|
|
251
283
|
}
|
|
284
|
+
addPersistentSystemEntry(session, text) {
|
|
285
|
+
appendPixSystemDisplayEntry(session, text);
|
|
286
|
+
this.host.addEntry({ id: createId("system"), kind: "system", text });
|
|
287
|
+
}
|
|
252
288
|
saveDefaultModel(modelRef) {
|
|
253
289
|
const saved = savePixDefaultModel(modelRef);
|
|
254
290
|
if (!saved)
|
|
@@ -2,6 +2,14 @@ import type { SessionInfo } from "@earendil-works/pi-coding-agent";
|
|
|
2
2
|
import type { CommandControllerHost } from "./command-host.js";
|
|
3
3
|
import { type ResumeSessionLoaderOptions } from "../session/resume-session-loader.js";
|
|
4
4
|
import type { PopupMenuPlacement } from "../types.js";
|
|
5
|
+
export declare function formatHistoryMenuLabel(text: string): string;
|
|
6
|
+
export declare function historyHighlightRanges(ranges: readonly {
|
|
7
|
+
start: number;
|
|
8
|
+
end: number;
|
|
9
|
+
}[], text: string): {
|
|
10
|
+
start: number;
|
|
11
|
+
end: number;
|
|
12
|
+
}[];
|
|
5
13
|
export declare class NavigationCommandActions {
|
|
6
14
|
private readonly host;
|
|
7
15
|
private readonly resumeSessionLoader;
|
|
@@ -11,6 +19,7 @@ export declare class NavigationCommandActions {
|
|
|
11
19
|
runCloneCommand(): Promise<void>;
|
|
12
20
|
runTreeCommand(argumentsText: string): Promise<void>;
|
|
13
21
|
runJumpCommand(argumentsText: string): Promise<void>;
|
|
22
|
+
runHistoryCommand(argumentsText: string): Promise<void>;
|
|
14
23
|
runSearchCommand(argumentsText: string): Promise<void>;
|
|
15
24
|
runUnsupportedBuiltinCommand(commandName: string, message: string): Promise<void>;
|
|
16
25
|
runResumePathCommand(sessionPath: string): Promise<void>;
|
|
@@ -11,6 +11,24 @@ function nextTick() {
|
|
|
11
11
|
setImmediate(resolve);
|
|
12
12
|
});
|
|
13
13
|
}
|
|
14
|
+
export function formatHistoryMenuLabel(text) {
|
|
15
|
+
return sanitizeText(text).replace(/\n/g, " ↵ ");
|
|
16
|
+
}
|
|
17
|
+
export function historyHighlightRanges(ranges, text) {
|
|
18
|
+
return ranges.map((range) => ({
|
|
19
|
+
start: historyLabelIndex(range.start, text),
|
|
20
|
+
end: historyLabelIndex(range.end, text),
|
|
21
|
+
})).filter((range) => range.end > range.start);
|
|
22
|
+
}
|
|
23
|
+
function historyLabelIndex(index, text) {
|
|
24
|
+
const before = text.slice(0, Math.max(0, Math.min(index, text.length)));
|
|
25
|
+
const newlineCount = before.split("\n").length - 1;
|
|
26
|
+
return before.length + newlineCount * 2;
|
|
27
|
+
}
|
|
28
|
+
function formatHistoryMenuDescription(text) {
|
|
29
|
+
const lines = sanitizeText(text).split("\n");
|
|
30
|
+
return lines.length > 1 ? `${lines.length} lines` : undefined;
|
|
31
|
+
}
|
|
14
32
|
export class NavigationCommandActions {
|
|
15
33
|
host;
|
|
16
34
|
resumeSessionLoader;
|
|
@@ -101,6 +119,50 @@ export class NavigationCommandActions {
|
|
|
101
119
|
this.host.openDirectPopupMenu("user-message-jump", { preserveStatus: true });
|
|
102
120
|
this.host.setDirectPopupMenuQuery(argumentsText.trim());
|
|
103
121
|
this.host.render();
|
|
122
|
+
try {
|
|
123
|
+
await this.host.refreshUserMessageJumpMenuItems();
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
this.host.toast.error(`Could not load jump messages: ${error instanceof Error ? error.message : String(error)}`);
|
|
127
|
+
}
|
|
128
|
+
finally {
|
|
129
|
+
this.host.render();
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async runHistoryCommand(argumentsText) {
|
|
133
|
+
const query = argumentsText.trim();
|
|
134
|
+
const matches = this.host.requestHistory().searchMatches(query, 100);
|
|
135
|
+
if (matches.length === 0) {
|
|
136
|
+
this.host.addEntry({ id: createId("system"), kind: "system", text: query ? `No command history found for: ${query}` : "Command history is empty." });
|
|
137
|
+
this.host.toast.info(query ? "No matching command history" : "Command history is empty");
|
|
138
|
+
this.host.setSessionStatus(this.host.runtime()?.session);
|
|
139
|
+
this.host.render();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const selected = await this.host.showMenu(matches.map((match) => {
|
|
143
|
+
const description = formatHistoryMenuDescription(match.value);
|
|
144
|
+
return {
|
|
145
|
+
value: match.value,
|
|
146
|
+
label: formatHistoryMenuLabel(match.value),
|
|
147
|
+
labelHighlightRanges: match.matchedText === match.label ? historyHighlightRanges(match.matchedRanges, match.value) : [],
|
|
148
|
+
...(description === undefined ? {} : { description }),
|
|
149
|
+
};
|
|
150
|
+
}), {
|
|
151
|
+
title: query ? `Search command history: ${query}` : "Command history",
|
|
152
|
+
placeholder: "Filter history",
|
|
153
|
+
emptyText: "No matching command history",
|
|
154
|
+
searchable: true,
|
|
155
|
+
minScorePerCharacter: 8,
|
|
156
|
+
preferKeyboardLayoutMatches: true,
|
|
157
|
+
});
|
|
158
|
+
if (!selected) {
|
|
159
|
+
this.host.setSessionStatus(this.host.runtime()?.session);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
this.host.setInput(selected);
|
|
163
|
+
this.host.toast.info("Restored command from history");
|
|
164
|
+
this.host.setSessionStatus(this.host.runtime()?.session);
|
|
165
|
+
this.host.render();
|
|
104
166
|
}
|
|
105
167
|
async runSearchCommand(argumentsText) {
|
|
106
168
|
const runtime = getIdleRuntime(this.host, "search");
|
|
@@ -5,6 +5,7 @@ export type CommandRegistryActions = {
|
|
|
5
5
|
runModelSlashCommand(argumentsText: string): Promise<void>;
|
|
6
6
|
runDefaultModelSlashCommand(argumentsText: string): Promise<void>;
|
|
7
7
|
runAutocompleteSlashCommand(argumentsText: string): Promise<void>;
|
|
8
|
+
runNoContextFilesSlashCommand(argumentsText: string): Promise<void>;
|
|
8
9
|
runScopedModelsCommand(argumentsText: string): Promise<void>;
|
|
9
10
|
runThinkingSlashCommand(argumentsText: string): Promise<void>;
|
|
10
11
|
runDefaultThinkingSlashCommand(argumentsText: string): Promise<void>;
|
|
@@ -24,6 +25,7 @@ export type CommandRegistryActions = {
|
|
|
24
25
|
runCloneCommand(): Promise<void>;
|
|
25
26
|
runTreeCommand(argumentsText: string): Promise<void>;
|
|
26
27
|
runJumpCommand(argumentsText: string): Promise<void>;
|
|
28
|
+
runHistoryCommand(argumentsText: string): Promise<void>;
|
|
27
29
|
runSearchCommand(argumentsText: string): Promise<void>;
|
|
28
30
|
runUnsupportedBuiltinCommand(commandName: string, message: string): Promise<void>;
|
|
29
31
|
runReloadCommand(): Promise<void>;
|