@agi-fans/dsh-tui 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/autocomplete.js +0 -2
- package/lib/autocomplete.js.map +1 -1
- package/lib/{command-queue.d.ts → command-export.d.ts} +2 -2
- package/lib/command-export.js +39 -0
- package/lib/command-export.js.map +1 -0
- package/lib/{command-transcript.d.ts → command-permission.d.ts} +2 -2
- package/lib/{command-mode.js → command-permission.js} +28 -21
- package/lib/command-permission.js.map +1 -0
- package/lib/command-session.js +1 -1
- package/lib/command-session.js.map +1 -1
- package/lib/{command-mode.d.ts → command-steer.d.ts} +2 -2
- package/lib/command-steer.js +18 -0
- package/lib/command-steer.js.map +1 -0
- package/lib/definition.d.ts +14 -0
- package/lib/event-views.d.ts +32 -8
- package/lib/event-views.js +249 -45
- package/lib/event-views.js.map +1 -1
- package/lib/hotkeys.d.ts +2 -5
- package/lib/hotkeys.js +4 -14
- package/lib/hotkeys.js.map +1 -1
- package/lib/provider-local.d.ts +4 -1
- package/lib/provider-local.js +171 -43
- package/lib/provider-local.js.map +1 -1
- package/lib/renderer.d.ts +2 -0
- package/lib/renderer.js +48 -25
- package/lib/renderer.js.map +1 -1
- package/lib/runner.js +28 -0
- package/lib/runner.js.map +1 -1
- package/lib/session-controller.d.ts +27 -3
- package/lib/session-controller.js +206 -8
- package/lib/session-controller.js.map +1 -1
- package/lib/welcome-tips.js +2 -2
- package/lib/welcome-tips.js.map +1 -1
- package/package.json +13 -12
- package/lib/command-mode.js.map +0 -1
- package/lib/command-queue.js +0 -62
- package/lib/command-queue.js.map +0 -1
- package/lib/command-transcript.js +0 -85
- package/lib/command-transcript.js.map +0 -1
- package/lib/pwd.d.ts +0 -13
- package/lib/pwd.js +0 -14
- package/lib/pwd.js.map +0 -1
package/lib/provider-local.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Owns the tty: raw-mode key input (editing, history, slash/tab
|
|
5
5
|
* autocomplete, /settings overlay, /copy picker, Ctrl-R history search, PgUp/PgDn
|
|
6
6
|
* and mouse-wheel transcript scroll, click-to-caret, Ctrl-O tool
|
|
7
|
-
* expand, bracketed paste, double Ctrl-C exit, Ctrl-D quit),
|
|
7
|
+
* expand, bracketed paste, double-Escape conversation rewind, double Ctrl-C exit, Ctrl-D quit),
|
|
8
8
|
* SIGWINCH reflow, and the differential renderer. In non-tty mode
|
|
9
9
|
* (pipes, CI) it degrades to line-based input with plain append-only
|
|
10
10
|
* printing of settled blocks.
|
|
@@ -22,12 +22,11 @@ import { buildCopyTargets, extractCopyTarget, parseCopyKind } from "./copy-targe
|
|
|
22
22
|
import { applyHistorySearchEvent, createHistorySearch, hitTestHistorySearch, } from "./history-search.js";
|
|
23
23
|
import { InputEditor, lineEnd, lineStart } from "./editor.js";
|
|
24
24
|
import { applySettingsEvent, createSettings, hitTestSettings, selectSetting, tuiSettingItems, } from "./settings-list.js";
|
|
25
|
-
import { applyEvent, blockLines, initialTranscript, renderView, TRANSCRIPT_FAST_SCROLL, TRANSCRIPT_WHEEL_SCROLL, } from "./event-views.js";
|
|
25
|
+
import { applyEvent, blockLines, initialTranscript, replayEvents, renderView, TRANSCRIPT_FAST_SCROLL, TRANSCRIPT_WHEEL_SCROLL, } from "./event-views.js";
|
|
26
26
|
import { flushPending, MOUSE_TRACKING_OFF, MOUSE_TRACKING_ON, parseKeys } from "./keys.js";
|
|
27
27
|
import { LineRenderer } from "./renderer.js";
|
|
28
28
|
import { hitTestEditor } from "./box.js";
|
|
29
29
|
import { createTheme, detectTrueColor, parseThemeName } from "./theme.js";
|
|
30
|
-
import { formatWorkspaceText } from "./pwd.js";
|
|
31
30
|
import { TUI_SETTINGS_NAMESPACE, TuiSettingsSchema } from "./tui-settings.js";
|
|
32
31
|
import { defaultStatusBarConfig, resolveStatusBarConfig } from "./status-config.js";
|
|
33
32
|
import { HistoryStore } from "./history-store.js";
|
|
@@ -37,10 +36,12 @@ import { settingsNamespace } from '@deepseek-ai/dsh-settings';
|
|
|
37
36
|
import { movePromptSelection, filteredPromptOptions, selectedPromptAnswer, selectedFilteredPromptAnswer, togglePromptSelection, } from "./prompt-selector.js";
|
|
38
37
|
import { resolveProjectContext } from "./project-context.js";
|
|
39
38
|
import { pickWelcomeTips } from "./welcome-tips.js";
|
|
39
|
+
import { formatHotkeysText, hotkeyCount } from "./hotkeys.js";
|
|
40
40
|
import { imageMarker, imagePathCandidates, probeImageDimensions, readImageFile, readImageFromClipboard, readMacClipboardFiles, } from "./image-paste.js";
|
|
41
41
|
const APP_NAME = 'omdsh';
|
|
42
42
|
const APP_VERSION = '0.1.0';
|
|
43
43
|
const DOUBLE_CTRL_C_MS = 500;
|
|
44
|
+
const DOUBLE_ESCAPE_MS = 500;
|
|
44
45
|
function shortenPath(cwd) {
|
|
45
46
|
const home = homedir();
|
|
46
47
|
if (cwd === home)
|
|
@@ -50,8 +51,6 @@ function shortenPath(cwd) {
|
|
|
50
51
|
return cwd;
|
|
51
52
|
}
|
|
52
53
|
export const name = 'omdsh-tui';
|
|
53
|
-
/** Harness commands replaced by terminal-native interaction surfaces. */
|
|
54
|
-
const HIDDEN_RUNTIME_COMMANDS = new Set(['permission']);
|
|
55
54
|
/**
|
|
56
55
|
* Local terminal presentation service.
|
|
57
56
|
*/
|
|
@@ -73,11 +72,17 @@ export class LocalTui {
|
|
|
73
72
|
#settings = null;
|
|
74
73
|
#copySelector = null;
|
|
75
74
|
#pending = null;
|
|
76
|
-
#
|
|
75
|
+
#queuedSubmissions = [];
|
|
76
|
+
/** Newer queue entries temporarily detached while Up browses backward. */
|
|
77
|
+
#queueEditNewer = null;
|
|
78
|
+
#queueEditPending = false;
|
|
77
79
|
#quitRequested = false;
|
|
78
80
|
#resumeHintRequested = false;
|
|
79
81
|
#lastSigintTime = 0;
|
|
82
|
+
#lastEscapeTime = 0;
|
|
80
83
|
#interrupts = new Set();
|
|
84
|
+
#queueEdits = new Set();
|
|
85
|
+
#rewinds = new Set();
|
|
81
86
|
#disposed = false;
|
|
82
87
|
#pendingKeys = '';
|
|
83
88
|
#escapeTimer = null;
|
|
@@ -202,6 +207,8 @@ export class LocalTui {
|
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
209
|
setStatus(status) {
|
|
210
|
+
if (this.#state.status === 'compacting')
|
|
211
|
+
return;
|
|
205
212
|
this.#state = { ...this.#state, status };
|
|
206
213
|
this.#syncTick();
|
|
207
214
|
if (this.#tty)
|
|
@@ -282,10 +289,8 @@ export class LocalTui {
|
|
|
282
289
|
});
|
|
283
290
|
}
|
|
284
291
|
replaceSession(events, presentations) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
state = applyEvent(state, event, presentations?.get(event.seq));
|
|
288
|
-
this.#state = { ...state, status: 'idle' };
|
|
292
|
+
const state = replayEvents(events, presentations);
|
|
293
|
+
this.#state = { ...state, status: 'idle', compactCommandId: undefined };
|
|
289
294
|
this.#plainPrinted = 0;
|
|
290
295
|
this.#followTail();
|
|
291
296
|
if (this.#tty)
|
|
@@ -337,9 +342,11 @@ export class LocalTui {
|
|
|
337
342
|
return this.#readlinePlain();
|
|
338
343
|
// Lines submitted while a turn was still running were queued instead of
|
|
339
344
|
// dropped; serve the oldest before waiting for fresh input.
|
|
340
|
-
const queued = this.#
|
|
341
|
-
if (queued !== undefined)
|
|
345
|
+
const queued = this.#queuedSubmissions.shift();
|
|
346
|
+
if (queued !== undefined) {
|
|
347
|
+
this.#render();
|
|
342
348
|
return Promise.resolve(queued);
|
|
349
|
+
}
|
|
343
350
|
return new Promise((resolve) => {
|
|
344
351
|
this.#pending = { resolve };
|
|
345
352
|
});
|
|
@@ -363,10 +370,49 @@ export class LocalTui {
|
|
|
363
370
|
if (this.#tty)
|
|
364
371
|
this.#render();
|
|
365
372
|
}
|
|
373
|
+
resolveQueueEdit(submission) {
|
|
374
|
+
if (!this.#queueEditPending)
|
|
375
|
+
return;
|
|
376
|
+
this.#queueEditPending = false;
|
|
377
|
+
if (submission === null) {
|
|
378
|
+
if (this.#editor.text === '' && this.#images.length === 0 && this.#queueEditNewer?.length === 0) {
|
|
379
|
+
this.#queueEditNewer = null;
|
|
380
|
+
}
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
if (this.#queueEditNewer === null)
|
|
384
|
+
this.#queueEditNewer = [];
|
|
385
|
+
if (this.#editor.text !== '' || this.#images.length > 0) {
|
|
386
|
+
this.#queueEditNewer.unshift(this.#currentSubmission());
|
|
387
|
+
}
|
|
388
|
+
this.#replaceInput(submission);
|
|
389
|
+
}
|
|
390
|
+
#currentSubmission() {
|
|
391
|
+
return {
|
|
392
|
+
text: this.#editor.text,
|
|
393
|
+
images: this.#images.map(image => ({ ...image })),
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
#replaceInput(submission) {
|
|
397
|
+
this.#images = submission.images.map(image => ({ ...image }));
|
|
398
|
+
this.#editor.setText(submission.text);
|
|
399
|
+
this.#historyIndex = 0;
|
|
400
|
+
this.#refreshAutocomplete();
|
|
401
|
+
if (this.#tty)
|
|
402
|
+
this.#render();
|
|
403
|
+
}
|
|
366
404
|
onInterrupt(listener) {
|
|
367
405
|
this.#interrupts.add(listener);
|
|
368
406
|
return () => { this.#interrupts.delete(listener); };
|
|
369
407
|
}
|
|
408
|
+
onQueueEdit(listener) {
|
|
409
|
+
this.#queueEdits.add(listener);
|
|
410
|
+
return () => { this.#queueEdits.delete(listener); };
|
|
411
|
+
}
|
|
412
|
+
onRewind(listener) {
|
|
413
|
+
this.#rewinds.add(listener);
|
|
414
|
+
return () => { this.#rewinds.delete(listener); };
|
|
415
|
+
}
|
|
370
416
|
dispose() {
|
|
371
417
|
if (this.#disposed)
|
|
372
418
|
return;
|
|
@@ -471,7 +517,7 @@ export class LocalTui {
|
|
|
471
517
|
this.#term.output.write(out);
|
|
472
518
|
}
|
|
473
519
|
#busy() {
|
|
474
|
-
if (this.#state.status
|
|
520
|
+
if (this.#state.status !== 'idle')
|
|
475
521
|
return true;
|
|
476
522
|
return this.#state.blocks.some((block) => block.kind === 'tool' && block.status === 'running');
|
|
477
523
|
}
|
|
@@ -506,6 +552,9 @@ export class LocalTui {
|
|
|
506
552
|
input: this.#editor.text,
|
|
507
553
|
inputCursor: this.#editor.cursor,
|
|
508
554
|
inputImages: this.#images.length,
|
|
555
|
+
queuedSubmissions: this.#queueEditNewer === null
|
|
556
|
+
? this.#queuedSubmissions
|
|
557
|
+
: [...this.#queuedSubmissions, ...this.#queueEditNewer],
|
|
509
558
|
colors: this.#colors,
|
|
510
559
|
pwd: this.#pwd,
|
|
511
560
|
...(this.#branch !== undefined ? { branch: this.#branch } : {}),
|
|
@@ -761,6 +810,22 @@ export class LocalTui {
|
|
|
761
810
|
this.#editor.setText(text, Math.min(this.#editor.cursor, text.length));
|
|
762
811
|
}
|
|
763
812
|
#dispatch(event) {
|
|
813
|
+
if (this.#state.status === 'compacting') {
|
|
814
|
+
if (event.type === 'mouse' && event.wheel !== null) {
|
|
815
|
+
this.#scrollBy(event.wheel < 0 ? -TRANSCRIPT_WHEEL_SCROLL : TRANSCRIPT_WHEEL_SCROLL, true);
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
if (event.type === 'key' && event.id === 'pageUp') {
|
|
819
|
+
this.#scrollBy(-this.#pageSize());
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
if (event.type === 'key' && event.id === 'pageDown') {
|
|
823
|
+
this.#scrollBy(this.#pageSize());
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
if (event.type !== 'key' || event.id !== 'ctrl+c')
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
764
829
|
// Clipboard image inspection is asynchronous. Preserve the exact key
|
|
765
830
|
// order so a fast Ctrl+V, Enter submits the finished image draft rather
|
|
766
831
|
// than an empty prompt.
|
|
@@ -789,9 +854,12 @@ export class LocalTui {
|
|
|
789
854
|
return;
|
|
790
855
|
}
|
|
791
856
|
if (event.type === 'mouse') {
|
|
857
|
+
this.#lastEscapeTime = 0;
|
|
792
858
|
this.#handleMouse(event);
|
|
793
859
|
return;
|
|
794
860
|
}
|
|
861
|
+
if (event.type !== 'key' || event.id !== 'escape')
|
|
862
|
+
this.#lastEscapeTime = 0;
|
|
795
863
|
if (this.#handlePrompt(event))
|
|
796
864
|
return;
|
|
797
865
|
if (event.type === 'key') {
|
|
@@ -830,7 +898,7 @@ export class LocalTui {
|
|
|
830
898
|
return;
|
|
831
899
|
}
|
|
832
900
|
this.#lastSigintTime = now;
|
|
833
|
-
if (this.#state.status
|
|
901
|
+
if (this.#state.status !== 'idle') {
|
|
834
902
|
for (const listener of this.#interrupts)
|
|
835
903
|
listener();
|
|
836
904
|
}
|
|
@@ -863,8 +931,29 @@ export class LocalTui {
|
|
|
863
931
|
this.#applySearch(event);
|
|
864
932
|
return;
|
|
865
933
|
}
|
|
866
|
-
if (this.#handleAutocomplete(event))
|
|
934
|
+
if (this.#handleAutocomplete(event)) {
|
|
935
|
+
if (event.type === 'key' && event.id === 'escape')
|
|
936
|
+
this.#lastEscapeTime = 0;
|
|
867
937
|
return;
|
|
938
|
+
}
|
|
939
|
+
if (event.type === 'key' && event.id === 'escape') {
|
|
940
|
+
if (this.#state.status !== 'idle' || this.#pending === null
|
|
941
|
+
|| this.#editor.text !== '' || this.#images.length > 0) {
|
|
942
|
+
this.#lastEscapeTime = 0;
|
|
943
|
+
}
|
|
944
|
+
else {
|
|
945
|
+
const now = Date.now();
|
|
946
|
+
if (now - this.#lastEscapeTime < DOUBLE_ESCAPE_MS) {
|
|
947
|
+
this.#lastEscapeTime = 0;
|
|
948
|
+
for (const listener of this.#rewinds)
|
|
949
|
+
listener();
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
this.#lastEscapeTime = now;
|
|
953
|
+
}
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
868
957
|
if (event.type === 'key' && (event.id === 'backspace' || event.id === 'delete')
|
|
869
958
|
&& this.#removeImageAtCursor(event.id))
|
|
870
959
|
return;
|
|
@@ -1428,6 +1517,8 @@ export class LocalTui {
|
|
|
1428
1517
|
return;
|
|
1429
1518
|
}
|
|
1430
1519
|
if (command.kind === 'historyPrev') {
|
|
1520
|
+
if (this.#restoreLatestQueuedSubmission())
|
|
1521
|
+
return;
|
|
1431
1522
|
this.#historyPrev();
|
|
1432
1523
|
return;
|
|
1433
1524
|
}
|
|
@@ -1445,6 +1536,8 @@ export class LocalTui {
|
|
|
1445
1536
|
if (command.kind === 'clear') {
|
|
1446
1537
|
this.#editor.clear();
|
|
1447
1538
|
this.#images = [];
|
|
1539
|
+
this.#queueEditNewer = null;
|
|
1540
|
+
this.#queueEditPending = false;
|
|
1448
1541
|
this.#historyIndex = 0;
|
|
1449
1542
|
this.#ac = null;
|
|
1450
1543
|
this.#search = null;
|
|
@@ -1482,6 +1575,41 @@ export class LocalTui {
|
|
|
1482
1575
|
this.#refreshAutocomplete();
|
|
1483
1576
|
this.#render();
|
|
1484
1577
|
}
|
|
1578
|
+
#restoreLatestQueuedSubmission() {
|
|
1579
|
+
if (this.#queueEditPending)
|
|
1580
|
+
return true;
|
|
1581
|
+
if (this.#queueEditNewer !== null) {
|
|
1582
|
+
const previous = this.#queuedSubmissions.pop();
|
|
1583
|
+
if (previous !== undefined) {
|
|
1584
|
+
this.#queueEditNewer.unshift(this.#currentSubmission());
|
|
1585
|
+
this.#replaceInput(previous);
|
|
1586
|
+
return true;
|
|
1587
|
+
}
|
|
1588
|
+
const hasDurableFollowup = this.#state.nextTurnInbox.some(message => message.source.kind === 'user');
|
|
1589
|
+
if (!hasDurableFollowup || this.#queueEdits.size === 0)
|
|
1590
|
+
return true;
|
|
1591
|
+
this.#queueEditPending = true;
|
|
1592
|
+
for (const listener of this.#queueEdits)
|
|
1593
|
+
listener();
|
|
1594
|
+
return true;
|
|
1595
|
+
}
|
|
1596
|
+
if (this.#editor.text !== '' || this.#images.length > 0 || this.#historyIndex !== 0)
|
|
1597
|
+
return false;
|
|
1598
|
+
const submission = this.#queuedSubmissions.pop();
|
|
1599
|
+
if (submission !== undefined) {
|
|
1600
|
+
this.#queueEditNewer = [];
|
|
1601
|
+
this.#replaceInput(submission);
|
|
1602
|
+
return true;
|
|
1603
|
+
}
|
|
1604
|
+
const hasDurableFollowup = this.#state.nextTurnInbox.some(message => message.source.kind === 'user');
|
|
1605
|
+
if (!hasDurableFollowup || this.#queueEdits.size === 0)
|
|
1606
|
+
return false;
|
|
1607
|
+
this.#queueEditNewer = [];
|
|
1608
|
+
this.#queueEditPending = true;
|
|
1609
|
+
for (const listener of this.#queueEdits)
|
|
1610
|
+
listener();
|
|
1611
|
+
return true;
|
|
1612
|
+
}
|
|
1485
1613
|
#historyNext() {
|
|
1486
1614
|
if (this.#images.length > 0)
|
|
1487
1615
|
return;
|
|
@@ -1512,6 +1640,7 @@ export class LocalTui {
|
|
|
1512
1640
|
}
|
|
1513
1641
|
const images = this.#images.map(image => ({ ...image }));
|
|
1514
1642
|
const submittedText = images.length > 0 ? text.trim() : text;
|
|
1643
|
+
const queueEditNewer = this.#queueEditNewer;
|
|
1515
1644
|
const historyText = images.reduce((value, image, index) => value.replaceAll(imageMarker(index, image), ''), submittedText)
|
|
1516
1645
|
.replace(/[ \t]{2,}/gu, ' ')
|
|
1517
1646
|
.trim();
|
|
@@ -1521,6 +1650,8 @@ export class LocalTui {
|
|
|
1521
1650
|
}
|
|
1522
1651
|
this.#historyIndex = 0;
|
|
1523
1652
|
this.#draft = '';
|
|
1653
|
+
this.#queueEditNewer = null;
|
|
1654
|
+
this.#queueEditPending = false;
|
|
1524
1655
|
this.#editor.setText('');
|
|
1525
1656
|
this.#images = [];
|
|
1526
1657
|
this.#ac = null;
|
|
@@ -1530,18 +1661,26 @@ export class LocalTui {
|
|
|
1530
1661
|
this.#followTail();
|
|
1531
1662
|
const slash = images.length === 0 ? parseSlashInput(submittedText) : null;
|
|
1532
1663
|
if (slash !== null) {
|
|
1664
|
+
if (queueEditNewer !== null)
|
|
1665
|
+
this.#queuedSubmissions.push(...queueEditNewer);
|
|
1533
1666
|
this.#runSlash(slash.name, slash.args);
|
|
1534
1667
|
return;
|
|
1535
1668
|
}
|
|
1536
|
-
this.#render();
|
|
1537
1669
|
const pending = this.#pending;
|
|
1538
1670
|
if (pending !== null) {
|
|
1539
1671
|
this.#pending = null;
|
|
1540
1672
|
pending.resolve({ text: submittedText, images });
|
|
1673
|
+
if (queueEditNewer !== null)
|
|
1674
|
+
this.#queuedSubmissions.push(...queueEditNewer);
|
|
1541
1675
|
}
|
|
1542
|
-
else if (submittedText !== '' || images.length > 0) {
|
|
1543
|
-
|
|
1676
|
+
else if (submittedText !== '' || images.length > 0 || queueEditNewer !== null) {
|
|
1677
|
+
if (submittedText !== '' || images.length > 0) {
|
|
1678
|
+
this.#queuedSubmissions.push({ text: submittedText, images });
|
|
1679
|
+
}
|
|
1680
|
+
if (queueEditNewer !== null)
|
|
1681
|
+
this.#queuedSubmissions.push(...queueEditNewer);
|
|
1544
1682
|
}
|
|
1683
|
+
this.#render();
|
|
1545
1684
|
}
|
|
1546
1685
|
#runSlash(name, args = '') {
|
|
1547
1686
|
if (name === '') {
|
|
@@ -1569,11 +1708,6 @@ export class LocalTui {
|
|
|
1569
1708
|
this.#runSettings(args);
|
|
1570
1709
|
return;
|
|
1571
1710
|
}
|
|
1572
|
-
if (command.name === 'hotkeys') {
|
|
1573
|
-
this.#hotkeyCatalog();
|
|
1574
|
-
this.#render();
|
|
1575
|
-
return;
|
|
1576
|
-
}
|
|
1577
1711
|
if (command.name === 'copy') {
|
|
1578
1712
|
void this.#runCopy(args);
|
|
1579
1713
|
return;
|
|
@@ -1583,17 +1717,7 @@ export class LocalTui {
|
|
|
1583
1717
|
this.#render();
|
|
1584
1718
|
return;
|
|
1585
1719
|
}
|
|
1586
|
-
if (command.name === 'pwd') {
|
|
1587
|
-
this.#notice(formatWorkspaceText({
|
|
1588
|
-
cwd: process.cwd(),
|
|
1589
|
-
model: this.#model,
|
|
1590
|
-
...(this.#branch !== undefined ? { branch: this.#branch } : {}),
|
|
1591
|
-
}));
|
|
1592
|
-
this.#render();
|
|
1593
|
-
return;
|
|
1594
|
-
}
|
|
1595
1720
|
if (!BUILTIN_SLASH_COMMANDS.some((entry) => entry.name === command.name)) {
|
|
1596
|
-
this.#render();
|
|
1597
1721
|
const raw = '/' + name + (args === '' ? '' : ' ' + args);
|
|
1598
1722
|
const pending = this.#pending;
|
|
1599
1723
|
if (pending !== null) {
|
|
@@ -1601,13 +1725,24 @@ export class LocalTui {
|
|
|
1601
1725
|
pending.resolve({ text: raw, images: [] });
|
|
1602
1726
|
}
|
|
1603
1727
|
else {
|
|
1604
|
-
this.#
|
|
1728
|
+
this.#queuedSubmissions.push({ text: raw, images: [] });
|
|
1605
1729
|
}
|
|
1730
|
+
this.#render();
|
|
1606
1731
|
return;
|
|
1607
1732
|
}
|
|
1608
1733
|
this.#state = {
|
|
1609
1734
|
...this.#state,
|
|
1610
|
-
blocks: [...this.#state.blocks, {
|
|
1735
|
+
blocks: [...this.#state.blocks, {
|
|
1736
|
+
kind: 'commandOutput',
|
|
1737
|
+
command: 'help',
|
|
1738
|
+
text: [
|
|
1739
|
+
formatHelpText(this.#commands()),
|
|
1740
|
+
'',
|
|
1741
|
+
`**Keyboard Shortcuts · ${hotkeyCount(this.#keybindings)} bindings**`,
|
|
1742
|
+
'',
|
|
1743
|
+
formatHotkeysText(this.#keybindings),
|
|
1744
|
+
].join('\n'),
|
|
1745
|
+
}],
|
|
1611
1746
|
};
|
|
1612
1747
|
this.#focusLatestBlock();
|
|
1613
1748
|
this.#render();
|
|
@@ -1615,7 +1750,7 @@ export class LocalTui {
|
|
|
1615
1750
|
#commands() {
|
|
1616
1751
|
const localNames = new Set(BUILTIN_SLASH_COMMANDS.flatMap((command) => [command.name, ...(command.aliases ?? [])]));
|
|
1617
1752
|
const runtime = this.#runtimeCommands
|
|
1618
|
-
.filter((command) => !localNames.has(command.name)
|
|
1753
|
+
.filter((command) => !localNames.has(command.name))
|
|
1619
1754
|
.map((command) => ({
|
|
1620
1755
|
name: command.name,
|
|
1621
1756
|
description: command.description,
|
|
@@ -1684,13 +1819,6 @@ export class LocalTui {
|
|
|
1684
1819
|
};
|
|
1685
1820
|
this.#focusLatestBlock();
|
|
1686
1821
|
}
|
|
1687
|
-
#hotkeyCatalog() {
|
|
1688
|
-
this.#state = {
|
|
1689
|
-
...this.#state,
|
|
1690
|
-
blocks: [...this.#state.blocks, { kind: 'hotkeyCatalog', bindings: this.#keybindings }],
|
|
1691
|
-
};
|
|
1692
|
-
this.#focusLatestBlock();
|
|
1693
|
-
}
|
|
1694
1822
|
#focusLatestBlock() {
|
|
1695
1823
|
this.#follow = false;
|
|
1696
1824
|
this.#focusBlock = Math.max(0, this.#state.blocks.length - 1);
|