aoaoe 0.87.0 → 0.88.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 +17 -1
- package/dist/input.d.ts +3 -0
- package/dist/input.js +14 -0
- package/dist/tui.d.ts +7 -0
- package/dist/tui.js +35 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { wakeableSleep } from "./wake.js";
|
|
|
15
15
|
import { classifyMessages, formatUserMessages, buildReceipts, shouldSkipSleep, hasPendingFile, isInsistMessage, stripInsistPrefix } from "./message.js";
|
|
16
16
|
import { TaskManager, loadTaskDefinitions, loadTaskState, formatTaskTable } from "./task-manager.js";
|
|
17
17
|
import { runTaskCli, handleTaskSlashCommand } from "./task-cli.js";
|
|
18
|
-
import { TUI, hitTestSession, nextSortMode, SORT_MODES } from "./tui.js";
|
|
18
|
+
import { TUI, hitTestSession, nextSortMode, SORT_MODES, formatUptime } from "./tui.js";
|
|
19
19
|
import { isDaemonRunningFromState } from "./chat.js";
|
|
20
20
|
import { sendNotification, sendTestNotification } from "./notify.js";
|
|
21
21
|
import { startHealthServer } from "./health.js";
|
|
@@ -464,6 +464,22 @@ async function main() {
|
|
|
464
464
|
tui.log("system", "filter cleared");
|
|
465
465
|
}
|
|
466
466
|
});
|
|
467
|
+
// wire /uptime listing
|
|
468
|
+
input.onUptime(() => {
|
|
469
|
+
const firstSeen = tui.getAllFirstSeen();
|
|
470
|
+
const sessions = tui.getSessions();
|
|
471
|
+
if (sessions.length === 0) {
|
|
472
|
+
tui.log("system", "no sessions — uptime not available");
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
const now = Date.now();
|
|
476
|
+
for (const s of sessions) {
|
|
477
|
+
const start = firstSeen.get(s.id);
|
|
478
|
+
const up = start !== undefined ? formatUptime(now - start) : "unknown";
|
|
479
|
+
tui.log("system", ` ${s.title}: ${up}`);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
});
|
|
467
483
|
// wire /note set/clear
|
|
468
484
|
input.onNote((target, text) => {
|
|
469
485
|
const num = /^\d+$/.test(target) ? parseInt(target, 10) : undefined;
|
package/dist/input.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export type MarksHandler = () => void;
|
|
|
14
14
|
export type MuteHandler = (target: string) => void;
|
|
15
15
|
export type UnmuteAllHandler = () => void;
|
|
16
16
|
export type TagFilterHandler = (tag: string | null) => void;
|
|
17
|
+
export type UptimeHandler = () => void;
|
|
17
18
|
export type NoteHandler = (target: string, text: string) => void;
|
|
18
19
|
export type NotesHandler = () => void;
|
|
19
20
|
export interface MouseEvent {
|
|
@@ -52,6 +53,7 @@ export declare class InputReader {
|
|
|
52
53
|
private muteHandler;
|
|
53
54
|
private unmuteAllHandler;
|
|
54
55
|
private tagFilterHandler;
|
|
56
|
+
private uptimeHandler;
|
|
55
57
|
private noteHandler;
|
|
56
58
|
private notesHandler;
|
|
57
59
|
private mouseDataListener;
|
|
@@ -74,6 +76,7 @@ export declare class InputReader {
|
|
|
74
76
|
onMute(handler: MuteHandler): void;
|
|
75
77
|
onUnmuteAll(handler: UnmuteAllHandler): void;
|
|
76
78
|
onTagFilter(handler: TagFilterHandler): void;
|
|
79
|
+
onUptime(handler: UptimeHandler): void;
|
|
77
80
|
onNote(handler: NoteHandler): void;
|
|
78
81
|
onNotes(handler: NotesHandler): void;
|
|
79
82
|
private notifyQueueChange;
|
package/dist/input.js
CHANGED
|
@@ -46,6 +46,7 @@ export class InputReader {
|
|
|
46
46
|
muteHandler = null;
|
|
47
47
|
unmuteAllHandler = null;
|
|
48
48
|
tagFilterHandler = null;
|
|
49
|
+
uptimeHandler = null;
|
|
49
50
|
noteHandler = null;
|
|
50
51
|
notesHandler = null;
|
|
51
52
|
mouseDataListener = null;
|
|
@@ -125,6 +126,10 @@ export class InputReader {
|
|
|
125
126
|
onTagFilter(handler) {
|
|
126
127
|
this.tagFilterHandler = handler;
|
|
127
128
|
}
|
|
129
|
+
// register a callback for uptime listing (/uptime)
|
|
130
|
+
onUptime(handler) {
|
|
131
|
+
this.uptimeHandler = handler;
|
|
132
|
+
}
|
|
128
133
|
// register a callback for note commands (/note <target> <text>)
|
|
129
134
|
onNote(handler) {
|
|
130
135
|
this.noteHandler = handler;
|
|
@@ -318,6 +323,7 @@ ${BOLD}navigation:${RESET}
|
|
|
318
323
|
/mute [N|name] mute/unmute a session's activity entries (toggle)
|
|
319
324
|
/unmute-all unmute all sessions at once
|
|
320
325
|
/filter [tag] filter activity by tag (error, system, etc. — no arg = clear)
|
|
326
|
+
/uptime show session uptimes (time since first observed)
|
|
321
327
|
/note N|name text attach a note to a session (no text = clear)
|
|
322
328
|
/notes list all session notes
|
|
323
329
|
/mark bookmark current activity position
|
|
@@ -484,6 +490,14 @@ ${BOLD}other:${RESET}
|
|
|
484
490
|
}
|
|
485
491
|
break;
|
|
486
492
|
}
|
|
493
|
+
case "/uptime":
|
|
494
|
+
if (this.uptimeHandler) {
|
|
495
|
+
this.uptimeHandler();
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
console.error(`${DIM}uptime not available (no TUI)${RESET}`);
|
|
499
|
+
}
|
|
500
|
+
break;
|
|
487
501
|
case "/note": {
|
|
488
502
|
const noteArg = line.slice("/note".length).trim();
|
|
489
503
|
if (this.noteHandler) {
|
package/dist/tui.d.ts
CHANGED
|
@@ -57,6 +57,8 @@ export declare function formatMuteBadge(count: number): string;
|
|
|
57
57
|
export declare function matchesTagFilter(entry: ActivityEntry, tag: string): boolean;
|
|
58
58
|
/** Format the tag filter indicator text for the separator bar. */
|
|
59
59
|
export declare function formatTagFilterIndicator(tag: string, matchCount: number, totalCount: number): string;
|
|
60
|
+
/** Format milliseconds as human-readable uptime: "2h 15m", "45m", "3d 2h", "< 1m". */
|
|
61
|
+
export declare function formatUptime(ms: number): string;
|
|
60
62
|
export declare class TUI {
|
|
61
63
|
private active;
|
|
62
64
|
private countdownTimer;
|
|
@@ -90,6 +92,7 @@ export declare class TUI {
|
|
|
90
92
|
private mutedIds;
|
|
91
93
|
private mutedEntryCounts;
|
|
92
94
|
private sessionNotes;
|
|
95
|
+
private sessionFirstSeen;
|
|
93
96
|
private viewMode;
|
|
94
97
|
private drilldownSessionId;
|
|
95
98
|
private sessionOutputs;
|
|
@@ -161,6 +164,10 @@ export declare class TUI {
|
|
|
161
164
|
getAllNotes(): ReadonlyMap<string, string>;
|
|
162
165
|
/** Return the current sessions (read-only, for resolving IDs to titles in the UI). */
|
|
163
166
|
getSessions(): readonly DaemonSessionState[];
|
|
167
|
+
/** Return the uptime in ms for a session (0 if not tracked). */
|
|
168
|
+
getUptime(id: string): number;
|
|
169
|
+
/** Return all session first-seen timestamps (for /uptime listing). */
|
|
170
|
+
getAllFirstSeen(): ReadonlyMap<string, number>;
|
|
164
171
|
/**
|
|
165
172
|
* Add a bookmark at the current activity position.
|
|
166
173
|
* Returns the bookmark number (1-indexed) or 0 if buffer is empty.
|
package/dist/tui.js
CHANGED
|
@@ -191,6 +191,23 @@ export function matchesTagFilter(entry, tag) {
|
|
|
191
191
|
export function formatTagFilterIndicator(tag, matchCount, totalCount) {
|
|
192
192
|
return `${SLATE}filter:${RESET} ${AMBER}${tag}${RESET} ${DIM}(${matchCount}/${totalCount})${RESET}`;
|
|
193
193
|
}
|
|
194
|
+
// ── Uptime ───────────────────────────────────────────────────────────────────
|
|
195
|
+
/** Format milliseconds as human-readable uptime: "2h 15m", "45m", "3d 2h", "< 1m". */
|
|
196
|
+
export function formatUptime(ms) {
|
|
197
|
+
if (ms < 0)
|
|
198
|
+
return "< 1m";
|
|
199
|
+
const totalMin = Math.floor(ms / 60_000);
|
|
200
|
+
if (totalMin < 1)
|
|
201
|
+
return "< 1m";
|
|
202
|
+
const days = Math.floor(totalMin / 1440);
|
|
203
|
+
const hours = Math.floor((totalMin % 1440) / 60);
|
|
204
|
+
const minutes = totalMin % 60;
|
|
205
|
+
if (days > 0)
|
|
206
|
+
return hours > 0 ? `${days}d ${hours}h` : `${days}d`;
|
|
207
|
+
if (hours > 0)
|
|
208
|
+
return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
|
|
209
|
+
return `${minutes}m`;
|
|
210
|
+
}
|
|
194
211
|
// ── TUI class ───────────────────────────────────────────────────────────────
|
|
195
212
|
export class TUI {
|
|
196
213
|
active = false;
|
|
@@ -225,6 +242,7 @@ export class TUI {
|
|
|
225
242
|
mutedIds = new Set(); // muted session IDs (activity entries hidden)
|
|
226
243
|
mutedEntryCounts = new Map(); // session ID → suppressed entry count since mute
|
|
227
244
|
sessionNotes = new Map(); // session ID → note text
|
|
245
|
+
sessionFirstSeen = new Map(); // session ID → epoch ms when first observed
|
|
228
246
|
// drill-down mode: show a single session's full output
|
|
229
247
|
viewMode = "overview";
|
|
230
248
|
drilldownSessionId = null;
|
|
@@ -483,6 +501,17 @@ export class TUI {
|
|
|
483
501
|
getSessions() {
|
|
484
502
|
return this.sessions;
|
|
485
503
|
}
|
|
504
|
+
/** Return the uptime in ms for a session (0 if not tracked). */
|
|
505
|
+
getUptime(id) {
|
|
506
|
+
const firstSeen = this.sessionFirstSeen.get(id);
|
|
507
|
+
if (firstSeen === undefined)
|
|
508
|
+
return 0;
|
|
509
|
+
return Date.now() - firstSeen;
|
|
510
|
+
}
|
|
511
|
+
/** Return all session first-seen timestamps (for /uptime listing). */
|
|
512
|
+
getAllFirstSeen() {
|
|
513
|
+
return this.sessionFirstSeen;
|
|
514
|
+
}
|
|
486
515
|
/**
|
|
487
516
|
* Add a bookmark at the current activity position.
|
|
488
517
|
* Returns the bookmark number (1-indexed) or 0 if buffer is empty.
|
|
@@ -547,9 +576,11 @@ export class TUI {
|
|
|
547
576
|
if (opts.pendingCount !== undefined)
|
|
548
577
|
this.pendingCount = opts.pendingCount;
|
|
549
578
|
if (opts.sessions !== undefined) {
|
|
550
|
-
// track activity changes for sort-by-activity
|
|
579
|
+
// track activity changes for sort-by-activity + first-seen for uptime
|
|
551
580
|
const now = Date.now();
|
|
552
581
|
for (const s of opts.sessions) {
|
|
582
|
+
if (!this.sessionFirstSeen.has(s.id))
|
|
583
|
+
this.sessionFirstSeen.set(s.id, now);
|
|
553
584
|
const prev = this.prevLastActivity.get(s.id);
|
|
554
585
|
if (s.lastActivity !== undefined && s.lastActivity !== prev) {
|
|
555
586
|
this.lastChangeAt.set(s.id, now);
|
|
@@ -1099,7 +1130,9 @@ export class TUI {
|
|
|
1099
1130
|
const title = session ? session.title : this.drilldownSessionId ?? "?";
|
|
1100
1131
|
const noteText = this.drilldownSessionId ? this.sessionNotes.get(this.drilldownSessionId) : undefined;
|
|
1101
1132
|
const noteSuffix = noteText ? `"${noteText}" ` : "";
|
|
1102
|
-
const
|
|
1133
|
+
const firstSeen = this.drilldownSessionId ? this.sessionFirstSeen.get(this.drilldownSessionId) : undefined;
|
|
1134
|
+
const uptimeSuffix = firstSeen !== undefined ? `${DIM}${formatUptime(Date.now() - firstSeen)}${RESET} ` : "";
|
|
1135
|
+
const prefix = `${BOX.h}${BOX.h} ${title} ${uptimeSuffix}${noteSuffix}`;
|
|
1103
1136
|
let hints;
|
|
1104
1137
|
if (this.drilldownScrollOffset > 0) {
|
|
1105
1138
|
const outputLines = this.sessionOutputs.get(this.drilldownSessionId ?? "") ?? [];
|