aoaoe 0.85.0 → 0.86.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 +10 -0
- package/dist/input.d.ts +3 -0
- package/dist/input.js +14 -0
- package/dist/tui.d.ts +7 -0
- package/dist/tui.js +43 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -444,6 +444,16 @@ async function main() {
|
|
|
444
444
|
tui.log("system", `session not found: ${target}`);
|
|
445
445
|
}
|
|
446
446
|
});
|
|
447
|
+
// wire /unmute-all
|
|
448
|
+
input.onUnmuteAll(() => {
|
|
449
|
+
const count = tui.unmuteAll();
|
|
450
|
+
if (count > 0) {
|
|
451
|
+
tui.log("system", `unmuted ${count} session${count === 1 ? "" : "s"}`);
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
tui.log("system", "no sessions are muted");
|
|
455
|
+
}
|
|
456
|
+
});
|
|
447
457
|
// wire /note set/clear
|
|
448
458
|
input.onNote((target, text) => {
|
|
449
459
|
const num = /^\d+$/.test(target) ? parseInt(target, 10) : undefined;
|
package/dist/input.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ 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 UnmuteAllHandler = () => void;
|
|
15
16
|
export type NoteHandler = (target: string, text: string) => void;
|
|
16
17
|
export type NotesHandler = () => void;
|
|
17
18
|
export interface MouseEvent {
|
|
@@ -48,6 +49,7 @@ export declare class InputReader {
|
|
|
48
49
|
private jumpHandler;
|
|
49
50
|
private marksHandler;
|
|
50
51
|
private muteHandler;
|
|
52
|
+
private unmuteAllHandler;
|
|
51
53
|
private noteHandler;
|
|
52
54
|
private notesHandler;
|
|
53
55
|
private mouseDataListener;
|
|
@@ -68,6 +70,7 @@ export declare class InputReader {
|
|
|
68
70
|
onJump(handler: JumpHandler): void;
|
|
69
71
|
onMarks(handler: MarksHandler): void;
|
|
70
72
|
onMute(handler: MuteHandler): void;
|
|
73
|
+
onUnmuteAll(handler: UnmuteAllHandler): void;
|
|
71
74
|
onNote(handler: NoteHandler): void;
|
|
72
75
|
onNotes(handler: NotesHandler): void;
|
|
73
76
|
private notifyQueueChange;
|
package/dist/input.js
CHANGED
|
@@ -44,6 +44,7 @@ export class InputReader {
|
|
|
44
44
|
jumpHandler = null;
|
|
45
45
|
marksHandler = null;
|
|
46
46
|
muteHandler = null;
|
|
47
|
+
unmuteAllHandler = null;
|
|
47
48
|
noteHandler = null;
|
|
48
49
|
notesHandler = null;
|
|
49
50
|
mouseDataListener = null;
|
|
@@ -115,6 +116,10 @@ export class InputReader {
|
|
|
115
116
|
onMute(handler) {
|
|
116
117
|
this.muteHandler = handler;
|
|
117
118
|
}
|
|
119
|
+
// register a callback for unmuting all sessions (/unmute-all)
|
|
120
|
+
onUnmuteAll(handler) {
|
|
121
|
+
this.unmuteAllHandler = handler;
|
|
122
|
+
}
|
|
118
123
|
// register a callback for note commands (/note <target> <text>)
|
|
119
124
|
onNote(handler) {
|
|
120
125
|
this.noteHandler = handler;
|
|
@@ -306,6 +311,7 @@ ${BOLD}navigation:${RESET}
|
|
|
306
311
|
/bell toggle terminal bell on errors/completions
|
|
307
312
|
/focus toggle focus mode (show only pinned sessions)
|
|
308
313
|
/mute [N|name] mute/unmute a session's activity entries (toggle)
|
|
314
|
+
/unmute-all unmute all sessions at once
|
|
309
315
|
/note N|name text attach a note to a session (no text = clear)
|
|
310
316
|
/notes list all session notes
|
|
311
317
|
/mark bookmark current activity position
|
|
@@ -454,6 +460,14 @@ ${BOLD}other:${RESET}
|
|
|
454
460
|
}
|
|
455
461
|
break;
|
|
456
462
|
}
|
|
463
|
+
case "/unmute-all":
|
|
464
|
+
if (this.unmuteAllHandler) {
|
|
465
|
+
this.unmuteAllHandler();
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
console.error(`${DIM}unmute-all not available (no TUI)${RESET}`);
|
|
469
|
+
}
|
|
470
|
+
break;
|
|
457
471
|
case "/note": {
|
|
458
472
|
const noteArg = line.slice("/note".length).trim();
|
|
459
473
|
if (this.noteHandler) {
|
package/dist/tui.d.ts
CHANGED
|
@@ -51,6 +51,8 @@ export declare const MAX_NOTE_LEN = 80;
|
|
|
51
51
|
export declare function truncateNote(text: string): string;
|
|
52
52
|
/** Determine if an activity entry should be hidden due to muting. */
|
|
53
53
|
export declare function shouldMuteEntry(entry: ActivityEntry, mutedIds: Set<string>): boolean;
|
|
54
|
+
/** Format a suppressed entry count badge for muted sessions. Returns empty string for 0. */
|
|
55
|
+
export declare function formatMuteBadge(count: number): string;
|
|
54
56
|
export declare class TUI {
|
|
55
57
|
private active;
|
|
56
58
|
private countdownTimer;
|
|
@@ -81,6 +83,7 @@ export declare class TUI {
|
|
|
81
83
|
private bellEnabled;
|
|
82
84
|
private lastBellAt;
|
|
83
85
|
private mutedIds;
|
|
86
|
+
private mutedEntryCounts;
|
|
84
87
|
private sessionNotes;
|
|
85
88
|
private viewMode;
|
|
86
89
|
private drilldownSessionId;
|
|
@@ -132,10 +135,14 @@ export declare class TUI {
|
|
|
132
135
|
* Returns true if session found.
|
|
133
136
|
*/
|
|
134
137
|
toggleMute(sessionIdOrIndex: string | number): boolean;
|
|
138
|
+
/** Unmute all sessions at once. Returns count of sessions unmuted. */
|
|
139
|
+
unmuteAll(): number;
|
|
135
140
|
/** Check if a session ID is muted. */
|
|
136
141
|
isMuted(id: string): boolean;
|
|
137
142
|
/** Return count of muted sessions. */
|
|
138
143
|
getMutedCount(): number;
|
|
144
|
+
/** Return count of suppressed entries for a muted session (0 if not muted). */
|
|
145
|
+
getMutedEntryCount(id: string): number;
|
|
139
146
|
/**
|
|
140
147
|
* Set a note on a session (by 1-indexed number, ID, ID prefix, or title).
|
|
141
148
|
* Returns true if session found. Pass empty text to clear.
|
package/dist/tui.js
CHANGED
|
@@ -174,6 +174,13 @@ export function shouldMuteEntry(entry, mutedIds) {
|
|
|
174
174
|
return false;
|
|
175
175
|
return mutedIds.has(entry.sessionId);
|
|
176
176
|
}
|
|
177
|
+
/** Format a suppressed entry count badge for muted sessions. Returns empty string for 0. */
|
|
178
|
+
export function formatMuteBadge(count) {
|
|
179
|
+
if (count <= 0)
|
|
180
|
+
return "";
|
|
181
|
+
const label = count > 999 ? "999+" : String(count);
|
|
182
|
+
return `${DIM}(${label})${RESET}`;
|
|
183
|
+
}
|
|
177
184
|
// ── TUI class ───────────────────────────────────────────────────────────────
|
|
178
185
|
export class TUI {
|
|
179
186
|
active = false;
|
|
@@ -205,6 +212,7 @@ export class TUI {
|
|
|
205
212
|
bellEnabled = false;
|
|
206
213
|
lastBellAt = 0;
|
|
207
214
|
mutedIds = new Set(); // muted session IDs (activity entries hidden)
|
|
215
|
+
mutedEntryCounts = new Map(); // session ID → suppressed entry count since mute
|
|
208
216
|
sessionNotes = new Map(); // session ID → note text
|
|
209
217
|
// drill-down mode: show a single session's full output
|
|
210
218
|
viewMode = "overview";
|
|
@@ -380,9 +388,11 @@ export class TUI {
|
|
|
380
388
|
return false;
|
|
381
389
|
if (this.mutedIds.has(sessionId)) {
|
|
382
390
|
this.mutedIds.delete(sessionId);
|
|
391
|
+
this.mutedEntryCounts.delete(sessionId);
|
|
383
392
|
}
|
|
384
393
|
else {
|
|
385
394
|
this.mutedIds.add(sessionId);
|
|
395
|
+
this.mutedEntryCounts.set(sessionId, 0);
|
|
386
396
|
}
|
|
387
397
|
// repaint sessions (mute icon) and activity (filter changes)
|
|
388
398
|
if (this.active) {
|
|
@@ -391,6 +401,19 @@ export class TUI {
|
|
|
391
401
|
}
|
|
392
402
|
return true;
|
|
393
403
|
}
|
|
404
|
+
/** Unmute all sessions at once. Returns count of sessions unmuted. */
|
|
405
|
+
unmuteAll() {
|
|
406
|
+
const count = this.mutedIds.size;
|
|
407
|
+
if (count === 0)
|
|
408
|
+
return 0;
|
|
409
|
+
this.mutedIds.clear();
|
|
410
|
+
this.mutedEntryCounts.clear();
|
|
411
|
+
if (this.active) {
|
|
412
|
+
this.paintSessions();
|
|
413
|
+
this.repaintActivityRegion();
|
|
414
|
+
}
|
|
415
|
+
return count;
|
|
416
|
+
}
|
|
394
417
|
/** Check if a session ID is muted. */
|
|
395
418
|
isMuted(id) {
|
|
396
419
|
return this.mutedIds.has(id);
|
|
@@ -399,6 +422,10 @@ export class TUI {
|
|
|
399
422
|
getMutedCount() {
|
|
400
423
|
return this.mutedIds.size;
|
|
401
424
|
}
|
|
425
|
+
/** Return count of suppressed entries for a muted session (0 if not muted). */
|
|
426
|
+
getMutedEntryCount(id) {
|
|
427
|
+
return this.mutedEntryCounts.get(id) ?? 0;
|
|
428
|
+
}
|
|
402
429
|
/**
|
|
403
430
|
* Set a note on a session (by 1-indexed number, ID, ID prefix, or title).
|
|
404
431
|
* Returns true if session found. Pass empty text to clear.
|
|
@@ -557,6 +584,10 @@ export class TUI {
|
|
|
557
584
|
process.stderr.write("\x07");
|
|
558
585
|
}
|
|
559
586
|
}
|
|
587
|
+
// track suppressed entry counts regardless of active state (for badge accuracy)
|
|
588
|
+
if (shouldMuteEntry(entry, this.mutedIds) && entry.sessionId) {
|
|
589
|
+
this.mutedEntryCounts.set(entry.sessionId, (this.mutedEntryCounts.get(entry.sessionId) ?? 0) + 1);
|
|
590
|
+
}
|
|
560
591
|
if (this.active) {
|
|
561
592
|
// muted entries are still buffered + persisted but hidden from display
|
|
562
593
|
if (shouldMuteEntry(entry, this.mutedIds)) {
|
|
@@ -911,12 +942,16 @@ export class TUI {
|
|
|
911
942
|
const pinned = this.pinnedIds.has(s.id);
|
|
912
943
|
const muted = this.mutedIds.has(s.id);
|
|
913
944
|
const noted = this.sessionNotes.has(s.id);
|
|
945
|
+
const muteBadge = muted ? formatMuteBadge(this.mutedEntryCounts.get(s.id) ?? 0) : "";
|
|
946
|
+
const muteBadgeWidth = muted ? String(Math.min(this.mutedEntryCounts.get(s.id) ?? 0, 9999)).length + 2 : 0; // "(N)" visible chars, 0 when count is 0
|
|
947
|
+
const actualBadgeWidth = (this.mutedEntryCounts.get(s.id) ?? 0) > 0 ? muteBadgeWidth + 1 : 0; // +1 for trailing space
|
|
914
948
|
const pin = pinned ? `${AMBER}${PIN_ICON}${RESET} ` : "";
|
|
915
949
|
const mute = muted ? `${DIM}${MUTE_ICON}${RESET} ` : "";
|
|
916
950
|
const note = noted ? `${TEAL}${NOTE_ICON}${RESET} ` : "";
|
|
917
|
-
const
|
|
951
|
+
const badgeSuffix = muteBadge ? `${muteBadge} ` : "";
|
|
952
|
+
const iconsWidth = (pinned ? 2 : 0) + (muted ? 2 : 0) + (noted ? 2 : 0) + actualBadgeWidth;
|
|
918
953
|
const cardWidth = innerWidth - 1 - iconsWidth;
|
|
919
|
-
const line = `${bg}${SLATE}${BOX.v}${RESET}${bg} ${pin}${mute}${note}${formatSessionCard(s, cardWidth)}`;
|
|
954
|
+
const line = `${bg}${SLATE}${BOX.v}${RESET}${bg} ${pin}${mute}${badgeSuffix}${note}${formatSessionCard(s, cardWidth)}`;
|
|
920
955
|
const padded = padBoxLineHover(line, this.cols, isHovered);
|
|
921
956
|
process.stderr.write(moveTo(startRow + 1 + i, 1) + CLEAR_LINE + padded);
|
|
922
957
|
}
|
|
@@ -949,12 +984,16 @@ export class TUI {
|
|
|
949
984
|
const pinned = this.pinnedIds.has(s.id);
|
|
950
985
|
const muted = this.mutedIds.has(s.id);
|
|
951
986
|
const noted = this.sessionNotes.has(s.id);
|
|
987
|
+
const muteBadge = muted ? formatMuteBadge(this.mutedEntryCounts.get(s.id) ?? 0) : "";
|
|
988
|
+
const actualBadgeWidth = (this.mutedEntryCounts.get(s.id) ?? 0) > 0
|
|
989
|
+
? String(Math.min(this.mutedEntryCounts.get(s.id) ?? 0, 9999)).length + 3 : 0; // "(N) " visible chars
|
|
952
990
|
const pin = pinned ? `${AMBER}${PIN_ICON}${RESET} ` : "";
|
|
953
991
|
const mute = muted ? `${DIM}${MUTE_ICON}${RESET} ` : "";
|
|
954
992
|
const note = noted ? `${TEAL}${NOTE_ICON}${RESET} ` : "";
|
|
955
|
-
const
|
|
993
|
+
const badgeSuffix = muteBadge ? `${muteBadge} ` : "";
|
|
994
|
+
const iconsWidth = (pinned ? 2 : 0) + (muted ? 2 : 0) + (noted ? 2 : 0) + actualBadgeWidth;
|
|
956
995
|
const cardWidth = innerWidth - 1 - iconsWidth;
|
|
957
|
-
const line = `${bg}${SLATE}${BOX.v}${RESET}${bg} ${pin}${mute}${note}${formatSessionCard(s, cardWidth)}`;
|
|
996
|
+
const line = `${bg}${SLATE}${BOX.v}${RESET}${bg} ${pin}${mute}${badgeSuffix}${note}${formatSessionCard(s, cardWidth)}`;
|
|
958
997
|
const padded = padBoxLineHover(line, this.cols, isHovered);
|
|
959
998
|
process.stderr.write(SAVE_CURSOR + moveTo(startRow + 1 + i, 1) + CLEAR_LINE + padded + RESTORE_CURSOR);
|
|
960
999
|
}
|