singularity-forge/packages/tui/src/components/autonomous-status-bar.ts
Mikael Hugo de77cf439f
Some checks are pending
CI / detect-changes (push) Waiting to run
CI / docs-check (push) Blocked by required conditions
CI / lint (push) Blocked by required conditions
CI / build (push) Blocked by required conditions
CI / integration-tests (push) Blocked by required conditions
CI / windows-portability (push) Blocked by required conditions
CI / rtk-portability (linux, blacksmith-4vcpu-ubuntu-2404) (push) Blocked by required conditions
CI / rtk-portability (macos, macos-15) (push) Blocked by required conditions
CI / rtk-portability (windows, blacksmith-4vcpu-windows-2025) (push) Blocked by required conditions
fix(tui): error boundary in doRender, extract autonomousStatus, clean parseCellSize
- doRender() now catches render errors and emits a fallback line
- autonomousStatus ANSI formatting extracted to renderAutonomousStatus()
  with named color constants instead of raw escape strings
- parseCellSizeResponse extracted to pure function with proper validation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 12:41:47 +02:00

93 lines
2.5 KiB
TypeScript

import type { Component } from "../tui.js";
/**
* Snapshot for the autonomous-mode strip above main TUI content.
*/
export type AutonomousModeStatus = {
currentSlice?: string;
sliceStatus?: string;
progress?: number;
totalTasks?: number;
completedTasks?: number;
};
// Named ANSI color constants for the autonomous status bar
const DIM = "\x1b[90m";
const BOLD_WHITE = "\x1b[97m";
const CYAN = "\x1b[96m";
const GREEN = "\x1b[92m";
const YELLOW = "\x1b[93m";
const MAGENTA = "\x1b[95m";
const RESET = "\x1b[0m";
/**
* Renders the autonomous-mode status bar as a single terminal line.
*
* Purpose: isolate autonomous chrome from `TUI` so `tui.ts` stays smaller and
* this strip can evolve independently (copy, colors, layout).
*/
export class AutonomousStatusBar implements Component {
private status: AutonomousModeStatus | undefined;
setStatus(status: AutonomousModeStatus | undefined): void {
this.status = status;
}
getStatus(): AutonomousModeStatus | undefined {
return this.status;
}
invalidate(): void {}
/** Format a single status value with ANSI cyan highlighting. */
private renderAutonomousStatus(status: string): string {
return `${CYAN}${status}${RESET}`;
}
render(width: number): string[] {
if (!this.status) return [];
const { currentSlice, sliceStatus, progress, totalTasks, completedTasks } =
this.status;
const noColor = process.env.NO_COLOR === "1";
let statusLine = noColor
? "│ AUTONOMOUS MODE "
: `${DIM}│ AUTONOMOUS MODE `;
if (currentSlice) {
statusLine += noColor
? `Slice: ${currentSlice} `
: `${BOLD_WHITE}Slice: ${this.renderAutonomousStatus(currentSlice)} `;
}
if (sliceStatus) {
statusLine += noColor
? `Status: ${sliceStatus} `
: `${BOLD_WHITE}Status: ${GREEN}${sliceStatus} `;
}
if (progress !== undefined) {
const progressBar = createProgressBar(progress, width - 30);
statusLine += noColor
? `Progress: ${progressBar} `
: `${BOLD_WHITE}Progress: ${YELLOW}${progressBar} `;
}
if (totalTasks !== undefined && completedTasks !== undefined) {
statusLine += noColor
? `Tasks: ${completedTasks}/${totalTasks} `
: `${BOLD_WHITE}Tasks: ${MAGENTA}${completedTasks}/${totalTasks} `;
}
statusLine += noColor ? "│" : `${DIM}${RESET}`;
return [statusLine];
}
}
function createProgressBar(progress: number, width: number): string {
const barWidth = Math.min(20, Math.max(5, width));
const filled = Math.floor((progress / 100) * barWidth);
const empty = barWidth - filled;
return `[${"█".repeat(filled)}${"░".repeat(empty)}] ${progress}%`;
}