"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InteractiveMode = void 0;
const readline = __importStar(require("readline"));
const chalk_1 = __importDefault(require("chalk"));
const ora_1 = __importDefault(require("ora"));
const inquirer_1 = __importDefault(require("inquirer"));
class InteractiveMode {
    chat;
    options;
    session;
    rl;
    messages = [];
    running = false;
    constructor(chat, options) {
        this.chat = chat;
        this.options = options;
        this.session = chat.createSession(options.provider);
        this.rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout,
            prompt: chalk_1.default.cyan('You> ')
        });
        // Add system message if provided
        if (options.systemMessage) {
            this.messages.push({
                role: 'system',
                content: options.systemMessage
            });
        }
    }
    async start() {
        this.running = true;
        console.log(chalk_1.default.green('🤖 Interactive Chat Mode'));
        console.log(chalk_1.default.gray('Type /help for commands, /exit to quit\n'));
        if (this.options.provider) {
            console.log(chalk_1.default.gray(`Provider: ${this.options.provider}`));
        }
        if (this.options.model) {
            console.log(chalk_1.default.gray(`Model: ${this.options.model}`));
        }
        if (this.options.enableTools) {
            console.log(chalk_1.default.gray(`Tools: Enabled (${this.options.autoExecute ? 'auto-execute' : 'with confirmation'})`));
        }
        console.log();
        this.rl.prompt();
        this.rl.on('line', async (line) => {
            const input = line.trim();
            if (input.startsWith('/')) {
                await this.handleCommand(input);
            }
            else if (input.length > 0) {
                await this.handleMessage(input);
            }
            if (this.running) {
                this.rl.prompt();
            }
        });
        this.rl.on('close', () => {
            console.log(chalk_1.default.yellow('\nGoodbye! 👋'));
            process.exit(0);
        });
        // Keep the process alive
        await new Promise(() => { });
    }
    async handleCommand(command) {
        const [cmd, ...args] = command.split(' ');
        switch (cmd) {
            case '/help':
                this.showHelp();
                break;
            case '/exit':
            case '/quit':
                this.running = false;
                this.rl.close();
                break;
            case '/clear':
                this.messages = this.messages.filter(m => m.role === 'system');
                console.log(chalk_1.default.green('✓ Conversation cleared'));
                break;
            case '/history':
                this.showHistory();
                break;
            case '/save':
                await this.saveConversation(args[0]);
                break;
            case '/load':
                await this.loadConversation(args[0]);
                break;
            case '/model':
                if (args.length > 0) {
                    this.options.model = args.join(' ');
                    console.log(chalk_1.default.green(`✓ Model set to: ${this.options.model}`));
                }
                else {
                    console.log(chalk_1.default.gray(`Current model: ${this.options.model || 'default'}`));
                }
                break;
            case '/provider':
                if (args.length > 0) {
                    const newProvider = args[0];
                    if (this.chat.listProviders().includes(newProvider)) {
                        this.options.provider = newProvider;
                        this.session = this.chat.createSession(newProvider);
                        console.log(chalk_1.default.green(`✓ Provider set to: ${newProvider}`));
                    }
                    else {
                        console.log(chalk_1.default.red(`Invalid provider. Available: ${this.chat.listProviders().join(', ')}`));
                    }
                }
                else {
                    console.log(chalk_1.default.gray(`Current provider: ${this.options.provider || 'default'}`));
                }
                break;
            case '/system':
                if (args.length > 0) {
                    const systemMessage = args.join(' ');
                    // Remove old system message and add new one
                    this.messages = this.messages.filter(m => m.role !== 'system');
                    this.messages.unshift({
                        role: 'system',
                        content: systemMessage
                    });
                    console.log(chalk_1.default.green('✓ System message updated'));
                }
                else {
                    const system = this.messages.find(m => m.role === 'system');
                    if (system) {
                        console.log(chalk_1.default.gray('System message:'));
                        console.log(system.content);
                    }
                    else {
                        console.log(chalk_1.default.gray('No system message set'));
                    }
                }
                break;
            case '/tools':
                this.options.enableTools = !this.options.enableTools;
                console.log(chalk_1.default.green(`✓ Tools ${this.options.enableTools ? 'enabled' : 'disabled'}`));
                break;
            case '/auto':
                this.options.autoExecute = !this.options.autoExecute;
                console.log(chalk_1.default.green(`✓ Auto-execute ${this.options.autoExecute ? 'enabled' : 'disabled'}`));
                break;
            case '/multiline':
                await this.handleMultilineInput();
                break;
            default:
                console.log(chalk_1.default.red(`Unknown command: ${cmd}`));
                this.showHelp();
        }
    }
    async handleMessage(message) {
        this.messages.push({
            role: 'user',
            content: message
        });
        const spinner = (0, ora_1.default)('Thinking...').start();
        try {
            const request = {
                model: this.options.model || 'gpt-4',
                messages: this.messages,
                max_steps: this.options.enableTools ? 5 : 0
            };
            let response;
            if (this.options.enableTools && !this.options.autoExecute) {
                // Handle tool execution with confirmation
                response = await this.executeWithConfirmation(request);
            }
            else {
                // Normal execution
                response = await this.session.send(message, request);
            }
            spinner.stop();
            const assistantMessage = response.choices[0].message;
            this.messages.push(assistantMessage);
            console.log(chalk_1.default.green('\nAssistant:'));
            console.log(assistantMessage.content);
            // Show tool calls if any
            if (assistantMessage.tool_calls && assistantMessage.tool_calls.length > 0) {
                console.log(chalk_1.default.yellow('\nTool calls:'));
                for (const call of assistantMessage.tool_calls) {
                    console.log(`  - ${call.function.name}: ${call.function.arguments}`);
                }
            }
            // Show token usage
            if (response.usage) {
                console.log(chalk_1.default.gray(`\n[Tokens: ${response.usage.total_tokens}]`));
            }
            console.log();
        }
        catch (error) {
            spinner.fail('Error');
            console.error(chalk_1.default.red('Error:'), error instanceof Error ? error.message : error);
        }
    }
    async executeWithConfirmation(request) {
        // First, get the response without executing tools
        const initialRequest = { ...request, max_steps: 0 };
        let response = await this.session.send('', initialRequest);
        // Check for tool calls
        const toolCalls = response.choices[0].message.tool_calls;
        if (toolCalls && toolCalls.length > 0) {
            console.log(chalk_1.default.yellow('\nThe assistant wants to execute the following tools:'));
            for (const call of toolCalls) {
                console.log(`  - ${call.function.name}: ${call.function.arguments}`);
            }
            const { proceed } = await inquirer_1.default.prompt([
                {
                    type: 'confirm',
                    name: 'proceed',
                    message: 'Do you want to execute these tools?',
                    default: true
                }
            ]);
            if (proceed) {
                // Execute with tools
                response = await this.session.send('', request);
            }
        }
        return response;
    }
    async handleMultilineInput() {
        console.log(chalk_1.default.gray('Enter multiline input. Type END on a new line to finish:'));
        const lines = [];
        const multilineRl = readline.createInterface({
            input: process.stdin,
            output: process.stdout,
            prompt: chalk_1.default.gray('... ')
        });
        multilineRl.prompt();
        return new Promise((resolve) => {
            multilineRl.on('line', (line) => {
                if (line.trim() === 'END') {
                    multilineRl.close();
                    const message = lines.join('\n');
                    this.handleMessage(message).then(() => resolve());
                }
                else {
                    lines.push(line);
                    multilineRl.prompt();
                }
            });
        });
    }
    showHelp() {
        console.log(chalk_1.default.cyan('\nAvailable Commands:'));
        console.log('  /help           - Show this help message');
        console.log('  /exit, /quit    - Exit interactive mode');
        console.log('  /clear          - Clear conversation history');
        console.log('  /history        - Show conversation history');
        console.log('  /save <file>    - Save conversation to file');
        console.log('  /load <file>    - Load conversation from file');
        console.log('  /model <name>   - Set or show current model');
        console.log('  /provider <name>- Set or show current provider');
        console.log('  /system <msg>   - Set or show system message');
        console.log('  /tools          - Toggle tool execution');
        console.log('  /auto           - Toggle auto-execute for tools');
        console.log('  /multiline      - Enter multiline input');
        console.log();
    }
    showHistory() {
        if (this.messages.length === 0) {
            console.log(chalk_1.default.gray('No messages in history'));
            return;
        }
        console.log(chalk_1.default.cyan('\nConversation History:'));
        for (const message of this.messages) {
            const role = message.role.charAt(0).toUpperCase() + message.role.slice(1);
            const color = message.role === 'user' ? chalk_1.default.blue :
                message.role === 'assistant' ? chalk_1.default.green :
                    chalk_1.default.gray;
            console.log(color(`${role}:`), message.content);
        }
        console.log();
    }
    async saveConversation(filename) {
        if (!filename) {
            console.log(chalk_1.default.red('Please provide a filename'));
            return;
        }
        try {
            const fs = await Promise.resolve().then(() => __importStar(require('fs-extra')));
            const data = {
                timestamp: new Date().toISOString(),
                provider: this.options.provider,
                model: this.options.model,
                messages: this.messages
            };
            await fs.writeJson(filename, data, { spaces: 2 });
            console.log(chalk_1.default.green(`✓ Conversation saved to ${filename}`));
        }
        catch (error) {
            console.error(chalk_1.default.red('Error saving conversation:'), error);
        }
    }
    async loadConversation(filename) {
        if (!filename) {
            console.log(chalk_1.default.red('Please provide a filename'));
            return;
        }
        try {
            const fs = await Promise.resolve().then(() => __importStar(require('fs-extra')));
            const data = await fs.readJson(filename);
            this.messages = data.messages || [];
            if (data.provider) {
                this.options.provider = data.provider;
                this.session = this.chat.createSession(data.provider);
            }
            if (data.model) {
                this.options.model = data.model;
            }
            console.log(chalk_1.default.green(`✓ Conversation loaded from ${filename}`));
            console.log(chalk_1.default.gray(`  Messages: ${this.messages.length}`));
            if (data.timestamp) {
                console.log(chalk_1.default.gray(`  Saved: ${data.timestamp}`));
            }
        }
        catch (error) {
            console.error(chalk_1.default.red('Error loading conversation:'), error);
        }
    }
}
exports.InteractiveMode = InteractiveMode;
//# sourceMappingURL=interactive.js.map