@agi-fans/dsh-tui 0.25.0 → 0.26.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/lib/CHANGELOG.md +31 -2
- package/lib/chrome/box.d.ts +7 -0
- package/lib/chrome/box.js +1 -0
- package/lib/chrome/box.js.map +1 -1
- package/lib/chrome/main-screen-renderer.d.ts +2 -0
- package/lib/chrome/main-screen-renderer.js +6 -0
- package/lib/chrome/main-screen-renderer.js.map +1 -1
- package/lib/chrome/renderer.d.ts +12 -0
- package/lib/chrome/renderer.js.map +1 -1
- package/lib/chrome/status-line.js +3 -2
- package/lib/chrome/status-line.js.map +1 -1
- package/lib/chrome/width.d.ts +2 -0
- package/lib/chrome/width.js +10 -0
- package/lib/chrome/width.js.map +1 -1
- package/lib/commands/session.js +23 -12
- package/lib/commands/session.js.map +1 -1
- package/lib/definition.d.ts +16 -2
- package/lib/input/actions.d.ts +1 -1
- package/lib/input/actions.js +16 -5
- package/lib/input/actions.js.map +1 -1
- package/lib/input/clipboard.js +2 -1
- package/lib/input/clipboard.js.map +1 -1
- package/lib/input/editor.js +4 -0
- package/lib/input/editor.js.map +1 -1
- package/lib/input/key-platform.d.ts +2 -0
- package/lib/input/key-platform.js +8 -0
- package/lib/input/key-platform.js.map +1 -0
- package/lib/input/keybindings-config.d.ts +2 -1
- package/lib/input/keybindings-config.js +14 -9
- package/lib/input/keybindings-config.js.map +1 -1
- package/lib/input/keys.d.ts +2 -0
- package/lib/input/keys.js +10 -0
- package/lib/input/keys.js.map +1 -1
- package/lib/locale/zh.d.ts +3 -2
- package/lib/locale/zh.js +3 -2
- package/lib/locale/zh.js.map +1 -1
- package/lib/runtime/help-reader.d.ts +1 -1
- package/lib/runtime/help-reader.js +2 -2
- package/lib/runtime/help-reader.js.map +1 -1
- package/lib/runtime/herdr-agent.d.ts +2 -0
- package/lib/runtime/herdr-agent.js +7 -1
- package/lib/runtime/herdr-agent.js.map +1 -1
- package/lib/runtime/provider-local.d.ts +9 -1
- package/lib/runtime/provider-local.js +247 -51
- package/lib/runtime/provider-local.js.map +1 -1
- package/lib/runtime/terminal-state.d.ts +4 -1
- package/lib/runtime/terminal-state.js +28 -7
- package/lib/runtime/terminal-state.js.map +1 -1
- package/lib/session/session-controller.js +56 -6
- package/lib/session/session-controller.js.map +1 -1
- package/lib/views/file-browser.d.ts +3 -0
- package/lib/views/file-browser.js +1 -0
- package/lib/views/file-browser.js.map +1 -1
- package/lib/views/hotkeys.d.ts +4 -4
- package/lib/views/hotkeys.js +24 -14
- package/lib/views/hotkeys.js.map +1 -1
- package/lib/views/settings-list.js +2 -2
- package/lib/views/settings-list.js.map +1 -1
- package/lib/views/transcript-render.d.ts +1 -0
- package/lib/views/transcript-render.js +25 -12
- package/lib/views/transcript-render.js.map +1 -1
- package/package.json +1 -1
|
@@ -64,11 +64,11 @@ import { appendTrajectoryEvent, applyTrajectoryEvent, createTrajectory, trajecto
|
|
|
64
64
|
import { applyEvent, applyStreamChunk, renderedBlocks, formatAgentElapsed, rosterPreviewStart, initialTranscript, replayEvents, renderView, turnGroups, transcriptSeam, TRANSCRIPT_FAST_SCROLL, withWorkspaceSummary, } from "../views/event-views.js";
|
|
65
65
|
import { applyTranscriptSearchEvent, createTranscriptSearch, searchMatches, } from "../views/transcript-search.js";
|
|
66
66
|
import { nextRevealStep, revealStreamingAssistant, streamingAssistantKey, streamingAssistantUnits, } from "../views/streaming-reveal.js";
|
|
67
|
-
import { flushPending, parseKeys } from "../input/keys.js";
|
|
67
|
+
import { flushPending, normalizeKeyId, parseKeys } from "../input/keys.js";
|
|
68
68
|
import { sanitizeDisplayLine } from "../chrome/renderer.js";
|
|
69
69
|
import { blockFileAction } from "../views/file-actions.js";
|
|
70
70
|
import { fileDocument, reviewFiles } from "./file-review.js";
|
|
71
|
-
import { stripAnsi } from "../chrome/width.js";
|
|
71
|
+
import { indexAtCell, stripAnsi } from "../chrome/width.js";
|
|
72
72
|
import { MainScreenRenderer } from "../chrome/main-screen-renderer.js";
|
|
73
73
|
import { supportsHyperlinks } from "./terminal-probe.js";
|
|
74
74
|
import { colorDisabledByEnv, createTheme, detectColorDepth } from "../chrome/theme.js";
|
|
@@ -207,6 +207,8 @@ export class LocalTui {
|
|
|
207
207
|
#keyTest;
|
|
208
208
|
#mouseActionPress;
|
|
209
209
|
#fileActionFrame;
|
|
210
|
+
#inputFrame;
|
|
211
|
+
#inputPress;
|
|
210
212
|
#imageTemporary = new Set();
|
|
211
213
|
#terminalProfile;
|
|
212
214
|
#resizeDebounceMs;
|
|
@@ -227,7 +229,7 @@ export class LocalTui {
|
|
|
227
229
|
#files = new ComposerFiles({ text: () => this.#editor.text,
|
|
228
230
|
append: marker => { this.#editor.setCursor(this.#editor.text.length); this.#editor.handle({ type: 'text', value: (this.#editor.text === '' ? '' : ' ') + marker }); } });
|
|
229
231
|
insertText(text) {
|
|
230
|
-
if (text === '')
|
|
232
|
+
if (text === '' || this.#inspected?.writable === false)
|
|
231
233
|
return;
|
|
232
234
|
const before = this.#editor.text.slice(0, this.#editor.cursor);
|
|
233
235
|
const after = this.#editor.text.slice(this.#editor.cursor);
|
|
@@ -289,6 +291,7 @@ export class LocalTui {
|
|
|
289
291
|
#resumeHintRequested = false;
|
|
290
292
|
#lastSigintTime = 0;
|
|
291
293
|
#lastEscapeTime = 0;
|
|
294
|
+
#receivedModifiedEnter = new Set();
|
|
292
295
|
#inspectEscapeFenceUntil = 0;
|
|
293
296
|
#interrupts = new Set();
|
|
294
297
|
#queueEdits = new Set();
|
|
@@ -436,6 +439,8 @@ export class LocalTui {
|
|
|
436
439
|
#expandedReasoning = new Set();
|
|
437
440
|
#expandedToolRows = new Set();
|
|
438
441
|
#processSelection;
|
|
442
|
+
#promptAnchor;
|
|
443
|
+
#transcriptScopeChanged = false;
|
|
439
444
|
#closedReasoning = new Set();
|
|
440
445
|
/**
|
|
441
446
|
* The last action's confirmation, drawn on the composer's bottom border.
|
|
@@ -505,6 +510,7 @@ export class LocalTui {
|
|
|
505
510
|
#keybindingsPath;
|
|
506
511
|
#keybindings;
|
|
507
512
|
#cwd;
|
|
513
|
+
#rootDirectory;
|
|
508
514
|
#projectRoot;
|
|
509
515
|
#home;
|
|
510
516
|
#listDir;
|
|
@@ -559,6 +565,7 @@ export class LocalTui {
|
|
|
559
565
|
this.#cwd = paths.cwd ?? fallback.cwd;
|
|
560
566
|
this.#readImagePath = paths.readImagePath ?? (path => readImageFile(path, this.#cwd));
|
|
561
567
|
const project = resolveProjectContext(this.#cwd);
|
|
568
|
+
this.#rootDirectory = { cwd: this.#cwd, branch: project.gitLabel };
|
|
562
569
|
this.#projectRoot = paths.projectRoot ?? project.root;
|
|
563
570
|
this.#home = paths.home ?? fallback.home;
|
|
564
571
|
this.#listDir = paths.listDir ?? fallback.listDir;
|
|
@@ -606,6 +613,7 @@ export class LocalTui {
|
|
|
606
613
|
// live window so it stays anchored at the bottom.
|
|
607
614
|
this.#selection.clear();
|
|
608
615
|
this.#mouseActionPress = undefined;
|
|
616
|
+
this.#inputPress = undefined;
|
|
609
617
|
this.#workspacePress = undefined;
|
|
610
618
|
this.#jumpPress = undefined;
|
|
611
619
|
this.#disclosurePress = undefined;
|
|
@@ -649,23 +657,38 @@ export class LocalTui {
|
|
|
649
657
|
this.#syncWindowTitle();
|
|
650
658
|
}
|
|
651
659
|
/** Follow the viewed Session without replacing its transcript or native history. */
|
|
652
|
-
setWorkingDirectory(cwd) {
|
|
660
|
+
setWorkingDirectory(cwd, options = {}) {
|
|
661
|
+
const root = options.root ?? this.#inspected === undefined;
|
|
662
|
+
const project = resolveProjectContext(cwd);
|
|
663
|
+
if (root) {
|
|
664
|
+
this.#rootDirectory = { cwd, branch: project.gitLabel };
|
|
665
|
+
this.#syncWindowTitle();
|
|
666
|
+
if (this.#inspected !== undefined)
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
653
669
|
if (cwd === this.#cwd && cwd === this.#projectRoot)
|
|
654
670
|
return;
|
|
655
|
-
this.#cwd
|
|
671
|
+
this.#setViewedDirectory(cwd);
|
|
672
|
+
this.#syncWindowTitle();
|
|
673
|
+
if (this.#tty)
|
|
674
|
+
this.#render();
|
|
675
|
+
}
|
|
676
|
+
#setViewedDirectory(cwd) {
|
|
656
677
|
const project = resolveProjectContext(cwd);
|
|
678
|
+
this.#cwd = cwd;
|
|
657
679
|
this.#projectRoot = cwd;
|
|
658
680
|
this.#pwd = shortenPath(cwd);
|
|
659
681
|
this.#branch = project.gitLabel;
|
|
660
682
|
this.#refreshAutocomplete();
|
|
661
|
-
this.#syncWindowTitle();
|
|
662
|
-
if (this.#tty)
|
|
663
|
-
this.#render();
|
|
664
683
|
}
|
|
665
684
|
/** Refresh Git metadata without changing the Session's effective directory. */
|
|
666
685
|
#refreshProjectContext() {
|
|
667
686
|
const branch = refreshProjectContext(this.#cwd).gitLabel;
|
|
668
|
-
|
|
687
|
+
const rootBranch = this.#rootDirectory.cwd === this.#cwd ? branch : refreshProjectContext(this.#rootDirectory.cwd).gitLabel;
|
|
688
|
+
const rootChanged = rootBranch !== this.#rootDirectory.branch;
|
|
689
|
+
if (rootChanged)
|
|
690
|
+
this.#rootDirectory = { ...this.#rootDirectory, branch: rootBranch };
|
|
691
|
+
if (branch === this.#branch && !rootChanged)
|
|
669
692
|
return;
|
|
670
693
|
this.#branch = branch;
|
|
671
694
|
this.#syncWindowTitle();
|
|
@@ -712,9 +735,19 @@ export class LocalTui {
|
|
|
712
735
|
this.#compactionStartedAt = Date.now();
|
|
713
736
|
else if (!compacting)
|
|
714
737
|
this.#compactionStartedAt = undefined;
|
|
715
|
-
if (
|
|
716
|
-
|
|
717
|
-
|
|
738
|
+
if (this.#inspected === undefined) {
|
|
739
|
+
if (event.type === 'compaction/start') {
|
|
740
|
+
this.#herdr.compactionStart(event.data.compactionId);
|
|
741
|
+
this.#syncWindowTitle();
|
|
742
|
+
}
|
|
743
|
+
else if (event.type === 'compaction/end') {
|
|
744
|
+
this.#herdr.compactionEnd(event.data.compactionId, event.data.error);
|
|
745
|
+
this.#syncWindowTitle();
|
|
746
|
+
}
|
|
747
|
+
else if (event.type === 'turn/end') {
|
|
748
|
+
this.#herdr.settled(event.data.reason.kind);
|
|
749
|
+
this.#syncWindowTitle();
|
|
750
|
+
}
|
|
718
751
|
}
|
|
719
752
|
this.#emitNotification(this.#notifications.event({
|
|
720
753
|
type: event.type,
|
|
@@ -777,6 +810,12 @@ export class LocalTui {
|
|
|
777
810
|
// Parent lifecycle remains authoritative while the child owns the visible view.
|
|
778
811
|
if (options.root === true || this.#inspected === undefined) {
|
|
779
812
|
this.#herdr.setRunning(status === 'running');
|
|
813
|
+
if (options.compaction?.phase === 'start') {
|
|
814
|
+
this.#herdr.compactionStart(options.compaction.id);
|
|
815
|
+
}
|
|
816
|
+
else if (options.compaction?.phase === 'end') {
|
|
817
|
+
this.#herdr.compactionEnd(options.compaction.id, options.compaction.error);
|
|
818
|
+
}
|
|
780
819
|
if (options.outcome !== undefined)
|
|
781
820
|
this.#herdr.settled(options.outcome);
|
|
782
821
|
this.#syncWindowTitle();
|
|
@@ -842,6 +881,7 @@ export class LocalTui {
|
|
|
842
881
|
const current = this.#subagents?.agents.find(agent => agent.id === inspected.id);
|
|
843
882
|
if (current !== undefined) {
|
|
844
883
|
this.#inspected = {
|
|
884
|
+
...inspected,
|
|
845
885
|
id: current.id,
|
|
846
886
|
label: current.label,
|
|
847
887
|
phase: current.phase,
|
|
@@ -860,15 +900,25 @@ export class LocalTui {
|
|
|
860
900
|
setInspectedSubagent(inspected) {
|
|
861
901
|
if (this.#inspected?.id === inspected?.id && this.#inspected?.label === inspected?.label
|
|
862
902
|
&& this.#inspected?.phase === inspected?.phase && this.#inspected?.needsApproval === inspected?.needsApproval && this.#inspected?.mode === inspected?.mode
|
|
863
|
-
&& this.#inspected?.writable === inspected?.writable
|
|
903
|
+
&& this.#inspected?.writable === inspected?.writable && this.#inspected?.model === inspected?.model
|
|
904
|
+
&& this.#inspected?.reasoningEffort === inspected?.reasoningEffort && this.#inspected?.stats === inspected?.stats
|
|
905
|
+
&& this.#inspected?.controls === inspected?.controls)
|
|
864
906
|
return;
|
|
865
907
|
if (this.#inspected?.id !== inspected?.id) {
|
|
908
|
+
this.#transcriptScopeChanged = true;
|
|
866
909
|
this.#workspacePress = undefined;
|
|
867
910
|
this.#fileReviewAbort?.abort();
|
|
868
911
|
this.#closeFileBrowser();
|
|
912
|
+
this.#transcriptSearch = null;
|
|
913
|
+
this.#followTail();
|
|
869
914
|
}
|
|
870
|
-
this.#
|
|
915
|
+
const leaving = this.#inspected !== undefined && inspected === undefined;
|
|
871
916
|
this.#inspected = inspected === undefined ? undefined : { ...inspected };
|
|
917
|
+
if (leaving) {
|
|
918
|
+
this.#setViewedDirectory(this.#rootDirectory.cwd);
|
|
919
|
+
this.#syncWindowTitle();
|
|
920
|
+
}
|
|
921
|
+
this.#switchDraft(inspected?.id ?? this.#sessionId);
|
|
872
922
|
this.#drainPendingInput();
|
|
873
923
|
if (inspected !== undefined) {
|
|
874
924
|
this.#inspectEscapeFenceUntil = 0;
|
|
@@ -902,7 +952,7 @@ export class LocalTui {
|
|
|
902
952
|
this.#settings = null;
|
|
903
953
|
this.#search = null;
|
|
904
954
|
this.#ac = null;
|
|
905
|
-
const browser = new FileBrowser(request, () => { if (!this.#disposed)
|
|
955
|
+
const browser = new FileBrowser({ ...request, canQuote: request.canQuote && (this.#inspected === undefined || this.#inspected.writable) }, () => { if (!this.#disposed)
|
|
906
956
|
this.#render(); }, () => {
|
|
907
957
|
if (this.#fileBrowser === browser)
|
|
908
958
|
this.#fileBrowser = null;
|
|
@@ -1249,9 +1299,9 @@ export class LocalTui {
|
|
|
1249
1299
|
this.#flushPasteBurst(true);
|
|
1250
1300
|
this.#pasteBurst.clear();
|
|
1251
1301
|
if (request.notify !== false) {
|
|
1252
|
-
this.#emitNotification(this.#notifications.humanPrompt());
|
|
1253
1302
|
this.#herdr.prompt(request.title, request.attentionKind);
|
|
1254
1303
|
this.#syncWindowTitle();
|
|
1304
|
+
this.#emitNotification(this.#notifications.humanPrompt());
|
|
1255
1305
|
}
|
|
1256
1306
|
if (this.#tty && request.documentImage !== undefined && this.#imageProtocol !== undefined)
|
|
1257
1307
|
this.#term.output.write('\x1b[16t');
|
|
@@ -1370,10 +1420,23 @@ export class LocalTui {
|
|
|
1370
1420
|
// A notice does not turn a blank session into a document that /new needs
|
|
1371
1421
|
// to separate. Refreshes are the same document.
|
|
1372
1422
|
const boundary = reason === 'open' || (reason === 'new' && this.#state.blocks.some(block => block.kind !== 'notice'));
|
|
1373
|
-
const
|
|
1423
|
+
const refreshing = reason === 'refresh' && !this.#transcriptScopeChanged;
|
|
1424
|
+
this.#transcriptScopeChanged = false;
|
|
1425
|
+
const seam = refreshing && this.#state.blocks[0]?.kind === 'notice' && this.#state.blocks[0].boundary === true
|
|
1426
|
+
? this.#state.blocks[0] : undefined;
|
|
1427
|
+
const blocks = boundary ? [transcriptSeam('session-opened'), ...state.blocks] : seam === undefined ? state.blocks : [seam, ...state.blocks];
|
|
1374
1428
|
this.#state = { ...state, status, compactCommandId: undefined, blocks };
|
|
1375
1429
|
this.#plain.resetPrinted();
|
|
1376
|
-
this.#
|
|
1430
|
+
this.#promptAnchor = undefined;
|
|
1431
|
+
if (!refreshing) {
|
|
1432
|
+
this.#transcriptSearch = null;
|
|
1433
|
+
this.#followTail();
|
|
1434
|
+
}
|
|
1435
|
+
else if (this.#transcriptSearch !== null) {
|
|
1436
|
+
const match = this.#searchOccurrences()[this.#transcriptSearch.focus];
|
|
1437
|
+
if (match !== undefined)
|
|
1438
|
+
this.#focusSearchMatch(match);
|
|
1439
|
+
}
|
|
1377
1440
|
this.#deferInitialRender = false;
|
|
1378
1441
|
this.#renderer.startEpoch({ replay: reason === 'refresh' ? 'viewport' : status === 'idle' ? 'full' : 'pinned' });
|
|
1379
1442
|
if (this.#tty)
|
|
@@ -1383,6 +1446,7 @@ export class LocalTui {
|
|
|
1383
1446
|
}
|
|
1384
1447
|
setSession(info) {
|
|
1385
1448
|
if (info.id !== this.#sessionId) {
|
|
1449
|
+
this.#transcriptScopeChanged = true;
|
|
1386
1450
|
this.#workspacePress = undefined;
|
|
1387
1451
|
this.#fileReviewAbort?.abort();
|
|
1388
1452
|
this.#closeFileBrowser();
|
|
@@ -1414,14 +1478,15 @@ export class LocalTui {
|
|
|
1414
1478
|
this.#render();
|
|
1415
1479
|
}
|
|
1416
1480
|
/** Only the foreground terminal owner emits title and program-state sequences. */
|
|
1417
|
-
#syncWindowTitle(
|
|
1481
|
+
#syncWindowTitle() {
|
|
1418
1482
|
if (!this.#tty || this.#disposed || this.#session.handedOff)
|
|
1419
1483
|
return;
|
|
1420
1484
|
const status = this.#herdr.programStatus;
|
|
1421
1485
|
this.#writeWorkingDirectory(this.#cwd);
|
|
1422
1486
|
this.#syncProgress(status.state);
|
|
1423
|
-
const
|
|
1424
|
-
|
|
1487
|
+
const nativeStatus = this.#reportsProgramState;
|
|
1488
|
+
const title = terminalTitle(this.#terminalTitle, status, this.#sessionTitle, this.#rootDirectory.cwd, this.#rootDirectory.branch, nativeStatus);
|
|
1489
|
+
if (title !== this.#writtenWindowTitle && !(title === '' && this.#writtenWindowTitle === undefined)) {
|
|
1425
1490
|
this.#writtenWindowTitle = title;
|
|
1426
1491
|
this.#term.output.write(`\x1b]2;${title}\x07`);
|
|
1427
1492
|
}
|
|
@@ -1429,7 +1494,7 @@ export class LocalTui {
|
|
|
1429
1494
|
this.#programQuerySent = true;
|
|
1430
1495
|
this.#term.output.write(PROGRAM_STATUS_QUERY);
|
|
1431
1496
|
}
|
|
1432
|
-
if (!
|
|
1497
|
+
if (!nativeStatus) {
|
|
1433
1498
|
if (this.#writtenProgramState !== undefined)
|
|
1434
1499
|
this.#term.output.write(programStatusSequence('clear'));
|
|
1435
1500
|
this.#writtenProgramState = undefined;
|
|
@@ -1438,17 +1503,8 @@ export class LocalTui {
|
|
|
1438
1503
|
// Only the session name is exported as metadata; prompt bodies and errors stay in the TUI.
|
|
1439
1504
|
const sequence = programStatusSequence({ state: status.state,
|
|
1440
1505
|
...(status.kind === undefined ? {} : { kind: status.kind }),
|
|
1441
|
-
...(this.#sessionTitle === undefined ? {} : {
|
|
1506
|
+
...(this.#sessionTitle === undefined ? {} : { title: this.#sessionTitle }),
|
|
1442
1507
|
});
|
|
1443
|
-
// Supporting terminals can turn these states into desktop notifications.
|
|
1444
|
-
// New attention reports use the same coalescing and focus gate as OSC 9.
|
|
1445
|
-
if (programStatusNeedsAttention(status.state)
|
|
1446
|
-
&& (this.#notificationPolicy === 'off' || !notify && sequence !== this.#writtenProgramState)) {
|
|
1447
|
-
if (this.#writtenProgramState !== undefined)
|
|
1448
|
-
this.#term.output.write(programStatusSequence('clear'));
|
|
1449
|
-
this.#writtenProgramState = undefined;
|
|
1450
|
-
return;
|
|
1451
|
-
}
|
|
1452
1508
|
if (sequence === this.#writtenProgramState)
|
|
1453
1509
|
return;
|
|
1454
1510
|
this.#writtenProgramState = sequence;
|
|
@@ -2005,6 +2061,19 @@ export class LocalTui {
|
|
|
2005
2061
|
refresh() {
|
|
2006
2062
|
this.#render();
|
|
2007
2063
|
}
|
|
2064
|
+
searchTranscript(query) {
|
|
2065
|
+
if (!this.#tty || this.#disposed || query.trim() === '')
|
|
2066
|
+
return;
|
|
2067
|
+
// Commit the resumed document before moving its live viewport into history.
|
|
2068
|
+
this.#render();
|
|
2069
|
+
this.#transcriptSearch = { query, editing: false, focus: 0 };
|
|
2070
|
+
this.#promptAnchor = undefined;
|
|
2071
|
+
this.#ac = null;
|
|
2072
|
+
const match = this.#searchOccurrences()[0];
|
|
2073
|
+
if (match !== undefined)
|
|
2074
|
+
this.#focusSearchMatch(match);
|
|
2075
|
+
this.#render();
|
|
2076
|
+
}
|
|
2008
2077
|
#busy() {
|
|
2009
2078
|
if (this.#state.status !== 'idle')
|
|
2010
2079
|
return true;
|
|
@@ -2230,6 +2299,13 @@ export class LocalTui {
|
|
|
2230
2299
|
if (this.#probeGate)
|
|
2231
2300
|
return;
|
|
2232
2301
|
const width = this.#term.width();
|
|
2302
|
+
const alternateSendKey = keysForAction(Object.fromEntries(Object.entries(this.#keybindings).filter(([key]) => {
|
|
2303
|
+
if (key === 'super+enter')
|
|
2304
|
+
return this.#receivedModifiedEnter.has(key);
|
|
2305
|
+
if (key === 'ctrl+enter')
|
|
2306
|
+
return this.#session.keyboardProtocol === 'kitty' || this.#receivedModifiedEnter.has(key);
|
|
2307
|
+
return true;
|
|
2308
|
+
})), 'alternate-send');
|
|
2233
2309
|
const renderState = this.#reveal === undefined
|
|
2234
2310
|
? this.#state
|
|
2235
2311
|
: revealStreamingAssistant(this.#state, this.#reveal.revealed);
|
|
@@ -2288,6 +2364,7 @@ export class LocalTui {
|
|
|
2288
2364
|
toolDetailsKey: keysForAction(this.#keybindings, 'toggle-tool-details'),
|
|
2289
2365
|
turnDetailsKey: keysForAction(this.#keybindings, 'toggle-tools'),
|
|
2290
2366
|
busyEnter: this.#queueEditNewer !== null || this.#queueEditPending ? 'queue' : this.#busyEnter,
|
|
2367
|
+
...(this.#queueEditNewer !== null || this.#queueEditPending || alternateSendKey === 'Disabled' ? {} : { alternateSendKey }),
|
|
2291
2368
|
steerKey: keysForAction(this.#keybindings, 'steer-turn'),
|
|
2292
2369
|
queueKey: keysForAction(this.#keybindings, 'follow-up'),
|
|
2293
2370
|
openedGroups: this.#openedGroups,
|
|
@@ -2323,7 +2400,8 @@ export class LocalTui {
|
|
|
2323
2400
|
this.#syncScroll(frame.transcript);
|
|
2324
2401
|
this.#jumpToLatest = frame.jumpToLatest;
|
|
2325
2402
|
this.#fileActionFrame = frame.transcript === undefined || frame.transientSurface === 'overlay' ? undefined : frame;
|
|
2326
|
-
this.#
|
|
2403
|
+
this.#inputFrame = frame.inputRows === undefined ? undefined : frame;
|
|
2404
|
+
this.#setMouseTracking(this.#inputFrame !== undefined || this.#fileBrowser !== null || this.#trajectory !== null || this.#documentMouseEnabled() || this.#promptChoices.length > 0 || this.#promptActions.length > 0 || (frame.transcript !== undefined && frame.transientSurface !== 'overlay'
|
|
2327
2405
|
&& (this.#inspecting || this.#maxStart > 0 || (frame.transcript.fileRegions?.length ?? 0) > 0 || (frame.transcript.disclosures?.length ?? 0) > 0)));
|
|
2328
2406
|
// A run opening or folding reshapes rows above the screen in place; the
|
|
2329
2407
|
// renderer's frozen boundary is a row index and has to be told, or a fold
|
|
@@ -2369,6 +2447,7 @@ export class LocalTui {
|
|
|
2369
2447
|
}
|
|
2370
2448
|
#scrollBy(delta) {
|
|
2371
2449
|
this.#workspacePress = undefined;
|
|
2450
|
+
this.#promptAnchor = undefined;
|
|
2372
2451
|
if (this.#follow && (delta > 0 || this.#maxStart === 0))
|
|
2373
2452
|
return;
|
|
2374
2453
|
if (delta === 0 && this.#maxStart === 0)
|
|
@@ -2392,6 +2471,7 @@ export class LocalTui {
|
|
|
2392
2471
|
this.#render();
|
|
2393
2472
|
}
|
|
2394
2473
|
#followTail() {
|
|
2474
|
+
this.#promptAnchor = undefined;
|
|
2395
2475
|
this.#follow = true;
|
|
2396
2476
|
this.#scrollStart = this.#maxStart;
|
|
2397
2477
|
this.#endInspection();
|
|
@@ -2479,6 +2559,7 @@ export class LocalTui {
|
|
|
2479
2559
|
* or go back to the live tail once nothing is open any more.
|
|
2480
2560
|
*/
|
|
2481
2561
|
#inspect(target) {
|
|
2562
|
+
this.#promptAnchor = undefined;
|
|
2482
2563
|
const open = this.#toolsExpanded || this.#openedGroups.size > 0 || this.#expandedOutputs.size > 0;
|
|
2483
2564
|
if (!open) {
|
|
2484
2565
|
this.#inspecting = false;
|
|
@@ -2814,6 +2895,40 @@ export class LocalTui {
|
|
|
2814
2895
|
this.#handleTrajectoryMouse(event);
|
|
2815
2896
|
return;
|
|
2816
2897
|
}
|
|
2898
|
+
const frameRow = this.#renderer.frameRowAt(event.row);
|
|
2899
|
+
const inputRow = this.#inputFrame?.inputRows?.find(row => row.row === frameRow);
|
|
2900
|
+
const completionRow = this.#inputFrame?.autocompleteRows?.find(row => row.row === frameRow);
|
|
2901
|
+
if (event.button === 'left') {
|
|
2902
|
+
const pressed = this.#inputPress;
|
|
2903
|
+
if (event.action === 'press' && !event.shift && (inputRow !== undefined || completionRow !== undefined)) {
|
|
2904
|
+
const completion = completionRow === undefined ? undefined : this.#ac?.items[completionRow.index];
|
|
2905
|
+
this.#inputPress = { row: event.row, column: event.column, text: this.#editor.text,
|
|
2906
|
+
...(inputRow === undefined ? {} : { cursor: inputRow.start + indexAtCell(inputRow.text, Math.max(0, event.column - inputRow.column)) }),
|
|
2907
|
+
...(completion === undefined ? {} : { completion }) };
|
|
2908
|
+
}
|
|
2909
|
+
else if (event.action === 'drag')
|
|
2910
|
+
this.#inputPress = undefined;
|
|
2911
|
+
else if (event.action === 'release') {
|
|
2912
|
+
this.#inputPress = undefined;
|
|
2913
|
+
if (pressed !== undefined && !event.shift && pressed.row === event.row && pressed.column === event.column && pressed.text === this.#editor.text) {
|
|
2914
|
+
this.#selection.clear();
|
|
2915
|
+
this.#processSelection = undefined;
|
|
2916
|
+
this.#subagentSelection = undefined;
|
|
2917
|
+
this.#transcriptSearch = null;
|
|
2918
|
+
if (pressed.completion !== undefined && this.#ac !== null && completionRow !== undefined && this.#ac.items[completionRow.index] === pressed.completion) {
|
|
2919
|
+
this.#ac.selected = completionRow.index;
|
|
2920
|
+
this.#applySelectedCompletion();
|
|
2921
|
+
}
|
|
2922
|
+
else if (pressed.cursor !== undefined && inputRow !== undefined
|
|
2923
|
+
&& pressed.cursor === inputRow.start + indexAtCell(inputRow.text, Math.max(0, event.column - inputRow.column))) {
|
|
2924
|
+
this.#editor.setCursor(pressed.cursor);
|
|
2925
|
+
this.#refreshAutocomplete();
|
|
2926
|
+
}
|
|
2927
|
+
this.#render();
|
|
2928
|
+
return;
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2817
2932
|
const promptAction = this.#promptActions.find(action => event.row === action.row && event.column >= action.column && event.column < action.column + action.width);
|
|
2818
2933
|
if (this.#promptActionPress !== undefined) {
|
|
2819
2934
|
const pressed = this.#promptActionPress;
|
|
@@ -3085,15 +3200,20 @@ export class LocalTui {
|
|
|
3085
3200
|
}
|
|
3086
3201
|
}
|
|
3087
3202
|
#canQuoteSelection() {
|
|
3088
|
-
return this.#prompt === null && this.#settings === null && this.#trajectory === null && this.#fileBrowser === null && this.#search === null
|
|
3203
|
+
return this.#prompt === null && this.#settings === null && this.#trajectory === null && (this.#fileBrowser === null || this.#fileBrowser.state.canQuote && !this.#fileBrowserOwnsInput()) && this.#search === null
|
|
3089
3204
|
&& this.#transcriptSearch === null && (this.#inspected === undefined || this.#inspected.writable === true);
|
|
3090
3205
|
}
|
|
3206
|
+
#fileBrowserOwnsInput() {
|
|
3207
|
+
const state = this.#fileBrowser?.state;
|
|
3208
|
+
return state !== undefined && (state.editing !== undefined || state.help || state.menu !== undefined);
|
|
3209
|
+
}
|
|
3091
3210
|
#quoteSelection() {
|
|
3092
3211
|
if (!this.#canQuoteSelection())
|
|
3093
3212
|
return;
|
|
3094
3213
|
const text = this.#selection.valid(this.#renderer.viewport()) ? this.#selection.text() : undefined;
|
|
3095
3214
|
this.#selection.clear();
|
|
3096
3215
|
if (text !== undefined) {
|
|
3216
|
+
this.#closeFileBrowser();
|
|
3097
3217
|
this.#appendQuote(text.split('\n').map(line => '> ' + line).join('\n'));
|
|
3098
3218
|
}
|
|
3099
3219
|
this.#render();
|
|
@@ -3216,6 +3336,9 @@ export class LocalTui {
|
|
|
3216
3336
|
}
|
|
3217
3337
|
if (this.#session.handle(event))
|
|
3218
3338
|
return;
|
|
3339
|
+
if (!this.#paste && event.type === 'key' && (event.id === 'ctrl+enter' || event.id === 'super+enter')) {
|
|
3340
|
+
this.#receivedModifiedEnter.add(event.id);
|
|
3341
|
+
}
|
|
3219
3342
|
if (event.type === 'focus') {
|
|
3220
3343
|
this.#terminalFocused = event.focused;
|
|
3221
3344
|
if (event.focused && this.#notificationPolicy === 'unfocused')
|
|
@@ -3232,17 +3355,22 @@ export class LocalTui {
|
|
|
3232
3355
|
this.#disclosurePress = undefined;
|
|
3233
3356
|
this.#mouseActionPress = undefined;
|
|
3234
3357
|
this.#workspacePress = undefined;
|
|
3358
|
+
this.#inputPress = undefined;
|
|
3235
3359
|
if (this.#keyTest !== undefined && this.#prompt?.request.signal === this.#keyTest.signal
|
|
3236
3360
|
&& (event.type === 'text' || event.type === 'paste-start' || event.type === 'paste-end' || event.type === 'key' && !['escape', 'ctrl+c'].includes(event.id))) {
|
|
3237
3361
|
this.#keyTest.observe(event);
|
|
3238
3362
|
return;
|
|
3239
3363
|
}
|
|
3240
3364
|
if (this.#selection.active) {
|
|
3241
|
-
if (event.type === 'key' && this.#boundAction(event.id) === 'quote-selection') {
|
|
3365
|
+
if (event.type === 'key' && this.#boundAction(event.id) === 'quote-selection' && this.#canQuoteSelection()) {
|
|
3366
|
+
this.#quoteSelection();
|
|
3367
|
+
return;
|
|
3368
|
+
}
|
|
3369
|
+
if (this.#fileBrowser !== null && event.type === 'text' && event.value.toLowerCase() === 'q' && this.#canQuoteSelection()) {
|
|
3242
3370
|
this.#quoteSelection();
|
|
3243
3371
|
return;
|
|
3244
3372
|
}
|
|
3245
|
-
if (event.type === 'key' && (
|
|
3373
|
+
if (event.type === 'key' && (event.id === 'super+c' || event.id === 'enter' && !this.#fileBrowserOwnsInput() || this.#boundAction(event.id) === 'copy-prompt')) {
|
|
3246
3374
|
void this.#copySelection();
|
|
3247
3375
|
return;
|
|
3248
3376
|
}
|
|
@@ -3262,6 +3390,11 @@ export class LocalTui {
|
|
|
3262
3390
|
this.#applyTrajectoryInput(event);
|
|
3263
3391
|
return;
|
|
3264
3392
|
}
|
|
3393
|
+
if (this.#ac !== null && this.#inputFrame?.autocompleteRows?.some(row => row.row === this.#renderer.frameRowAt(event.row ?? -1))) {
|
|
3394
|
+
this.#ac.selected = nextSelectableAutocompleteIndex(this.#ac.items, this.#ac.selected + (event.direction === 'up' ? -1 : 1), event.direction === 'up' ? -1 : 1);
|
|
3395
|
+
this.#render();
|
|
3396
|
+
return;
|
|
3397
|
+
}
|
|
3265
3398
|
this.#jumpPress = undefined;
|
|
3266
3399
|
if (this.#mouseTracking && !this.#paste && this.#pasteInFlight === 0) {
|
|
3267
3400
|
const step = wheelStep(this.#wheelGesture, Date.now(), event.direction === 'up' ? -1 : 1, !this.#wheelAccelerates);
|
|
@@ -3408,7 +3541,7 @@ export class LocalTui {
|
|
|
3408
3541
|
this.#render();
|
|
3409
3542
|
return;
|
|
3410
3543
|
}
|
|
3411
|
-
if (event.type === 'key' && (event.id === 'ctrl+-' || event.id === 'ctrl+_')
|
|
3544
|
+
if (event.type === 'key' && (event.id === 'ctrl+-' || event.id === 'ctrl+_' || event.id === 'super+z')
|
|
3412
3545
|
&& this.#clearedDraft !== undefined && this.#clearedDraft.revision === this.#editor.revision
|
|
3413
3546
|
&& !this.#hasComposerContent()) {
|
|
3414
3547
|
const cleared = this.#clearedDraft.draft;
|
|
@@ -4737,6 +4870,11 @@ export class LocalTui {
|
|
|
4737
4870
|
this.#queuedSubmissions.push(submission);
|
|
4738
4871
|
this.#pendingInputs.flush(this.#pendingScope());
|
|
4739
4872
|
}
|
|
4873
|
+
#resolveDelivery(delivery) {
|
|
4874
|
+
if (delivery === 'alternate')
|
|
4875
|
+
return this.#busyEnter === 'queue' ? 'steer' : 'queue';
|
|
4876
|
+
return delivery ?? this.#busyEnter;
|
|
4877
|
+
}
|
|
4740
4878
|
#submit(text, delivery) {
|
|
4741
4879
|
if (this.#prompt !== null) {
|
|
4742
4880
|
if (this.#prompt.request.presentation === 'progress')
|
|
@@ -4758,7 +4896,7 @@ export class LocalTui {
|
|
|
4758
4896
|
submission.literal = true;
|
|
4759
4897
|
const command = !submission.literal && (submittedText.trimStart().startsWith('/') || (images.length === 0 && files.length === 0 && submittedText.startsWith('!')));
|
|
4760
4898
|
if (!command && this.#state.status === 'running') {
|
|
4761
|
-
submission.delivery = queueEditNewer !== null || this.#queueEditPending ? 'queue' :
|
|
4899
|
+
submission.delivery = queueEditNewer !== null || this.#queueEditPending ? 'queue' : this.#resolveDelivery(delivery);
|
|
4762
4900
|
}
|
|
4763
4901
|
if (historyText !== '' && this.#history[this.#history.length - 1] !== historyText) {
|
|
4764
4902
|
this.#history.push(historyText);
|
|
@@ -4806,7 +4944,7 @@ export class LocalTui {
|
|
|
4806
4944
|
const newer = this.#queueEditNewer;
|
|
4807
4945
|
if (delivery === 'steer')
|
|
4808
4946
|
submission.literal = true;
|
|
4809
|
-
submission.delivery = newer !== null || this.#queueEditPending
|
|
4947
|
+
submission.delivery = newer !== null || this.#queueEditPending || this.#state.status !== 'running' ? 'queue' : this.#resolveDelivery(delivery);
|
|
4810
4948
|
const { images, files = [], literal = false, text: submittedText } = submission;
|
|
4811
4949
|
if (historyText !== '' && this.#history[this.#history.length - 1] !== historyText) {
|
|
4812
4950
|
this.#history.push(historyText);
|
|
@@ -5151,6 +5289,8 @@ export class LocalTui {
|
|
|
5151
5289
|
#emitNotification(notification) {
|
|
5152
5290
|
if (notification === undefined || !this.#tty || this.#disposed)
|
|
5153
5291
|
return;
|
|
5292
|
+
if (this.#reportsProgramState && notification.programState !== undefined && programStatusNeedsAttention(notification.programState))
|
|
5293
|
+
return;
|
|
5154
5294
|
if (this.#notificationPolicy === 'unfocused' && this.#terminalFocused === true)
|
|
5155
5295
|
return;
|
|
5156
5296
|
this.#notificationQueue.offer(notification);
|
|
@@ -5169,20 +5309,19 @@ export class LocalTui {
|
|
|
5169
5309
|
return;
|
|
5170
5310
|
if (pending.programState !== undefined && pending.programState !== this.#herdr.programStatus.state)
|
|
5171
5311
|
return;
|
|
5172
|
-
if (this.#reportsProgramState && programStatusNeedsAttention(
|
|
5173
|
-
this.#syncWindowTitle(true);
|
|
5312
|
+
if (this.#reportsProgramState && pending.programState !== undefined && programStatusNeedsAttention(pending.programState))
|
|
5174
5313
|
return;
|
|
5175
|
-
}
|
|
5176
5314
|
const sequence = terminalNotificationSequence(pending);
|
|
5177
5315
|
if (sequence !== '')
|
|
5178
5316
|
this.#term.output.write(sequence);
|
|
5179
5317
|
}, 25);
|
|
5180
5318
|
}
|
|
5181
5319
|
#runHelp(full) {
|
|
5320
|
+
const enhancedKeys = this.#session.keyboardProtocol === 'kitty';
|
|
5182
5321
|
if (!this.#tty) {
|
|
5183
|
-
this.commandOutput('help', ['Help', '', '## Essential Shortcuts', '', formatEssentialHotkeysText(this.#keybindings),
|
|
5322
|
+
this.commandOutput('help', ['Help', '', '## Essential Shortcuts', '', formatEssentialHotkeysText(this.#keybindings, enhancedKeys),
|
|
5184
5323
|
'', formatHelpText(this.#commands(), resolveUiLanguage(this.#uiLanguage)),
|
|
5185
|
-
...(full ? ['', formatHotkeysText(this.#keybindings)] : ['', 'Use `/help full` to view every keyboard shortcut.'])].join('\n'));
|
|
5324
|
+
...(full ? ['', formatHotkeysText(this.#keybindings, enhancedKeys)] : ['', 'Use `/help full` to view every keyboard shortcut.'])].join('\n'));
|
|
5186
5325
|
return;
|
|
5187
5326
|
}
|
|
5188
5327
|
if (this.#fileReviewAbort !== undefined || this.#prompt !== null)
|
|
@@ -5194,7 +5333,7 @@ export class LocalTui {
|
|
|
5194
5333
|
copyText: (text, label) => this.copyText(text, label),
|
|
5195
5334
|
insertText: (text) => this.insertText(text),
|
|
5196
5335
|
};
|
|
5197
|
-
void browseHelp(surface, this.#commands(), this.#keybindings, resolveUiLanguage(this.#uiLanguage), full, abort.signal)
|
|
5336
|
+
void browseHelp(surface, this.#commands(), this.#keybindings, resolveUiLanguage(this.#uiLanguage), full, abort.signal, enhancedKeys)
|
|
5198
5337
|
.catch(error => { if (!abort.signal.aborted && !this.#disposed)
|
|
5199
5338
|
this.notice(String(error), { level: 'error' }); })
|
|
5200
5339
|
.finally(() => { if (this.#fileReviewAbort === abort)
|
|
@@ -5250,6 +5389,19 @@ export class LocalTui {
|
|
|
5250
5389
|
// closes. Claiming it here would skip that layering.
|
|
5251
5390
|
if (action === 'interrupt')
|
|
5252
5391
|
return false;
|
|
5392
|
+
if (action === 'alternate-send') {
|
|
5393
|
+
if (this.#settings !== null || this.#search !== null)
|
|
5394
|
+
return false;
|
|
5395
|
+
if (this.#inspected !== undefined && !this.#inspected.writable)
|
|
5396
|
+
return true;
|
|
5397
|
+
if (this.#handleAutocomplete({ type: 'key', id: 'enter' }))
|
|
5398
|
+
return true;
|
|
5399
|
+
if (this.#hasComposerContent())
|
|
5400
|
+
this.#submit(this.#editor.expandedText, 'alternate');
|
|
5401
|
+
else
|
|
5402
|
+
this.#render();
|
|
5403
|
+
return true;
|
|
5404
|
+
}
|
|
5253
5405
|
if (action === 'clear-composer')
|
|
5254
5406
|
return this.#runClearComposer();
|
|
5255
5407
|
if (action === 'quit') {
|
|
@@ -5416,6 +5568,33 @@ export class LocalTui {
|
|
|
5416
5568
|
this.#scrollBy(-this.#pageSize());
|
|
5417
5569
|
return true;
|
|
5418
5570
|
}
|
|
5571
|
+
if (action === 'previous-turn' || action === 'next-turn') {
|
|
5572
|
+
if (this.#search !== null)
|
|
5573
|
+
return false;
|
|
5574
|
+
const prompts = this.#state.blocks.flatMap((block, index) => block.kind === 'user' ? [index] : []);
|
|
5575
|
+
const anchor = this.#promptAnchor === undefined ? -1 : this.#state.blocks.indexOf(this.#promptAnchor);
|
|
5576
|
+
const top = this.#follow
|
|
5577
|
+
? this.#renderer.viewport().map((_, row) => this.#renderer.documentRowAt(row)).find(row => row !== undefined) ?? this.#scrollStart
|
|
5578
|
+
: this.#scrollStart;
|
|
5579
|
+
const target = action === 'previous-turn'
|
|
5580
|
+
? prompts.findLast(index => anchor >= 0 ? index < anchor : (this.#blockStarts[index] ?? 0) < top)
|
|
5581
|
+
: prompts.find(index => anchor >= 0 ? index > anchor : (this.#blockStarts[index] ?? 0) > top);
|
|
5582
|
+
this.#processSelection = undefined;
|
|
5583
|
+
this.#ac = null;
|
|
5584
|
+
if (target === undefined) {
|
|
5585
|
+
if (action === 'next-turn')
|
|
5586
|
+
this.#followTail();
|
|
5587
|
+
}
|
|
5588
|
+
else {
|
|
5589
|
+
this.#promptAnchor = this.#state.blocks[target];
|
|
5590
|
+
this.#inspecting = true;
|
|
5591
|
+
this.#follow = false;
|
|
5592
|
+
this.#focusBlock = target;
|
|
5593
|
+
this.#focusBlockEdge = 'start';
|
|
5594
|
+
}
|
|
5595
|
+
this.#render();
|
|
5596
|
+
return true;
|
|
5597
|
+
}
|
|
5419
5598
|
if (action === 'scroll-page-down') {
|
|
5420
5599
|
if (this.#search !== null)
|
|
5421
5600
|
return false;
|
|
@@ -5711,7 +5890,7 @@ export class LocalTui {
|
|
|
5711
5890
|
});
|
|
5712
5891
|
if (entered === null || this.#disposed)
|
|
5713
5892
|
continue;
|
|
5714
|
-
const normalized = entered
|
|
5893
|
+
const normalized = normalizeKeyId(entered);
|
|
5715
5894
|
if (normalized === '')
|
|
5716
5895
|
continue;
|
|
5717
5896
|
const next = { ...this.#keybindings };
|
|
@@ -5846,6 +6025,7 @@ export class LocalTui {
|
|
|
5846
6025
|
return true;
|
|
5847
6026
|
}
|
|
5848
6027
|
if (event.id === 'home') {
|
|
6028
|
+
this.#promptAnchor = undefined;
|
|
5849
6029
|
const current = this.#fileActionFrame?.transcript?.disclosures?.findLast(target => target.detailEnd !== undefined && this.#scrollStart > target.row && this.#scrollStart < target.detailEnd);
|
|
5850
6030
|
this.#processSelection = current?.block ?? selected;
|
|
5851
6031
|
this.#focusBlock = this.#processSelection;
|
|
@@ -5854,6 +6034,7 @@ export class LocalTui {
|
|
|
5854
6034
|
return true;
|
|
5855
6035
|
}
|
|
5856
6036
|
if (event.id === 'up' || event.id === 'down') {
|
|
6037
|
+
this.#promptAnchor = undefined;
|
|
5857
6038
|
const rows = this.#processRows();
|
|
5858
6039
|
const at = Math.max(0, rows.indexOf(selected));
|
|
5859
6040
|
const next = rows[Math.max(0, Math.min(rows.length - 1, at + (event.id === 'up' ? -1 : 1)))];
|
|
@@ -6040,12 +6221,18 @@ export class LocalTui {
|
|
|
6040
6221
|
return;
|
|
6041
6222
|
}
|
|
6042
6223
|
this.#transcriptSearch = command.state;
|
|
6043
|
-
if (command.kind === 'focus')
|
|
6044
|
-
this.#
|
|
6045
|
-
this.#focusBlockEdge = 'start';
|
|
6046
|
-
}
|
|
6224
|
+
if (command.kind === 'focus')
|
|
6225
|
+
this.#focusSearchMatch(command.match);
|
|
6047
6226
|
this.#render();
|
|
6048
6227
|
}
|
|
6228
|
+
#focusSearchMatch(match) {
|
|
6229
|
+
this.#promptAnchor = undefined;
|
|
6230
|
+
this.#processSelection = undefined;
|
|
6231
|
+
this.#inspecting = true;
|
|
6232
|
+
this.#follow = false;
|
|
6233
|
+
this.#focusBlock = match.block;
|
|
6234
|
+
this.#focusBlockEdge = 'start';
|
|
6235
|
+
}
|
|
6049
6236
|
}
|
|
6050
6237
|
/**
|
|
6051
6238
|
* Mount the local terminal provider as the tui service.
|
|
@@ -6084,7 +6271,16 @@ export function apply(ctx, config) {
|
|
|
6084
6271
|
},
|
|
6085
6272
|
terminalProfile,
|
|
6086
6273
|
alternateScreenOverlays: terminalProfile === 'direct',
|
|
6087
|
-
herdrReporter:
|
|
6274
|
+
herdrReporter: (() => {
|
|
6275
|
+
const interactive = term.input.isTTY === true && term.output.isTTY === true;
|
|
6276
|
+
const reporter = new HerdrAgentReporter({ interactive });
|
|
6277
|
+
if (interactive && process.env.OMDSH === undefined) {
|
|
6278
|
+
process.env.OMDSH = '1';
|
|
6279
|
+
ctx.effect(() => () => { if (process.env.OMDSH === '1')
|
|
6280
|
+
delete process.env.OMDSH; });
|
|
6281
|
+
}
|
|
6282
|
+
return reporter;
|
|
6283
|
+
})(),
|
|
6088
6284
|
historyPath: config.historyPath ?? join(dshHome, 'omdsh', 'history.jsonl'),
|
|
6089
6285
|
draftsPath: join(config.dshHome ?? dshHome, 'omdsh', 'drafts'),
|
|
6090
6286
|
keybindingsPath: config.keybindingsPath ?? join(dshHome, 'omdsh', 'keybindings.json'),
|