aoaoe 0.78.0 → 0.79.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 +11 -2
- package/dist/input.d.ts +3 -0
- package/dist/input.js +14 -0
- package/dist/tui.d.ts +16 -1
- package/dist/tui.js +80 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -318,6 +318,9 @@ async function main() {
|
|
|
318
318
|
tui.log("system", "returned to overview");
|
|
319
319
|
return;
|
|
320
320
|
}
|
|
321
|
+
// compact mode: no per-session click targeting (use quick-switch or /view)
|
|
322
|
+
if (tui.isCompact())
|
|
323
|
+
return;
|
|
321
324
|
const sessionIdx = hitTestSession(row, 1, tui.getSessionCount());
|
|
322
325
|
if (sessionIdx !== null) {
|
|
323
326
|
const ok = tui.enterDrilldown(sessionIdx);
|
|
@@ -369,9 +372,15 @@ async function main() {
|
|
|
369
372
|
tui.log("system", `unknown sort mode: ${mode} (try: status, name, activity, default)`);
|
|
370
373
|
}
|
|
371
374
|
});
|
|
372
|
-
// wire
|
|
375
|
+
// wire /compact toggle
|
|
376
|
+
input.onCompact(() => {
|
|
377
|
+
const enabled = !tui.isCompact();
|
|
378
|
+
tui.setCompact(enabled);
|
|
379
|
+
tui.log("system", `compact mode: ${enabled ? "on" : "off"}`);
|
|
380
|
+
});
|
|
381
|
+
// wire mouse move to hover highlight on session cards (disabled in compact)
|
|
373
382
|
input.onMouseMove((row, _col) => {
|
|
374
|
-
if (tui.getViewMode() === "overview") {
|
|
383
|
+
if (tui.getViewMode() === "overview" && !tui.isCompact()) {
|
|
375
384
|
const sessionIdx = hitTestSession(row, 1, tui.getSessionCount());
|
|
376
385
|
tui.setHoverSession(sessionIdx);
|
|
377
386
|
}
|
package/dist/input.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export type ViewHandler = (target: string | null) => void;
|
|
|
4
4
|
export type SearchHandler = (pattern: string | null) => void;
|
|
5
5
|
export type QuickSwitchHandler = (sessionNum: number) => void;
|
|
6
6
|
export type SortHandler = (mode: string | null) => void;
|
|
7
|
+
export type CompactHandler = () => void;
|
|
7
8
|
export interface MouseEvent {
|
|
8
9
|
button: number;
|
|
9
10
|
col: number;
|
|
@@ -30,6 +31,7 @@ export declare class InputReader {
|
|
|
30
31
|
private searchHandler;
|
|
31
32
|
private quickSwitchHandler;
|
|
32
33
|
private sortHandler;
|
|
34
|
+
private compactHandler;
|
|
33
35
|
private mouseDataListener;
|
|
34
36
|
onScroll(handler: (dir: ScrollDirection) => void): void;
|
|
35
37
|
onQueueChange(handler: (count: number) => void): void;
|
|
@@ -40,6 +42,7 @@ export declare class InputReader {
|
|
|
40
42
|
onSearch(handler: SearchHandler): void;
|
|
41
43
|
onQuickSwitch(handler: QuickSwitchHandler): void;
|
|
42
44
|
onSort(handler: SortHandler): void;
|
|
45
|
+
onCompact(handler: CompactHandler): void;
|
|
43
46
|
private notifyQueueChange;
|
|
44
47
|
start(): void;
|
|
45
48
|
drain(): string[];
|
package/dist/input.js
CHANGED
|
@@ -36,6 +36,7 @@ export class InputReader {
|
|
|
36
36
|
searchHandler = null;
|
|
37
37
|
quickSwitchHandler = null;
|
|
38
38
|
sortHandler = null;
|
|
39
|
+
compactHandler = null;
|
|
39
40
|
mouseDataListener = null;
|
|
40
41
|
// register a callback for scroll key events (PgUp/PgDn/Home/End)
|
|
41
42
|
onScroll(handler) {
|
|
@@ -73,6 +74,10 @@ export class InputReader {
|
|
|
73
74
|
onSort(handler) {
|
|
74
75
|
this.sortHandler = handler;
|
|
75
76
|
}
|
|
77
|
+
// register a callback for compact mode toggle (/compact)
|
|
78
|
+
onCompact(handler) {
|
|
79
|
+
this.compactHandler = handler;
|
|
80
|
+
}
|
|
76
81
|
notifyQueueChange() {
|
|
77
82
|
this.queueChangeHandler?.(this.queue.length);
|
|
78
83
|
}
|
|
@@ -251,6 +256,7 @@ ${BOLD}navigation:${RESET}
|
|
|
251
256
|
/view [N|name] drill into a session's live output (default: 1)
|
|
252
257
|
/back return to overview from drill-down
|
|
253
258
|
/sort [mode] sort sessions: status, name, activity, default (or cycle)
|
|
259
|
+
/compact toggle compact mode (dense session panel)
|
|
254
260
|
/search <pattern> filter activity entries by substring (case-insensitive)
|
|
255
261
|
/search clear active search filter
|
|
256
262
|
click session click an agent card to drill down (click again to go back)
|
|
@@ -340,6 +346,14 @@ ${BOLD}other:${RESET}
|
|
|
340
346
|
}
|
|
341
347
|
break;
|
|
342
348
|
}
|
|
349
|
+
case "/compact":
|
|
350
|
+
if (this.compactHandler) {
|
|
351
|
+
this.compactHandler();
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
console.error(`${DIM}compact mode not available (no TUI)${RESET}`);
|
|
355
|
+
}
|
|
356
|
+
break;
|
|
343
357
|
case "/search": {
|
|
344
358
|
const searchArg = line.slice("/search".length).trim();
|
|
345
359
|
if (this.searchHandler) {
|
package/dist/tui.d.ts
CHANGED
|
@@ -6,6 +6,16 @@ declare const SORT_MODES: SortMode[];
|
|
|
6
6
|
declare function sortSessions(sessions: DaemonSessionState[], mode: SortMode, lastChangeAt?: Map<string, number>): DaemonSessionState[];
|
|
7
7
|
/** Cycle to the next sort mode. */
|
|
8
8
|
declare function nextSortMode(current: SortMode): SortMode;
|
|
9
|
+
/** Max name length in compact token. */
|
|
10
|
+
declare const COMPACT_NAME_LEN = 10;
|
|
11
|
+
/**
|
|
12
|
+
* Format sessions as inline compact tokens, wrapped to fit maxWidth.
|
|
13
|
+
* Each token: "{idx}{dot}{name}" — e.g. "1●Alpha" with colored dot and bold name.
|
|
14
|
+
* Returns array of formatted row strings (one per display row).
|
|
15
|
+
*/
|
|
16
|
+
declare function formatCompactRows(sessions: DaemonSessionState[], maxWidth: number): string[];
|
|
17
|
+
/** Compute how many display rows compact mode needs (minimum 1). */
|
|
18
|
+
declare function computeCompactRowCount(sessions: DaemonSessionState[], maxWidth: number): number;
|
|
9
19
|
declare function phaseDisplay(phase: DaemonPhase, paused: boolean, spinnerFrame: number): string;
|
|
10
20
|
export interface ActivityEntry {
|
|
11
21
|
time: string;
|
|
@@ -35,6 +45,7 @@ export declare class TUI {
|
|
|
35
45
|
private sortMode;
|
|
36
46
|
private lastChangeAt;
|
|
37
47
|
private prevLastActivity;
|
|
48
|
+
private compactMode;
|
|
38
49
|
private viewMode;
|
|
39
50
|
private drilldownSessionId;
|
|
40
51
|
private sessionOutputs;
|
|
@@ -56,6 +67,10 @@ export declare class TUI {
|
|
|
56
67
|
setSortMode(mode: SortMode): void;
|
|
57
68
|
/** Return the current sort mode. */
|
|
58
69
|
getSortMode(): SortMode;
|
|
70
|
+
/** Toggle or set compact mode. Recomputes layout and repaints. */
|
|
71
|
+
setCompact(enabled: boolean): void;
|
|
72
|
+
/** Return whether compact mode is enabled. */
|
|
73
|
+
isCompact(): boolean;
|
|
59
74
|
updateState(opts: {
|
|
60
75
|
phase?: DaemonPhase;
|
|
61
76
|
pollCount?: number;
|
|
@@ -146,5 +161,5 @@ declare function formatSearchIndicator(pattern: string, matchCount: number, tota
|
|
|
146
161
|
* (row = headerHeight + 2 + i for 0-indexed session i)
|
|
147
162
|
*/
|
|
148
163
|
export declare function hitTestSession(row: number, headerHeight: number, sessionCount: number): number | null;
|
|
149
|
-
export { formatActivity, formatSessionCard, truncateAnsi, truncatePlain, padBoxLine, padBoxLineHover, padToWidth, stripAnsiForLen, phaseDisplay, computeScrollSlice, formatScrollIndicator, formatDrilldownScrollIndicator, formatPrompt, formatDrilldownHeader, matchesSearch, formatSearchIndicator, computeSparkline, formatSparkline, sortSessions, nextSortMode, SORT_MODES };
|
|
164
|
+
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 };
|
|
150
165
|
//# sourceMappingURL=tui.d.ts.map
|
package/dist/tui.js
CHANGED
|
@@ -48,6 +48,50 @@ function nextSortMode(current) {
|
|
|
48
48
|
const idx = SORT_MODES.indexOf(current);
|
|
49
49
|
return SORT_MODES[(idx + 1) % SORT_MODES.length];
|
|
50
50
|
}
|
|
51
|
+
// ── Compact mode ────────────────────────────────────────────────────────────
|
|
52
|
+
/** Max name length in compact token. */
|
|
53
|
+
const COMPACT_NAME_LEN = 10;
|
|
54
|
+
/**
|
|
55
|
+
* Format sessions as inline compact tokens, wrapped to fit maxWidth.
|
|
56
|
+
* Each token: "{idx}{dot}{name}" — e.g. "1●Alpha" with colored dot and bold name.
|
|
57
|
+
* Returns array of formatted row strings (one per display row).
|
|
58
|
+
*/
|
|
59
|
+
function formatCompactRows(sessions, maxWidth) {
|
|
60
|
+
if (sessions.length === 0)
|
|
61
|
+
return [`${DIM}no agents connected${RESET}`];
|
|
62
|
+
const tokens = [];
|
|
63
|
+
const widths = [];
|
|
64
|
+
for (let i = 0; i < sessions.length; i++) {
|
|
65
|
+
const s = sessions[i];
|
|
66
|
+
const idx = String(i + 1);
|
|
67
|
+
const dot = STATUS_DOT[s.status] ?? `${AMBER}${DOT.filled}${RESET}`;
|
|
68
|
+
const name = truncatePlain(s.title, COMPACT_NAME_LEN);
|
|
69
|
+
tokens.push(`${SLATE}${idx}${RESET}${dot}${BOLD}${name}${RESET}`);
|
|
70
|
+
widths.push(idx.length + 1 + name.length); // idx chars + dot char + name chars
|
|
71
|
+
}
|
|
72
|
+
const rows = [];
|
|
73
|
+
let currentRow = "";
|
|
74
|
+
let currentWidth = 0;
|
|
75
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
76
|
+
const gap = currentWidth > 0 ? 2 : 0;
|
|
77
|
+
if (currentWidth + gap + widths[i] > maxWidth && currentWidth > 0) {
|
|
78
|
+
rows.push(currentRow);
|
|
79
|
+
currentRow = tokens[i];
|
|
80
|
+
currentWidth = widths[i];
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
currentRow += (currentWidth > 0 ? " " : "") + tokens[i];
|
|
84
|
+
currentWidth += gap + widths[i];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (currentRow)
|
|
88
|
+
rows.push(currentRow);
|
|
89
|
+
return rows;
|
|
90
|
+
}
|
|
91
|
+
/** Compute how many display rows compact mode needs (minimum 1). */
|
|
92
|
+
function computeCompactRowCount(sessions, maxWidth) {
|
|
93
|
+
return Math.max(1, formatCompactRows(sessions, maxWidth).length);
|
|
94
|
+
}
|
|
51
95
|
// ── Status rendering ────────────────────────────────────────────────────────
|
|
52
96
|
const STATUS_DOT = {
|
|
53
97
|
working: `${LIME}${DOT.filled}${RESET}`,
|
|
@@ -96,6 +140,7 @@ export class TUI {
|
|
|
96
140
|
sortMode = "default";
|
|
97
141
|
lastChangeAt = new Map(); // session ID → epoch ms of last activity change
|
|
98
142
|
prevLastActivity = new Map(); // session ID → previous lastActivity string
|
|
143
|
+
compactMode = false;
|
|
99
144
|
// drill-down mode: show a single session's full output
|
|
100
145
|
viewMode = "overview";
|
|
101
146
|
drilldownSessionId = null;
|
|
@@ -167,6 +212,20 @@ export class TUI {
|
|
|
167
212
|
getSortMode() {
|
|
168
213
|
return this.sortMode;
|
|
169
214
|
}
|
|
215
|
+
/** Toggle or set compact mode. Recomputes layout and repaints. */
|
|
216
|
+
setCompact(enabled) {
|
|
217
|
+
if (enabled === this.compactMode)
|
|
218
|
+
return;
|
|
219
|
+
this.compactMode = enabled;
|
|
220
|
+
if (this.active) {
|
|
221
|
+
this.computeLayout(this.sessions.length);
|
|
222
|
+
this.paintAll();
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/** Return whether compact mode is enabled. */
|
|
226
|
+
isCompact() {
|
|
227
|
+
return this.compactMode;
|
|
228
|
+
}
|
|
170
229
|
// ── State updates ───────────────────────────────────────────────────────
|
|
171
230
|
updateState(opts) {
|
|
172
231
|
if (opts.phase !== undefined)
|
|
@@ -460,7 +519,9 @@ export class TUI {
|
|
|
460
519
|
}
|
|
461
520
|
else {
|
|
462
521
|
// overview: header (1) + sessions box + separator + activity + input
|
|
463
|
-
const sessBodyRows =
|
|
522
|
+
const sessBodyRows = this.compactMode
|
|
523
|
+
? computeCompactRowCount(this.sessions, this.cols - 2)
|
|
524
|
+
: Math.max(sessionCount, 1);
|
|
464
525
|
this.sessionRows = sessBodyRows + 2; // + top/bottom borders
|
|
465
526
|
this.separatorRow = this.headerHeight + this.sessionRows + 1;
|
|
466
527
|
this.inputRow = this.rows;
|
|
@@ -520,8 +581,11 @@ export class TUI {
|
|
|
520
581
|
paintSessions() {
|
|
521
582
|
const startRow = this.headerHeight + 1;
|
|
522
583
|
const innerWidth = this.cols - 2; // inside the box borders
|
|
523
|
-
// top border with label (includes sort mode
|
|
524
|
-
const
|
|
584
|
+
// top border with label (includes compact/sort mode tags)
|
|
585
|
+
const sortTag = this.sortMode !== "default" ? this.sortMode : "";
|
|
586
|
+
const compactTag = this.compactMode ? "compact" : "";
|
|
587
|
+
const tags = [compactTag, sortTag].filter(Boolean).join(", ");
|
|
588
|
+
const label = tags ? ` agents (${tags}) ` : " agents ";
|
|
525
589
|
const borderAfterLabel = Math.max(0, innerWidth - label.length);
|
|
526
590
|
const topBorder = `${SLATE}${BOX.rtl}${BOX.h}${RESET}${SLATE}${label}${RESET}${SLATE}${BOX.h.repeat(borderAfterLabel)}${BOX.rtr}${RESET}`;
|
|
527
591
|
process.stderr.write(SAVE_CURSOR + moveTo(startRow, 1) + CLEAR_LINE + truncateAnsi(topBorder, this.cols));
|
|
@@ -531,6 +595,15 @@ export class TUI {
|
|
|
531
595
|
const padded = padBoxLine(empty, this.cols);
|
|
532
596
|
process.stderr.write(moveTo(startRow + 1, 1) + CLEAR_LINE + padded);
|
|
533
597
|
}
|
|
598
|
+
else if (this.compactMode) {
|
|
599
|
+
// compact: inline tokens, multiple per row
|
|
600
|
+
const compactRows = formatCompactRows(this.sessions, innerWidth - 1);
|
|
601
|
+
for (let r = 0; r < compactRows.length; r++) {
|
|
602
|
+
const line = `${SLATE}${BOX.v}${RESET} ${compactRows[r]}`;
|
|
603
|
+
const padded = padBoxLine(line, this.cols);
|
|
604
|
+
process.stderr.write(moveTo(startRow + 1 + r, 1) + CLEAR_LINE + padded);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
534
607
|
else {
|
|
535
608
|
for (let i = 0; i < this.sessions.length; i++) {
|
|
536
609
|
const s = this.sessions[i];
|
|
@@ -542,7 +615,9 @@ export class TUI {
|
|
|
542
615
|
}
|
|
543
616
|
}
|
|
544
617
|
// bottom border
|
|
545
|
-
const bodyRows =
|
|
618
|
+
const bodyRows = this.compactMode
|
|
619
|
+
? computeCompactRowCount(this.sessions, innerWidth)
|
|
620
|
+
: Math.max(this.sessions.length, 1);
|
|
546
621
|
const bottomRow = startRow + 1 + bodyRows;
|
|
547
622
|
const bottomBorder = `${SLATE}${BOX.rbl}${BOX.h.repeat(Math.max(0, this.cols - 2))}${BOX.rbr}${RESET}`;
|
|
548
623
|
process.stderr.write(moveTo(bottomRow, 1) + CLEAR_LINE + truncateAnsi(bottomBorder, this.cols));
|
|
@@ -931,5 +1006,5 @@ export function hitTestSession(row, headerHeight, sessionCount) {
|
|
|
931
1006
|
return row - firstSessionRow + 1; // 1-indexed
|
|
932
1007
|
}
|
|
933
1008
|
// ── Exported pure helpers (for testing) ─────────────────────────────────────
|
|
934
|
-
export { formatActivity, formatSessionCard, truncateAnsi, truncatePlain, padBoxLine, padBoxLineHover, padToWidth, stripAnsiForLen, phaseDisplay, computeScrollSlice, formatScrollIndicator, formatDrilldownScrollIndicator, formatPrompt, formatDrilldownHeader, matchesSearch, formatSearchIndicator, computeSparkline, formatSparkline, sortSessions, nextSortMode, SORT_MODES };
|
|
1009
|
+
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 };
|
|
935
1010
|
//# sourceMappingURL=tui.js.map
|