// @ts-nocheck
import { io as createSocketClient } from 'socket.io-client';
import { renderLatexInRealtime } from './useMarkdownRenderer';

export async function initializeLegacySocket(ctx: any) {
    try {
        const SOCKET_DEBUG_LOGS_ENABLED = true;
        const socketLog = (...args: any[]) => {
            if (!SOCKET_DEBUG_LOGS_ENABLED) {
                return;
            }
            console.log(...args);
        };

        socketLog('初始化WebSocket连接...');

        const socketOptions = {
            transports: ['websocket', 'polling'],
            autoConnect: false
        };

        ctx.socket = createSocketClient('/', socketOptions);

        // 可开关的逐字打印功能，默认关闭
        const STREAMING_ENABLED = false;
        const STREAMING_CHAR_DELAY = 22;
        const STREAMING_FINALIZE_DELAY = 1000;
        const STREAMING_DEBUG = false;
        const STREAMING_DEBUG_HISTORY_LIMIT = 2000;
        const streamingState = {
            buffer: [] as string[],
            timer: null as number | null,
            completionTimer: null as number | null,
            apiCompleted: false,
            pendingCompleteContent: '' as string,
            renderedText: '' as string,
            activeMessageIndex: null as number | null,
            activeTextAction: null as any,
            ignoreThinking: false
        };

        const pendingToolEvents: Array<{ event: string; data: any; handler: () => void }> = [];

        const startIntentTyping = (action: any, intentText: any) => {
            if (!action || !action.tool) {
                return;
            }
            if (typeof intentText !== 'string') {
                return;
            }
            const text = intentText.trim();
            if (!text) {
                return;
            }
            if (action.tool.intent_full === text) {
                if (console && console.debug) {
                    console.debug('[tool_intent] skip (same text)', {
                        id: action?.id || action?.tool?.id,
                        name: action?.tool?.name,
                        text
                    });
                }
                return;
            }
            if (typeof console !== 'undefined' && console.debug) {
                console.debug('[tool_intent] typing start', {
                    id: action?.id || action?.tool?.id,
                    name: action?.tool?.name,
                    text
                });
            }
            if (action.tool.intent_full === text && action.tool.intent_rendered === text) {
                return;
            }
            // 清理旧定时器
            if (action.tool.intent_typing_timer) {
                clearInterval(action.tool.intent_typing_timer);
                action.tool.intent_typing_timer = null;
            }
            action.tool.intent_full = text;
            action.tool.intent_rendered = '';
            const duration = 1000;
            const step = Math.max(10, Math.floor(duration / Math.max(1, text.length)));
            let index = 0;
            action.tool.intent_typing_timer = window.setInterval(() => {
                action.tool.intent_rendered = text.slice(0, index + 1);
                if (index === 0 && console && console.debug) {
                    console.debug('[tool_intent] typing tick', {
                        id: action?.id || action?.tool?.id,
                        name: action?.tool?.name,
                        next: action.tool.intent_rendered
                    });
                }
                index += 1;
                if (index >= text.length) {
                    clearInterval(action.tool.intent_typing_timer);
                    action.tool.intent_typing_timer = null;
                    action.tool.intent_rendered = text;
                    if (console && console.debug) {
                        console.debug('[tool_intent] typing done', {
                            id: action?.id || action?.tool?.id,
                            name: action?.tool?.name,
                            full: text
                        });
                    }
                }
                if (typeof ctx?.$forceUpdate === 'function') {
                    ctx.$forceUpdate();
                }
            }, step);
        };

        const hasPendingStreamingText = () =>
            STREAMING_ENABLED &&
            ( !!streamingState.buffer.length ||
              !!streamingState.pendingCompleteContent ||
              streamingState.timer !== null ||
              streamingState.completionTimer !== null);

        const resetPendingToolEvents = () => {
            pendingToolEvents.length = 0;
        };

        const flushPendingToolEvents = () => {
            if (!pendingToolEvents.length) {
                return;
            }
            const queue = pendingToolEvents.splice(0);
            queue.forEach((item) => {
                try {
                    item.handler();
                } catch (error) {
                    console.warn('延后工具事件处理失败:', item.event, error);
                }
            });
        };

        const snapshotStreamingState = () => ({
            bufferLength: streamingState.buffer.length,
            timerActive: streamingState.timer !== null,
            completionTimerActive: streamingState.completionTimer !== null,
            apiCompleted: streamingState.apiCompleted,
            pendingLength: (streamingState.pendingCompleteContent || '').length,
            renderedLength: streamingState.renderedText.length,
            currentMessageIndex:
                typeof ctx?.currentMessageIndex === 'number' ? ctx.currentMessageIndex : null,
            messagesLength: Array.isArray(ctx?.messages) ? ctx.messages.length : null,
            streamingMessage: !!ctx?.streamingMessage
        });

        const streamingDebugHistory: Array<any> = [];

        const sanitizeBubbleText = (text: unknown) => {
            if (typeof text !== 'string') {
                return '';
            }
            return text.replace(/\r/g, '');
        };

        const getActiveMessage = () => {
            if (streamingState.activeMessageIndex === null) {
                return null;
            }
            const messages = ctx?.messages;
            if (!Array.isArray(messages)) {
                return null;
            }
            return messages[streamingState.activeMessageIndex] || null;
        };

        const ensureActiveMessageBinding = () => {
            if (
                streamingState.activeMessageIndex === null &&
                typeof ctx?.currentMessageIndex === 'number' &&
                ctx.currentMessageIndex >= 0
            ) {
                streamingState.activeMessageIndex = ctx.currentMessageIndex;
            }
            if (
                typeof ctx?.currentMessageIndex !== 'number' ||
                ctx.currentMessageIndex < 0
            ) {
                if (streamingState.activeMessageIndex !== null) {
                    ctx.currentMessageIndex = streamingState.activeMessageIndex;
                }
            }
            if (!ctx.streamingMessage) {
                ctx.streamingMessage = true;
            }
            const msg = getActiveMessage();
            if (!msg && Array.isArray(ctx?.messages) && ctx.messages.length) {
                streamingState.activeMessageIndex = ctx.messages.length - 1;
            }
            return getActiveMessage();
        };

        const ensureActiveTextAction = () => {
            const msg = getActiveMessage();
            if (!msg || !Array.isArray(msg.actions) || !msg.actions.length) {
                return null;
            }
            const known = streamingState.activeTextAction;
            if (known && msg.actions.includes(known)) {
                return known;
            }
            for (let i = msg.actions.length - 1; i >= 0; i--) {
                const action = msg.actions[i];
                if (action && action.type === 'text') {
                    streamingState.activeTextAction = action;
                    return action;
                }
            }
            return null;
        };

        const fallbackAppendToActiveMessage = (text: string) => {
            const msg = ensureActiveMessageBinding();
            if (!msg) {
                return null;
            }
            if (typeof msg.streamingText !== 'string') {
                msg.streamingText = '';
            }
            msg.streamingText += text;
            const action = ensureActiveTextAction();
            if (!action) {
                return null;
            }
            if (typeof action.content !== 'string') {
                action.content = '';
            }
            action.content += text;
            action.streaming = action.streaming !== false;
            streamingState.activeTextAction = action;
            ctx.$forceUpdate();
            ctx.conditionalScrollToBottom();
            renderLatexInRealtime();
            return action;
        };

        const completeActiveTextAction = (fullContent: string) => {
            const msg = ensureActiveMessageBinding();
            if (!msg) {
                return false;
            }
            const action = ensureActiveTextAction();
            if (action) {
                action.streaming = false;
                const fallback =
                    (typeof fullContent === 'string' && fullContent.length
                        ? fullContent
                        : action.content) || '';
                action.content = fallback;
            }
            msg.streamingText = '';
            msg.currentStreamingType = null;
            return !!action;
        };

        const logStreamingDebug = (event: string, detail?: any) => {
            if (!STREAMING_DEBUG) {
                return;
            }
            const payload = typeof detail === 'undefined' ? snapshotStreamingState() : detail;
            const entry = {
                event,
                detail: payload,
                conversationId: ctx.currentConversationId || null,
                timestamp: Date.now()
            };
            streamingDebugHistory.push(entry);
            if (streamingDebugHistory.length > STREAMING_DEBUG_HISTORY_LIMIT) {
                streamingDebugHistory.shift();
            }
            try {
                window.__streamingDebugLogs = streamingDebugHistory.slice();
            } catch (error) {
                // ignore
            }
            console.log('[streaming-debug]', event, payload);
            try {
                if (ctx.socket && typeof ctx.socket.emit === 'function') {
                    ctx.socket.emit('client_stream_debug_log', entry);
                }
            } catch (error) {
                console.warn('上报 streaming debug 日志失败:', error);
            }
        };

        const markStreamingIdleIfPossible = (source: string) => {
            try {
                if (!ctx) {
                    return;
                }
                if (typeof ctx.maybeResetStreamingState === 'function') {
                    const reset = ctx.maybeResetStreamingState(source);
                    if (reset) {
                        logStreamingDebug('streaming_idle_reset', { source });
                    }
                    return;
                }
                if (!ctx.streamingMessage) {
                    return;
                }
                const hasPending =
                    typeof ctx.hasPendingToolActions === 'function'
                        ? ctx.hasPendingToolActions()
                        : false;
                if (!hasPending) {
                    ctx.streamingMessage = false;
                    ctx.stopRequested = false;
                    logStreamingDebug('streaming_idle_reset:fallback', { source });
                }
            } catch (error) {
                console.warn('自动结束流式状态失败:', error);
            }
        };

        const stopStreamingTimer = () => {
            if (streamingState.timer !== null) {
                clearTimeout(streamingState.timer);
                streamingState.timer = null;
                logStreamingDebug('stopStreamingTimer', snapshotStreamingState());
            }
        };

        const stopCompletionTimer = () => {
            if (streamingState.completionTimer !== null) {
                clearTimeout(streamingState.completionTimer);
                streamingState.completionTimer = null;
                logStreamingDebug('stopCompletionTimer', snapshotStreamingState());
            }
        };

        const finalizeStreamingText = (options?: { force?: boolean; allowIncomplete?: boolean }) => {
            const forceFlush = !!options?.force;
            const allowIncomplete = !!options?.allowIncomplete;
            logStreamingDebug('finalizeStreamingText:start', { forceFlush, allowIncomplete, snapshot: snapshotStreamingState() });
            if (!forceFlush) {
                if (streamingState.buffer.length) {
                    logStreamingDebug('finalizeStreamingText:blocked-buffer', snapshotStreamingState());
                    return false;
                }
                if (!allowIncomplete && !streamingState.apiCompleted) {
                    logStreamingDebug('finalizeStreamingText:blocked-api-incomplete', snapshotStreamingState());
                    return false;
                }
            }
            stopStreamingTimer();
            stopCompletionTimer();
            if (forceFlush && streamingState.buffer.length) {
                const remainder = streamingState.buffer.join('');
                streamingState.buffer.length = 0;
                if (remainder) {
                    applyTextChunk(remainder);
                    logStreamingDebug('finalizeStreamingText:force-flush-buffer', { flushedChars: remainder.length });
                }
            }
            const pendingText = streamingState.pendingCompleteContent || '';
            const renderedText = streamingState.renderedText || '';
            let finalText = pendingText || renderedText || '';
            let remainderToAppend = '';
            if (!pendingText) {
                finalText = renderedText;
            } else if (!renderedText) {
                finalText = pendingText;
                remainderToAppend = pendingText;
            } else if (pendingText.length < renderedText.length) {
                // 后端返回的最终内容比已渲染的还短，避免覆盖已展示的字符
                finalText = renderedText;
            } else if (pendingText.startsWith(renderedText)) {
                finalText = pendingText;
                remainderToAppend = pendingText.slice(renderedText.length);
            } else {
                finalText = pendingText;
            }
            logStreamingDebug('finalizeStreamingText:resolved-final-text', {
                pendingLength: pendingText.length,
                renderedLength: renderedText.length,
                remainderToAppendLength: remainderToAppend.length,
                finalLength: finalText.length
            });
            if (remainderToAppend) {
                applyTextChunk(remainderToAppend);
            }
            streamingState.pendingCompleteContent = '';
            streamingState.apiCompleted = false;
            streamingState.renderedText = '';
            ctx.chatCompleteTextAction(finalText || '');
            completeActiveTextAction(finalText || '');
            ctx.$forceUpdate();
            // 注意：不在这里重置 streamingMessage，因为可能还有工具调用在进行
            // streamingMessage 只在 task_complete 事件时重置
            logStreamingDebug('finalizeStreamingText:complete', snapshotStreamingState());
            streamingState.activeMessageIndex = null;
            streamingState.activeTextAction = null;
            markStreamingIdleIfPossible('finalizeStreamingText');
            flushPendingToolEvents();
            return true;
        };

        const scheduleFinalizationAfterDrain = () => {
            if (streamingState.buffer.length) {
                logStreamingDebug('scheduleFinalizationAfterDrain:buffer-not-empty', snapshotStreamingState());
                return;
            }
            if (streamingState.completionTimer !== null) {
                logStreamingDebug('scheduleFinalizationAfterDrain:already-scheduled', snapshotStreamingState());
                return;
            }
            logStreamingDebug('scheduleFinalizationAfterDrain:scheduled', snapshotStreamingState());
            streamingState.completionTimer = window.setTimeout(() => {
                streamingState.completionTimer = null;
                logStreamingDebug('scheduleFinalizationAfterDrain:timer-fired', snapshotStreamingState());
                finalizeStreamingText({ allowIncomplete: true });
            }, STREAMING_FINALIZE_DELAY);
        };

        const resetStreamingBuffer = () => {
            stopStreamingTimer();
            stopCompletionTimer();
            streamingState.buffer.length = 0;
            streamingState.apiCompleted = false;
            streamingState.pendingCompleteContent = '';
            streamingState.renderedText = '';
            streamingState.activeMessageIndex = null;
            streamingState.activeTextAction = null;
            resetPendingToolEvents();
            logStreamingDebug('resetStreamingBuffer', snapshotStreamingState());
        };

        const applyTextChunk = (text: string) => {
            if (!text) {
                return null;
            }
            ensureActiveMessageBinding();
            let action = ctx.chatAppendTextChunk(text);
            if (action) {
                ctx.$forceUpdate();
                ctx.conditionalScrollToBottom();
                renderLatexInRealtime();
            } else {
                action = fallbackAppendToActiveMessage(text);
            }
            streamingState.renderedText += text;
            const appended = !!action;
            logStreamingDebug('applyTextChunk', {
                chunkLength: text.length,
                appended,
                snapshot: snapshotStreamingState()
            });
            if (!appended) {
                logStreamingDebug('applyTextChunk:missing-target', {
                    chunkLength: text.length,
                    currentMessageIndex:
                        typeof ctx?.currentMessageIndex === 'number' ? ctx.currentMessageIndex : null,
                    messagesLength: Array.isArray(ctx?.messages) ? ctx.messages.length : null
                });
            }
            return action;
        };

        const drainStreamingBufferImmediately = () => {
            if (!streamingState.buffer.length) {
                return;
            }
            const chunk = streamingState.buffer.join('');
            streamingState.buffer.length = 0;
            applyTextChunk(chunk);
        };

        const scheduleStreamingFlush = () => {
            const shouldFlushImmediately = typeof document !== 'undefined' && document.hidden === true;
            if (shouldFlushImmediately) {
                stopStreamingTimer();
                drainStreamingBufferImmediately();
                if (streamingState.apiCompleted) {
                    finalizeStreamingText({ force: true });
                } else {
                    scheduleFinalizationAfterDrain();
                }
                return;
            }
            if (streamingState.timer !== null) {
                logStreamingDebug('scheduleStreamingFlush:timer-exists', snapshotStreamingState());
                return;
            }
            if (!streamingState.buffer.length) {
                logStreamingDebug('scheduleStreamingFlush:no-buffer', snapshotStreamingState());
                return;
            }
            logStreamingDebug('scheduleStreamingFlush:start', snapshotStreamingState());
            const process = () => {
                streamingState.timer = null;
                logStreamingDebug('scheduleStreamingFlush:tick', snapshotStreamingState());
                if (!streamingState.buffer.length) {
                    logStreamingDebug('scheduleStreamingFlush:buffer-empty', snapshotStreamingState());
                    return;
                }
                const piece = streamingState.buffer.shift();
                if (piece) {
                    applyTextChunk(piece);
                }
                if (streamingState.buffer.length) {
                    scheduleStreamingFlush();
                } else {
                    logStreamingDebug('scheduleStreamingFlush:buffer-drained', snapshotStreamingState());
                    scheduleFinalizationAfterDrain();
                }
            };
            streamingState.timer = window.setTimeout(process, STREAMING_CHAR_DELAY);
        };

        const enqueueStreamingContent = (text: string) => {
            if (!text) {
                return;
            }
            stopCompletionTimer();
            if (!STREAMING_ENABLED) {
                // 关闭逐字模式：整块入缓冲并立即刷新，保持与 chunk 顺序一致
                streamingState.pendingCompleteContent = '';
                streamingState.buffer.length = 0;
                streamingState.apiCompleted = false;
                applyTextChunk(text);
                return;
            }
            logStreamingDebug('enqueueStreamingContent', { incomingLength: text.length });
            for (const ch of Array.from(text)) {
                streamingState.buffer.push(ch);
            }
            logStreamingDebug('enqueueStreamingContent:buffered', snapshotStreamingState());
            scheduleStreamingFlush();
        };


        const scheduleHistoryReload = (delay = 0, options: { force?: boolean } = {}) => {
            const { force = false } = options;
            if (!ctx || typeof ctx.fetchAndDisplayHistory !== 'function') {
                return;
            }
            setTimeout(() => {
                const targetConversationId = ctx.currentConversationId;
                if (!targetConversationId || targetConversationId.startsWith('temp_')) {
                    return;
                }
                try {
                    if (!force) {
                        const loadingSame =
                            !!ctx.historyLoading && ctx.historyLoadingFor === targetConversationId;
                        const historyReady =
                            ctx.lastHistoryLoadedConversationId === targetConversationId &&
                            Array.isArray(ctx.messages) &&
                            ctx.messages.length > 0;
                        if (loadingSame || historyReady) {
                            socketLog('跳过重复历史加载(scheduleHistoryReload)');
                            return;
                        }
                    }
                    ctx.fetchAndDisplayHistory({ force });
                    if (typeof ctx.fetchConversationTokenStatistics === 'function') {
                        ctx.fetchConversationTokenStatistics();
                    }
                    if (typeof ctx.updateCurrentContextTokens === 'function') {
                        ctx.updateCurrentContextTokens();
                    }
                } catch (error) {
                    console.warn('重新加载对话历史失败:', error);
                }
            }, delay);
        };

        const assignSocketToken = async () => {
            if (typeof window.requestSocketToken !== 'function') {
                console.warn('缺少 requestSocketToken()，无法获取实时连接凭证');
                return false;
            }
            try {
                const freshToken = await window.requestSocketToken();
                ctx.socket.auth = { socket_token: freshToken };
                return true;
            } catch (error) {
                console.error('获取 WebSocket token 失败:', error);
                return false;
            }
        };

        if (ctx.socket.io && typeof ctx.socket.io.on === 'function') {
            ctx.socket.io.on('reconnect_attempt', async () => {
                await assignSocketToken();
            });
        }

        let hasConnectedOnce = false;

        // 连接事件
        ctx.socket.on('connect', () => {
            const isReconnect = hasConnectedOnce;
            const historyLoadingSame =
                !!ctx.historyLoading && ctx.historyLoadingFor === ctx.currentConversationId;
            const historyReady =
                ctx.lastHistoryLoadedConversationId === ctx.currentConversationId &&
                Array.isArray(ctx.messages) &&
                ctx.messages.length > 0;

            ctx.isConnected = true;
            socketLog('WebSocket已连接');

            // 首次连接且历史已在加载/已就绪时，避免重复清空与重复动画
            if (!isReconnect && (historyLoadingSame || historyReady)) {
                socketLog('初次连接已存在历史，跳过重复重置与加载');
                hasConnectedOnce = true;
                return;
            }

            hasConnectedOnce = true;
            ctx.resetAllStates(isReconnect ? 'socket:reconnect' : 'socket:connect');
            scheduleHistoryReload(200, { force: isReconnect });
        });

        ctx.socket.on('disconnect', () => {
            ctx.isConnected = false;
            socketLog('WebSocket已断开');
            // 断线时也重置状态，防止状态混乱
            ctx.resetAllStates('socket:disconnect');
        });

        ctx.socket.on('connect_error', (error) => {
            console.error('WebSocket连接错误:', error.message);
        });

        ctx.socket.on('quota_update', (data) => {
            if (data && data.quotas) {
                ctx.resourceSetUsageQuota({ quotas: data.quotas });
            } else {
                ctx.fetchUsageQuota();
            }
        });

        ctx.socket.on('quota_notice', (data) => {
            ctx.showQuotaToast(data || {});
            ctx.fetchUsageQuota();
        });

        ctx.socket.on('quota_exceeded', (data) => {
            ctx.showQuotaToast(data || {});
            ctx.fetchUsageQuota();
        });

        ctx.socket.on('reconnect_attempt', async () => {
            await assignSocketToken();
        });

        const ready = await assignSocketToken();
        if (!ready) {
            console.error('无法获取实时连接凭证，WebSocket 初始化中止。');
            return;
        }
        ctx.socket.connect();

        // ==========================================
        // Token统计WebSocket事件处理（修复版）
        // ==========================================

        ctx.socket.on('token_update', (data) => {
            socketLog('收到token更新事件:', data);

            // 只处理当前对话的token更新
            if (data.conversation_id === ctx.currentConversationId) {
                // 更新累计统计（使用后端提供的准确字段名）
                ctx.currentConversationTokens.cumulative_input_tokens = data.cumulative_input_tokens || 0;
                ctx.currentConversationTokens.cumulative_output_tokens = data.cumulative_output_tokens || 0;
                ctx.currentConversationTokens.cumulative_total_tokens = data.cumulative_total_tokens || 0;

                socketLog(`累计Token统计更新: 输入=${data.cumulative_input_tokens}, 输出=${data.cumulative_output_tokens}, 总计=${data.cumulative_total_tokens}`);

                const hasContextTokens = typeof data.current_context_tokens === 'number';
                if (hasContextTokens && typeof ctx.resourceSetCurrentContextTokens === 'function') {
                    ctx.resourceSetCurrentContextTokens(data.current_context_tokens);
                } else {
                    // 同时更新当前上下文Token（关键修复）
                    ctx.updateCurrentContextTokens();
                }

                ctx.$forceUpdate();
            }
        });

        // 上下文过长提示
        ctx.socket.on('context_warning', (data) => {
            const title = data?.title || '上下文过长';
            const message =
                data?.message ||
                '当前对话上下文接近上限，建议使用压缩功能。';
            if (typeof ctx.uiPushToast === 'function') {
                ctx.uiPushToast({
                    title,
                    message,
                    type: data?.type || 'warning',
                    duration: data?.duration || 6000
                });
            }
        });

        ctx.socket.on('todo_updated', (data) => {
            socketLog('收到todo更新事件:', data);
            // 初始化期间不修改 currentConversationId，避免与 bootstrapRoute 冲突
            if (ctx.initialRouteResolved && data && data.conversation_id) {
                ctx.currentConversationId = data.conversation_id;
            }
            ctx.fileSetTodoList((data && data.todo_list) || null);
        });

        // 系统就绪
        ctx.socket.on('system_ready', (data) => {
            ctx.projectPath = data.project_path || '';
            ctx.agentVersion = data.version || ctx.agentVersion;
            ctx.thinkingMode = !!data.thinking_mode;
            if (data.run_mode) {
                ctx.runMode = data.run_mode;
            } else {
                ctx.runMode = ctx.thinkingMode ? 'thinking' : 'fast';
            }
            socketLog('系统就绪:', data);

            // 系统就绪后立即加载对话列表
            ctx.loadConversationsList();
        });

        ctx.socket.on('tool_settings_updated', (data) => {
            socketLog('收到工具设置更新:', data);
            if (data && Array.isArray(data.categories)) {
                ctx.applyToolSettingsSnapshot(data.categories);
            }
        });

        // ==========================================
        // 对话管理相关Socket事件
        // ==========================================

        // 监听对话变更事件
        ctx.socket.on('conversation_changed', (data) => {
            socketLog('对话已切换:', data);
            console.log('[conv-trace] socket:conversation_changed', data);

            // 初始化期间不修改 currentConversationId，避免与 bootstrapRoute 冲突
            if (ctx.initialRouteResolved) {
                ctx.currentConversationId = data.conversation_id;
                ctx.currentConversationTitle = data.title || '';
                ctx.promoteConversationToTop(data.conversation_id);

                if (data.cleared) {
                    // 对话被清空
                    ctx.logMessageState?.('socket:conversation_changed-clearing', { event: data });
                    ctx.messages = [];
                    ctx.logMessageState?.('socket:conversation_changed-cleared', { event: data });
                    ctx.currentConversationId = null;
                    ctx.currentConversationTitle = '';
                    // 重置Token统计
                    ctx.resetTokenStatistics();
                    history.replaceState({}, '', '/new');
                }

                // 刷新对话列表
                ctx.loadConversationsList();
                ctx.fetchTodoList();
                ctx.fetchSubAgents();
            }
        });

        ctx.socket.on('conversation_resolved', (data) => {
            if (!data || !data.conversation_id) {
                return;
            }
            const convId = data.conversation_id;
            console.log('[conv-trace] socket:conversation_resolved', data);

            // 初始化期间不修改 currentConversationId，避免与 bootstrapRoute 冲突
            if (ctx.initialRouteResolved) {
                ctx.currentConversationId = convId;
                if (data.title) {
                    ctx.currentConversationTitle = data.title;
                }
                ctx.promoteConversationToTop(convId);
                const pathFragment = ctx.stripConversationPrefix(convId);
                const currentPath = window.location.pathname.replace(/^\/+/, '');
                if (data.created) {
                    history.pushState({ conversationId: convId }, '', `/${pathFragment}`);
                } else if (currentPath !== pathFragment) {
                    history.replaceState({ conversationId: convId }, '', `/${pathFragment}`);
                }
            }
        });

        // 监听对话加载事件
        ctx.socket.on('conversation_loaded', (data) => {
            socketLog('对话已加载:', data);
            if (ctx.skipConversationLoadedEvent) {
                ctx.skipConversationLoadedEvent = false;
                socketLog('跳过重复的 conversation_loaded 处理');
                return;
            }
            const targetConversationId = (data && data.conversation_id) || ctx.currentConversationId;
            const historyLoadingSame =
                !!targetConversationId &&
                !!ctx.historyLoading &&
                ctx.historyLoadingFor === targetConversationId;
            const historyReady =
                !!targetConversationId &&
                ctx.lastHistoryLoadedConversationId === targetConversationId &&
                Array.isArray(ctx.messages) &&
                ctx.messages.length > 0;
            const forceReload = !!(data && data.force_reload);

            if (!forceReload && (historyLoadingSame || historyReady)) {
                socketLog('conversation_loaded: 历史已加载/加载中，跳过重复刷新');
            } else {
                if (data.clear_ui) {
                    // 清理当前UI状态，准备显示历史内容
                    ctx.resetAllStates('socket:conversation_loaded');
                }
                // 延迟获取并显示历史对话内容
                setTimeout(() => {
                    ctx.fetchAndDisplayHistory({ force: forceReload });
                }, 300);
            }

            // 延迟获取Token统计（累计+当前上下文）
            setTimeout(() => {
                ctx.fetchConversationTokenStatistics();
                ctx.updateCurrentContextTokens();
                ctx.fetchTodoList();
            }, 500);
        });

        // 监听对话列表更新事件
        ctx.socket.on('conversation_list_update', (data) => {
            socketLog('对话列表已更新:', data);
            // 刷新对话列表
            ctx.conversationsOffset = 0;
            ctx.hasMoreConversations = false;
            ctx.loadingMoreConversations = false;
            ctx.loadConversationsList();
        });

        // 监听状态更新事件
        ctx.socket.on('status_update', (status) => {
            ctx.applyStatusSnapshot(status);
            // 只有在初始化完成后，才允许 status_update 修改 currentConversationId
            // 避免与 bootstrapRoute 冲突
            if (status.conversation && status.conversation.current_id) {
                if (ctx.initialRouteResolved && !ctx.currentConversationId) {
                    // 初始化完成且当前没有对话ID，才设置
                    ctx.currentConversationId = status.conversation.current_id;
                }
            }
            if (typeof status.run_mode === 'string') {
                ctx.runMode = status.run_mode;
            } else if (typeof status.thinking_mode !== 'undefined') {
                ctx.runMode = status.thinking_mode ? 'thinking' : 'fast';
            }
        });

        // 用户消息（后台子智能体完成后自动触发）
        ctx.socket.on('user_message', (data) => {
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                return;
            }
            if (!data) {
                return;
            }
            if (data?.conversation_id && data.conversation_id !== ctx.currentConversationId) {
                socketLog('跳过user_message(对话不匹配)', data.conversation_id);
                return;
            }
            const message = (data.message || data.content || '').trim();
            if (!message) {
                return;
            }
            ctx.chatAddUserMessage(message, data.images || [], data.videos || []);
            ctx.taskInProgress = true;
            ctx.streamingMessage = false;
            ctx.stopRequested = false;
            if (data?.sub_agent_notice && data?.task_id && ctx.usePollingMode) {
                if (typeof data?.has_running_sub_agents === 'boolean') {
                    ctx.waitingForSubAgent = data.has_running_sub_agents;
                } else if (typeof data?.remaining_count === 'number') {
                    ctx.waitingForSubAgent = data.remaining_count > 0;
                }
                (async () => {
                    try {
                        const { useTaskStore } = await import('../stores/task');
                        const taskStore = useTaskStore();
                        taskStore.resumeTask(data.task_id);
                    } catch (error) {
                        console.warn('恢复任务轮询失败', error);
                    }
                })();
            }
            ctx.$forceUpdate();
            ctx.conditionalScrollToBottom();
        });


        // AI消息开始（已废弃，改用 REST API 轮询）
        ctx.socket.on('ai_message_start', () => {
            // 只处理子智能体模式
            if (ctx.waitingForSubAgent) {
                ctx.waitingForSubAgent = false;
                ctx.taskInProgress = false;
            }
        });

        // 思考流开始
        ctx.socket.on('thinking_start', () => {
            // 轮询模式下跳过 WebSocket 事件
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                socketLog('思考开始 (轮询模式，跳过)');
                return;
            }
            socketLog('思考开始');
            const ignoreThinking = ctx.runMode === 'fast' || ctx.thinkingMode === false;
            streamingState.ignoreThinking = ignoreThinking;
            if (ignoreThinking) {
                ctx.monitorEndModelOutput();
                return;
            }
            ctx.monitorShowThinking();
            const result = ctx.chatStartThinkingAction();
            if (result && result.blockId) {
                const blockId = result.blockId;
                ctx.chatExpandBlock(blockId);
                // 开始思考时尝试滚动到底部，但不改变用户锁定选择
                ctx.scrollToBottom();
                ctx.chatSetThinkingLock(blockId, true);
                ctx.$forceUpdate();
            }
        });

        // 思考内容块
        ctx.socket.on('thinking_chunk', (data) => {
            // 轮询模式下跳过 WebSocket 事件
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                return;
            }
            if (streamingState.ignoreThinking) {
                return;
            }
            const thinkingAction = ctx.chatAppendThinkingChunk(data.content);
            if (thinkingAction) {
                ctx.$forceUpdate();
                ctx.$nextTick(() => {
                    if (thinkingAction && thinkingAction.blockId) {
                        ctx.scrollThinkingToBottom(thinkingAction.blockId);
                    }
                    ctx.conditionalScrollToBottom();
                });
            }
            ctx.monitorShowThinking();
        });

        // 思考结束
        ctx.socket.on('thinking_end', (data) => {
            // 轮询模式下跳过 WebSocket 事件
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                socketLog('思考结束 (轮询模式，跳过)');
                return;
            }
            socketLog('思考结束');
            if (streamingState.ignoreThinking) {
                streamingState.ignoreThinking = false;
                return;
            }
            const blockId = ctx.chatCompleteThinkingAction(data.full_content);
            if (blockId) {
                setTimeout(() => {
                    ctx.chatCollapseBlock(blockId);
                    ctx.chatSetThinkingLock(blockId, false);
                    ctx.$forceUpdate();
                }, 1000);
                ctx.$nextTick(() => ctx.scrollThinkingToBottom(blockId));
            }
            ctx.$forceUpdate();
            ctx.monitorEndModelOutput();
        });

        // 文本流开始
        ctx.socket.on('text_start', () => {
            // 轮询模式下跳过 WebSocket 事件
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                socketLog('文本开始 (轮询模式，跳过)');
                return;
            }
            console.log('[DEBUG] 收到 text_start 事件:', {
                currentConversationId: ctx.currentConversationId,
                messagesCount: ctx.messages.length,
                currentMessageIndex: ctx.currentMessageIndex
            });
            socketLog('文本开始');
            logStreamingDebug('socket:text_start');
            finalizeStreamingText({ force: true });
            resetStreamingBuffer();
            const action = ctx.chatStartTextAction();
            streamingState.activeMessageIndex =
                typeof ctx.currentMessageIndex === 'number' ? ctx.currentMessageIndex : null;
            streamingState.activeTextAction = action || ensureActiveTextAction();
            ensureActiveMessageBinding();
            ctx.$forceUpdate();
            console.log('[DEBUG] text_start 处理完成');
        });

        // 文本内容块
        ctx.socket.on('text_chunk', (data) => {
            // 轮询模式下跳过 WebSocket 事件
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                return;
            }
            console.log('[DEBUG] 收到 text_chunk 事件:', {
                conversation_id: data?.conversation_id,
                currentConversationId: ctx.currentConversationId,
                chunkLength: (data?.content || '').length,
                index: data?.index
            });
            logStreamingDebug('socket:text_chunk', {
                index: data?.index ?? null,
                elapsed: data?.elapsed ?? null,
                chunkLength: (data?.content || '').length,
                snapshot: snapshotStreamingState()
            });
            try {
                ctx.socket.emit('client_chunk_log', {
                    conversation_id: ctx.currentConversationId,
                    index: data?.index ?? null,
                    elapsed: data?.elapsed ?? null,
                    length: (data?.content || '').length,
                    ts: Date.now()
                });
            } catch (error) {
                console.warn('上报chunk日志失败:', error);
            }
            if (data && typeof data.content === 'string' && data.content.length) {
                if (STREAMING_ENABLED) {
                    enqueueStreamingContent(data.content);
                } else {
                    // 关闭逐字模式时，直接追加当前chunk
                    applyTextChunk(data.content);
                }
                const speech = sanitizeBubbleText(data.content);
                if (speech) {
                    ctx.monitorShowSpeech(speech);
                }
            }
        });

        // 文本结束
        ctx.socket.on('text_end', (data) => {
            // 轮询模式下跳过 WebSocket 事件
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                socketLog('文本结束 (轮询模式，跳过)');
                return;
            }
            socketLog('文本结束');
            logStreamingDebug('socket:text_end', {
                finalLength: (data?.full_content || '').length,
                snapshot: snapshotStreamingState()
            });
            if (!STREAMING_ENABLED) {
                // 已逐块追加，这里保证动作收尾
                const full = data?.full_content || '';
                if (full) {
                    ctx.chatCompleteTextAction(full);
                } else {
                    ctx.chatCompleteTextAction('');
                }
                streamingState.buffer.length = 0;
                streamingState.pendingCompleteContent = '';
                streamingState.renderedText = '';
                streamingState.apiCompleted = false;
                ctx.monitorEndModelOutput();
                flushPendingToolEvents();
                return;
            }
            streamingState.apiCompleted = true;
            streamingState.pendingCompleteContent = data?.full_content || '';
            const hidden = typeof document !== 'undefined' && document.hidden === true;
            if (hidden) {
                stopStreamingTimer();
                drainStreamingBufferImmediately();
                finalizeStreamingText({ force: true });
            } else if (!streamingState.buffer.length) {
                scheduleFinalizationAfterDrain();
            } else {
                scheduleStreamingFlush();
            }
            ctx.monitorEndModelOutput();
            flushPendingToolEvents();
        });

        // 工具提示事件（可选）
        ctx.socket.on('tool_hint', (data) => {
            socketLog('工具提示:', data.name);
            if (data?.conversation_id && data.conversation_id !== ctx.currentConversationId) {
                socketLog('跳过tool_hint(对话不匹配)', data.conversation_id);
                return;
            }
            // 可以在这里添加提示UI
        });

        // 工具准备中事件 - 实时显示
        ctx.socket.on('tool_preparing', (data) => {
            // 轮询模式下跳过 WebSocket 事件
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                return;
            }
            if (ctx.dropToolEvents) {
                return;
            }
            console.log('[DEBUG] 收到 tool_preparing 事件:', {
                name: data.name,
                id: data.id,
                conversation_id: data?.conversation_id,
                currentConversationId: ctx.currentConversationId,
                match: data?.conversation_id === ctx.currentConversationId
            });
            socketLog('工具准备中:', data.name);
            if (typeof console !== 'undefined' && console.debug) {
                console.debug('[tool_intent] preparing', {
                    id: data?.id,
                    name: data?.name,
                    intent: data?.intent,
                    convo: data?.conversation_id
                });
            }
            if (data?.conversation_id && data.conversation_id !== ctx.currentConversationId) {
                console.log('[DEBUG] 跳过 tool_preparing (对话不匹配)');
                socketLog('跳过tool_preparing(对话不匹配)', data.conversation_id);
                return;
            }
            const msg = ctx.chatEnsureAssistantMessage();
            if (!msg) {
                console.log('[DEBUG] tool_preparing: 无法获取assistant消息');
                return;
            }
            if (msg.awaitingFirstContent) {
                msg.awaitingFirstContent = false;
                msg.generatingLabel = '';
            }
            const action = {
                id: data.id,
                type: 'tool',
                tool: {
                    id: data.id,
                    name: data.name,
                    arguments: {},
                    argumentSnapshot: null,
                    argumentLabel: '',
                    status: 'preparing',
                    result: null,
                    message: data.message || `准备调用 ${data.name}...`,
                    intent_full: data.intent || '',
                    intent_rendered: data.intent || ''
                },
                timestamp: Date.now()
            };
            msg.actions.push(action);
            ctx.preparingTools.set(data.id, action);
            ctx.toolRegisterAction(action, data.id);
            ctx.toolTrackAction(data.name, action);
            if (data.intent) {
                startIntentTyping(action, data.intent);
            }
            console.log('[DEBUG] tool_preparing 处理完成，action已添加');
            ctx.$forceUpdate();
            ctx.conditionalScrollToBottom();
            if (ctx.monitorPreviewTool) {
                ctx.monitorPreviewTool(data);
            }
        });

        // 工具意图（流式增量）事件
        ctx.socket.on('tool_intent', (data) => {
            // 轮询模式下跳过 WebSocket 事件
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                return;
            }
            if (ctx.dropToolEvents) {
                return;
            }
            if (data?.conversation_id && data.conversation_id !== ctx.currentConversationId) {
                return;
            }
            if (typeof console !== 'undefined' && console.debug) {
                console.debug('[tool_intent] update', {
                    id: data?.id,
                    name: data?.name,
                    intent: data?.intent,
                    convo: data?.conversation_id
                });
            }
            const target =
                ctx.toolFindAction(data.id, data.preparing_id, data.execution_id) ||
                ctx.toolGetLatestAction(data.name);
            if (target) {
                startIntentTyping(target, data.intent);
            }
            ctx.$forceUpdate();
        });

        // 工具状态更新事件 - 实时显示详细状态
        ctx.socket.on('tool_status', (data) => {
            // 轮询模式下跳过 WebSocket 事件
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                return;
            }
            if (ctx.dropToolEvents) {
                return;
            }
            socketLog('工具状态:', data);
            if (data?.conversation_id && data.conversation_id !== ctx.currentConversationId) {
                socketLog('跳过tool_status(对话不匹配)', data.conversation_id);
                return;
            }
            const target = ctx.toolFindAction(data.id, data.preparing_id, data.execution_id);
            if (target) {
                target.tool.statusDetail = data.detail;
                target.tool.statusType = data.status;
                if (data.intent) {
                    startIntentTyping(target, data.intent);
                }
                ctx.$forceUpdate();
                return;
            }
            const fallbackAction = ctx.toolGetLatestAction(data.tool);
            if (fallbackAction) {
                fallbackAction.tool.statusDetail = data.detail;
                fallbackAction.tool.statusType = data.status;
                ctx.toolRegisterAction(fallbackAction, data.execution_id || data.id || data.preparing_id);
                if (data.intent) {
                    startIntentTyping(fallbackAction, data.intent);
                }
                ctx.$forceUpdate();
            }
        });

        // 工具开始（从准备转为执行）
        ctx.socket.on('tool_start', (data) => {
            // 轮询模式下跳过 WebSocket 事件
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                return;
            }
            if (ctx.dropToolEvents) {
                return;
            }
            socketLog('工具开始执行:', data.name);
            if (data?.conversation_id && data.conversation_id !== ctx.currentConversationId) {
                socketLog('跳过tool_start(对话不匹配)', data.conversation_id);
                return;
            }
            const handler = () => {
                let action = null;
                if (data.preparing_id && ctx.preparingTools.has(data.preparing_id)) {
                    action = ctx.preparingTools.get(data.preparing_id);
                    ctx.preparingTools.delete(data.preparing_id);
                } else {
                    action = ctx.toolFindAction(data.id, data.preparing_id, data.execution_id);
                }
                if (!action) {
                    const msg = ctx.chatEnsureAssistantMessage();
                    if (!msg) {
                        return;
                    }
                    action = {
                        id: data.id,
                        type: 'tool',
                            tool: {
                                id: data.id,
                                name: data.name,
                                arguments: {},
                                argumentSnapshot: null,
                                argumentLabel: '',
                                status: 'running',
                                result: null
                            },
                            timestamp: Date.now()
                        };
                    msg.actions.push(action);
                }
                action.tool.status = 'running';
                action.tool.arguments = data.arguments;
                action.tool.argumentSnapshot = ctx.cloneToolArguments(data.arguments);
                action.tool.argumentLabel = ctx.buildToolLabel(action.tool.argumentSnapshot);
                action.tool.message = null;
                action.tool.id = data.id;
                action.tool.executionId = data.id;
                if (data.arguments && data.arguments.intent) {
                    startIntentTyping(action, data.arguments.intent);
                }
                ctx.toolRegisterAction(action, data.id);
                ctx.toolTrackAction(data.name, action);
                ctx.$forceUpdate();
                ctx.conditionalScrollToBottom();
                ctx.monitorQueueTool(data);

                if (data.name === 'view_video' && typeof ctx.uiPushToast === 'function') {
                    ctx.uiPushToast({
                        title: '视频读取中',
                        message: '读取视频需要较长时间，请耐心等待',
                        type: 'info',
                        duration: 5000
                    });
                }
            };

            handler();
        });

        // 更新action（工具完成）
        ctx.socket.on('update_action', (data) => {
            // 轮询模式下跳过 WebSocket 事件
            if (ctx.usePollingMode && !ctx.waitingForSubAgent) {
                return;
            }
            if (ctx.dropToolEvents) {
                return;
            }
            socketLog('更新action:', data.id, 'status:', data.status);
            if (data?.conversation_id && data.conversation_id !== ctx.currentConversationId) {
                socketLog('跳过update_action(对话不匹配)', data.conversation_id);
                return;
            }
            const handler = () => {
                let targetAction = ctx.toolFindAction(data.id, data.preparing_id, data.execution_id);
                if (!targetAction && data.preparing_id && ctx.preparingTools.has(data.preparing_id)) {
                    targetAction = ctx.preparingTools.get(data.preparing_id);
                }
                if (!targetAction) {
                    outer: for (const message of ctx.messages) {
                        if (!message.actions) continue;
                        for (const action of message.actions) {
                            if (action.type !== 'tool') continue;
                            const matchByExecution = action.tool.executionId && action.tool.executionId === data.id;
                            const matchByToolId = action.tool.id === data.id;
                            const matchByPreparingId = action.id === data.preparing_id;
                            if (matchByExecution || matchByToolId || matchByPreparingId) {
                                targetAction = action;
                                break outer;
                            }
                        }
                    }
                }
                if (targetAction) {
                    if (data.status) {
                        targetAction.tool.status = data.status;
                    }
                    if (data.result !== undefined) {
                        targetAction.tool.result = data.result;
                    }
                    if (targetAction.tool && targetAction.tool.name === 'trigger_easter_egg' && data.result !== undefined) {
                        const eggPromise = ctx.handleEasterEggPayload(data.result);
                        if (eggPromise && typeof eggPromise.catch === 'function') {
                            eggPromise.catch((error) => {
                                console.warn('彩蛋处理异常:', error);
                            });
                        }
                    }
                    if (data.message !== undefined) {
                        targetAction.tool.message = data.message;
                    }
                    if (data.arguments && data.arguments.intent) {
                        startIntentTyping(targetAction, data.arguments.intent);
                    }
                    if (data.awaiting_content) {
                        targetAction.tool.awaiting_content = true;
                    } else if (data.status === 'completed') {
                        targetAction.tool.awaiting_content = false;
                    }
                    if (!targetAction.tool.executionId && (data.execution_id || data.id)) {
                        targetAction.tool.executionId = data.execution_id || data.id;
                    }
                    if (data.arguments) {
                        targetAction.tool.arguments = data.arguments;
                        targetAction.tool.argumentSnapshot = ctx.cloneToolArguments(data.arguments);
                        targetAction.tool.argumentLabel = ctx.buildToolLabel(targetAction.tool.argumentSnapshot);
                        if (data.arguments.intent) {
                            startIntentTyping(targetAction, data.arguments.intent);
                        }
                    }
                    ctx.toolRegisterAction(targetAction, data.execution_id || data.id);
                    if (data.status && ["completed", "failed", "error"].includes(data.status) && !data.awaiting_content) {
                        ctx.toolUnregisterAction(targetAction);
                        if (data.id) {
                            ctx.preparingTools.delete(data.id);
                        }
                        if (data.preparing_id) {
                            ctx.preparingTools.delete(data.preparing_id);
                        }
                    }
                    ctx.$forceUpdate();
                    ctx.conditionalScrollToBottom();
                }

                if (data.status === 'completed') {
                    setTimeout(() => {
                        ctx.updateCurrentContextTokens();
                    }, 500);
                    try {
                        ctx.fileFetchTree();
                    } catch (error) {
                        console.warn('刷新文件树失败', error);
                    }
                }
                ctx.monitorResolveTool(data);
            };

            handler();
        });

        ctx.socket.on('append_payload', (data) => {
            if (ctx.dropToolEvents) {
                return;
            }
            socketLog('收到append_payload事件:', data);
            if (data?.conversation_id && data.conversation_id !== ctx.currentConversationId) {
                socketLog('跳过append_payload(对话不匹配)', data.conversation_id);
                return;
            }
            ctx.chatAddAppendPayloadAction({
                path: data.path || '未知文件',
                forced: !!data.forced,
                success: data.success === undefined ? true : !!data.success,
                lines: data.lines ?? null,
                bytes: data.bytes ?? null
            });
            ctx.$forceUpdate();
            ctx.conditionalScrollToBottom();
        });

        ctx.socket.on('modify_payload', (data) => {
            if (ctx.dropToolEvents) {
                return;
            }
            socketLog('收到modify_payload事件:', data);
            if (data?.conversation_id && data.conversation_id !== ctx.currentConversationId) {
                socketLog('跳过modify_payload(对话不匹配)', data.conversation_id);
                return;
            }
            ctx.chatAddModifyPayloadAction({
                path: data.path || '未知文件',
                total: data.total ?? null,
                completed: data.completed || [],
                failed: data.failed || [],
                forced: !!data.forced
            });
            ctx.$forceUpdate();
            ctx.conditionalScrollToBottom();
        });

        // 停止请求确认
        ctx.socket.on('stop_requested', (data) => {
            socketLog('停止请求已接收:', data.message);
            // 可以显示提示信息
            try {
                if (typeof ctx.clearPendingTools === 'function') {
                    ctx.clearPendingTools('socket:stop_requested');
                }
            } catch (error) {
                console.warn('清理未完成工具失败', error);
            }
        });

        // 任务停止
        ctx.socket.on('task_stopped', (data) => {
            socketLog('任务已停止:', data.message);
            ctx.taskInProgress = false;
            ctx.scheduleResetAfterTask('socket:task_stopped', { preserveMonitorWindows: true });
        });

        // 任务完成（重点：更新Token统计）
        ctx.socket.on('task_complete', (data) => {
            console.log('[DEBUG] 收到 task_complete 事件:', data);
            console.log('[DEBUG] 当前状态 (before task_complete):', {
                taskInProgress: ctx.taskInProgress,
                streamingMessage: ctx.streamingMessage,
                has_running_sub_agents: data.has_running_sub_agents
            });
            socketLog('任务完成', data);

            // 如果有运行中的子智能体，不重置任务状态
            if (!data.has_running_sub_agents) {
                console.log('[DEBUG] 没有运行中的子智能体，重置任务状态');
                if (ctx.waitingForSubAgent) {
                    ctx.waitingForSubAgent = false;
                }
                ctx.taskInProgress = false;
                ctx.scheduleResetAfterTask('socket:task_complete', { preserveMonitorWindows: true });
            } else {
                console.log('[DEBUG] 有运行中的子智能体，保持任务状态');
            }

            console.log('[DEBUG] 当前状态 (after task_complete):', {
                taskInProgress: ctx.taskInProgress,
                streamingMessage: ctx.streamingMessage
            });

            resetPendingToolEvents();

            // 任务完成后立即更新Token统计（关键修复）
            if (ctx.currentConversationId) {
                ctx.updateCurrentContextTokens();
                ctx.fetchConversationTokenStatistics();
            }
        });

        // 子智能体等待状态
        ctx.socket.on('sub_agent_waiting', (data) => {
            console.log('[DEBUG] 收到 sub_agent_waiting 事件:', data);
            console.log('[DEBUG] 当前状态 (before sub_agent_waiting):', {
                taskInProgress: ctx.taskInProgress,
                streamingMessage: ctx.streamingMessage,
                stopRequested: ctx.stopRequested
            });
            socketLog('等待子智能体完成:', data);

            // 设置标志：有子智能体在运行，阻止状态重置
            ctx.waitingForSubAgent = true;

            // 保持任务进行中状态
            ctx.taskInProgress = true;
            ctx.streamingMessage = false;
            ctx.stopRequested = false;

            console.log('[DEBUG] 当前状态 (after sub_agent_waiting):', {
                taskInProgress: ctx.taskInProgress,
                streamingMessage: ctx.streamingMessage,
                stopRequested: ctx.stopRequested,
                waitingForSubAgent: ctx.waitingForSubAgent
            });

            // 显示等待提示
            if (typeof ctx.appendSystemAction === 'function') {
                const taskList = data.tasks.map((t: any) => `子智能体${t.agent_id} (${t.summary || '无描述'})`).join('、');
                ctx.appendSystemAction(`⏳ 等待 ${data.count} 个后台子智能体完成：${taskList}`);
            }

            ctx.$forceUpdate();
            console.log('[DEBUG] sub_agent_waiting 处理完成');
        });

        // 聚焦文件更新
        ctx.socket.on('focused_files_update', (data) => {
            ctx.focusSetFiles(data || {});
            // 聚焦文件变化时更新当前上下文Token（关键修复）
            if (ctx.currentConversationId) {
                setTimeout(() => {
                    ctx.updateCurrentContextTokens();
                }, 500);
            }
        });

        // 文件树更新
        ctx.socket.on('file_tree_update', (data) => {
            ctx.fileSetTreeFromResponse(data);
            // 文件树变化时也可能影响上下文
            if (ctx.currentConversationId) {
                setTimeout(() => {
                    ctx.updateCurrentContextTokens();
                }, 500);
            }
        });

        // 系统消息
        ctx.socket.on('system_message', (data) => {
            if (!data || !data.content) {
                return;
            }
            ctx.appendSystemAction(data.content);
        });

        // 错误处理
        ctx.socket.on('error', (data) => {
            const msg = data?.message || '发生未知错误';
            const code = data?.status_code;
            const errType = data?.error_type;
            const errCode = data?.error_code;
            const dumpPath = data?.request_dump;
            const baseUrl = data?.base_url;
            const modelId = data?.model_id;
            const conversationId = data?.conversation_id;
            const taskId = data?.task_id;
            const shouldRetry = Boolean(data?.retry);
            const retryIn = Number(data?.retry_in) || 5;
            const retryAttempt = Number(data?.attempt) || 1;
            const retryMax = Number(data?.max_attempts) || retryAttempt;
            const detailParts = [
                dumpPath ? `请求记录: ${dumpPath}` : '',
                baseUrl ? `接口: ${baseUrl}` : '',
                modelId ? `模型: ${modelId}` : '',
                conversationId ? `对话ID: ${conversationId}` : '',
                taskId ? `任务ID: ${taskId}` : ''
            ].filter(Boolean);
            const detailText = detailParts.length ? `\n${detailParts.join('\n')}` : '';
            if (typeof ctx.uiPushToast === 'function') {
                ctx.uiPushToast({
                    title: code ? `API错误 ${code}` : 'API错误',
                    message: `${errType ? `${errType}${errCode ? `(${errCode})` : ''}: ${msg}` : msg}${detailText}`,
                    type: 'error',
                    duration: 6000
                });
                if (shouldRetry) {
                    ctx.uiPushToast({
                        title: '即将重试',
                        message: `将在 ${retryIn} 秒后重试（第 ${retryAttempt}/${retryMax} 次）`,
                        type: 'info',
                        duration: Math.max(retryIn, 1) * 1000
                    });
                }
            }
            if (shouldRetry) {
                // 错误后保持停止按钮态，用户可手动停止或等待自动重试
                ctx.stopRequested = false;
                ctx.taskInProgress = true;
                ctx.streamingMessage = true;
                return;
            }

            if (typeof ctx.appendSystemAction === 'function') {
                ctx.appendSystemAction(
                    `${code ? `[API ${code}] ` : '[API] '}${errType ? `${errType}${errCode ? `(${errCode})` : ''}: ` : ''}${msg}${detailText}`
                );
            }

            // 最后一次报错：恢复输入状态并清理提示动画
            const msgIndex = typeof ctx.currentMessageIndex === 'number' ? ctx.currentMessageIndex : -1;
            if (msgIndex >= 0 && Array.isArray(ctx.messages)) {
                const currentMessage = ctx.messages[msgIndex];
                if (currentMessage && currentMessage.role === 'assistant') {
                    currentMessage.awaitingFirstContent = false;
                    currentMessage.generatingLabel = '';
                }
            }
            if (typeof ctx.chatClearThinkingLocks === 'function') {
                ctx.chatClearThinkingLocks();
            }
            ctx.streamingMessage = false;
            ctx.stopRequested = false;
            ctx.taskInProgress = false;
        });

        // 命令结果
        ctx.socket.on('command_result', (data) => {
            if (data.command === 'clear' && data.success) {
                ctx.logMessageState?.('socket:command_result-clear', { data });
                ctx.messages = [];
                ctx.logMessageState?.('socket:command_result-cleared', { data });
                ctx.currentMessageIndex = -1;
                ctx.chatClearExpandedBlocks();
                // 清除对话时重置Token统计
                ctx.resetTokenStatistics();
            } else if (data.command === 'status' && data.success) {
                ctx.addSystemMessage(`系统状态:\n${JSON.stringify(data.data, null, 2)}`);
            } else if (!data.success) {
                ctx.addSystemMessage(`命令失败: ${data.message}`);
            }
        });

    } catch (error) {
        console.error('Socket初始化失败:', error);
    }
}
