"use strict";
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
    return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (g && (g = 0, op[0] && (_ = 0)), _) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
    if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
        if (ar || !(i in from)) {
            if (!ar) ar = Array.prototype.slice.call(from, 0, i);
            ar[i] = from[i];
        }
    }
    return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CHAT_CONNECTION = void 0;
exports.invalidateChatConversationListCache = invalidateChatConversationListCache;
exports.sortChatConversationSummaries = sortChatConversationSummaries;
exports.clearStoredChatClientConversationState = clearStoredChatClientConversationState;
exports.isPreparingChatReplyText = isPreparingChatReplyText;
exports.getChatClientSessionId = getChatClientSessionId;
exports.setChatClientSessionId = setChatClientSessionId;
exports.getLastReceivedChatEventId = getLastReceivedChatEventId;
exports.persistLastReceivedChatEventId = persistLastReceivedChatEventId;
exports.resetLastReceivedChatEventId = resetLastReceivedChatEventId;
exports.getStoredChatOfflineNotificationSetting = getStoredChatOfflineNotificationSetting;
exports.setStoredChatOfflineNotificationSetting = setStoredChatOfflineNotificationSetting;
exports.clearStoredChatOfflineNotificationSetting = clearStoredChatOfflineNotificationSetting;
exports.getStoredChatSessionLastTypeId = getStoredChatSessionLastTypeId;
exports.setStoredChatSessionLastTypeId = setStoredChatSessionLastTypeId;
exports.formatTime = formatTime;
exports.createLocalMessage = createLocalMessage;
exports.createChatMessage = createChatMessage;
exports.createActivityLogPlaceholder = createActivityLogPlaceholder;
exports.isMissingRequestMessage = isMissingRequestMessage;
exports.isExecutionFailureMessage = isExecutionFailureMessage;
exports.hydrateActivityLogMessages = hydrateActivityLogMessages;
exports.appendActivityEventToMessages = appendActivityEventToMessages;
exports.createIntroMessage = createIntroMessage;
exports.buildOfflineReply = buildOfflineReply;
exports.resolveChatWebSocketUrl = resolveChatWebSocketUrl;
exports.diagnoseConnectionFailure = diagnoseConnectionFailure;
exports.copyText = copyText;
exports.copyPreviewContent = copyPreviewContent;
exports.resolvePreviewBodyForCopy = resolvePreviewBodyForCopy;
exports.fetchChatConversations = fetchChatConversations;
exports.fetchChatConversationDetail = fetchChatConversationDetail;
exports.fetchChatRuntimeSnapshot = fetchChatRuntimeSnapshot;
exports.fetchChatRuntimeJobDetail = fetchChatRuntimeJobDetail;
exports.cancelChatRuntimeJob = cancelChatRuntimeJob;
exports.removeChatRuntimeJob = removeChatRuntimeJob;
exports.rollbackChatRuntimeJob = rollbackChatRuntimeJob;
exports.uploadChatComposerFile = uploadChatComposerFile;
exports.createChatConversationRoom = createChatConversationRoom;
exports.renameChatConversationRoom = renameChatConversationRoom;
exports.updateChatConversationRoom = updateChatConversationRoom;
exports.markChatConversationResponsesRead = markChatConversationResponsesRead;
exports.deleteChatConversationRoom = deleteChatConversationRoom;
exports.deleteChatConversationRequest = deleteChatConversationRequest;
exports.upsertChatMessage = upsertChatMessage;
exports.mergeRecoveredChatMessages = mergeRecoveredChatMessages;
exports.handleChatServerEvent = handleChatServerEvent;
var clientIdentity_1 = require("../clientIdentity");
var tokenAccess_1 = require("../tokenAccess");
var errorLogApi_1 = require("../errorLogApi");
var CONNECT_TIMEOUT_MS = 20000;
var CHAT_SESSION_ID_KEY = 'main-chat-panel:session-id';
var CHAT_LAST_EVENT_ID_STORAGE_PREFIX = 'main-chat-panel:last-event-id:';
var CHAT_NOTIFY_OFFLINE_STORAGE_PREFIX = 'main-chat-panel:notify-offline:';
var CHAT_SESSION_LAST_TYPE_STORAGE_PREFIX = 'main-chat-panel:last-chat-type:';
var CHAT_INTRO_MESSAGE = '요청은 기본적으로 순차 처리됩니다. 급한 요청만 즉시 실행을 사용하세요. 여러 Codex를 추가한 즉시 실행은 병렬로 처리됩니다.';
var CHAT_ACTIVITY_MESSAGE_PREFIX = '[[activity-log]]';
var CHAT_MISSING_REQUEST_MESSAGE_PREFIX = '[[missing-request]]';
var CHAT_EXECUTION_FAILURE_MESSAGE_PREFIX = '[[execution-failure]]';
var CHAT_COMPOSER_UPLOAD_FILE_SIZE_LIMIT = 10 * 1024 * 1024;
var KST_TIME_ZONE = 'Asia/Seoul';
var chatSessionLastTypeMemory = new Map();
var chatLastEventIdMemory = new Map();
var chatOfflineNotificationMemory = new Map();
var chatClientSessionIdMemory = '';
var localMessageSequence = 0;
var chatConversationListRequestPromise = null;
function invalidateChatConversationListCache() {
    chatConversationListRequestPromise = null;
}
function toConversationSortTime(value) {
    if (typeof value !== 'string' || !value.trim()) {
        return 0;
    }
    var parsed = Date.parse(value);
    return Number.isNaN(parsed) ? 0 : parsed;
}
function getConversationLastMessageSortTime(item) {
    var lastMessageTime = toConversationSortTime(item.lastMessageAt);
    if (lastMessageTime > 0) {
        return lastMessageTime;
    }
    return Math.max(toConversationSortTime(item.createdAt), toConversationSortTime(item.updatedAt));
}
function sortChatConversationSummaries(items) {
    return __spreadArray([], items, true).sort(function (left, right) {
        var leftTime = getConversationLastMessageSortTime(left);
        var rightTime = getConversationLastMessageSortTime(right);
        if (rightTime !== leftTime) {
            return rightTime - leftTime;
        }
        return left.sessionId.localeCompare(right.sessionId, 'ko-KR');
    });
}
exports.CHAT_CONNECTION = {
    reconnectDelayMs: 1500,
    connectTimeoutMs: CONNECT_TIMEOUT_MS,
    sessionIdKey: CHAT_SESSION_ID_KEY,
    lastEventIdStoragePrefix: CHAT_LAST_EVENT_ID_STORAGE_PREFIX,
    notifyOfflineStoragePrefix: CHAT_NOTIFY_OFFLINE_STORAGE_PREFIX,
    sessionLastTypeStoragePrefix: CHAT_SESSION_LAST_TYPE_STORAGE_PREFIX,
    introMessage: CHAT_INTRO_MESSAGE,
};
function buildNotifyOfflineStorageKey(sessionId, clientId) {
    var normalizedSessionId = sessionId.trim() || 'default';
    var normalizedClientId = (clientId === null || clientId === void 0 ? void 0 : clientId.trim()) || (0, clientIdentity_1.getOrCreateClientId)() || 'default-client';
    return "".concat(exports.CHAT_CONNECTION.notifyOfflineStoragePrefix).concat(normalizedSessionId, ":").concat(normalizedClientId);
}
function createBrowserSessionId() {
    if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
        return crypto.randomUUID();
    }
    return "chat-session-".concat(Date.now().toString(36), "-").concat(Math.random().toString(36).slice(2, 10));
}
function clearStoredChatClientConversationState() {
    if (typeof window === 'undefined') {
        return;
    }
    chatClientSessionIdMemory = '';
    chatSessionLastTypeMemory.clear();
    chatLastEventIdMemory.clear();
    chatOfflineNotificationMemory.clear();
}
function normalizeChatConversationRequest(item) {
    var hasResponse = item.hasResponse === true;
    return __assign(__assign({}, item), { hasResponse: hasResponse, canDelete: item.canDelete === true || (!hasResponse && item.status !== 'queued' && item.status !== 'started' && item.status !== 'removed') });
}
function isPreparingChatReplyText(text) {
    var normalized = String(text !== null && text !== void 0 ? text : '').replace(/\s+/g, ' ').trim();
    return normalized.startsWith('응답을 준비하고 있습니다');
}
function getChatClientSessionId() {
    if (typeof window === 'undefined') {
        return '';
    }
    if (chatClientSessionIdMemory) {
        return chatClientSessionIdMemory;
    }
    chatClientSessionIdMemory = createBrowserSessionId();
    return chatClientSessionIdMemory;
}
function setChatClientSessionId(sessionId) {
    if (typeof window === 'undefined') {
        return;
    }
    var normalizedSessionId = sessionId.trim();
    if (!normalizedSessionId) {
        return;
    }
    chatClientSessionIdMemory = normalizedSessionId;
}
function getLastReceivedChatEventId(sessionId) {
    var _a;
    if (typeof window === 'undefined') {
        return 0;
    }
    var normalizedSessionId = sessionId.trim();
    if (!normalizedSessionId) {
        return 0;
    }
    return (_a = chatLastEventIdMemory.get(normalizedSessionId)) !== null && _a !== void 0 ? _a : 0;
}
function persistLastReceivedChatEventId(sessionId, eventId) {
    if (typeof window === 'undefined' || !Number.isFinite(eventId) || eventId <= 0) {
        return;
    }
    var normalizedSessionId = sessionId.trim();
    if (!normalizedSessionId) {
        return;
    }
    var currentEventId = getLastReceivedChatEventId(normalizedSessionId);
    if (eventId <= currentEventId) {
        return;
    }
    chatLastEventIdMemory.set(normalizedSessionId, eventId);
}
function resetLastReceivedChatEventId(sessionId) {
    if (typeof window === 'undefined') {
        return;
    }
    var normalizedSessionId = sessionId.trim();
    if (!normalizedSessionId) {
        return;
    }
    chatLastEventIdMemory.delete(normalizedSessionId);
}
function getStoredChatOfflineNotificationSetting(sessionId, clientId) {
    var _a;
    if (typeof window === 'undefined') {
        return null;
    }
    var key = buildNotifyOfflineStorageKey(sessionId, clientId);
    if (!chatOfflineNotificationMemory.has(key)) {
        return null;
    }
    return (_a = chatOfflineNotificationMemory.get(key)) !== null && _a !== void 0 ? _a : null;
}
function setStoredChatOfflineNotificationSetting(sessionId, enabled, clientId) {
    if (typeof window === 'undefined') {
        return;
    }
    chatOfflineNotificationMemory.set(buildNotifyOfflineStorageKey(sessionId, clientId), enabled);
}
function clearStoredChatOfflineNotificationSetting(sessionId, clientId) {
    if (typeof window === 'undefined') {
        return;
    }
    chatOfflineNotificationMemory.delete(buildNotifyOfflineStorageKey(sessionId, clientId));
}
function resolveSyncedChatOfflineNotificationSetting(sessionId, serverValue, clientId) {
    var storedValue = getStoredChatOfflineNotificationSetting(sessionId, clientId);
    if (storedValue == null) {
        setStoredChatOfflineNotificationSetting(sessionId, serverValue, clientId);
        return serverValue;
    }
    if (storedValue !== serverValue) {
        setStoredChatOfflineNotificationSetting(sessionId, serverValue, clientId);
    }
    return serverValue;
}
function getStoredChatSessionLastTypeId(sessionId) {
    var _a, _b;
    var normalizedSessionId = sessionId.trim();
    if (!normalizedSessionId) {
        return null;
    }
    var raw = (_b = (_a = chatSessionLastTypeMemory.get(normalizedSessionId)) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : '';
    return raw || null;
}
function setStoredChatSessionLastTypeId(sessionId, chatTypeId) {
    var normalizedSessionId = sessionId.trim();
    var normalizedChatTypeId = chatTypeId.trim();
    if (!normalizedSessionId) {
        return;
    }
    if (!normalizedChatTypeId) {
        chatSessionLastTypeMemory.delete(normalizedSessionId);
        return;
    }
    chatSessionLastTypeMemory.set(normalizedSessionId, normalizedChatTypeId);
}
function formatTime(date) {
    return new Intl.DateTimeFormat('sv-SE', {
        timeZone: KST_TIME_ZONE,
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        hour12: false,
    })
        .format(date)
        .replace(',', '');
}
function createLocalMessageId() {
    localMessageSequence = (localMessageSequence + 1) % 1000;
    return Date.now() * 1000 + localMessageSequence;
}
function createRecoveredMessageId(requestId, variant) {
    var baseId = hashRequestId(requestId) * 10;
    if (variant === 'user') {
        return -(baseId + 3);
    }
    if (variant === 'missing-request') {
        return -(baseId + 2);
    }
    if (variant === 'activity') {
        return -(baseId + 1);
    }
    if (variant === 'execution-failure') {
        return -(baseId + 4);
    }
    return -(baseId + 5);
}
function hashRequestId(value) {
    var hash = 0;
    for (var _i = 0, value_1 = value; _i < value_1.length; _i++) {
        var character = value_1[_i];
        hash = (hash * 31 + character.charCodeAt(0)) | 0;
    }
    return Math.abs(hash) + 1000000;
}
function createLocalMessage(text) {
    return {
        id: createLocalMessageId(),
        author: 'system',
        text: text,
        timestamp: formatTime(new Date()),
    };
}
function createChatMessage(author, text, clientRequestId) {
    return {
        id: createLocalMessageId(),
        author: author,
        text: text,
        timestamp: formatTime(new Date()),
        clientRequestId: (clientRequestId === null || clientRequestId === void 0 ? void 0 : clientRequestId.trim()) || null,
    };
}
function createActivityLogPlaceholder(requestId, lines) {
    var normalizedRequestId = requestId.trim();
    if (!normalizedRequestId) {
        return null;
    }
    var normalizedLines = (lines !== null && lines !== void 0 ? lines : []).map(function (line) { return line.trim(); }).filter(Boolean);
    var fallbackLine = '요청을 접수했습니다. 활동 로그를 준비하고 있습니다.';
    return {
        id: hashRequestId(normalizedRequestId),
        author: 'system',
        text: "".concat(CHAT_ACTIVITY_MESSAGE_PREFIX, "\n").concat((normalizedLines.length > 0 ? normalizedLines : [fallbackLine]).join('\n\n')),
        timestamp: formatTime(new Date()),
        clientRequestId: normalizedRequestId,
    };
}
function isActivityLogMessage(message) {
    return message.author === 'system' && message.text.startsWith("".concat(CHAT_ACTIVITY_MESSAGE_PREFIX, "\n"));
}
function isMissingRequestMessage(message) {
    return message.author === 'system' && message.text.startsWith("".concat(CHAT_MISSING_REQUEST_MESSAGE_PREFIX, "\n"));
}
function isExecutionFailureMessage(message) {
    return message.author === 'system' && message.text.startsWith("".concat(CHAT_EXECUTION_FAILURE_MESSAGE_PREFIX, "\n"));
}
function isEmptyCodexExecutionResponse(text) {
    var normalized = text.replace(/\s+/g, ' ').trim();
    return normalized === 'Codex 실행 결과가 비어 있습니다.';
}
function extractActivityLogFailureReason(lines) {
    var normalizedLines = (lines !== null && lines !== void 0 ? lines : []).map(function (line) { return line.trim(); }).filter(Boolean);
    for (var index = normalizedLines.length - 1; index >= 0; index -= 1) {
        var line = normalizedLines[index];
        if (!line.startsWith('# 오류:')) {
            continue;
        }
        var raw = line.slice('# 오류:'.length).trim();
        if (!raw) {
            continue;
        }
        try {
            var parsed = JSON.parse(raw);
            var message = typeof parsed.message === 'string' ? parsed.message.trim() : '';
            if (message) {
                return message;
            }
        }
        catch (_a) {
            return raw;
        }
    }
    return '';
}
function buildExecutionFailureMessage(reason) {
    var normalizedReason = reason.trim();
    if (!normalizedReason) {
        return "".concat(CHAT_EXECUTION_FAILURE_MESSAGE_PREFIX, "\n\uC2E4\uD589 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
    }
    var simplifiedReason = normalizedReason.includes("mkdir '") && normalizedReason.includes('/resource/uploads')
        ? "\uC138\uC158 \uB9AC\uC18C\uC2A4 \uC5C5\uB85C\uB4DC \uD3F4\uB354\uB97C \uB9CC\uB4E4 \uAD8C\uD55C\uC774 \uC5C6\uC5B4 \uC751\uB2F5 \uC0DD\uC131\uC774 \uC911\uB2E8\uB418\uC5C8\uC2B5\uB2C8\uB2E4.\n\n\uC6D0\uC778: ".concat(normalizedReason)
        : "\uC2E4\uD589 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.\n\n\uC6D0\uC778: ".concat(normalizedReason);
    return "".concat(CHAT_EXECUTION_FAILURE_MESSAGE_PREFIX, "\n").concat(simplifiedReason);
}
function buildFailurePreviewText(reason) {
    var normalizedReason = reason.trim();
    if (!normalizedReason) {
        return '실행 실패';
    }
    if (normalizedReason.includes("mkdir '") && normalizedReason.includes('/resource/uploads')) {
        return '실행 실패: 세션 리소스 업로드 폴더 권한 오류';
    }
    return "\uC2E4\uD589 \uC2E4\uD328: ".concat(normalizedReason);
}
function enrichFailedRequestsWithActivityLogs(requests, activityLogs) {
    var activityLogMap = new Map(activityLogs.map(function (item) { return [item.requestId.trim(), item]; }));
    return requests.map(function (request) {
        var _a;
        if (request.status !== 'failed') {
            return request;
        }
        var activityLog = activityLogMap.get(request.requestId.trim());
        var failureReason = extractActivityLogFailureReason(activityLog === null || activityLog === void 0 ? void 0 : activityLog.lines);
        var normalizedStatusMessage = String((_a = request.statusMessage) !== null && _a !== void 0 ? _a : '').trim();
        if (!failureReason) {
            return request;
        }
        if (normalizedStatusMessage && normalizedStatusMessage !== '요청 처리 실패') {
            return request;
        }
        return __assign(__assign({}, request), { statusMessage: failureReason });
    });
}
function replaceGenericFailureMessages(messages, requests, activityLogs) {
    var requestMap = new Map(requests.map(function (item) { return [item.requestId.trim(), item]; }));
    var activityLogMap = new Map(activityLogs.map(function (item) { return [item.requestId.trim(), item]; }));
    return messages.map(function (message) {
        var _a, _b, _c;
        var requestId = (_b = (_a = message.clientRequestId) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : '';
        if (!requestId || message.author !== 'codex' || !isEmptyCodexExecutionResponse(message.text)) {
            return message;
        }
        var request = requestMap.get(requestId);
        if ((request === null || request === void 0 ? void 0 : request.status) !== 'failed') {
            return message;
        }
        var failureReason = extractActivityLogFailureReason((_c = activityLogMap.get(requestId)) === null || _c === void 0 ? void 0 : _c.lines);
        if (!failureReason) {
            return message;
        }
        return __assign(__assign({}, message), { author: 'system', text: buildExecutionFailureMessage(failureReason) });
    });
}
function resolveConversationFailurePreview(currentPreview, requests, activityLogs) {
    if (!isEmptyCodexExecutionResponse(currentPreview)) {
        return currentPreview;
    }
    var latestFailedRequest = __spreadArray([], requests, true).reverse()
        .find(function (request) { var _a; return request.status === 'failed' && isEmptyCodexExecutionResponse(String((_a = request.responseText) !== null && _a !== void 0 ? _a : '').trim()); });
    if (!latestFailedRequest) {
        return currentPreview;
    }
    var activityLog = activityLogs.find(function (item) { return item.requestId.trim() === latestFailedRequest.requestId.trim(); });
    var failureReason = extractActivityLogFailureReason(activityLog === null || activityLog === void 0 ? void 0 : activityLog.lines);
    if (!failureReason) {
        return currentPreview;
    }
    return buildFailurePreviewText(failureReason);
}
function extractActivityLogLines(text) {
    return text
        .slice("".concat(CHAT_ACTIVITY_MESSAGE_PREFIX, "\n").length)
        .split('\n\n')
        .map(function (line) { return line.trim(); })
        .filter(Boolean);
}
function getActivityLogLines(message) {
    if (!message || !isActivityLogMessage(message)) {
        return [];
    }
    return extractActivityLogLines(message.text);
}
function mergeActivityLines(existingLines, incomingLines) {
    var merged = [];
    for (var _i = 0, _a = __spreadArray(__spreadArray([], existingLines, true), incomingLines, true); _i < _a.length; _i++) {
        var line = _a[_i];
        var normalized = line.trim();
        if (!normalized || merged.at(-1) === normalized) {
            continue;
        }
        merged.push(normalized);
    }
    return merged;
}
function buildActivityMessageIndex(messages) {
    var indexByRequestId = new Map();
    messages.forEach(function (message, index) {
        var _a;
        var requestId = (_a = message.clientRequestId) === null || _a === void 0 ? void 0 : _a.trim();
        if (!requestId || !isActivityLogMessage(message)) {
            return;
        }
        indexByRequestId.set(requestId, index);
    });
    return indexByRequestId;
}
function findActivityAnchorIndex(messages, requestId) {
    var _a;
    var fallbackUserIndex = -1;
    for (var index = 0; index < messages.length; index += 1) {
        var message = messages[index];
        if (((_a = message.clientRequestId) === null || _a === void 0 ? void 0 : _a.trim()) !== requestId) {
            continue;
        }
        if (isActivityLogMessage(message)) {
            return index;
        }
        if (message.author === 'user') {
            fallbackUserIndex = index;
        }
    }
    return fallbackUserIndex >= 0 ? fallbackUserIndex + 1 : messages.length;
}
function upsertActivityLogMessage(messages, activityMessage) {
    var _a;
    var requestId = (_a = activityMessage.clientRequestId) === null || _a === void 0 ? void 0 : _a.trim();
    if (!requestId) {
        return messages;
    }
    var existingIndex = messages.findIndex(function (message) { var _a; return isActivityLogMessage(message) && ((_a = message.clientRequestId) === null || _a === void 0 ? void 0 : _a.trim()) === requestId; });
    if (existingIndex >= 0) {
        var nextMessages = __spreadArray([], messages, true);
        nextMessages[existingIndex] = activityMessage;
        return nextMessages;
    }
    var insertIndex = findActivityAnchorIndex(messages, requestId);
    return __spreadArray(__spreadArray(__spreadArray([], messages.slice(0, insertIndex), true), [activityMessage], false), messages.slice(insertIndex), true);
}
function hydrateActivityLogMessages(messages, activityLogs) {
    var _a, _b, _c, _d;
    if (activityLogs.length === 0) {
        return messages;
    }
    var nextMessages = __spreadArray([], messages, true);
    var _loop_1 = function (activityLog) {
        var requestId = (_a = activityLog.requestId) === null || _a === void 0 ? void 0 : _a.trim();
        if (!requestId) {
            return "continue";
        }
        var placeholder = createActivityLogPlaceholder(requestId, activityLog.lines);
        if (!placeholder) {
            return "continue";
        }
        var existingMessage = nextMessages.find(function (message) { var _a; return isActivityLogMessage(message) && ((_a = message.clientRequestId) === null || _a === void 0 ? void 0 : _a.trim()) === requestId; });
        var mergedLines = mergeActivityLines(getActivityLogLines(existingMessage), activityLog.lines);
        var nextActivityMessage = __assign(__assign(__assign({}, (existingMessage !== null && existingMessage !== void 0 ? existingMessage : placeholder)), placeholder), { text: (_c = (_b = createActivityLogPlaceholder(requestId, mergedLines)) === null || _b === void 0 ? void 0 : _b.text) !== null && _c !== void 0 ? _c : placeholder.text, timestamp: ((_d = activityLog.updatedAt) === null || _d === void 0 ? void 0 : _d.trim()) || (existingMessage === null || existingMessage === void 0 ? void 0 : existingMessage.timestamp) || placeholder.timestamp });
        nextMessages = upsertActivityLogMessage(nextMessages, nextActivityMessage);
    };
    for (var _i = 0, activityLogs_1 = activityLogs; _i < activityLogs_1.length; _i++) {
        var activityLog = activityLogs_1[_i];
        _loop_1(activityLog);
    }
    return nextMessages;
}
function appendActivityEventToMessages(previous, event) {
    var requestId = event.requestId.trim();
    if (!requestId) {
        return previous;
    }
    var activityMessageIndex = buildActivityMessageIndex(previous);
    var existingIndex = activityMessageIndex.get(requestId);
    var existingMessage = existingIndex == null ? undefined : previous[existingIndex];
    var mergedLines = mergeActivityLines(getActivityLogLines(existingMessage), [event.line]);
    var nextMessage = createActivityLogPlaceholder(requestId, mergedLines);
    if (!nextMessage) {
        return previous;
    }
    var nextActivityMessage = existingIndex == null
        ? nextMessage
        : __assign(__assign({}, existingMessage), nextMessage);
    return upsertActivityLogMessage(previous, nextActivityMessage);
}
function createIntroMessage(chatTypeLabel, chatTypeDescription) {
    var _a;
    var normalizedChatTypeLabel = (_a = chatTypeLabel === null || chatTypeLabel === void 0 ? void 0 : chatTypeLabel.trim()) !== null && _a !== void 0 ? _a : '';
    var contextLabelLine = normalizedChatTypeLabel && normalizedChatTypeLabel !== '일반 요청' && normalizedChatTypeLabel !== '기본처리'
        ? "\uC120\uD0DD \uCEE8\uD14D\uC2A4\uD2B8: ".concat(normalizedChatTypeLabel)
        : '';
    var contextDescriptionLine = chatTypeDescription ? "\uAE30\uBCF8 \uBB38\uB9E5: ".concat(chatTypeDescription) : '';
    return createChatMessage('codex', [exports.CHAT_CONNECTION.introMessage, contextLabelLine, contextDescriptionLine].filter(Boolean).join('\n'));
}
function buildOfflineReply(context, input) {
    var _a, _b;
    var normalized = input.toLowerCase();
    var normalizedChatTypeLabel = (_b = (_a = context.chatTypeLabel) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : '';
    var typeLine = normalizedChatTypeLabel && normalizedChatTypeLabel !== '일반 요청' && normalizedChatTypeLabel !== '기본처리'
        ? "- \uCEE8\uD14D\uC2A4\uD2B8: ".concat(normalizedChatTypeLabel)
        : '';
    var descriptionLine = context.chatTypeDescription ? "- \uAE30\uBCF8 \uBB38\uB9E5: ".concat(context.chatTypeDescription) : '';
    if (normalized.includes('preview') || normalized.includes('링크') || normalized.includes('url')) {
        return ['결과', "- preview: ".concat(context.pageUrl), typeLine, descriptionLine].filter(Boolean).join('\n');
    }
    if (input.includes('계획') || normalized.includes('plan')) {
        return ['결과', '- Plan 상세 조회는 서버 연결 후 가능합니다.', typeLine, descriptionLine].filter(Boolean).join('\n');
    }
    return ['결과', "- \uD604\uC7AC \uD654\uBA74: ".concat(context.pageTitle), '- 서버 연결 후 더 정확한 정보를 줄 수 있습니다.', typeLine, descriptionLine]
        .filter(Boolean)
        .join('\n');
}
function resolveChatWebSocketUrl(sessionId, lastEventId, clientId) {
    var configuredBaseUrl = import.meta.env.VITE_WORK_SERVER_URL;
    var resolvedClientId = clientId || (0, clientIdentity_1.getOrCreateClientId)();
    var accessToken = (0, tokenAccess_1.getRegisteredAccessToken)();
    if (typeof window === 'undefined') {
        return '';
    }
    if (configuredBaseUrl) {
        var normalizedUrl = new URL(configuredBaseUrl, window.location.origin);
        normalizedUrl.protocol = normalizedUrl.protocol === 'https:' ? 'wss:' : 'ws:';
        var trimmedPathname = normalizedUrl.pathname.replace(/\/+$/, '');
        normalizedUrl.pathname = trimmedPathname.endsWith('/api')
            ? "".concat(trimmedPathname.slice(0, -4) || '', "/ws/chat")
            : "".concat(trimmedPathname || '', "/ws/chat");
        normalizedUrl.search = '';
        normalizedUrl.hash = '';
        if (sessionId) {
            normalizedUrl.searchParams.set('sessionId', sessionId);
        }
        if (resolvedClientId) {
            normalizedUrl.searchParams.set('clientId', resolvedClientId);
        }
        if (accessToken) {
            normalizedUrl.searchParams.set('accessToken', accessToken);
        }
        if (Number.isFinite(lastEventId) && (lastEventId !== null && lastEventId !== void 0 ? lastEventId : 0) > 0) {
            normalizedUrl.searchParams.set('lastEventId', String(lastEventId));
        }
        return normalizedUrl.toString();
    }
    var protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    var url = new URL("".concat(protocol, "//").concat(window.location.host, "/ws/chat"));
    if (sessionId) {
        url.searchParams.set('sessionId', sessionId);
    }
    if (resolvedClientId) {
        url.searchParams.set('clientId', resolvedClientId);
    }
    if (accessToken) {
        url.searchParams.set('accessToken', accessToken);
    }
    if (Number.isFinite(lastEventId) && (lastEventId !== null && lastEventId !== void 0 ? lastEventId : 0) > 0) {
        url.searchParams.set('lastEventId', String(lastEventId));
    }
    return url.toString();
}
function resolveWorkServerHealthUrl() {
    var configuredBaseUrl = import.meta.env.VITE_WORK_SERVER_URL;
    if (typeof window === 'undefined') {
        return '';
    }
    var normalizedUrl = configuredBaseUrl
        ? new URL(configuredBaseUrl, window.location.origin)
        : new URL(window.location.origin);
    var trimmedPathname = normalizedUrl.pathname.replace(/\/+$/, '');
    normalizedUrl.pathname = trimmedPathname.endsWith('/api')
        ? "".concat(trimmedPathname.slice(0, -4) || '', "/health")
        : "".concat(trimmedPathname || '', "/health");
    normalizedUrl.search = '';
    normalizedUrl.hash = '';
    return normalizedUrl.toString();
}
function diagnoseConnectionFailure(targetUrl, closeEvent) {
    return __awaiter(this, void 0, void 0, function () {
        var diagnostics, healthUrl, response, error_1;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    diagnostics = [];
                    if (typeof navigator !== 'undefined' && !navigator.onLine) {
                        diagnostics.push('브라우저가 오프라인 상태입니다.');
                    }
                    if (typeof window !== 'undefined' && window.location.protocol === 'https:' && targetUrl.startsWith('ws://')) {
                        diagnostics.push('HTTPS 화면에서 비보안 `ws://` 연결이 차단되었을 수 있습니다.');
                    }
                    if (closeEvent) {
                        diagnostics.push("\uC885\uB8CC \uCF54\uB4DC ".concat(closeEvent.code).concat(closeEvent.reason ? " (".concat(closeEvent.reason, ")") : ''));
                    }
                    healthUrl = resolveWorkServerHealthUrl();
                    if (!healthUrl) return [3 /*break*/, 4];
                    _a.label = 1;
                case 1:
                    _a.trys.push([1, 3, , 4]);
                    return [4 /*yield*/, fetch(healthUrl, {
                            cache: 'no-store',
                        })];
                case 2:
                    response = _a.sent();
                    if (response.ok) {
                        diagnostics.push("\uD5EC\uC2A4\uCCB4\uD06C \uC131\uACF5: ".concat(healthUrl));
                        diagnostics.push("HTTP \uC11C\uBC84\uB294 \uC751\uB2F5 \uC911\uC785\uB2C8\uB2E4. WebSocket \uC5F0\uACB0 \uB300\uC0C1: ".concat(targetUrl));
                        diagnostics.push('WebSocket 업그레이드 또는 프록시 설정을 확인해 주세요.');
                    }
                    else {
                        diagnostics.push("\uD5EC\uC2A4\uCCB4\uD06C \uC2E4\uD328: ".concat(response.status, " ").concat(response.statusText));
                    }
                    return [3 /*break*/, 4];
                case 3:
                    error_1 = _a.sent();
                    diagnostics.push("\uD5EC\uC2A4\uCCB4\uD06C \uC694\uCCAD \uC2E4\uD328: ".concat(error_1 instanceof Error ? error_1.message : '서버에 도달하지 못했습니다.'));
                    return [3 /*break*/, 4];
                case 4: return [2 /*return*/, diagnostics.join(' / ')];
            }
        });
    });
}
function copyText(text) {
    return __awaiter(this, void 0, void 0, function () {
        var textarea, copied;
        var _a;
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    if (!(typeof navigator !== 'undefined' && ((_a = navigator.clipboard) === null || _a === void 0 ? void 0 : _a.writeText))) return [3 /*break*/, 2];
                    return [4 /*yield*/, navigator.clipboard.writeText(text)];
                case 1:
                    _b.sent();
                    return [2 /*return*/];
                case 2:
                    if (typeof document === 'undefined') {
                        throw new Error('클립보드를 사용할 수 없습니다.');
                    }
                    textarea = document.createElement('textarea');
                    textarea.value = text;
                    textarea.setAttribute('readonly', '');
                    textarea.style.position = 'fixed';
                    textarea.style.opacity = '0';
                    document.body.appendChild(textarea);
                    textarea.select();
                    try {
                        copied = document.execCommand('copy');
                        if (!copied) {
                            throw new Error('복사 명령이 거부되었습니다.');
                        }
                    }
                    finally {
                        document.body.removeChild(textarea);
                    }
                    return [2 /*return*/];
            }
        });
    });
}
function copyImagePreview(url) {
    return __awaiter(this, void 0, void 0, function () {
        var response, imageBlob;
        var _a;
        var _b;
        return __generator(this, function (_c) {
            switch (_c.label) {
                case 0: return [4 /*yield*/, fetch(url, {
                        cache: 'no-store',
                    })];
                case 1:
                    response = _c.sent();
                    if (!response.ok) {
                        throw new Error("preview \uC774\uBBF8\uC9C0\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. (".concat(response.status, ")"));
                    }
                    return [4 /*yield*/, response.blob()];
                case 2:
                    imageBlob = _c.sent();
                    if (!imageBlob.type.startsWith('image/')) {
                        throw new Error('이미지 preview만 이미지 자체를 복사할 수 있습니다.');
                    }
                    if (!(typeof navigator !== 'undefined' && ((_b = navigator.clipboard) === null || _b === void 0 ? void 0 : _b.write) && typeof ClipboardItem !== 'undefined')) return [3 /*break*/, 4];
                    return [4 /*yield*/, navigator.clipboard.write([
                            new ClipboardItem((_a = {},
                                _a[imageBlob.type] = imageBlob,
                                _a)),
                        ])];
                case 3:
                    _c.sent();
                    return [2 /*return*/, 'image'];
                case 4: return [4 /*yield*/, copyText(url)];
                case 5:
                    _c.sent();
                    return [2 /*return*/, 'url'];
            }
        });
    });
}
function canCopyPreviewBody(kind) {
    return !['image', 'video', 'pdf', 'file'].includes(String(kind !== null && kind !== void 0 ? kind : '').trim().toLowerCase());
}
function copyPreviewContent(_a) {
    return __awaiter(this, arguments, void 0, function (_b) {
        var normalizedKind, previewBody;
        var kind = _b.kind, url = _b.url, fallbackText = _b.fallbackText;
        return __generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    normalizedKind = String(kind !== null && kind !== void 0 ? kind : '').trim().toLowerCase();
                    if (normalizedKind === 'image') {
                        return [2 /*return*/, copyImagePreview(url)];
                    }
                    return [4 /*yield*/, resolvePreviewBodyForCopy({
                            kind: kind,
                            url: url,
                            fallbackText: fallbackText,
                        })];
                case 1:
                    previewBody = _c.sent();
                    return [4 /*yield*/, copyText(previewBody)];
                case 2:
                    _c.sent();
                    return [2 /*return*/, 'text'];
            }
        });
    });
}
function resolvePreviewBodyForCopy(_a) {
    return __awaiter(this, arguments, void 0, function (_b) {
        var normalizedFallbackText, response, bodyText, error_2;
        var kind = _b.kind, url = _b.url, fallbackText = _b.fallbackText;
        return __generator(this, function (_c) {
            switch (_c.label) {
                case 0:
                    normalizedFallbackText = String(fallbackText !== null && fallbackText !== void 0 ? fallbackText : '');
                    if (!canCopyPreviewBody(kind)) {
                        throw new Error('이 미리보기는 본문 텍스트를 복사할 수 없습니다.');
                    }
                    _c.label = 1;
                case 1:
                    _c.trys.push([1, 4, , 5]);
                    return [4 /*yield*/, fetch(url, {
                            cache: 'no-store',
                        })];
                case 2:
                    response = _c.sent();
                    if (!response.ok) {
                        throw new Error("preview \uBCF8\uBB38\uC744 \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. (".concat(response.status, ")"));
                    }
                    return [4 /*yield*/, response.text()];
                case 3:
                    bodyText = _c.sent();
                    if (bodyText.trim()) {
                        return [2 /*return*/, bodyText];
                    }
                    return [3 /*break*/, 5];
                case 4:
                    error_2 = _c.sent();
                    if (!normalizedFallbackText.trim()) {
                        throw error_2;
                    }
                    return [3 /*break*/, 5];
                case 5:
                    if (normalizedFallbackText.trim()) {
                        return [2 /*return*/, normalizedFallbackText];
                    }
                    throw new Error('복사할 preview 본문이 없습니다.');
            }
        });
    });
}
function resolveChatApiBaseUrl() {
    if (import.meta.env.VITE_WORK_SERVER_URL) {
        return import.meta.env.VITE_WORK_SERVER_URL;
    }
    return '/api';
}
function requestChatApi(path, init) {
    return __awaiter(this, void 0, void 0, function () {
        var headers, accessToken, method, controller, timeoutId, response, error_3, text_1, payload, normalizedMessage, text;
        var _a, _b, _c, _d;
        return __generator(this, function (_e) {
            switch (_e.label) {
                case 0:
                    headers = (0, clientIdentity_1.appendClientIdHeader)(init === null || init === void 0 ? void 0 : init.headers);
                    accessToken = (0, tokenAccess_1.getRegisteredAccessToken)();
                    method = (_b = (_a = init === null || init === void 0 ? void 0 : init.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) !== null && _b !== void 0 ? _b : 'GET';
                    controller = new AbortController();
                    timeoutId = window.setTimeout(function () { return controller.abort(); }, 8000);
                    if (!(0, tokenAccess_1.hasRegisteredAccessTokenAccess)()) {
                        window.clearTimeout(timeoutId);
                        throw new Error('등록된 접근 토큰이 없어 채팅 요청을 보낼 수 없습니다.');
                    }
                    if (accessToken && !headers.has('X-Access-Token')) {
                        headers.set('X-Access-Token', accessToken);
                    }
                    if ((init === null || init === void 0 ? void 0 : init.body) != null && !headers.has('Content-Type')) {
                        headers.set('Content-Type', 'application/json');
                    }
                    if (method === 'GET') {
                        if (!headers.has('Cache-Control')) {
                            headers.set('Cache-Control', 'no-store, no-cache, max-age=0');
                        }
                        if (!headers.has('Pragma')) {
                            headers.set('Pragma', 'no-cache');
                        }
                    }
                    _e.label = 1;
                case 1:
                    _e.trys.push([1, 3, , 4]);
                    return [4 /*yield*/, fetch("".concat(resolveChatApiBaseUrl(), "/chat").concat(path), __assign(__assign({}, init), { headers: headers, signal: controller.signal, cache: (_c = init === null || init === void 0 ? void 0 : init.cache) !== null && _c !== void 0 ? _c : (method === 'GET' ? 'no-store' : undefined) }))];
                case 2:
                    response = _e.sent();
                    return [3 /*break*/, 4];
                case 3:
                    error_3 = _e.sent();
                    window.clearTimeout(timeoutId);
                    if (error_3 instanceof DOMException && error_3.name === 'AbortError') {
                        throw new Error('채팅 서버 응답이 지연됩니다.');
                    }
                    throw new Error('채팅 서버 연결에 실패했습니다.');
                case 4:
                    window.clearTimeout(timeoutId);
                    if (!!response.ok) return [3 /*break*/, 6];
                    return [4 /*yield*/, response.text()];
                case 5:
                    text_1 = _e.sent();
                    if (text_1.trim()) {
                        try {
                            payload = JSON.parse(text_1);
                            normalizedMessage = String((_d = payload.message) !== null && _d !== void 0 ? _d : '').trim();
                            if (normalizedMessage) {
                                throw new Error(normalizedMessage === 'fetch failed' ? '채팅 서버 연결에 실패했습니다.' : normalizedMessage);
                            }
                        }
                        catch (error) {
                            if (error instanceof Error && error.message) {
                                throw error;
                            }
                        }
                    }
                    throw new Error('채팅 API 요청에 실패했습니다.');
                case 6: return [4 /*yield*/, response.text()];
                case 7:
                    text = _e.sent();
                    if (!text.trim()) {
                        throw new Error('채팅 서버 응답이 비어 있습니다.');
                    }
                    try {
                        return [2 /*return*/, JSON.parse(text)];
                    }
                    catch (_f) {
                        throw new Error('채팅 서버 응답을 해석하지 못했습니다.');
                    }
                    return [2 /*return*/];
            }
        });
    });
}
function readFileAsBase64(file) {
    return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
            return [2 /*return*/, new Promise(function (resolve, reject) {
                    var reader = new FileReader();
                    reader.onload = function () {
                        if (typeof reader.result !== 'string') {
                            reject(new Error('파일 내용을 읽지 못했습니다.'));
                            return;
                        }
                        var commaIndex = reader.result.indexOf(',');
                        resolve(commaIndex >= 0 ? reader.result.slice(commaIndex + 1) : reader.result);
                    };
                    reader.onerror = function () {
                        var _a;
                        reject((_a = reader.error) !== null && _a !== void 0 ? _a : new Error('파일 내용을 읽지 못했습니다.'));
                    };
                    reader.readAsDataURL(file);
                })];
        });
    });
}
var FALLBACK_UPLOAD_MIME_BY_EXTENSION = {
    zip: 'application/zip',
    heic: 'image/heic',
    heif: 'image/heif',
    jpg: 'image/jpeg',
    jpeg: 'image/jpeg',
    png: 'image/png',
    webp: 'image/webp',
    gif: 'image/gif',
    pdf: 'application/pdf',
};
function resolveUploadMimeType(file) {
    var _a, _b, _c, _d;
    var normalizedName = String((_a = file.name) !== null && _a !== void 0 ? _a : '').trim().toLowerCase();
    var extension = normalizedName.includes('.') ? (_c = (_b = normalizedName.split('.').pop()) === null || _b === void 0 ? void 0 : _b.trim()) !== null && _c !== void 0 ? _c : '' : '';
    var normalizedType = String((_d = file.type) !== null && _d !== void 0 ? _d : '').trim().toLowerCase();
    if (normalizedType && normalizedType !== 'application/octet-stream') {
        return normalizedType;
    }
    if (extension && FALLBACK_UPLOAD_MIME_BY_EXTENSION[extension]) {
        return FALLBACK_UPLOAD_MIME_BY_EXTENSION[extension];
    }
    return normalizedType || 'application/octet-stream';
}
function fetchChatConversations() {
    return __awaiter(this, void 0, void 0, function () {
        var clientId;
        return __generator(this, function (_a) {
            if (chatConversationListRequestPromise) {
                return [2 /*return*/, chatConversationListRequestPromise];
            }
            clientId = (0, clientIdentity_1.getOrCreateClientId)();
            chatConversationListRequestPromise = requestChatApi('/conversations')
                .then(function (response) {
                return sortChatConversationSummaries(response.items.map(function (item) { return (__assign(__assign({}, item), { notifyOffline: resolveSyncedChatOfflineNotificationSetting(item.sessionId, item.notifyOffline, clientId) })); }));
            })
                .finally(function () {
                chatConversationListRequestPromise = null;
            });
            return [2 /*return*/, chatConversationListRequestPromise];
        });
    });
}
function fetchChatConversationDetail(sessionId_1) {
    return __awaiter(this, arguments, void 0, function (sessionId, options) {
        var clientId, query, response, normalizedRequests, visibleRequestIds, hydratedMessages, recoveredMessages;
        var _a;
        if (options === void 0) { options = {}; }
        return __generator(this, function (_b) {
            switch (_b.label) {
                case 0:
                    clientId = (0, clientIdentity_1.getOrCreateClientId)();
                    query = new URLSearchParams();
                    if (options.limit != null) {
                        query.set('limit', String(options.limit));
                    }
                    if (Number.isFinite(options.beforeMessageId) && ((_a = options.beforeMessageId) !== null && _a !== void 0 ? _a : 0) > 0) {
                        query.set('beforeMessageId', String(options.beforeMessageId));
                    }
                    return [4 /*yield*/, requestChatApi("/conversations/".concat(encodeURIComponent(sessionId)).concat(query.toString() ? "?".concat(query.toString()) : ''))];
                case 1:
                    response = _b.sent();
                    normalizedRequests = enrichFailedRequestsWithActivityLogs(response.requests.map(function (item) { return normalizeChatConversationRequest(item); }), response.activityLogs);
                    visibleRequestIds = new Set(response.messages
                        .map(function (message) { var _a, _b; return (_b = (_a = message.clientRequestId) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : ''; })
                        .filter(Boolean));
                    hydratedMessages = hydrateActivityLogMessages(replaceGenericFailureMessages(response.messages, normalizedRequests, response.activityLogs), response.activityLogs.filter(function (item) { var _a, _b; return visibleRequestIds.has((_b = (_a = item.requestId) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : ''); })).filter(function (message) {
                        return message.author !== 'system' ||
                            isActivityLogMessage(message) ||
                            isMissingRequestMessage(message) ||
                            isExecutionFailureMessage(message);
                    });
                    recoveredMessages = buildRecoveredMessagesFromConversationDetail(normalizedRequests, response.activityLogs);
                    return [2 /*return*/, __assign(__assign({}, response), { messages: mergeRecoveredChatMessages(recoveredMessages, hydratedMessages), item: __assign(__assign({}, response.item), { lastMessagePreview: resolveConversationFailurePreview(response.item.lastMessagePreview, normalizedRequests, response.activityLogs), notifyOffline: resolveSyncedChatOfflineNotificationSetting(response.item.sessionId, response.item.notifyOffline, clientId) }), requests: normalizedRequests })];
            }
        });
    });
}
function fetchChatRuntimeSnapshot() {
    return __awaiter(this, void 0, void 0, function () {
        var response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, requestChatApi('/runtime')];
                case 1:
                    response = _a.sent();
                    return [2 /*return*/, response.item];
            }
        });
    });
}
function fetchChatRuntimeJobDetail(requestId) {
    return __awaiter(this, void 0, void 0, function () {
        var response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, requestChatApi("/runtime/jobs/".concat(encodeURIComponent(requestId)))];
                case 1:
                    response = _a.sent();
                    return [2 /*return*/, response.item];
            }
        });
    });
}
function cancelChatRuntimeJob(requestId) {
    return __awaiter(this, void 0, void 0, function () {
        var response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, requestChatApi("/runtime/jobs/".concat(encodeURIComponent(requestId), "/cancel"), {
                        method: 'POST',
                    })];
                case 1:
                    response = _a.sent();
                    return [2 /*return*/, response.cancelled];
            }
        });
    });
}
function removeChatRuntimeJob(requestId) {
    return __awaiter(this, void 0, void 0, function () {
        var response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, requestChatApi("/runtime/jobs/".concat(encodeURIComponent(requestId), "/remove"), {
                        method: 'POST',
                    })];
                case 1:
                    response = _a.sent();
                    return [2 /*return*/, response.removed];
            }
        });
    });
}
function rollbackChatRuntimeJob(requestId, sessionId) {
    return __awaiter(this, void 0, void 0, function () {
        var response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, requestChatApi("/runtime/jobs/".concat(encodeURIComponent(requestId), "/rollback"), {
                        method: 'POST',
                        body: JSON.stringify({
                            sessionId: (sessionId === null || sessionId === void 0 ? void 0 : sessionId.trim()) || undefined,
                        }),
                    })];
                case 1:
                    response = _a.sent();
                    return [2 /*return*/, response.rolledBack];
            }
        });
    });
}
function uploadChatComposerFile(sessionId, file) {
    return __awaiter(this, void 0, void 0, function () {
        var normalizedSessionId, resolvedMimeType, reportUploadFailure, uploadError, uploadError, uploadError, contentBase64, error_4, message, uploadError, response, error_5, uploadError;
        var _this = this;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    normalizedSessionId = sessionId.trim();
                    resolvedMimeType = resolveUploadMimeType(file);
                    reportUploadFailure = function (stage, error) { return __awaiter(_this, void 0, void 0, function () {
                        return __generator(this, function (_a) {
                            switch (_a.label) {
                                case 0: return [4 /*yield*/, (0, errorLogApi_1.reportClientError)({
                                        errorType: 'chat:composer-upload',
                                        errorName: error.name,
                                        errorMessage: error.message,
                                        requestMethod: 'POST',
                                        requestPath: '/api/chat/attachments',
                                        context: {
                                            stage: stage,
                                            sessionId: normalizedSessionId || null,
                                            fileName: file.name,
                                            fileSize: file.size,
                                            fileType: file.type || null,
                                            resolvedMimeType: resolvedMimeType,
                                        },
                                    })];
                                case 1:
                                    _a.sent();
                                    return [2 /*return*/];
                            }
                        });
                    }); };
                    if (!!normalizedSessionId) return [3 /*break*/, 2];
                    uploadError = new Error('채팅 세션이 준비되지 않았습니다.');
                    return [4 /*yield*/, reportUploadFailure('validate-session', uploadError)];
                case 1:
                    _a.sent();
                    throw uploadError;
                case 2:
                    if (!(file.size <= 0)) return [3 /*break*/, 4];
                    uploadError = new Error('업로드할 파일 내용을 찾지 못했습니다.');
                    return [4 /*yield*/, reportUploadFailure('validate-file', uploadError)];
                case 3:
                    _a.sent();
                    throw uploadError;
                case 4:
                    if (!(file.size > CHAT_COMPOSER_UPLOAD_FILE_SIZE_LIMIT)) return [3 /*break*/, 6];
                    uploadError = new Error("\uCCA8\uBD80 \uD30C\uC77C\uC740 10MB \uC774\uD558\uB9CC \uC5C5\uB85C\uB4DC\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. (".concat(file.name, ")"));
                    return [4 /*yield*/, reportUploadFailure('validate-file', uploadError)];
                case 5:
                    _a.sent();
                    throw uploadError;
                case 6:
                    contentBase64 = '';
                    _a.label = 7;
                case 7:
                    _a.trys.push([7, 9, , 11]);
                    return [4 /*yield*/, readFileAsBase64(file)];
                case 8:
                    contentBase64 = _a.sent();
                    return [3 /*break*/, 11];
                case 9:
                    error_4 = _a.sent();
                    message = error_4 instanceof Error && error_4.message.trim() ? error_4.message.trim() : '파일 내용을 읽지 못했습니다.';
                    uploadError = new Error("".concat(message, " (").concat(file.name, ")"));
                    uploadError.name = error_4 instanceof Error && error_4.name ? error_4.name : 'FileReadError';
                    return [4 /*yield*/, reportUploadFailure('read-file', uploadError)];
                case 10:
                    _a.sent();
                    throw uploadError;
                case 11:
                    _a.trys.push([11, 13, , 15]);
                    return [4 /*yield*/, requestChatApi('/attachments', {
                            method: 'POST',
                            body: JSON.stringify({
                                sessionId: normalizedSessionId,
                                fileName: file.name,
                                mimeType: resolvedMimeType,
                                contentBase64: contentBase64,
                            }),
                        })];
                case 12:
                    response = _a.sent();
                    return [2 /*return*/, response.item];
                case 13:
                    error_5 = _a.sent();
                    uploadError = error_5 instanceof Error && error_5.message.trim()
                        ? error_5
                        : new Error("".concat(file.name, " \uC5C5\uB85C\uB4DC\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4."));
                    return [4 /*yield*/, reportUploadFailure('upload-request', uploadError)];
                case 14:
                    _a.sent();
                    throw uploadError;
                case 15: return [2 /*return*/];
            }
        });
    });
}
function createChatConversationRoom(args) {
    return __awaiter(this, void 0, void 0, function () {
        var clientId, notifyOffline, response;
        var _a, _b, _c, _d, _e, _f, _g, _h;
        return __generator(this, function (_j) {
            switch (_j.label) {
                case 0:
                    clientId = (0, clientIdentity_1.getOrCreateClientId)();
                    notifyOffline = (_a = args.notifyOffline) !== null && _a !== void 0 ? _a : true;
                    return [4 /*yield*/, requestChatApi('/conversations', {
                            method: 'POST',
                            body: JSON.stringify({
                                sessionId: args.sessionId,
                                title: (_b = args.title) !== null && _b !== void 0 ? _b : '새 대화',
                                chatTypeId: (_c = args.chatTypeId) !== null && _c !== void 0 ? _c : null,
                                lastChatTypeId: (_e = (_d = args.lastChatTypeId) !== null && _d !== void 0 ? _d : args.chatTypeId) !== null && _e !== void 0 ? _e : null,
                                generalSectionName: (_f = args.generalSectionName) !== null && _f !== void 0 ? _f : null,
                                contextLabel: (_g = args.contextLabel) !== null && _g !== void 0 ? _g : null,
                                contextDescription: (_h = args.contextDescription) !== null && _h !== void 0 ? _h : null,
                                notifyOffline: notifyOffline,
                                clientId: clientId,
                            }),
                        })];
                case 1:
                    response = _j.sent();
                    invalidateChatConversationListCache();
                    return [2 /*return*/, __assign(__assign({}, response.item), { notifyOffline: resolveSyncedChatOfflineNotificationSetting(response.item.sessionId, response.item.notifyOffline, clientId) })];
            }
        });
    });
}
function renameChatConversationRoom(sessionId, title) {
    return __awaiter(this, void 0, void 0, function () {
        var response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, requestChatApi("/conversations/".concat(encodeURIComponent(sessionId)), {
                        method: 'PATCH',
                        body: JSON.stringify({
                            title: title,
                        }),
                    })];
                case 1:
                    response = _a.sent();
                    invalidateChatConversationListCache();
                    return [2 /*return*/, response.item];
            }
        });
    });
}
function updateChatConversationRoom(sessionId, payload) {
    return __awaiter(this, void 0, void 0, function () {
        var clientId, response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    clientId = (0, clientIdentity_1.getOrCreateClientId)();
                    return [4 /*yield*/, requestChatApi("/conversations/".concat(encodeURIComponent(sessionId)), {
                            method: 'PATCH',
                            body: JSON.stringify(payload),
                        })];
                case 1:
                    response = _a.sent();
                    invalidateChatConversationListCache();
                    return [2 /*return*/, __assign(__assign({}, response.item), { notifyOffline: resolveSyncedChatOfflineNotificationSetting(response.item.sessionId, response.item.notifyOffline, clientId) })];
            }
        });
    });
}
function markChatConversationResponsesRead(sessionId) {
    return __awaiter(this, void 0, void 0, function () {
        var response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, requestChatApi("/conversations/".concat(encodeURIComponent(sessionId), "/read"), {
                        method: 'POST',
                    })];
                case 1:
                    response = _a.sent();
                    return [2 /*return*/, response];
            }
        });
    });
}
function deleteChatConversationRoom(sessionId) {
    return __awaiter(this, void 0, void 0, function () {
        var response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, requestChatApi("/conversations/".concat(encodeURIComponent(sessionId)), {
                        method: 'DELETE',
                    })];
                case 1:
                    response = _a.sent();
                    invalidateChatConversationListCache();
                    return [2 /*return*/, response];
            }
        });
    });
}
function deleteChatConversationRequest(sessionId, requestId) {
    return __awaiter(this, void 0, void 0, function () {
        var response;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, requestChatApi("/conversations/".concat(encodeURIComponent(sessionId), "/requests/").concat(encodeURIComponent(requestId)), {
                        method: 'DELETE',
                    })];
                case 1:
                    response = _a.sent();
                    return [2 /*return*/, response];
            }
        });
    });
}
function areChatMessagesEquivalent(left, right) {
    if (left.length !== right.length) {
        return false;
    }
    return left.every(function (message, index) {
        var other = right[index];
        return (other &&
            message.id === other.id &&
            message.author === other.author &&
            message.text === other.text &&
            message.timestamp === other.timestamp);
    });
}
function upsertChatMessage(previous, incoming) {
    var _a, _b, _c, _d;
    var existingIndex = previous.findIndex(function (message) {
        return message.id === incoming.id ||
            Boolean(incoming.clientRequestId &&
                message.clientRequestId &&
                (incoming.author === 'user' || incoming.author === 'codex') &&
                (message.author === 'user' || message.author === 'codex') &&
                incoming.author === message.author &&
                incoming.clientRequestId === message.clientRequestId);
    });
    if (existingIndex < 0) {
        return __spreadArray(__spreadArray([], previous, true), [incoming], false);
    }
    var nextMessages = __spreadArray([], previous, true);
    var existingMessage = nextMessages[existingIndex];
    var nextText = isActivityLogMessage(existingMessage) && isActivityLogMessage(incoming)
        ? (_d = (_c = createActivityLogPlaceholder((_b = (_a = incoming.clientRequestId) !== null && _a !== void 0 ? _a : existingMessage.clientRequestId) !== null && _b !== void 0 ? _b : '', mergeActivityLines(getActivityLogLines(existingMessage), getActivityLogLines(incoming)))) === null || _c === void 0 ? void 0 : _c.text) !== null && _d !== void 0 ? _d : incoming.text
        : incoming.text;
    nextMessages[existingIndex] = __assign(__assign(__assign({}, existingMessage), incoming), { text: nextText, deliveryStatus: null, retryCount: 0 });
    return nextMessages;
}
function isSameChatMessage(left, right) {
    if (left.id === right.id) {
        return true;
    }
    if (isActivityLogMessage(left) && isActivityLogMessage(right)) {
        return Boolean(left.clientRequestId && right.clientRequestId && left.clientRequestId === right.clientRequestId);
    }
    if (isMissingRequestMessage(left) && isMissingRequestMessage(right)) {
        return Boolean(left.clientRequestId && right.clientRequestId && left.clientRequestId === right.clientRequestId);
    }
    if (isExecutionFailureMessage(left) && isExecutionFailureMessage(right)) {
        return Boolean(left.clientRequestId && right.clientRequestId && left.clientRequestId === right.clientRequestId);
    }
    return Boolean((left.author === 'user' || left.author === 'codex') &&
        left.author === right.author &&
        left.clientRequestId &&
        right.clientRequestId &&
        left.clientRequestId === right.clientRequestId);
}
function buildComparableChatMessageKey(message) {
    if (isActivityLogMessage(message) && message.clientRequestId) {
        return "activity:".concat(message.clientRequestId);
    }
    if (isMissingRequestMessage(message) && message.clientRequestId) {
        return "missing-request:".concat(message.clientRequestId);
    }
    if (isExecutionFailureMessage(message) && message.clientRequestId) {
        return "execution-failure:".concat(message.clientRequestId);
    }
    if (message.author === 'user' && message.clientRequestId) {
        return "user-request:".concat(message.clientRequestId);
    }
    if (message.author === 'codex' && message.clientRequestId) {
        return "codex-request:".concat(message.clientRequestId);
    }
    return "id:".concat(message.id);
}
function getComparableChatMessageTime(message) {
    var _a;
    var parsed = Date.parse(String((_a = message.timestamp) !== null && _a !== void 0 ? _a : '').trim());
    return Number.isFinite(parsed) ? parsed : 0;
}
function getChatMessageRequestId(message) {
    var _a;
    return ((_a = message.clientRequestId) === null || _a === void 0 ? void 0 : _a.trim()) || '';
}
function getChatMessageOrderRank(message) {
    if (message.author === 'user') {
        return 0;
    }
    if (isMissingRequestMessage(message)) {
        return 1;
    }
    if (isExecutionFailureMessage(message)) {
        return 2;
    }
    if (isActivityLogMessage(message)) {
        return 3;
    }
    if (message.author === 'codex') {
        return 3;
    }
    return 4;
}
function sortConversationMessages(messages) {
    if (messages.length <= 1) {
        return messages;
    }
    var messageIndexMap = new Map(messages.map(function (message, index) { return [message, index]; }));
    var requestOrder = new Map();
    messages.forEach(function (message, index) {
        var requestId = getChatMessageRequestId(message);
        if (!requestId) {
            return;
        }
        var time = getComparableChatMessageTime(message);
        var existing = requestOrder.get(requestId);
        if (!existing) {
            requestOrder.set(requestId, {
                time: time,
                firstIndex: index,
            });
            return;
        }
        requestOrder.set(requestId, {
            time: existing.time > 0 && time > 0
                ? Math.min(existing.time, time)
                : existing.time > 0
                    ? existing.time
                    : time,
            firstIndex: Math.min(existing.firstIndex, index),
        });
    });
    return __spreadArray([], messages, true).sort(function (left, right) {
        var _a, _b, _c, _d, _e, _f;
        var leftRequestId = getChatMessageRequestId(left);
        var rightRequestId = getChatMessageRequestId(right);
        if (leftRequestId && rightRequestId && leftRequestId === rightRequestId) {
            var rankDiff = getChatMessageOrderRank(left) - getChatMessageOrderRank(right);
            if (rankDiff !== 0) {
                return rankDiff;
            }
        }
        var leftOrder = leftRequestId ? requestOrder.get(leftRequestId) : null;
        var rightOrder = rightRequestId ? requestOrder.get(rightRequestId) : null;
        var leftTime = (_a = leftOrder === null || leftOrder === void 0 ? void 0 : leftOrder.time) !== null && _a !== void 0 ? _a : getComparableChatMessageTime(left);
        var rightTime = (_b = rightOrder === null || rightOrder === void 0 ? void 0 : rightOrder.time) !== null && _b !== void 0 ? _b : getComparableChatMessageTime(right);
        if (leftTime !== rightTime) {
            return leftTime - rightTime;
        }
        var leftIndex = (_d = (_c = leftOrder === null || leftOrder === void 0 ? void 0 : leftOrder.firstIndex) !== null && _c !== void 0 ? _c : messageIndexMap.get(left)) !== null && _d !== void 0 ? _d : 0;
        var rightIndex = (_f = (_e = rightOrder === null || rightOrder === void 0 ? void 0 : rightOrder.firstIndex) !== null && _e !== void 0 ? _e : messageIndexMap.get(right)) !== null && _f !== void 0 ? _f : 0;
        if (leftIndex !== rightIndex) {
            return leftIndex - rightIndex;
        }
        if (leftRequestId && rightRequestId && leftRequestId !== rightRequestId) {
            var requestDiff = leftRequestId.localeCompare(rightRequestId, 'ko-KR');
            if (requestDiff !== 0) {
                return requestDiff;
            }
        }
        var messageTimeDiff = getComparableChatMessageTime(left) - getComparableChatMessageTime(right);
        if (messageTimeDiff !== 0) {
            return messageTimeDiff;
        }
        return left.id - right.id;
    });
}
function buildRecoveredMessagesFromConversationDetail(requests, activityLogs) {
    var nextMessages = [];
    var activityLogMap = new Map(activityLogs.map(function (item) { return [item.requestId.trim(), item]; }));
    requests.forEach(function (request) {
        var _a, _b, _c, _d, _e;
        var requestId = request.requestId.trim();
        if (!requestId || request.status === 'removed') {
            return;
        }
        var userText = String((_a = request.userText) !== null && _a !== void 0 ? _a : '').trim();
        var responseText = String((_b = request.responseText) !== null && _b !== void 0 ? _b : '').trim();
        var activityLog = activityLogMap.get(requestId);
        var failureReason = extractActivityLogFailureReason(activityLog === null || activityLog === void 0 ? void 0 : activityLog.lines);
        var shouldReplaceEmptyFailureResponse = request.status === 'failed' && isEmptyCodexExecutionResponse(responseText) && Boolean(failureReason);
        if (userText) {
            nextMessages.push({
                id: (_c = request.userMessageId) !== null && _c !== void 0 ? _c : createRecoveredMessageId(requestId, 'user'),
                author: 'user',
                text: userText,
                timestamp: request.createdAt || request.updatedAt || '',
                clientRequestId: requestId,
            });
        }
        else if (responseText || (activityLog === null || activityLog === void 0 ? void 0 : activityLog.lines.length)) {
            nextMessages.push({
                id: createRecoveredMessageId(requestId, 'missing-request'),
                author: 'system',
                text: "".concat(CHAT_MISSING_REQUEST_MESSAGE_PREFIX, "\n\uC774 \uC694\uCCAD\uC740 \uC800\uC7A5\uB41C \uC6D0\uBB38\uC774 \uC5C6\uC5B4 \uC2E4\uC81C \uC694\uCCAD \uBB38\uC7A5\uC744 \uD45C\uC2DC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."),
                timestamp: request.createdAt || request.updatedAt || '',
                clientRequestId: requestId,
            });
        }
        if (responseText && !shouldReplaceEmptyFailureResponse) {
            nextMessages.push({
                id: (_d = request.responseMessageId) !== null && _d !== void 0 ? _d : createRecoveredMessageId(requestId, 'codex'),
                author: 'codex',
                text: responseText,
                timestamp: request.answeredAt || request.updatedAt || request.createdAt || '',
                clientRequestId: requestId,
            });
        }
        if (shouldReplaceEmptyFailureResponse) {
            nextMessages.push({
                id: (_e = request.responseMessageId) !== null && _e !== void 0 ? _e : createRecoveredMessageId(requestId, 'execution-failure'),
                author: 'system',
                text: buildExecutionFailureMessage(failureReason),
                timestamp: request.answeredAt || request.updatedAt || request.createdAt || '',
                clientRequestId: requestId,
            });
        }
        if (activityLog && activityLog.lines.length > 0) {
            nextMessages.push({
                id: createRecoveredMessageId(requestId, 'activity'),
                author: 'system',
                text: "".concat(CHAT_ACTIVITY_MESSAGE_PREFIX, "\n").concat(activityLog.lines.join('\n\n')),
                timestamp: request.createdAt || request.updatedAt || activityLog.updatedAt || '',
                clientRequestId: requestId,
            });
        }
    });
    return sortConversationMessages(nextMessages);
}
function mergeRecoveredChatMessages(previous, incoming) {
    if (previous.length === 0) {
        return incoming;
    }
    if (areChatMessagesEquivalent(previous, incoming)) {
        return previous;
    }
    var previousBuckets = new Map();
    previous.forEach(function (message) {
        var key = buildComparableChatMessageKey(message);
        var bucket = previousBuckets.get(key);
        if (bucket) {
            bucket.push(message);
            return;
        }
        previousBuckets.set(key, [message]);
    });
    var consumeExistingMessage = function (target) {
        var key = buildComparableChatMessageKey(target);
        var bucket = previousBuckets.get(key);
        if (!bucket || bucket.length === 0) {
            return null;
        }
        var matchIndex = bucket.findIndex(function (message) { return isSameChatMessage(message, target); });
        if (matchIndex < 0) {
            return null;
        }
        var matched = bucket.splice(matchIndex, 1)[0];
        if (bucket.length === 0) {
            previousBuckets.delete(key);
        }
        return matched;
    };
    var mergedServerMessages = incoming.map(function (serverMessage) {
        var existingMessage = consumeExistingMessage(serverMessage);
        if (!existingMessage) {
            return serverMessage;
        }
        return __assign(__assign(__assign({}, existingMessage), serverMessage), { deliveryStatus: null, retryCount: 0 });
    });
    var incomingUserRequestIds = new Set(incoming
        .filter(function (message) { return message.author === 'user'; })
        .map(function (message) { return getChatMessageRequestId(message); })
        .filter(Boolean));
    var unmatchedLocalMessages = Array.from(previousBuckets.values())
        .flat()
        .filter(function (message) {
        if (!isMissingRequestMessage(message)) {
            return true;
        }
        var requestId = getChatMessageRequestId(message);
        if (!requestId) {
            return true;
        }
        return !incomingUserRequestIds.has(requestId);
    });
    var nextMessages = sortConversationMessages(__spreadArray(__spreadArray([], mergedServerMessages, true), unmatchedLocalMessages, true));
    return areChatMessagesEquivalent(previous, nextMessages) ? previous : nextMessages;
}
function handleChatServerEvent(_a) {
    return __awaiter(this, arguments, void 0, function (_b) {
        var payload_1, _c;
        var eventData = _b.eventData, currentPageUrl = _b.currentPageUrl, expectedSessionId = _b.expectedSessionId, setMessages = _b.setMessages, onMessageEvent = _b.onMessageEvent, onJobEvent = _b.onJobEvent, onRuntimeEvent = _b.onRuntimeEvent, onRuntimeDetailEvent = _b.onRuntimeDetailEvent, onActivityEvent = _b.onActivityEvent, onEventReceived = _b.onEventReceived;
        return __generator(this, function (_d) {
            switch (_d.label) {
                case 0:
                    _d.trys.push([0, 1, , 3]);
                    payload_1 = JSON.parse(eventData);
                    // Ignore late events from a previously selected conversation so they don't
                    // overwrite or interleave with the active thread.
                    if (expectedSessionId && payload_1.sessionId !== expectedSessionId) {
                        return [2 /*return*/];
                    }
                    onEventReceived === null || onEventReceived === void 0 ? void 0 : onEventReceived(payload_1.eventId, payload_1.sessionId);
                    if (payload_1.type === 'chat:init') {
                        setMessages(function (previous) { return mergeRecoveredChatMessages(previous, payload_1.payload.messages); });
                        return [2 /*return*/];
                    }
                    if (payload_1.type === 'chat:message') {
                        onMessageEvent === null || onMessageEvent === void 0 ? void 0 : onMessageEvent(payload_1.payload, payload_1.sessionId);
                        setMessages(function (previous) { return upsertChatMessage(previous, payload_1.payload); });
                        return [2 /*return*/];
                    }
                    if (payload_1.type === 'chat:message:update') {
                        setMessages(function (previous) { return upsertChatMessage(previous, payload_1.payload); });
                        return [2 /*return*/];
                    }
                    if (payload_1.type === 'chat:job') {
                        onJobEvent === null || onJobEvent === void 0 ? void 0 : onJobEvent(payload_1.payload, payload_1.sessionId);
                        return [2 /*return*/];
                    }
                    if (payload_1.type === 'chat:runtime') {
                        onRuntimeEvent === null || onRuntimeEvent === void 0 ? void 0 : onRuntimeEvent(payload_1.payload);
                        return [2 /*return*/];
                    }
                    if (payload_1.type === 'chat:runtime:detail') {
                        onRuntimeDetailEvent === null || onRuntimeDetailEvent === void 0 ? void 0 : onRuntimeDetailEvent(payload_1.payload);
                        return [2 /*return*/];
                    }
                    if (payload_1.type === 'chat:activity') {
                        onActivityEvent === null || onActivityEvent === void 0 ? void 0 : onActivityEvent(payload_1.payload);
                        setMessages(function (previous) { return appendActivityEventToMessages(previous, payload_1.payload); });
                        return [2 /*return*/];
                    }
                    if (payload_1.type === 'chat:error') {
                        setMessages(function (previous) { return __spreadArray(__spreadArray([], previous, true), [createLocalMessage(payload_1.payload.message)], false); });
                    }
                    return [3 /*break*/, 3];
                case 1:
                    _c = _d.sent();
                    return [4 /*yield*/, (0, errorLogApi_1.reportClientError)({
                            errorType: 'chat:message-parse',
                            errorMessage: '채팅 응답 JSON 파싱에 실패했습니다.',
                            requestPath: currentPageUrl || null,
                            context: {
                                rawMessage: eventData.slice(0, 2000),
                            },
                        })];
                case 2:
                    _d.sent();
                    setMessages(function (previous) { return __spreadArray(__spreadArray([], previous, true), [
                        createLocalMessage('채팅 응답을 해석하지 못했습니다. 연결을 다시 확인합니다.'),
                    ], false); });
                    return [3 /*break*/, 3];
                case 3: return [2 /*return*/];
            }
        });
    });
}
