/**
 * repl.ts — `olam ask` (no args) opens an interactive multi-turn REPL.
 *
 * Conversation context is preserved by accumulating a running transcript and
 * prepending it to each new prompt. The SDK `query()` call is independent
 * per-turn (no session resume needed for a lightweight Q&A loop); the
 * transcript carries prior Q&A forward so follow-ups land in context.
 *
 * Exits on `/exit`, `/quit`, or Ctrl-D (EOF). Ctrl-C aborts the in-flight
 * answer (or exits at an empty prompt).
 */
import { createInterface } from 'node:readline';
import pc from 'picocolors';
import { KNOWLEDGE_PACK } from './knowledge-pack.generated.js';
import { assembleSystemPrompt } from './system-prompt.js';
import { findOlamCheckoutRoot } from './checkout.js';
import { askOnce, AskSdkUnavailableError } from './sdk-client.js';
import { printError } from '../output.js';
import { EXIT_GENERIC_ERROR } from '../exit-codes.js';
const EXIT_COMMANDS = new Set(['/exit', '/quit', '/q']);
/** Compose the next prompt from prior transcript + the new question. */
export function composeTurnPrompt(transcript, question) {
    if (transcript.trim().length === 0)
        return question;
    return `${transcript}\n\nNew question: ${question}`;
}
/** Append a completed Q&A pair to the transcript (immutable return). */
export function appendTurn(transcript, question, answer) {
    const pair = `Q: ${question}\nA: ${answer}`;
    return transcript.length === 0 ? pair : `${transcript}\n\n${pair}`;
}
/**
 * Run the interactive REPL. Returns the process exit code. Unit-testable via
 * an injected readline interface + query fn (no real stdin / API).
 */
export async function runRepl(deps = {}) {
    const write = deps.write ?? ((s) => void process.stdout.write(s));
    const repoRoot = deps.checkoutRoot !== undefined ? deps.checkoutRoot : findOlamCheckoutRoot();
    const systemPromptAppend = assembleSystemPrompt({
        knowledgePack: KNOWLEDGE_PACK,
        insideCheckout: repoRoot !== null,
        repoRoot: repoRoot ?? undefined,
    });
    write([
        pc.bold('olam ask') + pc.dim(' — interactive assistant (local Claude subscription, Sonnet)'),
        pc.dim(repoRoot
            ? `inside checkout: ${repoRoot} (live repo files available)`
            : 'no checkout detected — answering from the bundled knowledge pack'),
        pc.dim('Type a question. /exit (or Ctrl-D) to quit.'),
        '',
    ].join('\n'));
    const rl = deps.rl ??
        createInterface({ input: process.stdin, output: process.stdout, prompt: pc.cyan('olam ask> ') });
    let transcript = '';
    let exitCode = 0;
    // EOF (Ctrl-D) closes the interface. Track it once (not per-turn — a
    // per-turn `rl.once('close')` leaks listeners and warns after 10 turns).
    // An in-flight ask() resolves null when this fires.
    let closed = false;
    let onClose = null;
    rl.on('close', () => {
        closed = true;
        onClose?.();
    });
    const ask = () => new Promise((resolve) => {
        if (closed)
            return resolve(null);
        onClose = () => resolve(null);
        rl.question(pc.cyan('olam ask> '), (line) => {
            onClose = null;
            resolve(line);
        });
    });
    try {
        for (;;) {
            const line = await ask();
            if (line === null) {
                write('\n');
                break; // EOF
            }
            const question = line.trim();
            if (question.length === 0)
                continue;
            if (EXIT_COMMANDS.has(question.toLowerCase()))
                break;
            try {
                const answer = await askOnce(composeTurnPrompt(transcript, question), { systemPromptAppend, repoRoot: repoRoot ?? undefined, queryFn: deps.queryFn }, (chunk) => write(chunk));
                if (!answer.endsWith('\n'))
                    write('\n');
                write('\n');
                transcript = appendTurn(transcript, question, answer);
            }
            catch (err) {
                if (err instanceof AskSdkUnavailableError) {
                    printError(err.message);
                    exitCode = EXIT_GENERIC_ERROR;
                    break; // SDK gone → no point continuing the loop
                }
                printError(err instanceof Error ? err.message : String(err));
                // Transient per-turn error: keep the REPL alive for a retry.
            }
        }
    }
    finally {
        rl.close();
    }
    return exitCode;
}
//# sourceMappingURL=repl.js.map