"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClaudeCodeExecutor = void 0;
const child_process_1 = require("child_process");
const models_1 = require("../utils/models");
class ClaudeCodeExecutor {
    cliPath;
    constructor(cliPath = 'claude') {
        this.cliPath = cliPath;
    }
    getName() {
        return 'claude-code';
    }
    supportsStreaming() {
        return true;
    }
    async execute(options) {
        if (options.outputFormat === 'stream-json') {
            return this.executeStreaming(options);
        }
        else {
            return this.executeNonStreaming(options);
        }
    }
    buildEnvironment(options) {
        const env = { ...process.env };
        if (options.provider === 'bedrock' || options.provider === 'anthropic-bedrock' || options.bedrockApiKey) {
            env.CLAUDE_CODE_USE_BEDROCK = '1';
            env.AWS_BEARER_TOKEN_BEDROCK =
                options.bedrockApiKey ||
                    process.env.AWS_BEARER_TOKEN_BEDROCK ||
                    '';
            env.AWS_REGION = options.awsRegion || process.env.AWS_REGION || 'us-east-1';
        }
        else if (options.provider === 'anthropic' || options.anthropicApiKey) {
            env.ANTHROPIC_API_KEY = options.anthropicApiKey || process.env.ANTHROPIC_API_KEY || '';
        }
        if (options.awsAccessKeyId) {
            env.AWS_ACCESS_KEY_ID = options.awsAccessKeyId;
            env.AWS_SECRET_ACCESS_KEY = options.awsSecretAccessKey || '';
            if (options.awsSessionToken) {
                env.AWS_SESSION_TOKEN = options.awsSessionToken;
            }
        }
        return env;
    }
    buildArgs(options, useStreamJson = false) {
        const args = [];
        const userMessage = this.extractUserMessage(options.messages);
        if (!userMessage) {
            throw new Error('No user message found in messages array');
        }
        args.push('-p');
        if (useStreamJson) {
            args.push('--verbose');
        }
        if (useStreamJson) {
            args.push('--output-format', 'stream-json');
        }
        if (options.model) {
            const resolvedModel = (0, models_1.resolveModelSync)(options.model);
            args.push('--model', resolvedModel);
        }
        const systemMessage = this.extractSystemMessage(options.messages);
        if (systemMessage) {
            args.push('--system-prompt', systemMessage);
        }
        else if (options.systemPrompt) {
            args.push('--system-prompt', options.systemPrompt);
        }
        if (options.temperature !== undefined) {
            args.push('--temperature', String(options.temperature));
        }
        if (options.maxTokens !== undefined) {
            args.push('--max-tokens', String(options.maxTokens));
        }
        if (options.enableCoreTools || options.tools) {
            args.push('--tools');
        }
        if (options.disableTools) {
            args.push('--tools', '');
        }
        if (options.mcpConfig) {
            args.push('--mcp-config', options.mcpConfig);
        }
        if (options.allowedTools) {
            args.push('--allowed-tools', options.allowedTools);
        }
        if (options.disallowedTools) {
            args.push('--disallowed-tools', options.disallowedTools);
        }
        if (options.permissionPromptTool) {
            args.push('--permission-prompt-tool', options.permissionPromptTool);
        }
        if (options.cwd) {
            args.push('--add-dir', options.cwd);
        }
        args.push(userMessage);
        return args;
    }
    extractUserMessage(messages) {
        for (let i = messages.length - 1; i >= 0; i--) {
            if (messages[i].role === 'user') {
                const content = messages[i].content;
                return typeof content === 'string' ? content : JSON.stringify(content);
            }
        }
        return null;
    }
    extractSystemMessage(messages) {
        const systemMsg = messages.find(m => m.role === 'system');
        if (systemMsg) {
            return typeof systemMsg.content === 'string' ? systemMsg.content : JSON.stringify(systemMsg.content);
        }
        return null;
    }
    async executeNonStreaming(options) {
        const args = this.buildArgs(options, false);
        const env = this.buildEnvironment(options);
        return new Promise((resolve, reject) => {
            const childProcess = (0, child_process_1.spawn)(this.cliPath, args, {
                env,
                cwd: options.cwd || process.cwd(),
                stdio: ['pipe', 'pipe', 'pipe']
            });
            childProcess.stdin?.end();
            let stdout = '';
            let stderr = '';
            childProcess.stdout.on('data', (data) => {
                stdout += data.toString('utf8');
            });
            childProcess.stderr.on('data', (data) => {
                stderr += data.toString('utf8');
            });
            childProcess.on('error', (error) => {
                reject(new Error(`Failed to spawn Claude Code: ${error.message}`));
            });
            childProcess.on('close', (code) => {
                if (code !== 0) {
                    reject(new Error(`Claude Code exited with code ${code}${stderr ? `\n${stderr}` : ''}`));
                    return;
                }
                const response = {
                    id: `claude-code-${Date.now()}`,
                    object: 'chat.completion',
                    created: Math.floor(Date.now() / 1000),
                    model: options.model || 'claude-sonnet-4-5-20250929',
                    provider: 'claude-code',
                    choices: [
                        {
                            index: 0,
                            message: {
                                role: 'assistant',
                                content: stdout.trim()
                            },
                            finish_reason: 'stop'
                        }
                    ],
                    usage: {
                        prompt_tokens: 0,
                        completion_tokens: 0,
                        total_tokens: 0
                    }
                };
                resolve({ response });
            });
        });
    }
    async executeStreaming(options) {
        const args = this.buildArgs(options, true);
        const env = this.buildEnvironment(options);
        return new Promise((resolve, reject) => {
            const childProcess = (0, child_process_1.spawn)(this.cliPath, args, {
                env,
                cwd: options.cwd || process.cwd(),
                stdio: ['pipe', 'pipe', 'pipe']
            });
            childProcess.stdin?.end();
            let accumulatedContent = '';
            const toolCalls = [];
            childProcess.stdout.on('data', (data) => {
                const lines = data.toString('utf8').split('\n').filter(line => line.trim());
                for (const line of lines) {
                    try {
                        const parsed = JSON.parse(line);
                        if (parsed.type === 'message') {
                            if (parsed.role === 'assistant' && parsed.content) {
                                accumulatedContent += parsed.content;
                            }
                            if (options.onToolCall && parsed.tool_calls) {
                                for (const toolCall of parsed.tool_calls) {
                                    options.onToolCall(toolCall);
                                    toolCalls.push(toolCall);
                                }
                            }
                        }
                        else if (parsed.type === 'tool_result') {
                            if (options.onToolResult) {
                                options.onToolResult({ id: parsed.tool_call_id }, parsed.result);
                            }
                        }
                        process.stdout.write(line + '\n');
                    }
                    catch (e) {
                    }
                }
            });
            let stderrBuffer = '';
            childProcess.stderr.on('data', (data) => {
                stderrBuffer += data.toString('utf8');
            });
            childProcess.on('error', (error) => {
                reject(new Error(`Failed to spawn Claude Code: ${error.message}`));
            });
            childProcess.on('close', (code) => {
                if (code !== 0) {
                    reject(new Error(`Claude Code exited with code ${code}${stderrBuffer ? `\n${stderrBuffer}` : ''}`));
                    return;
                }
                const response = {
                    id: `claude-code-${Date.now()}`,
                    object: 'chat.completion',
                    created: Math.floor(Date.now() / 1000),
                    model: options.model || 'claude-sonnet-4-5-20250929',
                    provider: 'claude-code',
                    choices: [
                        {
                            index: 0,
                            message: {
                                role: 'assistant',
                                content: accumulatedContent,
                                tool_calls: toolCalls.length > 0 ? toolCalls : undefined
                            },
                            finish_reason: 'stop'
                        }
                    ],
                    usage: {
                        prompt_tokens: 0,
                        completion_tokens: 0,
                        total_tokens: 0
                    }
                };
                resolve({ response });
            });
        });
    }
}
exports.ClaudeCodeExecutor = ClaudeCodeExecutor;
//# sourceMappingURL=claude-code.executor.js.map