/**
 * Interactive REPL for Clawx.
 *
 * Simple readline-based REPL that feeds user input to the agent loop
 * and streams results back. Supports multi-turn conversations with
 * session persistence.
 */
import readline from "node:readline";
import chalk from "chalk";
import { runAgent, ToolsNotSupportedError } from "../core/agent.js";
import { createStreamRenderer } from "../core/streaming.js";
import { saveSession } from "../core/session.js";
import { agentMaster } from "../core/agent-master.js";
import { AgentRegistryManager } from "../core/agent-registry.js";
import { printBanner } from "./banner.js";
export async function startRepl(config, sessionId, existingMessages, options) {
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stderr,
        prompt: chalk.green("clawx> "),
    });
    let messages = [...existingMessages];
    let abortController = null;
    let chatOnly = options?.chatOnly ?? false; // set to true if model doesn't support tools
    const session = {
        id: sessionId,
        startedAt: Date.now(),
        workDir: config.workDir,
        model: config.model,
        provider: config.provider,
    };
    printBanner(config.model, config.provider);
    if (chatOnly) {
        console.error(chalk.yellow(`Chat mode — no tools (model does not support tool calling)`));
    }
    console.error(chalk.gray(`Working directory: ${config.workDir}`));
    console.error(chalk.gray(`Type your request. Ctrl+C to cancel, Ctrl+D or "exit" to quit.\n`));
    rl.prompt();
    rl.on("line", async (line) => {
        const input = line.trim();
        if (!input) {
            rl.prompt();
            return;
        }
        // Commands
        if (input === "exit" || input === "quit" || input === "/exit") {
            saveSession(config.sessionDir, session, messages);
            rl.close();
            return;
        }
        if (input === "/clear") {
            messages = [];
            console.error(chalk.gray("Session cleared."));
            rl.prompt();
            return;
        }
        if (input === "/save") {
            saveSession(config.sessionDir, session, messages);
            console.error(chalk.gray(`Session saved: ${sessionId}`));
            rl.prompt();
            return;
        }
        if (input === "/info") {
            console.error(chalk.gray(`Session: ${sessionId}`));
            console.error(chalk.gray(`Model: ${config.model}`));
            console.error(chalk.gray(`Provider: ${config.provider}`));
            console.error(chalk.gray(`Base URL: ${config.baseUrl}`));
            console.error(chalk.gray(`Messages: ${messages.length}`));
            console.error(chalk.gray(`Work dir: ${config.workDir}`));
            rl.prompt();
            return;
        }
        if (input.startsWith("/")) {
            console.error(chalk.yellow(`Unknown command: ${input}`));
            console.error(chalk.gray("Commands: /clear, /save, /info, /exit"));
            rl.prompt();
            return;
        }
        // Run agent
        abortController = new AbortController();
        const renderer = createStreamRenderer({
            getNetworkSnapshot: () => {
                if (!agentMaster.isServing())
                    return null;
                try {
                    const reg = new AgentRegistryManager();
                    const agents = reg.getAgents();
                    return {
                        serving: true,
                        workers: agents.filter(a => a.type === "local" && a.status !== "offline").length,
                        peers: agents.filter(a => a.type === "remote").length,
                        port: agentMaster.getServer()?.port,
                    };
                }
                catch {
                    return { serving: true, workers: 0, peers: 0 };
                }
            },
        });
        try {
            const result = await runAgent(config, {
                prompt: input,
                messages,
                onEvent: (event) => renderer.onEvent(event),
                signal: abortController.signal,
                noTools: chatOnly,
                parseTextToolCalls: !chatOnly,
            });
            renderer.finish();
            messages = result.messages;
            // Auto-save after each turn
            saveSession(config.sessionDir, session, messages);
        }
        catch (e) {
            if (e instanceof ToolsNotSupportedError) {
                chatOnly = true;
                console.error(chalk.yellow(`\n  Model '${config.model}' does not support tools — switching to chat mode (no file/command tools).`));
                console.error(chalk.gray(`  To use tools, switch model: clawx use deepseek\n`));
                // Retry the same prompt in chat mode
                try {
                    const retryResult = await runAgent(config, {
                        prompt: input,
                        messages,
                        onEvent: (event) => renderer.onEvent(event),
                        signal: abortController?.signal,
                        noTools: true,
                    });
                    renderer.finish();
                    messages = retryResult.messages;
                    saveSession(config.sessionDir, session, messages);
                }
                catch (retryErr) {
                    console.error(chalk.red(`\nError: ${retryErr instanceof Error ? retryErr.message : retryErr}`));
                }
            }
            else if (e.name === "AbortError") {
                console.error(chalk.yellow("\n[aborted]"));
            }
            else {
                console.error(chalk.red(`\nError: ${e instanceof Error ? e.message : e}`));
            }
        }
        abortController = null;
        rl.prompt();
    });
    // Handle Ctrl+C — abort current run or exit
    rl.on("SIGINT", () => {
        if (abortController) {
            abortController.abort();
            abortController = null;
        }
        else {
            console.error(chalk.gray("\nUse Ctrl+D or 'exit' to quit."));
            rl.prompt();
        }
    });
    rl.on("close", () => {
        saveSession(config.sessionDir, session, messages);
        console.error(chalk.gray("\nSession saved. Goodbye."));
        process.exit(0);
    });
    // Return a promise that resolves when the REPL closes
    return new Promise((resolve) => {
        rl.on("close", () => resolve());
    });
}
//# sourceMappingURL=repl.js.map