"use strict";
// src/orchestrator/story/adapters/ClaudeAdapter.ts
// v1.17.0 — Spawns `claude -p "<prompt>"` and captures stdout.
// Aligns with Host-Native Mode v1.10: the user's installed Claude Code
// CLI does the LLM work, OpenLife only orchestrates.
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClaudeAdapter = void 0;
const child_process_1 = require("child_process");
const util_1 = require("util");
const child_process_2 = require("child_process");
const execFileP = (0, util_1.promisify)(child_process_2.execFile);
class ClaudeAdapter {
    name = 'claude';
    async isAvailable() {
        // Probe via `claude --version` with short timeout.
        try {
            await execFileP('claude', ['--version'], { timeout: 5_000 });
            return true;
        }
        catch {
            return false;
        }
    }
    async invoke(prompt, opts = {}) {
        const start = Date.now();
        const timeoutMs = opts.timeoutMs ?? 300_000;
        // Claude CLI accepts -p / --print for non-interactive single-prompt mode.
        // When a skillFile is provided, prepend a slash-command activation hint.
        const args = ['-p'];
        if (opts.model)
            args.push('--model', opts.model);
        // The prompt itself is positional or via stdin — Claude CLI takes stdin
        // when -p is set with no positional arg. We pass via stdin to dodge
        // shell-quoting edge cases on long prompts.
        let stdout = '';
        let stderr = '';
        let exitCode = -1;
        let timedOut = false;
        try {
            await new Promise((resolve, reject) => {
                const child = (0, child_process_1.spawn)('claude', args, {
                    cwd: opts.cwd || process.cwd(),
                    env: { ...process.env, ...(opts.env || {}) },
                    stdio: ['pipe', 'pipe', 'pipe'],
                });
                const t = setTimeout(() => {
                    timedOut = true;
                    try {
                        child.kill('SIGTERM');
                    }
                    catch { /* */ }
                    setTimeout(() => { try {
                        child.kill('SIGKILL');
                    }
                    catch { /* */ } }, 2000).unref();
                }, timeoutMs);
                if (typeof t.unref === 'function')
                    t.unref();
                child.stdout?.on('data', (c) => { stdout += String(c); });
                child.stderr?.on('data', (c) => { stderr += String(c); });
                child.on('error', (err) => { clearTimeout(t); reject(err); });
                child.on('exit', (code) => {
                    clearTimeout(t);
                    exitCode = typeof code === 'number' ? code : -1;
                    resolve();
                });
                // Stream the prompt via stdin and close.
                child.stdin?.write(prompt);
                child.stdin?.end();
            });
        }
        catch (err) {
            return {
                ok: false,
                text: stdout,
                exitCode: -1,
                durationMs: Date.now() - start,
                adapter: this.name,
                error: `spawn_error: ${err instanceof Error ? err.message : String(err)}; stderr: ${stderr.slice(0, 200)}`,
            };
        }
        return {
            ok: exitCode === 0 && !timedOut,
            text: stdout,
            exitCode,
            durationMs: Date.now() - start,
            adapter: this.name,
            error: timedOut ? `timeout_after_${timeoutMs}ms` : (exitCode !== 0 ? `exit_${exitCode}: ${stderr.slice(0, 200)}` : undefined),
        };
    }
}
exports.ClaudeAdapter = ClaudeAdapter;
