"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MajkExecutor = void 0;
const majk_chat_core_1 = require("@majkapp/majk-chat-core");
const majk_chat_basic_tools_1 = require("@majkapp/majk-chat-basic-tools");
const majk_chat_document_tools_1 = require("@majkapp/majk-chat-document-tools");
const majk_chat_mcp_1 = require("@majkapp/majk-chat-mcp");
const credentials_1 = require("../utils/credentials");
const models_1 = require("../utils/models");
class MajkExecutor {
    getName() {
        return 'majk';
    }
    supportsStreaming() {
        return false;
    }
    async execute(options) {
        const setupResult = await this.setupChat(options);
        const { chat, toolRegistry } = setupResult;
        try {
            // Resolve model using ModelResolverService
            const actualProvider = (options.provider === 'bedrock' ? 'anthropic-bedrock' : (options.provider || 'openai'));
            const context = { requestId: `req-${Date.now()}` };
            const model = options.model
                ? await (0, models_1.resolveModel)(chat, options.model, actualProvider, context)
                : await (0, models_1.getDefaultModel)(chat, actualProvider, undefined, context);
            const tools = toolRegistry.getDefinitions();
            const request = {
                model,
                messages: options.messages,
                temperature: options.temperature,
                max_tokens: options.maxTokens,
                tools: tools.length > 0 ? tools : undefined,
                max_steps: options.maxSteps || (tools.length > 0 ? 5 : 0),
                return_transcript: false
            };
            const chatSession = chat.createSession(actualProvider);
            const lastMessage = options.messages[options.messages.length - 1];
            const messageContent = typeof lastMessage.content === 'string'
                ? lastMessage.content
                : JSON.stringify(lastMessage.content);
            const response = await chatSession.send(messageContent, request);
            await setupResult.cleanup();
            return {
                response,
                messages: options.messages
            };
        }
        catch (error) {
            await setupResult.cleanup();
            throw error;
        }
    }
    async setupChat(options) {
        const builder = new majk_chat_core_1.MajkChatBuilder();
        const credManager = new credentials_1.CredentialManager();
        majk_chat_basic_tools_1.WorkingDirectoryManager.initializeFromCLI();
        const credOptions = {
            openaiApiKey: options.openaiApiKey,
            anthropicApiKey: options.anthropicApiKey,
            azureOpenaiApiKey: options.azureOpenaiApiKey,
            azureOpenaiEndpoint: options.azureOpenaiEndpoint,
            azureOpenaiDeployment: options.azureOpenaiDeployment,
            awsAccessKeyId: options.awsAccessKeyId,
            awsSecretAccessKey: options.awsSecretAccessKey,
            awsSessionToken: options.awsSessionToken,
            awsRegion: options.awsRegion,
            bedrockApiKey: options.bedrockApiKey,
            profile: options.profile
        };
        const providers = await credManager.loadProviders(credOptions);
        let hasValidCredentials = false;
        if (providers.openai || options.provider === 'openai') {
            const creds = await credManager.getCredentials('openai', credOptions);
            if (creds?.apiKey) {
                builder.withOpenAI(creds);
                hasValidCredentials = true;
            }
        }
        if (providers.anthropic || options.provider === 'anthropic') {
            const creds = await credManager.getCredentials('anthropic', credOptions);
            if (creds?.apiKey) {
                builder.withAnthropic(creds);
                hasValidCredentials = true;
            }
        }
        if (providers.azureOpenai || options.provider === 'azure-openai') {
            const creds = await credManager.getCredentials('azure-openai', credOptions);
            if (creds?.apiKey) {
                builder.withAzureOpenAI(creds);
                hasValidCredentials = true;
            }
        }
        if (providers.bedrock || options.provider === 'bedrock' || options.provider === 'anthropic-bedrock') {
            const creds = await credManager.getCredentials('bedrock', credOptions);
            if (creds?.accessKeyId || creds?.bearerToken) {
                builder.withBedrock(creds);
                hasValidCredentials = true;
            }
        }
        if (!hasValidCredentials) {
            throw new Error('No valid API credentials found. Please provide API keys via command line options, environment variables, or .env files.');
        }
        const shouldEnableTools = !options.disableTools;
        const enableReadOnlyTools = shouldEnableTools && (options.enableReadOnlyTools !== false);
        const enableCoreTools = options.enableCoreTools || options.tools;
        const enablePlanningMode = options.planningMode;
        if (enableCoreTools || enableReadOnlyTools || enablePlanningMode) {
            const toolRegistry = builder.getToolRegistry();
            if (toolRegistry) {
                const basicToolsConfig = {};
                if (enableCoreTools || enablePlanningMode) {
                    (0, majk_chat_basic_tools_1.registerBasicTools)(toolRegistry, basicToolsConfig);
                    (0, majk_chat_document_tools_1.registerDocumentTools)(toolRegistry);
                }
                else if (enableReadOnlyTools) {
                    (0, majk_chat_basic_tools_1.registerReadOnlyBasicTools)(toolRegistry, basicToolsConfig);
                    (0, majk_chat_document_tools_1.registerDocumentTools)(toolRegistry);
                }
                if (options.allowedTools || options.disallowedTools) {
                    this.applyToolFiltering(toolRegistry, options.allowedTools, options.disallowedTools);
                }
                let toolResultLimit = 2000;
                if (options.toolResultLimit && !isNaN(options.toolResultLimit) && options.toolResultLimit > 0) {
                    toolResultLimit = options.toolResultLimit;
                }
                builder.withContextManagement({
                    enableTruncation: true,
                    maxLength: toolResultLimit,
                    conversationId: options.sessionId || 'cli-session'
                });
                if (options.savePrompts) {
                    builder.withExtension(new majk_chat_core_1.PromptLoggingExtension({
                        filePath: options.savePrompts,
                        includeContext: true,
                        includeTools: true,
                        includeMessages: true,
                        append: true
                    }));
                }
                if (enablePlanningMode) {
                    builder.withPlanningMode({
                        enabled: true,
                        autoActivation: {
                            enabled: true,
                            complexityThreshold: 70
                        },
                        guidance: {
                            reminderInterval: options.todoReminderInterval || 3,
                            enableProgressTracking: !options.disableAutoReminders
                        },
                        session: {
                            conversationId: options.sessionId || 'cli-session'
                        }
                    });
                }
                const defaultSteps = enableReadOnlyTools && !enableCoreTools && !enablePlanningMode ? 500 : 5;
                builder.withAutoToolExecution(options.maxSteps || defaultSteps);
            }
        }
        let mcpPlugin = null;
        if (options.mcpConfig || options.mcpServers) {
            mcpPlugin = await this.setupMCP(builder, options);
            if (!options.tools) {
                builder.withAutoToolExecution(options.maxSteps || 5);
            }
        }
        if (options.onToolCall || options.onToolResult) {
            builder.withToolCallbacks(options.onToolCall, options.onToolResult);
        }
        const toolRegistry = builder.getToolRegistry();
        let dryRunManager = null;
        let dryRunSessionId = null;
        if (options.dryRun || options.dryRunReview) {
            dryRunManager = new majk_chat_basic_tools_1.DryRunManager(toolRegistry, {
                interactive: options.dryRunReview,
                showPreview: true,
                autoApprove: 'none'
            });
            dryRunSessionId = dryRunManager.startDryRun();
        }
        return {
            chat: builder.build(),
            toolRegistry,
            dryRunManager,
            dryRunSessionId,
            cleanup: async () => {
                if (mcpPlugin) {
                    try {
                        await mcpPlugin.shutdown();
                    }
                    catch (error) {
                    }
                }
                process.stdin.removeAllListeners();
                if (process.stdin.readable) {
                    process.stdin.destroy();
                }
            }
        };
    }
    applyToolFiltering(registry, allowedTools, disallowedTools) {
        if (!allowedTools && !disallowedTools)
            return;
        const definitions = registry.getDefinitions();
        for (const definition of definitions) {
            const toolName = definition.function?.name;
            if (toolName && !this.shouldIncludeTool(toolName, allowedTools, disallowedTools)) {
                if (registry.remove) {
                    registry.remove(toolName);
                }
            }
        }
    }
    shouldIncludeTool(toolName, allowedTools, disallowedTools) {
        const allowed = allowedTools?.split(/[,\s]+/).filter(t => t.length > 0) || [];
        const disallowed = disallowedTools?.split(/[,\s]+/).filter(t => t.length > 0) || [];
        if (disallowed.length > 0) {
            for (const pattern of disallowed) {
                if (this.matchesPattern(toolName, pattern)) {
                    return false;
                }
            }
        }
        if (allowed.length > 0) {
            for (const pattern of allowed) {
                if (this.matchesPattern(toolName, pattern)) {
                    return true;
                }
            }
            return false;
        }
        return true;
    }
    matchesPattern(toolName, pattern) {
        if (pattern.includes('*')) {
            const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$');
            return regex.test(toolName);
        }
        return toolName === pattern;
    }
    async setupMCP(builder, options) {
        const mcpOptions = {};
        if (options.mcpConfig) {
            const configValue = options.mcpConfig.trim();
            if (configValue.startsWith('{')) {
                mcpOptions.configString = configValue;
            }
            else {
                mcpOptions.configPath = configValue;
            }
        }
        if (options.mcpServers) {
            mcpOptions.configString = options.mcpServers;
        }
        if (options.allowedTools) {
            mcpOptions.allowedTools = options.allowedTools
                .split(/[,\s]+/)
                .map((t) => t.trim())
                .filter((t) => t.length > 0);
        }
        if (options.disallowedTools) {
            mcpOptions.disallowedTools = options.disallowedTools
                .split(/[,\s]+/)
                .map((t) => t.trim())
                .filter((t) => t.length > 0);
        }
        if (options.permissionPromptTool) {
            mcpOptions.permissionPromptTool = options.permissionPromptTool;
        }
        mcpOptions.quiet = options.outputFormat === 'stream-json';
        const mcpPlugin = new majk_chat_mcp_1.MCPPlugin(mcpOptions);
        const registry = builder.getToolRegistry();
        if (registry) {
            try {
                await mcpPlugin.initialize(registry);
            }
            catch (error) {
            }
        }
        return mcpPlugin;
    }
}
exports.MajkExecutor = MajkExecutor;
//# sourceMappingURL=majk.executor.js.map