aoaoe 0.84.0 → 0.85.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/dist/index.js +31 -0
- package/dist/input.d.ts +6 -0
- package/dist/input.js +43 -0
- package/dist/tui.d.ts +22 -2
- package/dist/tui.js +75 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -444,6 +444,37 @@ async function main() {
|
|
|
444
444
|
tui.log("system", `session not found: ${target}`);
|
|
445
445
|
}
|
|
446
446
|
});
|
|
447
|
+
// wire /note set/clear
|
|
448
|
+
input.onNote((target, text) => {
|
|
449
|
+
const num = /^\d+$/.test(target) ? parseInt(target, 10) : undefined;
|
|
450
|
+
const ok = tui.setNote(num ?? target, text);
|
|
451
|
+
if (ok) {
|
|
452
|
+
if (text) {
|
|
453
|
+
tui.log("system", `note set for ${target}: "${text}"`);
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
tui.log("system", `note cleared for ${target}`);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
else {
|
|
460
|
+
tui.log("system", `session not found: ${target}`);
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
// wire /notes listing
|
|
464
|
+
input.onNotes(() => {
|
|
465
|
+
const notes = tui.getAllNotes();
|
|
466
|
+
if (notes.size === 0) {
|
|
467
|
+
tui.log("system", "no notes — use /note <N|name> <text> to add one");
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
const sessions = tui.getSessions();
|
|
471
|
+
for (const [id, text] of notes) {
|
|
472
|
+
const session = sessions.find((s) => s.id === id);
|
|
473
|
+
const label = session ? session.title : id.slice(0, 8);
|
|
474
|
+
tui.log("system", ` ${label}: "${text}"`);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
});
|
|
447
478
|
// wire mouse move to hover highlight on session cards (disabled in compact)
|
|
448
479
|
input.onMouseMove((row, _col) => {
|
|
449
480
|
if (tui.getViewMode() === "overview" && !tui.isCompact()) {
|
package/dist/input.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export type MarkHandler = () => void;
|
|
|
12
12
|
export type JumpHandler = (num: number) => void;
|
|
13
13
|
export type MarksHandler = () => void;
|
|
14
14
|
export type MuteHandler = (target: string) => void;
|
|
15
|
+
export type NoteHandler = (target: string, text: string) => void;
|
|
16
|
+
export type NotesHandler = () => void;
|
|
15
17
|
export interface MouseEvent {
|
|
16
18
|
button: number;
|
|
17
19
|
col: number;
|
|
@@ -46,6 +48,8 @@ export declare class InputReader {
|
|
|
46
48
|
private jumpHandler;
|
|
47
49
|
private marksHandler;
|
|
48
50
|
private muteHandler;
|
|
51
|
+
private noteHandler;
|
|
52
|
+
private notesHandler;
|
|
49
53
|
private mouseDataListener;
|
|
50
54
|
onScroll(handler: (dir: ScrollDirection) => void): void;
|
|
51
55
|
onQueueChange(handler: (count: number) => void): void;
|
|
@@ -64,6 +68,8 @@ export declare class InputReader {
|
|
|
64
68
|
onJump(handler: JumpHandler): void;
|
|
65
69
|
onMarks(handler: MarksHandler): void;
|
|
66
70
|
onMute(handler: MuteHandler): void;
|
|
71
|
+
onNote(handler: NoteHandler): void;
|
|
72
|
+
onNotes(handler: NotesHandler): void;
|
|
67
73
|
private notifyQueueChange;
|
|
68
74
|
start(): void;
|
|
69
75
|
drain(): string[];
|
package/dist/input.js
CHANGED
|
@@ -44,6 +44,8 @@ export class InputReader {
|
|
|
44
44
|
jumpHandler = null;
|
|
45
45
|
marksHandler = null;
|
|
46
46
|
muteHandler = null;
|
|
47
|
+
noteHandler = null;
|
|
48
|
+
notesHandler = null;
|
|
47
49
|
mouseDataListener = null;
|
|
48
50
|
// register a callback for scroll key events (PgUp/PgDn/Home/End)
|
|
49
51
|
onScroll(handler) {
|
|
@@ -113,6 +115,14 @@ export class InputReader {
|
|
|
113
115
|
onMute(handler) {
|
|
114
116
|
this.muteHandler = handler;
|
|
115
117
|
}
|
|
118
|
+
// register a callback for note commands (/note <target> <text>)
|
|
119
|
+
onNote(handler) {
|
|
120
|
+
this.noteHandler = handler;
|
|
121
|
+
}
|
|
122
|
+
// register a callback for listing notes (/notes)
|
|
123
|
+
onNotes(handler) {
|
|
124
|
+
this.notesHandler = handler;
|
|
125
|
+
}
|
|
116
126
|
notifyQueueChange() {
|
|
117
127
|
this.queueChangeHandler?.(this.queue.length);
|
|
118
128
|
}
|
|
@@ -296,6 +306,8 @@ ${BOLD}navigation:${RESET}
|
|
|
296
306
|
/bell toggle terminal bell on errors/completions
|
|
297
307
|
/focus toggle focus mode (show only pinned sessions)
|
|
298
308
|
/mute [N|name] mute/unmute a session's activity entries (toggle)
|
|
309
|
+
/note N|name text attach a note to a session (no text = clear)
|
|
310
|
+
/notes list all session notes
|
|
299
311
|
/mark bookmark current activity position
|
|
300
312
|
/jump N jump to bookmark N
|
|
301
313
|
/marks list all bookmarks
|
|
@@ -442,6 +454,37 @@ ${BOLD}other:${RESET}
|
|
|
442
454
|
}
|
|
443
455
|
break;
|
|
444
456
|
}
|
|
457
|
+
case "/note": {
|
|
458
|
+
const noteArg = line.slice("/note".length).trim();
|
|
459
|
+
if (this.noteHandler) {
|
|
460
|
+
// split: first word is target, rest is note text
|
|
461
|
+
const spaceIdx = noteArg.indexOf(" ");
|
|
462
|
+
if (spaceIdx > 0) {
|
|
463
|
+
const target = noteArg.slice(0, spaceIdx);
|
|
464
|
+
const text = noteArg.slice(spaceIdx + 1).trim();
|
|
465
|
+
this.noteHandler(target, text);
|
|
466
|
+
}
|
|
467
|
+
else if (noteArg) {
|
|
468
|
+
// target only, no text — clear note
|
|
469
|
+
this.noteHandler(noteArg, "");
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
console.error(`${DIM}usage: /note <N|name> <text> — set note, or /note <N|name> — clear${RESET}`);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
console.error(`${DIM}notes not available (no TUI)${RESET}`);
|
|
477
|
+
}
|
|
478
|
+
break;
|
|
479
|
+
}
|
|
480
|
+
case "/notes":
|
|
481
|
+
if (this.notesHandler) {
|
|
482
|
+
this.notesHandler();
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
console.error(`${DIM}notes not available (no TUI)${RESET}`);
|
|
486
|
+
}
|
|
487
|
+
break;
|
|
445
488
|
case "/mark":
|
|
446
489
|
if (this.markHandler) {
|
|
447
490
|
this.markHandler();
|
package/dist/tui.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ declare const PIN_ICON = "\u25B2";
|
|
|
31
31
|
* Each token: "{idx}{pin?}{mute?}{dot}{name}" — e.g. "1▲●Alpha" for pinned, "2◌●Bravo" for muted.
|
|
32
32
|
* Returns array of formatted row strings (one per display row).
|
|
33
33
|
*/
|
|
34
|
-
declare function formatCompactRows(sessions: DaemonSessionState[], maxWidth: number, pinnedIds?: Set<string>, mutedIds?: Set<string>): string[];
|
|
34
|
+
declare function formatCompactRows(sessions: DaemonSessionState[], maxWidth: number, pinnedIds?: Set<string>, mutedIds?: Set<string>, noteIds?: Set<string>): string[];
|
|
35
35
|
/** Compute how many display rows compact mode needs (minimum 1). */
|
|
36
36
|
declare function computeCompactRowCount(sessions: DaemonSessionState[], maxWidth: number): number;
|
|
37
37
|
declare function phaseDisplay(phase: DaemonPhase, paused: boolean, spinnerFrame: number): string;
|
|
@@ -43,6 +43,12 @@ export interface ActivityEntry {
|
|
|
43
43
|
}
|
|
44
44
|
/** Mute indicator for muted sessions (shown dim beside session card). */
|
|
45
45
|
declare const MUTE_ICON = "\u25CC";
|
|
46
|
+
/** Note indicator for sessions with notes. */
|
|
47
|
+
declare const NOTE_ICON = "\u270E";
|
|
48
|
+
/** Max length for a session note (visible chars). */
|
|
49
|
+
export declare const MAX_NOTE_LEN = 80;
|
|
50
|
+
/** Truncate a note to the max length. */
|
|
51
|
+
export declare function truncateNote(text: string): string;
|
|
46
52
|
/** Determine if an activity entry should be hidden due to muting. */
|
|
47
53
|
export declare function shouldMuteEntry(entry: ActivityEntry, mutedIds: Set<string>): boolean;
|
|
48
54
|
export declare class TUI {
|
|
@@ -75,6 +81,7 @@ export declare class TUI {
|
|
|
75
81
|
private bellEnabled;
|
|
76
82
|
private lastBellAt;
|
|
77
83
|
private mutedIds;
|
|
84
|
+
private sessionNotes;
|
|
78
85
|
private viewMode;
|
|
79
86
|
private drilldownSessionId;
|
|
80
87
|
private sessionOutputs;
|
|
@@ -129,6 +136,19 @@ export declare class TUI {
|
|
|
129
136
|
isMuted(id: string): boolean;
|
|
130
137
|
/** Return count of muted sessions. */
|
|
131
138
|
getMutedCount(): number;
|
|
139
|
+
/**
|
|
140
|
+
* Set a note on a session (by 1-indexed number, ID, ID prefix, or title).
|
|
141
|
+
* Returns true if session found. Pass empty text to clear.
|
|
142
|
+
*/
|
|
143
|
+
setNote(sessionIdOrIndex: string | number, text: string): boolean;
|
|
144
|
+
/** Get the note for a session ID (or undefined if none). */
|
|
145
|
+
getNote(id: string): string | undefined;
|
|
146
|
+
/** Return count of sessions with notes. */
|
|
147
|
+
getNoteCount(): number;
|
|
148
|
+
/** Return all session notes (for /notes listing). */
|
|
149
|
+
getAllNotes(): ReadonlyMap<string, string>;
|
|
150
|
+
/** Return the current sessions (read-only, for resolving IDs to titles in the UI). */
|
|
151
|
+
getSessions(): readonly DaemonSessionState[];
|
|
132
152
|
/**
|
|
133
153
|
* Add a bookmark at the current activity position.
|
|
134
154
|
* Returns the bookmark number (1-indexed) or 0 if buffer is empty.
|
|
@@ -233,5 +253,5 @@ declare function formatSearchIndicator(pattern: string, matchCount: number, tota
|
|
|
233
253
|
* (row = headerHeight + 2 + i for 0-indexed session i)
|
|
234
254
|
*/
|
|
235
255
|
export declare function hitTestSession(row: number, headerHeight: number, sessionCount: number): number | null;
|
|
236
|
-
export { formatActivity, formatSessionCard, truncateAnsi, truncatePlain, padBoxLine, padBoxLineHover, padToWidth, stripAnsiForLen, phaseDisplay, computeScrollSlice, formatScrollIndicator, formatDrilldownScrollIndicator, formatPrompt, formatDrilldownHeader, matchesSearch, formatSearchIndicator, computeSparkline, formatSparkline, sortSessions, nextSortMode, SORT_MODES, formatCompactRows, computeCompactRowCount, COMPACT_NAME_LEN, PIN_ICON, MUTE_ICON };
|
|
256
|
+
export { formatActivity, formatSessionCard, truncateAnsi, truncatePlain, padBoxLine, padBoxLineHover, padToWidth, stripAnsiForLen, phaseDisplay, computeScrollSlice, formatScrollIndicator, formatDrilldownScrollIndicator, formatPrompt, formatDrilldownHeader, matchesSearch, formatSearchIndicator, computeSparkline, formatSparkline, sortSessions, nextSortMode, SORT_MODES, formatCompactRows, computeCompactRowCount, COMPACT_NAME_LEN, PIN_ICON, MUTE_ICON, NOTE_ICON };
|
|
237
257
|
//# sourceMappingURL=tui.d.ts.map
|
package/dist/tui.js
CHANGED
|
@@ -90,7 +90,7 @@ const PIN_ICON = "▲";
|
|
|
90
90
|
* Each token: "{idx}{pin?}{mute?}{dot}{name}" — e.g. "1▲●Alpha" for pinned, "2◌●Bravo" for muted.
|
|
91
91
|
* Returns array of formatted row strings (one per display row).
|
|
92
92
|
*/
|
|
93
|
-
function formatCompactRows(sessions, maxWidth, pinnedIds, mutedIds) {
|
|
93
|
+
function formatCompactRows(sessions, maxWidth, pinnedIds, mutedIds, noteIds) {
|
|
94
94
|
if (sessions.length === 0)
|
|
95
95
|
return [`${DIM}no agents connected${RESET}`];
|
|
96
96
|
const tokens = [];
|
|
@@ -101,11 +101,13 @@ function formatCompactRows(sessions, maxWidth, pinnedIds, mutedIds) {
|
|
|
101
101
|
const dot = STATUS_DOT[s.status] ?? `${AMBER}${DOT.filled}${RESET}`;
|
|
102
102
|
const pinned = pinnedIds?.has(s.id) ?? false;
|
|
103
103
|
const muted = mutedIds?.has(s.id) ?? false;
|
|
104
|
+
const noted = noteIds?.has(s.id) ?? false;
|
|
104
105
|
const pin = pinned ? `${AMBER}${PIN_ICON}${RESET}` : "";
|
|
105
106
|
const muteIcon = muted ? `${DIM}${MUTE_ICON}${RESET}` : "";
|
|
107
|
+
const noteIcon = noted ? `${TEAL}${NOTE_ICON}${RESET}` : "";
|
|
106
108
|
const name = truncatePlain(s.title, COMPACT_NAME_LEN);
|
|
107
|
-
tokens.push(`${SLATE}${idx}${RESET}${pin}${muteIcon}${dot}${BOLD}${name}${RESET}`);
|
|
108
|
-
widths.push(idx.length + (pinned ? 1 : 0) + (muted ? 1 : 0) + 1 + name.length);
|
|
109
|
+
tokens.push(`${SLATE}${idx}${RESET}${pin}${muteIcon}${noteIcon}${dot}${BOLD}${name}${RESET}`);
|
|
110
|
+
widths.push(idx.length + (pinned ? 1 : 0) + (muted ? 1 : 0) + (noted ? 1 : 0) + 1 + name.length);
|
|
109
111
|
}
|
|
110
112
|
const rows = [];
|
|
111
113
|
let currentRow = "";
|
|
@@ -157,6 +159,15 @@ function phaseDisplay(phase, paused, spinnerFrame) {
|
|
|
157
159
|
// ── Mute helpers ──────────────────────────────────────────────────────────────
|
|
158
160
|
/** Mute indicator for muted sessions (shown dim beside session card). */
|
|
159
161
|
const MUTE_ICON = "◌";
|
|
162
|
+
// ── Notes ─────────────────────────────────────────────────────────────────────
|
|
163
|
+
/** Note indicator for sessions with notes. */
|
|
164
|
+
const NOTE_ICON = "✎";
|
|
165
|
+
/** Max length for a session note (visible chars). */
|
|
166
|
+
export const MAX_NOTE_LEN = 80;
|
|
167
|
+
/** Truncate a note to the max length. */
|
|
168
|
+
export function truncateNote(text) {
|
|
169
|
+
return text.length > MAX_NOTE_LEN ? text.slice(0, MAX_NOTE_LEN - 2) + ".." : text;
|
|
170
|
+
}
|
|
160
171
|
/** Determine if an activity entry should be hidden due to muting. */
|
|
161
172
|
export function shouldMuteEntry(entry, mutedIds) {
|
|
162
173
|
if (!entry.sessionId)
|
|
@@ -194,6 +205,7 @@ export class TUI {
|
|
|
194
205
|
bellEnabled = false;
|
|
195
206
|
lastBellAt = 0;
|
|
196
207
|
mutedIds = new Set(); // muted session IDs (activity entries hidden)
|
|
208
|
+
sessionNotes = new Map(); // session ID → note text
|
|
197
209
|
// drill-down mode: show a single session's full output
|
|
198
210
|
viewMode = "overview";
|
|
199
211
|
drilldownSessionId = null;
|
|
@@ -387,6 +399,52 @@ export class TUI {
|
|
|
387
399
|
getMutedCount() {
|
|
388
400
|
return this.mutedIds.size;
|
|
389
401
|
}
|
|
402
|
+
/**
|
|
403
|
+
* Set a note on a session (by 1-indexed number, ID, ID prefix, or title).
|
|
404
|
+
* Returns true if session found. Pass empty text to clear.
|
|
405
|
+
*/
|
|
406
|
+
setNote(sessionIdOrIndex, text) {
|
|
407
|
+
let sessionId;
|
|
408
|
+
if (typeof sessionIdOrIndex === "number") {
|
|
409
|
+
sessionId = this.sessions[sessionIdOrIndex - 1]?.id;
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
const needle = sessionIdOrIndex.toLowerCase();
|
|
413
|
+
const match = this.sessions.find((s) => s.id === sessionIdOrIndex || s.id.startsWith(needle) || s.title.toLowerCase() === needle);
|
|
414
|
+
sessionId = match?.id;
|
|
415
|
+
}
|
|
416
|
+
if (!sessionId)
|
|
417
|
+
return false;
|
|
418
|
+
if (text.trim() === "") {
|
|
419
|
+
this.sessionNotes.delete(sessionId);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
this.sessionNotes.set(sessionId, truncateNote(text.trim()));
|
|
423
|
+
}
|
|
424
|
+
if (this.active) {
|
|
425
|
+
this.paintSessions();
|
|
426
|
+
if (this.viewMode === "drilldown" && this.drilldownSessionId === sessionId) {
|
|
427
|
+
this.paintDrilldownSeparator();
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
/** Get the note for a session ID (or undefined if none). */
|
|
433
|
+
getNote(id) {
|
|
434
|
+
return this.sessionNotes.get(id);
|
|
435
|
+
}
|
|
436
|
+
/** Return count of sessions with notes. */
|
|
437
|
+
getNoteCount() {
|
|
438
|
+
return this.sessionNotes.size;
|
|
439
|
+
}
|
|
440
|
+
/** Return all session notes (for /notes listing). */
|
|
441
|
+
getAllNotes() {
|
|
442
|
+
return this.sessionNotes;
|
|
443
|
+
}
|
|
444
|
+
/** Return the current sessions (read-only, for resolving IDs to titles in the UI). */
|
|
445
|
+
getSessions() {
|
|
446
|
+
return this.sessions;
|
|
447
|
+
}
|
|
390
448
|
/**
|
|
391
449
|
* Add a bookmark at the current activity position.
|
|
392
450
|
* Returns the bookmark number (1-indexed) or 0 if buffer is empty.
|
|
@@ -837,7 +895,8 @@ export class TUI {
|
|
|
837
895
|
}
|
|
838
896
|
else if (this.compactMode) {
|
|
839
897
|
// compact: inline tokens, multiple per row (with pin indicators)
|
|
840
|
-
const
|
|
898
|
+
const noteIdSet = new Set(this.sessionNotes.keys());
|
|
899
|
+
const compactRows = formatCompactRows(visibleSessions, innerWidth - 1, this.pinnedIds, this.mutedIds, noteIdSet);
|
|
841
900
|
for (let r = 0; r < compactRows.length; r++) {
|
|
842
901
|
const line = `${SLATE}${BOX.v}${RESET} ${compactRows[r]}`;
|
|
843
902
|
const padded = padBoxLine(line, this.cols);
|
|
@@ -851,11 +910,13 @@ export class TUI {
|
|
|
851
910
|
const bg = isHovered ? BG_HOVER : "";
|
|
852
911
|
const pinned = this.pinnedIds.has(s.id);
|
|
853
912
|
const muted = this.mutedIds.has(s.id);
|
|
913
|
+
const noted = this.sessionNotes.has(s.id);
|
|
854
914
|
const pin = pinned ? `${AMBER}${PIN_ICON}${RESET} ` : "";
|
|
855
915
|
const mute = muted ? `${DIM}${MUTE_ICON}${RESET} ` : "";
|
|
856
|
-
const
|
|
916
|
+
const note = noted ? `${TEAL}${NOTE_ICON}${RESET} ` : "";
|
|
917
|
+
const iconsWidth = (pinned ? 2 : 0) + (muted ? 2 : 0) + (noted ? 2 : 0);
|
|
857
918
|
const cardWidth = innerWidth - 1 - iconsWidth;
|
|
858
|
-
const line = `${bg}${SLATE}${BOX.v}${RESET}${bg} ${pin}${mute}${formatSessionCard(s, cardWidth)}`;
|
|
919
|
+
const line = `${bg}${SLATE}${BOX.v}${RESET}${bg} ${pin}${mute}${note}${formatSessionCard(s, cardWidth)}`;
|
|
859
920
|
const padded = padBoxLineHover(line, this.cols, isHovered);
|
|
860
921
|
process.stderr.write(moveTo(startRow + 1 + i, 1) + CLEAR_LINE + padded);
|
|
861
922
|
}
|
|
@@ -887,11 +948,13 @@ export class TUI {
|
|
|
887
948
|
const bg = isHovered ? BG_HOVER : "";
|
|
888
949
|
const pinned = this.pinnedIds.has(s.id);
|
|
889
950
|
const muted = this.mutedIds.has(s.id);
|
|
951
|
+
const noted = this.sessionNotes.has(s.id);
|
|
890
952
|
const pin = pinned ? `${AMBER}${PIN_ICON}${RESET} ` : "";
|
|
891
953
|
const mute = muted ? `${DIM}${MUTE_ICON}${RESET} ` : "";
|
|
892
|
-
const
|
|
954
|
+
const note = noted ? `${TEAL}${NOTE_ICON}${RESET} ` : "";
|
|
955
|
+
const iconsWidth = (pinned ? 2 : 0) + (muted ? 2 : 0) + (noted ? 2 : 0);
|
|
893
956
|
const cardWidth = innerWidth - 1 - iconsWidth;
|
|
894
|
-
const line = `${bg}${SLATE}${BOX.v}${RESET}${bg} ${pin}${mute}${formatSessionCard(s, cardWidth)}`;
|
|
957
|
+
const line = `${bg}${SLATE}${BOX.v}${RESET}${bg} ${pin}${mute}${note}${formatSessionCard(s, cardWidth)}`;
|
|
895
958
|
const padded = padBoxLineHover(line, this.cols, isHovered);
|
|
896
959
|
process.stderr.write(SAVE_CURSOR + moveTo(startRow + 1 + i, 1) + CLEAR_LINE + padded + RESTORE_CURSOR);
|
|
897
960
|
}
|
|
@@ -952,7 +1015,9 @@ export class TUI {
|
|
|
952
1015
|
paintDrilldownSeparator() {
|
|
953
1016
|
const session = this.sessions.find((s) => s.id === this.drilldownSessionId);
|
|
954
1017
|
const title = session ? session.title : this.drilldownSessionId ?? "?";
|
|
955
|
-
const
|
|
1018
|
+
const noteText = this.drilldownSessionId ? this.sessionNotes.get(this.drilldownSessionId) : undefined;
|
|
1019
|
+
const noteSuffix = noteText ? `"${noteText}" ` : "";
|
|
1020
|
+
const prefix = `${BOX.h}${BOX.h} ${title} ${noteSuffix}`;
|
|
956
1021
|
let hints;
|
|
957
1022
|
if (this.drilldownScrollOffset > 0) {
|
|
958
1023
|
const outputLines = this.sessionOutputs.get(this.drilldownSessionId ?? "") ?? [];
|
|
@@ -1261,5 +1326,5 @@ export function hitTestSession(row, headerHeight, sessionCount) {
|
|
|
1261
1326
|
return row - firstSessionRow + 1; // 1-indexed
|
|
1262
1327
|
}
|
|
1263
1328
|
// ── Exported pure helpers (for testing) ─────────────────────────────────────
|
|
1264
|
-
export { formatActivity, formatSessionCard, truncateAnsi, truncatePlain, padBoxLine, padBoxLineHover, padToWidth, stripAnsiForLen, phaseDisplay, computeScrollSlice, formatScrollIndicator, formatDrilldownScrollIndicator, formatPrompt, formatDrilldownHeader, matchesSearch, formatSearchIndicator, computeSparkline, formatSparkline, sortSessions, nextSortMode, SORT_MODES, formatCompactRows, computeCompactRowCount, COMPACT_NAME_LEN, PIN_ICON, MUTE_ICON };
|
|
1329
|
+
export { formatActivity, formatSessionCard, truncateAnsi, truncatePlain, padBoxLine, padBoxLineHover, padToWidth, stripAnsiForLen, phaseDisplay, computeScrollSlice, formatScrollIndicator, formatDrilldownScrollIndicator, formatPrompt, formatDrilldownHeader, matchesSearch, formatSearchIndicator, computeSparkline, formatSparkline, sortSessions, nextSortMode, SORT_MODES, formatCompactRows, computeCompactRowCount, COMPACT_NAME_LEN, PIN_ICON, MUTE_ICON, NOTE_ICON };
|
|
1265
1330
|
//# sourceMappingURL=tui.js.map
|