Files
fusion/packages/cli/src/commands/dashboard-tui/log-ring-buffer.ts
gsxdsm b890c57a29 feat(cli): merge @fusion/tui into fn dashboard with Ink TUI
Replace the legacy ANSI-based DashboardTUI with an Ink/React rewrite
under packages/cli/src/commands/dashboard-tui/, delete the standalone
@fusion/tui package, and make `fn` (no args) launch the dashboard.

The new TUI keeps the existing 5-panel status mode (system, logs,
utilities, stats, settings) but adds an interactive mode (b/a/g) with
three views: a kanban board with project picker and per-task detail,
an agents list+detail with state management, and a settings editor.
Bordered focus-aware panels, solid-background help overlay, static
all-blue FUSION splash that adapts to small terminals. DashboardTUI
and DashboardLogSink public API are unchanged so dashboard.ts only
needed import-path updates plus interactiveData/loadingStatus wiring.

Also adds zod to @fusion/dashboard to satisfy a peer dep introduced
by pi-coding-agent 0.70.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 19:39:20 -07:00

49 lines
1.3 KiB
TypeScript

// ── Types ────────────────────────────────────────────────────────────────────
export interface LogEntry {
timestamp: Date;
level: "info" | "warn" | "error";
message: string;
prefix?: string;
}
// ── Ring Buffer ───────────────────────────────────────────────────────────────
const MAX_LOG_ENTRIES = 1000;
export class LogRingBuffer {
private entries: LogEntry[] = [];
private count = 0;
push(entry: LogEntry): void {
if (this.entries.length < MAX_LOG_ENTRIES) {
this.entries.push(entry);
} else {
// Overwrite oldest entry in circular fashion
this.entries[this.count % MAX_LOG_ENTRIES] = entry;
}
this.count++;
}
getAll(): LogEntry[] {
if (this.count <= MAX_LOG_ENTRIES) {
return this.entries.slice();
}
// Return entries in chronological order (oldest to newest)
const start = this.count % MAX_LOG_ENTRIES;
return [
...this.entries.slice(start),
...this.entries.slice(0, start),
];
}
clear(): void {
this.entries = [];
this.count = 0;
}
get total(): number {
return this.count;
}
}