/**
 * CLI Transport — renders GSD events as rich ANSI-colored output to a Writable stream.
 *
 * Implements TransportHandler with colored banners, step indicators, spawn markers,
 * and running cost totals. No external dependencies — ANSI codes are inline constants.
 */
import { GSDEventType } from './types.js';
// ─── ANSI escape constants (no dependency per D021) ──────────────────────────
const BOLD = '\x1b[1m';
const RESET = '\x1b[0m';
const GREEN = '\x1b[32m';
const RED = '\x1b[31m';
const YELLOW = '\x1b[33m';
const CYAN = '\x1b[36m';
const DIM = '\x1b[90m';
// ─── Helpers ─────────────────────────────────────────────────────────────────
/** Extract HH:MM:SS from an ISO-8601 timestamp. */
function formatTime(ts) {
    try {
        const d = new Date(ts);
        if (Number.isNaN(d.getTime()))
            return '??:??:??';
        return d.toISOString().slice(11, 19);
    }
    catch {
        return '??:??:??';
    }
}
/** Truncate a string to `max` characters, appending '…' if truncated. */
function truncate(s, max) {
    if (s.length <= max)
        return s;
    return s.slice(0, max - 1) + '…';
}
/** Format a USD amount. */
function usd(n) {
    return `$${n.toFixed(2)}`;
}
// ─── CLITransport ────────────────────────────────────────────────────────────
export class CLITransport {
    out;
    runningCostUsd = 0;
    constructor(out) {
        this.out = out ?? process.stdout;
    }
    /** Format and write a GSD event as a rich ANSI-colored line. Never throws. */
    onEvent(event) {
        try {
            const line = this.formatEvent(event);
            this.out.write(line + '\n');
        }
        catch {
            // TransportHandler contract: onEvent must never throw
        }
    }
    /** No-op — stdout doesn't need cleanup. */
    close() {
        // Nothing to clean up
    }
    // ─── Private formatting ────────────────────────────────────────────
    formatEvent(event) {
        const time = formatTime(event.timestamp);
        switch (event.type) {
            case GSDEventType.SessionInit:
                return `[${time}] [INIT] Session started — model: ${event.model}, tools: ${event.tools.length}, cwd: ${event.cwd}`;
            case GSDEventType.SessionComplete:
                return `[${time}] ${GREEN}✓ Session complete — cost: ${usd(event.totalCostUsd)}, turns: ${event.numTurns}, duration: ${(event.durationMs / 1000).toFixed(1)}s${RESET}`;
            case GSDEventType.SessionError:
                return `[${time}] ${RED}✗ Session failed — subtype: ${event.errorSubtype}, errors: [${event.errors.join(', ')}]${RESET}`;
            case GSDEventType.ToolCall:
                return `[${time}] [TOOL] ${event.toolName}(${truncate(JSON.stringify(event.input), 80)})`;
            case GSDEventType.PhaseStart:
                return `${BOLD}${CYAN}━━━ GSD ► PHASE ${event.phaseNumber}: ${event.phaseName} ━━━${RESET}`;
            case GSDEventType.PhaseComplete:
                return `[${time}] [PHASE] Phase ${event.phaseNumber} complete — success: ${event.success}, cost: ${usd(event.totalCostUsd)}, running: ${usd(this.runningCostUsd)}`;
            case GSDEventType.PhaseStepStart:
                return `${CYAN}◆ ${event.step}${RESET}`;
            case GSDEventType.PhaseStepComplete:
                return event.success
                    ? `${GREEN}✓ ${event.step}${RESET} ${DIM}${event.durationMs}ms${RESET}`
                    : `${RED}✗ ${event.step}${RESET} ${DIM}${event.durationMs}ms${RESET}`;
            case GSDEventType.WaveStart:
                return `${YELLOW}⟫ Wave ${event.waveNumber} (${event.planCount} plans)${RESET}`;
            case GSDEventType.WaveComplete:
                return `[${time}] [WAVE] Wave ${event.waveNumber} complete — ${GREEN}${event.successCount} success${RESET}, ${RED}${event.failureCount} failed${RESET}, ${event.durationMs}ms`;
            case GSDEventType.CostUpdate: {
                this.runningCostUsd += event.sessionCostUsd;
                return `${DIM}[${time}] Cost: session ${usd(event.sessionCostUsd)}, running ${usd(this.runningCostUsd)}${RESET}`;
            }
            case GSDEventType.MilestoneStart:
                return `${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}\n${BOLD}  GSD Milestone — ${event.phaseCount} phases${RESET}\n${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}`;
            case GSDEventType.MilestoneComplete:
                return `${BOLD}━━━ Milestone complete — success: ${event.success}, cost: ${usd(event.totalCostUsd)}, running: ${usd(this.runningCostUsd)} ━━━${RESET}`;
            case GSDEventType.AssistantText:
                return `${DIM}[${time}] ${truncate(event.text, 200)}${RESET}`;
            case GSDEventType.InitResearchSpawn:
                return `${CYAN}◆ Spawning ${event.sessionCount} researchers...${RESET}`;
            // Generic fallback for event types without specific formatting
            default:
                return `[${time}] [EVENT] ${event.type}`;
        }
    }
}
//# sourceMappingURL=cli-transport.js.map