/**
 * LiveOutputStream: tmux capture-pane snapshot + tail.
 */
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
import { CapabilityFlag } from '../../../capabilities.js';
import { UnexpectedError } from '../../../errors.js';
import { ANTHROPIC_HEADLESS_ID } from '../errors.js';
import { tmuxSessionFromHandle } from '../transport/agenticSessionHeadless.js';
const execFileAsync = promisify(execFile);
const ANSI_RE = /\[[0-9;?]*[A-Za-z]/g;
class AnthropicHeadlessLiveOutputStream {
    config;
    capability = CapabilityFlag.LiveOutputStream;
    constructor(config) {
        this.config = config;
    }
    async snapshot(session, options) {
        const tmuxName = tmuxSessionFromHandle(session);
        const lines = options?.maxLines ?? 200;
        const includeAnsi = options?.includeAnsi === true;
        try {
            const { stdout } = await execFileAsync(this.config.tmuxPath, ['capture-pane', '-t', `=${tmuxName}:`, '-p', '-S', `-${lines}`, ...(includeAnsi ? ['-e'] : [])], { timeout: 5000, maxBuffer: 4 * 1024 * 1024 });
            const text = includeAnsi ? stdout : stdout.replace(ANSI_RE, '');
            return {
                text,
                capturedAt: new Date().toISOString(),
                truncated: stdout.split('\n').length >= lines,
            };
        }
        catch (err) {
            throw new UnexpectedError(`Failed to capture pane for ${tmuxName}: ${err.message}`, ANTHROPIC_HEADLESS_ID, err);
        }
    }
    tail(session, options) {
        const tmuxPath = this.config.tmuxPath;
        const tmuxName = tmuxSessionFromHandle(session);
        const intervalMs = options?.flushIntervalMs ?? 250;
        const signal = options?.signal;
        return {
            async *[Symbol.asyncIterator]() {
                let lastBuffer = '';
                if (options?.includeBacklog) {
                    try {
                        const { stdout } = await execFileAsync(tmuxPath, ['capture-pane', '-t', `=${tmuxName}:`, '-p', '-S', '-500'], { timeout: 5000, maxBuffer: 4 * 1024 * 1024 });
                        const text = stdout.replace(ANSI_RE, '');
                        if (text) {
                            yield { text, emittedAt: new Date().toISOString() };
                            lastBuffer = stdout;
                        }
                    }
                    catch {
                        // session may not exist yet
                    }
                }
                while (!signal?.aborted) {
                    await new Promise((resolve) => setTimeout(resolve, intervalMs));
                    try {
                        const { stdout } = await execFileAsync(tmuxPath, ['capture-pane', '-t', `=${tmuxName}:`, '-p', '-S', '-200'], { timeout: 5000, maxBuffer: 4 * 1024 * 1024 });
                        if (stdout !== lastBuffer) {
                            const delta = stdout.slice(lastBuffer.length);
                            const cleaned = delta.replace(ANSI_RE, '');
                            if (cleaned) {
                                yield { text: cleaned, emittedAt: new Date().toISOString() };
                            }
                            lastBuffer = stdout;
                        }
                    }
                    catch {
                        // session ended; stop iterating
                        return;
                    }
                }
            },
        };
    }
}
export function createLiveOutputStream(config) {
    return new AnthropicHeadlessLiveOutputStream(config);
}
//# sourceMappingURL=liveOutputStream.js.map