aoaoe 0.90.0 → 0.92.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 +59 -1
- package/dist/input.d.ts +3 -0
- package/dist/input.js +20 -0
- package/dist/tui.d.ts +12 -0
- package/dist/tui.js +30 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import { wakeableSleep } from "./wake.js";
|
|
|
16
16
|
import { classifyMessages, formatUserMessages, buildReceipts, shouldSkipSleep, hasPendingFile, isInsistMessage, stripInsistPrefix } from "./message.js";
|
|
17
17
|
import { TaskManager, loadTaskDefinitions, loadTaskState, formatTaskTable } from "./task-manager.js";
|
|
18
18
|
import { runTaskCli, handleTaskSlashCommand } from "./task-cli.js";
|
|
19
|
-
import { TUI, hitTestSession, nextSortMode, SORT_MODES, formatUptime, formatClipText } from "./tui.js";
|
|
19
|
+
import { TUI, hitTestSession, nextSortMode, SORT_MODES, formatUptime, formatClipText, loadTuiPrefs, saveTuiPrefs } from "./tui.js";
|
|
20
20
|
import { isDaemonRunningFromState } from "./chat.js";
|
|
21
21
|
import { sendNotification, sendTestNotification } from "./notify.js";
|
|
22
22
|
import { startHealthServer } from "./health.js";
|
|
@@ -171,6 +171,34 @@ async function main() {
|
|
|
171
171
|
const pkg = readPkgVersion();
|
|
172
172
|
const useTui = process.stdin.isTTY === true;
|
|
173
173
|
const tui = useTui ? new TUI() : null;
|
|
174
|
+
// restore sticky prefs from previous run
|
|
175
|
+
if (tui) {
|
|
176
|
+
const prefs = loadTuiPrefs();
|
|
177
|
+
if (prefs.sortMode && SORT_MODES.includes(prefs.sortMode))
|
|
178
|
+
tui.setSortMode(prefs.sortMode);
|
|
179
|
+
if (prefs.compact)
|
|
180
|
+
tui.setCompact(true);
|
|
181
|
+
if (prefs.focus)
|
|
182
|
+
tui.setFocus(true);
|
|
183
|
+
if (prefs.bell)
|
|
184
|
+
tui.setBell(true);
|
|
185
|
+
if (prefs.autoPin)
|
|
186
|
+
tui.setAutoPin(true);
|
|
187
|
+
if (prefs.tagFilter)
|
|
188
|
+
tui.setTagFilter(prefs.tagFilter);
|
|
189
|
+
}
|
|
190
|
+
const persistPrefs = () => {
|
|
191
|
+
if (!tui)
|
|
192
|
+
return;
|
|
193
|
+
saveTuiPrefs({
|
|
194
|
+
sortMode: tui.getSortMode(),
|
|
195
|
+
compact: tui.isCompact(),
|
|
196
|
+
focus: tui.isFocused(),
|
|
197
|
+
bell: tui.isBellEnabled(),
|
|
198
|
+
autoPin: tui.isAutoPinEnabled(),
|
|
199
|
+
tagFilter: tui.getTagFilter(),
|
|
200
|
+
});
|
|
201
|
+
};
|
|
174
202
|
if (!useTui) {
|
|
175
203
|
// fallback: plain scrolling output (non-TTY / piped)
|
|
176
204
|
console.error("");
|
|
@@ -363,11 +391,13 @@ async function main() {
|
|
|
363
391
|
if (mode && SORT_MODES.includes(mode)) {
|
|
364
392
|
tui.setSortMode(mode);
|
|
365
393
|
tui.log("system", `sort: ${mode}`);
|
|
394
|
+
persistPrefs();
|
|
366
395
|
}
|
|
367
396
|
else if (!mode) {
|
|
368
397
|
const next = nextSortMode(tui.getSortMode());
|
|
369
398
|
tui.setSortMode(next);
|
|
370
399
|
tui.log("system", `sort: ${next}`);
|
|
400
|
+
persistPrefs();
|
|
371
401
|
}
|
|
372
402
|
else {
|
|
373
403
|
tui.log("system", `unknown sort mode: ${mode} (try: status, name, activity, default)`);
|
|
@@ -378,6 +408,7 @@ async function main() {
|
|
|
378
408
|
const enabled = !tui.isCompact();
|
|
379
409
|
tui.setCompact(enabled);
|
|
380
410
|
tui.log("system", `compact mode: ${enabled ? "on" : "off"}`);
|
|
411
|
+
persistPrefs();
|
|
381
412
|
});
|
|
382
413
|
// wire /mark bookmark
|
|
383
414
|
input.onMark(() => {
|
|
@@ -411,17 +442,42 @@ async function main() {
|
|
|
411
442
|
}
|
|
412
443
|
}
|
|
413
444
|
});
|
|
445
|
+
// wire /diff N to show activity since a bookmark
|
|
446
|
+
input.onDiff((num) => {
|
|
447
|
+
const bms = tui.getBookmarks();
|
|
448
|
+
const bm = bms[num - 1];
|
|
449
|
+
if (!bm) {
|
|
450
|
+
tui.log("system", `bookmark #${num} not found`);
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
const buffer = tui.getActivityBuffer();
|
|
454
|
+
const entries = buffer.slice(bm.index);
|
|
455
|
+
if (entries.length === 0) {
|
|
456
|
+
tui.log("system", `no activity since bookmark #${num}`);
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
tui.log("system", `${entries.length} entries since bookmark #${num} (${bm.label}):`);
|
|
460
|
+
for (const e of entries.slice(-30)) { // cap at last 30 to avoid spam
|
|
461
|
+
tui.log("system", ` [${e.time}] ${e.tag}: ${e.text}`);
|
|
462
|
+
}
|
|
463
|
+
if (entries.length > 30) {
|
|
464
|
+
tui.log("system", ` ... (${entries.length - 30} more — use /clip to export all)`);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
});
|
|
414
468
|
// wire /focus toggle
|
|
415
469
|
input.onFocus(() => {
|
|
416
470
|
const enabled = !tui.isFocused();
|
|
417
471
|
tui.setFocus(enabled);
|
|
418
472
|
tui.log("system", `focus mode: ${enabled ? "on (pinned only)" : "off (all sessions)"}`);
|
|
473
|
+
persistPrefs();
|
|
419
474
|
});
|
|
420
475
|
// wire /bell toggle
|
|
421
476
|
input.onBell(() => {
|
|
422
477
|
const enabled = !tui.isBellEnabled();
|
|
423
478
|
tui.setBell(enabled);
|
|
424
479
|
tui.log("system", `bell notifications: ${enabled ? "on" : "off"}`);
|
|
480
|
+
persistPrefs();
|
|
425
481
|
});
|
|
426
482
|
// wire /pin toggle
|
|
427
483
|
input.onPin((target) => {
|
|
@@ -464,6 +520,7 @@ async function main() {
|
|
|
464
520
|
else {
|
|
465
521
|
tui.log("system", "filter cleared");
|
|
466
522
|
}
|
|
523
|
+
persistPrefs();
|
|
467
524
|
});
|
|
468
525
|
// wire /uptime listing
|
|
469
526
|
input.onUptime(() => {
|
|
@@ -486,6 +543,7 @@ async function main() {
|
|
|
486
543
|
const enabled = !tui.isAutoPinEnabled();
|
|
487
544
|
tui.setAutoPin(enabled);
|
|
488
545
|
tui.log("system", `auto-pin on error: ${enabled ? "on" : "off"}`);
|
|
546
|
+
persistPrefs();
|
|
489
547
|
});
|
|
490
548
|
// wire /note set/clear
|
|
491
549
|
input.onNote((target, text) => {
|
package/dist/input.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export type AutoPinHandler = () => void;
|
|
|
19
19
|
export type NoteHandler = (target: string, text: string) => void;
|
|
20
20
|
export type NotesHandler = () => void;
|
|
21
21
|
export type ClipHandler = (count: number) => void;
|
|
22
|
+
export type DiffHandler = (bookmarkNum: number) => void;
|
|
22
23
|
export interface MouseEvent {
|
|
23
24
|
button: number;
|
|
24
25
|
col: number;
|
|
@@ -60,6 +61,7 @@ export declare class InputReader {
|
|
|
60
61
|
private noteHandler;
|
|
61
62
|
private notesHandler;
|
|
62
63
|
private clipHandler;
|
|
64
|
+
private diffHandler;
|
|
63
65
|
private mouseDataListener;
|
|
64
66
|
onScroll(handler: (dir: ScrollDirection) => void): void;
|
|
65
67
|
onQueueChange(handler: (count: number) => void): void;
|
|
@@ -85,6 +87,7 @@ export declare class InputReader {
|
|
|
85
87
|
onNote(handler: NoteHandler): void;
|
|
86
88
|
onNotes(handler: NotesHandler): void;
|
|
87
89
|
onClip(handler: ClipHandler): void;
|
|
90
|
+
onDiff(handler: DiffHandler): void;
|
|
88
91
|
private notifyQueueChange;
|
|
89
92
|
start(): void;
|
|
90
93
|
drain(): string[];
|
package/dist/input.js
CHANGED
|
@@ -51,6 +51,7 @@ export class InputReader {
|
|
|
51
51
|
noteHandler = null;
|
|
52
52
|
notesHandler = null;
|
|
53
53
|
clipHandler = null;
|
|
54
|
+
diffHandler = null;
|
|
54
55
|
mouseDataListener = null;
|
|
55
56
|
// register a callback for scroll key events (PgUp/PgDn/Home/End)
|
|
56
57
|
onScroll(handler) {
|
|
@@ -148,6 +149,10 @@ export class InputReader {
|
|
|
148
149
|
onClip(handler) {
|
|
149
150
|
this.clipHandler = handler;
|
|
150
151
|
}
|
|
152
|
+
// register a callback for bookmark diff (/diff N)
|
|
153
|
+
onDiff(handler) {
|
|
154
|
+
this.diffHandler = handler;
|
|
155
|
+
}
|
|
151
156
|
notifyQueueChange() {
|
|
152
157
|
this.queueChangeHandler?.(this.queue.length);
|
|
153
158
|
}
|
|
@@ -338,6 +343,7 @@ ${BOLD}navigation:${RESET}
|
|
|
338
343
|
/note N|name text attach a note to a session (no text = clear)
|
|
339
344
|
/notes list all session notes
|
|
340
345
|
/clip [N] copy last N activity entries to clipboard (default 20)
|
|
346
|
+
/diff N show activity since bookmark N
|
|
341
347
|
/mark bookmark current activity position
|
|
342
348
|
/jump N jump to bookmark N
|
|
343
349
|
/marks list all bookmarks
|
|
@@ -563,6 +569,20 @@ ${BOLD}other:${RESET}
|
|
|
563
569
|
}
|
|
564
570
|
break;
|
|
565
571
|
}
|
|
572
|
+
case "/diff": {
|
|
573
|
+
const diffArg = line.slice("/diff".length).trim();
|
|
574
|
+
const diffNum = parseInt(diffArg, 10);
|
|
575
|
+
if (this.diffHandler && !isNaN(diffNum) && diffNum > 0) {
|
|
576
|
+
this.diffHandler(diffNum);
|
|
577
|
+
}
|
|
578
|
+
else if (!this.diffHandler) {
|
|
579
|
+
console.error(`${DIM}diff not available (no TUI)${RESET}`);
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
console.error(`${DIM}usage: /diff N — show activity since bookmark N${RESET}`);
|
|
583
|
+
}
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
566
586
|
case "/mark":
|
|
567
587
|
if (this.markHandler) {
|
|
568
588
|
this.markHandler();
|
package/dist/tui.d.ts
CHANGED
|
@@ -65,6 +65,18 @@ export declare function formatClipText(entries: readonly ActivityEntry[], n?: nu
|
|
|
65
65
|
export declare function shouldAutoPin(tag: string): boolean;
|
|
66
66
|
/** Format milliseconds as human-readable uptime: "2h 15m", "45m", "3d 2h", "< 1m". */
|
|
67
67
|
export declare function formatUptime(ms: number): string;
|
|
68
|
+
export interface TuiPrefs {
|
|
69
|
+
sortMode?: string;
|
|
70
|
+
compact?: boolean;
|
|
71
|
+
focus?: boolean;
|
|
72
|
+
bell?: boolean;
|
|
73
|
+
autoPin?: boolean;
|
|
74
|
+
tagFilter?: string | null;
|
|
75
|
+
}
|
|
76
|
+
/** Load persisted TUI preferences. Returns empty object on any error. */
|
|
77
|
+
export declare function loadTuiPrefs(): TuiPrefs;
|
|
78
|
+
/** Save TUI preferences to disk. Silently ignores errors. */
|
|
79
|
+
export declare function saveTuiPrefs(prefs: TuiPrefs): void;
|
|
68
80
|
export declare class TUI {
|
|
69
81
|
private active;
|
|
70
82
|
private countdownTimer;
|
package/dist/tui.js
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
// tui.ts — block-style terminal UI for aoaoe daemon
|
|
2
|
+
// OpenCode-inspired design: box-drawn panels, 256-color palette, phase spinner,
|
|
3
|
+
// visual hierarchy. no external deps — raw ANSI escape codes only.
|
|
4
|
+
//
|
|
5
|
+
// layout (top to bottom):
|
|
6
|
+
// ┌─ header bar (1 row, BG_DARK) ─────────────────────────────────────────┐
|
|
7
|
+
// │ sessions panel (box-drawn, 1 row per session + 2 border rows) │
|
|
8
|
+
// ├─ separator with hints ────────────────────────────────────────────────┤
|
|
9
|
+
// │ activity scroll region (all daemon output scrolls here) │
|
|
10
|
+
// └─ input line (phase-aware prompt) ─────────────────────────────────────┘
|
|
11
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { homedir } from "node:os";
|
|
1
14
|
import { BOLD, DIM, RESET, GREEN, CYAN, WHITE, BG_DARK, BG_HOVER, INDIGO, TEAL, AMBER, SLATE, ROSE, LIME, SKY, BOX, SPINNER, DOT, } from "./colors.js";
|
|
2
15
|
import { appendHistoryEntry } from "./tui-history.js";
|
|
3
16
|
// ── ANSI helpers ────────────────────────────────────────────────────────────
|
|
@@ -223,7 +236,23 @@ export function formatUptime(ms) {
|
|
|
223
236
|
return minutes > 0 ? `${hours}h ${minutes}m` : `${hours}h`;
|
|
224
237
|
return `${minutes}m`;
|
|
225
238
|
}
|
|
226
|
-
|
|
239
|
+
const PREFS_PATH = join(homedir(), ".aoaoe", "tui-prefs.json");
|
|
240
|
+
/** Load persisted TUI preferences. Returns empty object on any error. */
|
|
241
|
+
export function loadTuiPrefs() {
|
|
242
|
+
try {
|
|
243
|
+
return JSON.parse(readFileSync(PREFS_PATH, "utf-8"));
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
return {};
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/** Save TUI preferences to disk. Silently ignores errors. */
|
|
250
|
+
export function saveTuiPrefs(prefs) {
|
|
251
|
+
try {
|
|
252
|
+
writeFileSync(PREFS_PATH, JSON.stringify(prefs) + "\n", "utf-8");
|
|
253
|
+
}
|
|
254
|
+
catch { /* best effort */ }
|
|
255
|
+
}
|
|
227
256
|
export class TUI {
|
|
228
257
|
active = false;
|
|
229
258
|
countdownTimer = null;
|