"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CliChatService = void 0;
const index_1 = require("../utils/index");
const microphone_1 = require("../microphone");
const editor_1 = __importDefault(require("@inquirer/editor"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const services_1 = require("../services");
const logger_1 = require("../logger");
class CliChatService {
    context;
    commands = [];
    modes = [];
    chatHistory = [];
    modules = [];
    inputHistory = [];
    historyFile = ".knowhow/chats/history.json";
    constructor(plugins = []) {
        this.context = {
            debugMode: false,
            agentMode: false,
            currentAgent: "Patcher",
            searchMode: false,
            voiceMode: false,
            multilineMode: false,
            currentModel: "gpt-5.4-nano",
            currentProvider: "openai",
            chatHistory: this.chatHistory,
            plugins,
        };
        this.loadInputHistory();
        (0, index_1.setOnNewHistoryEntry)((entry) => {
            this.addToInputHistory(entry);
        });
    }
    getModuleByName(name) {
        return this.modules.find((module) => module.name === "agent");
    }
    loadInputHistory() {
        try {
            if (fs_1.default.existsSync(this.historyFile)) {
                const historyData = fs_1.default.readFileSync(this.historyFile, "utf8");
                const parsedHistory = JSON.parse(historyData);
                this.inputHistory = parsedHistory.inputs || [];
            }
        }
        catch (error) {
            console.error("Error loading input history:", error);
            this.inputHistory = [];
        }
    }
    saveInputHistory() {
        try {
            const dir = path_1.default.dirname(this.historyFile);
            if (!fs_1.default.existsSync(dir)) {
                fs_1.default.mkdirSync(dir, { recursive: true });
            }
            const inputHistory = {
                inputs: this.inputHistory,
            };
            fs_1.default.writeFileSync(this.historyFile, JSON.stringify(inputHistory, null, 2));
        }
        catch (error) {
            console.error("Error saving input history:", error);
        }
    }
    addToInputHistory(input) {
        if (!input.startsWith("/") && input.trim() !== "") {
            this.inputHistory.push(input);
            if (this.inputHistory.length > 1000) {
                this.inputHistory = this.inputHistory.slice(-1000);
            }
            this.saveInputHistory();
        }
    }
    getContext() {
        return this.context;
    }
    getTools() {
        return this.context.selectedAgent?.tools;
    }
    setContext(context) {
        this.context = { ...this.context, ...context };
        if (this.context.chatHistory !== this.chatHistory) {
            this.context.chatHistory = this.chatHistory;
        }
    }
    setInputMethod(method) {
        this.context.inputMethod = method;
    }
    resetInputMethod() {
        delete this.context.inputMethod;
    }
    registerCommand(command) {
        this.commands.push(command);
    }
    registerMode(mode) {
        this.modes.push(mode);
    }
    registerModule(module) {
        this.modules.push(module);
    }
    getCommands() {
        return this.commands;
    }
    getCommandsForMode(mode) {
        return this.commands.filter((cmd) => !cmd.modes || cmd.modes.length === 0 || cmd.modes.includes(mode));
    }
    getCommandsForActiveModes() {
        const activeModes = this.modes
            .filter((mode) => mode.active)
            .map((mode) => mode.name);
        return this.commands.filter((cmd) => !cmd.modes ||
            cmd.modes.length === 0 ||
            cmd.modes.some((mode) => activeModes.includes(mode)));
    }
    setMode(mode) {
        this.modes.forEach((m) => {
            if (m.name !== "default" && m.name !== mode) {
                m.active = false;
            }
            else if (m.name === mode) {
                m.active = true;
            }
        });
    }
    getModes() {
        return this.modes;
    }
    getMode(name) {
        return this.modes.find((mode) => mode.name === name);
    }
    async processInput(input) {
        if (input.startsWith("/")) {
            const [commandName, ...args] = input.slice(1).split(" ");
            const availableCommands = this.getCommandsForActiveModes();
            const command = availableCommands.find((cmd) => cmd.name === commandName);
            if (command) {
                const result = await command.handler(args);
                if (result && typeof result === "object" && "handled" in result) {
                    if (result.handled) {
                        return true;
                    }
                    input = result.contents || input;
                }
                else {
                    return true;
                }
            }
            else {
                const availableCommands = this.getCommandsForActiveModes();
                console.log(`Unknown command "/${commandName}". Available commands: ${availableCommands
                    .map((cmd) => `/${cmd.name}`)
                    .join(", ")}`);
                return true;
            }
        }
        for (const module of this.modules) {
            try {
                const handled = await module.handleInput(input, this.context);
                if (handled) {
                    return true;
                }
            }
            catch (error) {
                console.error(`Error in module ${module.name}:`, error);
            }
        }
        return false;
    }
    enableMode(name) {
        const mode = this.modes.find((m) => m.name === name);
        if (mode) {
            mode.active = true;
        }
    }
    disableMode(name) {
        const mode = this.modes.find((m) => m.name === name);
        if (mode) {
            mode.active = false;
        }
    }
    async getInput(prompt = "> ", options = []) {
        if (this.context.inputMethod) {
            return await this.context.inputMethod.getInput(prompt);
        }
        let value = "";
        if (this.context.voiceMode) {
            value = await (0, microphone_1.voiceToText)();
        }
        else if (this.context.multilineMode) {
            const renderer = this.context.renderer;
            if (renderer)
                renderer.pause();
            logger_1.logger.silence();
            try {
                value = await (0, editor_1.default)({ message: prompt });
            }
            finally {
                if (renderer)
                    renderer.resume();
                logger_1.logger.unsilence();
            }
            this.context.multilineMode = false;
        }
        else {
            const history = this.inputHistory.slice();
            value = await (0, index_1.ask)(prompt, options, history);
        }
        return value.trim();
    }
    clearHistory() {
        this.chatHistory = [];
        this.context.chatHistory = this.chatHistory;
    }
    getChatHistory() {
        return this.chatHistory;
    }
    getInputHistory() {
        return [...this.inputHistory];
    }
    clearInputHistory() {
        this.inputHistory = [];
        this.saveInputHistory();
    }
    async formatChatInput(input, plugins = [], chatHistory = []) {
        const { Plugins } = (0, services_1.services)();
        const pluginText = await Plugins.callMany(plugins, input);
        const historyMessage = `<PreviousChats>
  This information is provided as historical context and is likely not related to the current task:
  ${JSON.stringify(chatHistory)}
    </PreviousChats>`;
        const fullPrompt = `
    ${historyMessage} \n
    <PluginContext> ${pluginText} </PluginContext>
    <CurrentTask>${input}</CurrentTask>
  `;
        return fullPrompt;
    }
    async startChatLoop() {
        const availableCommands = this.getCommandsForActiveModes();
        const commandNames = availableCommands.map((cmd) => `/${cmd.name}`);
        console.log("Commands:", commandNames.join(", "));
        while (true) {
            const currentCommandNames = this.getCommandsForActiveModes().map((cmd) => `/${cmd.name}`);
            const activeModeWithPrompt = this.modes
                .filter((m) => m.active && m.promptText)
                .slice(-1)[0];
            let modePrompt;
            if (activeModeWithPrompt?.promptText) {
                const p = activeModeWithPrompt.promptText;
                modePrompt = typeof p === "function" ? p() : p;
            }
            const promptText = modePrompt ||
                this.context.promptText ||
                (this.context.agentMode && this.context.currentAgent
                    ? `\nAsk knowhow ${this.context.currentAgent}: `
                    : `\nAsk knowhow: `);
            try {
                const input = await this.getInput(promptText, currentCommandNames);
                if (input.trim() === "") {
                    continue;
                }
                const handled = await this.processInput(input.trim());
                if (!handled) {
                    const interaction = {
                        input,
                        output: `I didn't understand that command. Available commands: ${currentCommandNames.join(", ")}`,
                    };
                    this.chatHistory.push(interaction);
                    console.log(interaction.output);
                }
            }
            catch (error) {
                console.error("Error in chat loop:", error);
            }
        }
    }
}
exports.CliChatService = CliChatService;
//# sourceMappingURL=CliChatService.js.map