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>
49 lines
1.3 KiB
TypeScript
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;
|
|
}
|
|
}
|