"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.AIService = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const axios_1 = __importDefault(require("axios"));
const data_dir_1 = require("../utils/data-dir");
// 去除 ANSI 转义序列
function stripAnsi(text) {
    return text
        .replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '')
        .replace(/\x1B\].*?\x07/g, '')
        .replace(/\x1B\[[\?]?[0-9;]*[hlm]/g, '')
        .replace(/\r/g, '');
}
/**
 * AI Agent 服务 - 支持工具调用和自主操作终端
 */
class AIService {
    configDir;
    configPath;
    config;
    historyDir;
    chatHistories = new Map();
    agentStates = new Map();
    toolRegistry = new Map();
    sshService;
    skillService;
    MAX_HISTORY_AGE = 24 * 60 * 60 * 1000;
    MAX_MESSAGES = 50;
    MAX_AGENT_ITERATIONS = 15;
    // Agent 系统提示词
    AGENT_SYSTEM_PROMPT = `你是一个强大的 AI 终端 Agent，可以直接操作用户的终端 Shell。

你的能力：
1. 通过 execute_command 工具直接在终端执行命令
2. 通过 read_terminal 工具读取终端当前输出
3. 理解命令执行结果并据此做出决策
4. 自动完成多步骤任务
5. 生成脚本文件来执行复杂或长步骤的操作

工作原则：
1. **直接行动**：当用户要求执行操作时，直接使用工具执行，不要只是建议命令
2. **验证结果**：执行命令后，检查输出确认是否成功
3. **安全第一**：rm 命令会自动将文件移动到回收站（~/.aicmd/.trash/）而非永久删除，极端破坏性操作会被阻止。对于其他危险操作（格式化、覆写磁盘等），在 content 中先说明风险，让用户确认后再执行
4. **分步执行**：复杂任务分步完成，每步执行后检查结果
5. **错误处理**：如果命令失败，分析原因并尝试修复或使用替代方案

脚本策略（重要）：
当任务符合以下任一条件时，生成脚本文件而不是逐条执行命令：
- 步骤超过 3 个且步骤间有依赖关系
- 需要循环、条件判断、错误处理等逻辑
- 需要处理大量文件或批量操作
- 需要解析文本/日志/JSON 等复杂数据

脚本执行流程：
1. 先用 \`which python3 node bash\` 检测可用语言（Windows: \`where python node powershell\`）
2. 优先使用系统环境信息中已知的语言
3. 根据平台创建并执行脚本：

**Linux/macOS (Bash):**
\`\`\`
cat > /tmp/_ai_task.sh << 'SCRIPT_EOF'
#!/bin/bash
set -e
# 脚本内容...
SCRIPT_EOF
chmod +x /tmp/_ai_task.sh && bash /tmp/_ai_task.sh
\`\`\`

**Windows (PowerShell):**
\`\`\`powershell
Set-Content -Path $env:TEMP\_ai_task.ps1 -Value @'
# PowerShell 脚本内容...
'@
& $env:TEMP\_ai_task.ps1
\`\`\`

4. 执行脚本并检查结果
5. 清理临时文件

语言选择优先级：
- Shell/Bash (Linux/macOS)：系统管理、文件操作、进程管理
- PowerShell (Windows)：系统管理、文件操作、进程管理、WMI/CIM 查询
- Python：日志分析、数据处理、文本解析、复杂逻辑（跨平台）
- Node.js：JSON 处理、HTTP 请求、复杂数据转换（跨平台）

跨平台注意：
- 根据系统环境信息中的 OS 和 Shell 字段判断目标平台
- Linux: OS=Linux，使用 bash 命令
- macOS: OS=Darwin，没有 \`free\`/\`ss\`/\`systemctl\`，用 \`vm_stat\`/\`lsof\`/\`launchctl\` 替代
- Windows: Shell=PowerShell，使用 PowerShell cmdlet，临时文件用 \`$env:TEMP\`
- 写脚本时先判断平台再选择对应命令

回复格式（重要）：
- 使用 Markdown 格式
- 工具调用前只需一句话说明要做什么，不要解释命令细节
- 任务完成后用简短的结论说明结果，不要重复命令输出、不要列举执行步骤、不要加多余的解释
- 如果操作成功，直接说结果（如“已创建”“已停止”“发现3个错误”）
- 如果操作失败，说明原因和建议的修复方式
- 禁止废话，禁止套话，禁止总结已经显而易见的信息
- 使用中文回复`;
    constructor(sshService, skillService) {
        this.configDir = (0, data_dir_1.getDataDir)();
        this.configPath = (0, data_dir_1.getDataPath)('ai-config.json');
        this.historyDir = (0, data_dir_1.getDataPath)('ai-history');
        this.config = this.getDefaultConfig();
        this.sshService = sshService;
        this.skillService = skillService;
        this.loadConfig();
        // 确保历史目录存在
        try {
            if (!fs.existsSync(this.historyDir))
                fs.mkdirSync(this.historyDir, { recursive: true });
        }
        catch (_) { /* ignore */ }
        this.cleanupOldHistories();
        this.registerBuiltinTools();
    }
    getDefaultConfig() {
        return {
            enabled: true,
            apiKey: '',
            baseUrl: 'https://api.openai.com/v1',
            model: 'gpt-4o-mini',
            maxTokens: 4000,
            temperature: 0.3,
        };
    }
    loadConfig() {
        try {
            if (fs.existsSync(this.configPath)) {
                const data = fs.readFileSync(this.configPath, 'utf-8');
                const savedConfig = JSON.parse(data);
                this.config = { ...this.getDefaultConfig(), ...savedConfig };
            }
        }
        catch (error) {
            console.error('[AIService] Failed to load config:', error);
        }
    }
    saveConfig() {
        try {
            if (!fs.existsSync(this.configDir)) {
                fs.mkdirSync(this.configDir, { recursive: true });
            }
            fs.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2));
        }
        catch (error) {
            console.error('[AIService] Failed to save config:', error);
            throw error;
        }
    }
    cleanupOldHistories() {
        const now = Date.now();
        for (const [sessionId, history] of this.chatHistories) {
            if (now - history.lastActive > this.MAX_HISTORY_AGE) {
                this.chatHistories.delete(sessionId);
            }
        }
    }
    // ========== 配置管理 ==========
    getConfig() {
        const maskedConfig = { ...this.config };
        if (maskedConfig.apiKey) {
            const key = maskedConfig.apiKey;
            maskedConfig.apiKey = key.substring(0, 8) + '****' + key.substring(key.length - 4);
        }
        return maskedConfig;
    }
    getFullConfig() {
        return { ...this.config };
    }
    updateConfig(updates) {
        this.config = { ...this.config, ...updates };
        this.saveConfig();
        return this.getConfig();
    }
    async testConfig(config) {
        const testConfig = { ...this.config, ...config };
        if (!testConfig.apiKey) {
            return { success: false, message: 'API Key 未配置' };
        }
        try {
            const response = await axios_1.default.post(`${testConfig.baseUrl}/chat/completions`, {
                model: testConfig.model,
                messages: [{ role: 'user', content: 'Hello' }],
                max_tokens: 10,
            }, {
                headers: {
                    'Authorization': `Bearer ${testConfig.apiKey}`,
                    'Content-Type': 'application/json',
                },
                timeout: 30000,
            });
            if (response.data?.choices?.[0]?.message?.content) {
                return { success: true, message: '连接成功，模型可用' };
            }
            return { success: false, message: '响应格式异常' };
        }
        catch (error) {
            const message = error.response?.data?.error?.message || error.message || '连接失败';
            return { success: false, message };
        }
    }
    // ========== 工具注册表 ==========
    /**
     * 注册工具
     */
    registerTool(name, definition, executor) {
        this.toolRegistry.set(name, { definition, executor });
        console.log(`[AIService] Tool registered: ${name}`);
    }
    /**
     * 获取所有工具定义（OpenAI tools 格式）
     */
    getToolDefinitions() {
        return Array.from(this.toolRegistry.values()).map(t => t.definition);
    }
    /**
     * 注册内置工具
     */
    registerBuiltinTools() {
        // execute_command - 执行 shell 命令
        this.registerTool('execute_command', {
            type: 'function',
            function: {
                name: 'execute_command',
                description: '在当前终端 Shell 中执行命令并返回输出。支持任意 bash/zsh 命令。',
                parameters: {
                    type: 'object',
                    properties: {
                        command: {
                            type: 'string',
                            description: '要执行的 shell 命令',
                        },
                        timeout: {
                            type: 'number',
                            description: '等待输出的时间（毫秒），默认 2000，对于耗时命令可以设大一些',
                        },
                    },
                    required: ['command'],
                },
            },
        }, async (args, sessionId) => {
            return this.executeCommand(args.command, sessionId, args.timeout || 2000);
        });
        // read_terminal - 读取终端输出
        this.registerTool('read_terminal', {
            type: 'function',
            function: {
                name: 'read_terminal',
                description: '读取终端当前的输出内容（最近 50 行），用于了解终端当前状态。',
                parameters: {
                    type: 'object',
                    properties: {},
                },
            },
        }, async (_args, sessionId) => {
            return this.readTerminal(sessionId);
        });
    }
    // ========== 工具执行器 ==========
    /**
     * 检测会话是否为 Windows 环境
     */
    async isWindowsSession(sessionId) {
        if (!this.sshService)
            return false;
        try {
            const ctx = await this.sshService.getSystemContext(sessionId);
            return /OS:.*Windows|Shell:.*PowerShell|Shell:.*pwsh/i.test(ctx);
        }
        catch {
            return false;
        }
    }
    /**
     * 危险命令拦截：将 rm/Remove-Item 转换为移动到回收站，阻止极端破坏性操作
     */
    async sanitizeCommand(command, sessionId) {
        const trimmed = command.trim();
        const isWin = await this.isWindowsSession(sessionId);
        if (isWin) {
            return this.sanitizeWindowsCommand(trimmed);
        }
        return this.sanitizeUnixCommand(trimmed);
    }
    /**
     * Unix (Linux/macOS) 命令安全检查
     */
    sanitizeUnixCommand(trimmed) {
        // 绝对禁止的命令
        const blocked = [
            /^rm\s+(-[a-zA-Z]*\s+)*\/$/m,
            /^rm\s+(-[a-zA-Z]*\s+)*\/\s*$/m,
            /^rm\s+-[a-zA-Z]*r[a-zA-Z]*\s+\/\s*$/m,
            /mkfs\./,
            /^dd\s+.*of=\/dev\/[sh]d/m,
            /^:\(\)\s*\{\s*:\|:\s*&\s*\}\s*;\s*:/,
        ];
        for (const pattern of blocked) {
            if (pattern.test(trimmed)) {
                return { safe: false, reason: 'BLOCKED: 极度危险的破坏性操作，已阻止执行' };
            }
        }
        // rm 命令改写为移动到回收站
        const rmMatch = trimmed.match(/^(sudo\s+)?rm\s+((?:-[a-zA-Z]+\s+)*)(.+)$/s);
        if (rmMatch) {
            const sudo = rmMatch[1] || '';
            const targets = rmMatch[3].trim();
            const trashDir = '~/.aicmd/.trash';
            const ts = Date.now();
            const firstTarget = targets.split(/\s+/)[0];
            const rewritten = `${sudo}mkdir -p ${trashDir} && ${sudo}mv ${targets} ${trashDir}/_del_${ts}_$(basename ${firstTarget}) 2>/dev/null || ${sudo}mv ${targets} ${trashDir}/_del_${ts}`;
            return { safe: true, rewritten };
        }
        return { safe: true };
    }
    /**
     * Windows (PowerShell) 命令安全检查
     */
    sanitizeWindowsCommand(trimmed) {
        const lower = trimmed.toLowerCase();
        // 绝对禁止的操作
        const blocked = [
            /format\s+[a-z]:/i, // format C:
            /clear-disk/i, // Clear-Disk
            /remove-item\s+.*[a-z]:\\\s*$/i, // Remove-Item C:\
            /remove-item\s+.*-recurse.*[a-z]:\\\s*$/i, // Remove-Item -Recurse C:\
            /rd\s+\/s\s+[a-z]:\\\s*$/i, // rd /s C:\
        ];
        for (const pattern of blocked) {
            if (pattern.test(trimmed)) {
                return { safe: false, reason: 'BLOCKED: 极度危险的破坏性操作，已阻止执行' };
            }
        }
        // Remove-Item / del / rd 改写为移动到回收站
        const removePatterns = [
            /^(Remove-Item|ri|del|rd)\s+(.+)$/i,
        ];
        for (const pattern of removePatterns) {
            const match = trimmed.match(pattern);
            if (match) {
                const targets = match[2]
                    .replace(/-Recurse/gi, '')
                    .replace(/-Force/gi, '')
                    .replace(/-Confirm:\$false/gi, '')
                    .replace(/\/s/gi, '')
                    .replace(/\/q/gi, '')
                    .trim();
                const trashDir = '$env:USERPROFILE\\.aicmd\\.trash';
                const ts = Date.now();
                const rewritten = `New-Item -ItemType Directory -Force -Path "${trashDir}" | Out-Null; Move-Item -Path ${targets} -Destination "${trashDir}\\_del_${ts}" -Force`;
                return { safe: true, rewritten };
            }
        }
        return { safe: true };
    }
    /**
     * 执行命令并捕获输出
     */
    async executeCommand(command, sessionId, timeout) {
        if (!this.sshService) {
            return '错误: SSH 服务不可用';
        }
        const session = this.sshService.getSession(sessionId);
        if (!session) {
            return `错误: 会话 ${sessionId} 不存在`;
        }
        // 安全检查：拦截/改写危险命令
        const check = await this.sanitizeCommand(command, sessionId);
        if (!check.safe) {
            return check.reason;
        }
        const actualCommand = check.rewritten || command;
        if (check.rewritten) {
            console.log(`[AIService] Safety: rewrote "${command}" -> "${actualCommand}"`);
        }
        try {
            // 启动输出捕获
            const outputPromise = this.sshService.captureOutput(sessionId, timeout);
            // 写入命令
            this.sshService.writeData(sessionId, actualCommand + '\n');
            // 等待输出
            const output = await outputPromise;
            // 清理输出：去除命令回显和空白
            const lines = output.split('\n');
            // 尝试去掉第一行的命令回显
            if (lines.length > 0 && lines[0].trim().includes(actualCommand.trim().substring(0, 20))) {
                lines.shift();
            }
            const cleanOutput = lines.join('\n').trim();
            if (!cleanOutput) {
                return '(命令执行完成，无输出)';
            }
            // 限制输出长度，避免过长
            const maxLength = 5000;
            if (cleanOutput.length > maxLength) {
                return cleanOutput.substring(0, maxLength) + `\n... (输出被截断，共 ${cleanOutput.length} 字符)`;
            }
            return cleanOutput;
        }
        catch (error) {
            return `执行命令失败: ${error.message}`;
        }
    }
    /**
     * 读取终端当前输出
     */
    async readTerminal(sessionId) {
        if (!this.sshService) {
            return '错误: SSH 服务不可用';
        }
        try {
            // 短暂捕获以获取当前缓冲区内容
            const output = await this.sshService.captureOutput(sessionId, 500);
            if (!output.trim()) {
                return '(终端当前无输出)';
            }
            const lines = output.split('\n').filter(l => l.trim());
            // 返回最后 50 行
            const last50 = lines.slice(-50);
            return last50.join('\n');
        }
        catch (error) {
            return `读取终端失败: ${error.message}`;
        }
    }
    // ========== 对话历史 ==========
    getOrCreateHistory(sessionId) {
        let history = this.chatHistories.get(sessionId);
        if (!history) {
            history = { sessionId, messages: [], lastActive: Date.now() };
            this.chatHistories.set(sessionId, history);
        }
        history.lastActive = Date.now();
        return history;
    }
    addMessage(history, message) {
        history.messages.push(message);
        while (history.messages.length > this.MAX_MESSAGES) {
            history.messages.shift();
        }
    }
    clearHistory(sessionId) {
        this.chatHistories.delete(sessionId);
        this.deleteDisplayHistoryFile(sessionId);
    }
    getHistory(sessionId) {
        const history = this.chatHistories.get(sessionId);
        return history ? [...history.messages] : null;
    }
    // ========== 对话历史持久化 ==========
    /**
     * 保存前端显示消息到文件（含元数据）
     */
    saveDisplayHistory(sessionId, displayMessages, sessionName) {
        try {
            const filePath = path.join(this.historyDir, `${sessionId}.json`);
            const firstUser = displayMessages.find(m => m.role === 'user');
            const preview = firstUser ? (firstUser.content || '').substring(0, 80) : '';
            const fileData = {
                meta: {
                    sessionId,
                    sessionName: sessionName || '',
                    savedAt: Date.now(),
                    messageCount: displayMessages.length,
                    preview,
                },
                messages: displayMessages,
            };
            fs.writeFileSync(filePath, JSON.stringify(fileData, null, 2), 'utf-8');
        }
        catch (error) {
            console.error('[AIService] Failed to save display history:', error);
        }
    }
    /**
     * 加载前端显示消息（兼容新旧格式）
     */
    loadDisplayHistory(sessionId) {
        try {
            const filePath = path.join(this.historyDir, `${sessionId}.json`);
            if (!fs.existsSync(filePath))
                return null;
            const raw = fs.readFileSync(filePath, 'utf-8');
            const data = JSON.parse(raw);
            if (data && Array.isArray(data.messages)) {
                return data.messages;
            }
            if (Array.isArray(data))
                return data;
            return null;
        }
        catch (error) {
            console.error('[AIService] Failed to load display history:', error);
            return null;
        }
    }
    /**
     * 列出所有历史对话（仅元数据）
     */
    listDisplayHistories() {
        const results = [];
        try {
            if (!fs.existsSync(this.historyDir))
                return results;
            const files = fs.readdirSync(this.historyDir).filter(f => f.endsWith('.json'));
            for (const file of files) {
                try {
                    const filePath = path.join(this.historyDir, file);
                    const raw = fs.readFileSync(filePath, 'utf-8');
                    const data = JSON.parse(raw);
                    if (data?.meta) {
                        results.push(data.meta);
                    }
                    else if (Array.isArray(data)) {
                        // 兼容旧格式（纯数组）
                        const sessionId = path.basename(file, '.json');
                        const firstUser = data.find((m) => m.role === 'user');
                        results.push({
                            sessionId,
                            sessionName: '',
                            savedAt: fs.statSync(filePath).mtimeMs,
                            messageCount: data.length,
                            preview: firstUser ? (firstUser.content || '').substring(0, 80) : '',
                        });
                    }
                }
                catch (_) { /* 跳过损坏的文件 */ }
            }
        }
        catch (error) {
            console.error('[AIService] Failed to list histories:', error);
        }
        // 按保存时间倒序
        results.sort((a, b) => b.savedAt - a.savedAt);
        return results;
    }
    /**
     * 删除持久化的对话历史
     */
    deleteDisplayHistoryFile(sessionId) {
        try {
            const filePath = path.join(this.historyDir, `${sessionId}.json`);
            if (fs.existsSync(filePath)) {
                fs.unlinkSync(filePath);
            }
        }
        catch (error) {
            console.error('[AIService] Failed to delete display history:', error);
        }
    }
    // ========== 系统环境上下文 ==========
    /**
     * 获取会话的系统上下文（从 sshService 的 session 元数据获取）
     * 保证每次对话都带上系统环境信息
     */
    async getSessionContext(sessionId) {
        if (!this.sshService)
            return '';
        try {
            return await this.sshService.getSystemContext(sessionId);
        }
        catch (error) {
            console.warn('[AIService] Failed to get system context:', error);
            return '';
        }
    }
    // ========== Agent 核心循环 ==========
    /**
     * 运行 Agent
     * Agent 循环：调用 LLM → 处理 tool_calls → 执行工具 → 反馈结果 → 重复直到完成
     */
    async agentRun(sessionId, userMessage, context, eventCallback, skillId) {
        if (!this.config.apiKey) {
            eventCallback({ type: 'error', error: 'AI 未配置 API Key，请在设置中填写' });
            return;
        }
        // 检查是否有正在运行的 agent
        const existingState = this.agentStates.get(sessionId);
        if (existingState?.running) {
            eventCallback({ type: 'error', error: 'Agent 正在运行中，请先等待完成或停止' });
            return;
        }
        // 设置运行状态
        const state = { running: true, aborted: false };
        this.agentStates.set(sessionId, state);
        const history = this.getOrCreateHistory(sessionId);
        const tools = this.getToolDefinitions();
        // 构建系统提示词
        let systemPrompt = this.AGENT_SYSTEM_PROMPT;
        // 自动注入系统环境上下文（首次对话自动采集）
        const sysContext = await this.getSessionContext(sessionId);
        if (sysContext && sysContext !== '无法采集系统信息') {
            systemPrompt += `\n\n${sysContext}`;
        }
        // 如果有 Skill，追加 Skill 指令
        if (skillId && this.skillService) {
            const skill = this.skillService.getSkill(skillId);
            if (skill) {
                systemPrompt += `\n\n## 当前任务指令（Skill: ${skill.name}）\n\n${skill.content}`;
            }
        }
        // 构建消息列表
        const messages = [
            { role: 'system', content: systemPrompt },
        ];
        // 添加终端上下文
        if (context) {
            messages.push({
                role: 'system',
                content: `当前终端最近的输出内容：\n\`\`\`\n${context}\n\`\`\``,
            });
        }
        // 添加历史消息
        messages.push(...history.messages);
        // 添加用户消息
        const userMsg = { role: 'user', content: userMessage };
        this.addMessage(history, userMsg);
        messages.push(userMsg);
        try {
            for (let iteration = 0; iteration < this.MAX_AGENT_ITERATIONS; iteration++) {
                // 检查是否被中断
                if (state.aborted) {
                    eventCallback({ type: 'done', content: '(Agent 已被用户中断)' });
                    break;
                }
                eventCallback({ type: 'thinking' });
                // 调用 LLM
                let response;
                try {
                    response = await this.callLLM(messages, tools);
                }
                catch (error) {
                    eventCallback({ type: 'error', error: `LLM 调用失败: ${error.message}` });
                    break;
                }
                const assistantMessage = response.choices?.[0]?.message;
                if (!assistantMessage) {
                    eventCallback({ type: 'error', error: 'LLM 响应为空' });
                    break;
                }
                // 添加 assistant 消息到历史
                const assistantMsg = {
                    role: 'assistant',
                    content: assistantMessage.content,
                };
                if (assistantMessage.tool_calls?.length) {
                    assistantMsg.tool_calls = assistantMessage.tool_calls;
                }
                this.addMessage(history, assistantMsg);
                messages.push(assistantMsg);
                // 如果有文本内容，推送给用户
                if (assistantMessage.content) {
                    eventCallback({ type: 'message', content: assistantMessage.content });
                }
                // 如果没有 tool_calls，Agent 完成
                if (!assistantMessage.tool_calls || assistantMessage.tool_calls.length === 0) {
                    eventCallback({ type: 'done' });
                    break;
                }
                // 处理 tool_calls
                for (const toolCall of assistantMessage.tool_calls) {
                    if (state.aborted)
                        break;
                    const toolName = toolCall.function.name;
                    let toolArgs = {};
                    try {
                        toolArgs = JSON.parse(toolCall.function.arguments || '{}');
                    }
                    catch {
                        toolArgs = {};
                    }
                    // 推送工具调用事件
                    eventCallback({ type: 'tool_call', tool: toolName, args: toolArgs });
                    // 执行工具
                    const tool = this.toolRegistry.get(toolName);
                    let result;
                    if (!tool) {
                        result = `错误: 未知工具 "${toolName}"`;
                    }
                    else {
                        try {
                            result = await tool.executor(toolArgs, sessionId);
                        }
                        catch (error) {
                            result = `工具执行失败: ${error.message}`;
                        }
                    }
                    // 推送工具结果事件
                    eventCallback({ type: 'tool_result', tool: toolName, result });
                    // 添加工具结果到消息列表
                    const toolMsg = {
                        role: 'tool',
                        content: result,
                        tool_call_id: toolCall.id,
                    };
                    messages.push(toolMsg);
                    this.addMessage(history, toolMsg);
                }
                // 如果是最后一次迭代且仍有 tool_calls，发送完成
                if (iteration === this.MAX_AGENT_ITERATIONS - 1) {
                    eventCallback({ type: 'done', content: '已达到最大执行次数限制' });
                }
            }
        }
        catch (error) {
            eventCallback({ type: 'error', error: error.message || 'Agent 运行异常' });
        }
        finally {
            state.running = false;
            this.agentStates.delete(sessionId);
        }
    }
    /**
     * 停止 Agent
     */
    stopAgent(sessionId) {
        const state = this.agentStates.get(sessionId);
        if (state?.running) {
            state.aborted = true;
            return true;
        }
        return false;
    }
    /**
     * 调用 OpenAI API（非流式，用于 Agent 循环）
     */
    async callLLM(messages, tools) {
        const requestBody = {
            model: this.config.model,
            messages,
            max_tokens: this.config.maxTokens || 4000,
            temperature: this.config.temperature || 0.3,
        };
        // 只有注册了工具才传 tools 参数
        if (tools.length > 0) {
            requestBody.tools = tools;
            requestBody.tool_choice = 'auto';
        }
        const response = await axios_1.default.post(`${this.config.baseUrl}/chat/completions`, requestBody, {
            headers: {
                'Authorization': `Bearer ${this.config.apiKey}`,
                'Content-Type': 'application/json',
            },
            timeout: 120000, // Agent 需要更长的超时
        });
        return response.data;
    }
    // ========== 旧版兼容（非 Agent 模式的简单对话） ==========
    async chat(sessionId, userMessage, context) {
        if (!this.config.apiKey) {
            throw new Error('AI 未配置 API Key，请在设置中填写');
        }
        const history = this.getOrCreateHistory(sessionId);
        const messages = [
            { role: 'system', content: this.AGENT_SYSTEM_PROMPT },
        ];
        if (context) {
            messages.push({
                role: 'system',
                content: `当前终端最近的输出内容：\n\`\`\`\n${context}\n\`\`\``,
            });
        }
        messages.push(...history.messages);
        this.addMessage(history, { role: 'user', content: userMessage });
        messages.push({ role: 'user', content: userMessage });
        try {
            const response = await axios_1.default.post(`${this.config.baseUrl}/chat/completions`, {
                model: this.config.model,
                messages,
                max_tokens: this.config.maxTokens || 4000,
                temperature: this.config.temperature || 0.3,
            }, {
                headers: {
                    'Authorization': `Bearer ${this.config.apiKey}`,
                    'Content-Type': 'application/json',
                },
                timeout: 60000,
            });
            const assistantMessage = response.data?.choices?.[0]?.message?.content;
            if (assistantMessage) {
                this.addMessage(history, { role: 'assistant', content: assistantMessage });
                return assistantMessage;
            }
            throw new Error('AI 响应为空');
        }
        catch (error) {
            history.messages.pop();
            const message = error.response?.data?.error?.message || error.message || 'AI 请求失败';
            throw new Error(message);
        }
    }
    async *chatStream(sessionId, userMessage, context) {
        if (!this.config.apiKey) {
            throw new Error('AI 未配置 API Key，请在设置中填写');
        }
        const history = this.getOrCreateHistory(sessionId);
        const messages = [
            { role: 'system', content: this.AGENT_SYSTEM_PROMPT },
        ];
        if (context) {
            messages.push({
                role: 'system',
                content: `当前终端最近的输出内容：\n\`\`\`\n${context}\n\`\`\``,
            });
        }
        messages.push(...history.messages);
        this.addMessage(history, { role: 'user', content: userMessage });
        messages.push({ role: 'user', content: userMessage });
        let fullResponse = '';
        try {
            const response = await axios_1.default.post(`${this.config.baseUrl}/chat/completions`, {
                model: this.config.model,
                messages,
                max_tokens: this.config.maxTokens || 4000,
                temperature: this.config.temperature || 0.3,
                stream: true,
            }, {
                headers: {
                    'Authorization': `Bearer ${this.config.apiKey}`,
                    'Content-Type': 'application/json',
                },
                responseType: 'stream',
                timeout: 60000,
            });
            for await (const chunk of response.data) {
                const lines = chunk.toString().split('\n');
                for (const line of lines) {
                    if (line.startsWith('data: ')) {
                        const data = line.slice(6).trim();
                        if (data === '[DONE]')
                            break;
                        try {
                            const parsed = JSON.parse(data);
                            const content = parsed.choices?.[0]?.delta?.content;
                            if (content) {
                                fullResponse += content;
                                yield content;
                            }
                        }
                        catch { /* ignore */ }
                    }
                }
            }
            if (fullResponse) {
                this.addMessage(history, { role: 'assistant', content: fullResponse });
            }
        }
        catch (error) {
            history.messages.pop();
            const message = error.response?.data?.error?.message || error.message || 'AI 请求失败';
            throw new Error(message);
        }
    }
}
exports.AIService = AIService;
//# sourceMappingURL=ai.service.js.map