import { mergeSidebarRepoSections } from './sidebar-repo-section.js';
/**
 * Runs inside Cursor renderer — must be self-contained.
 */
export function extractionFunction(containerSelectors, tabSelectors, editorAuxiliaryTabSelectors, inputSelectors, approveSelectors, approveTextMatch, rejectSelectors, rejectTextMatch) {
    function findFirst(sels) {
        for (const sel of sels) {
            try {
                const el = document.querySelector(sel);
                if (el)
                    return el;
            }
            catch {
                /* skip */
            }
        }
        return null;
    }
    function buildSelectorPath(el) {
        const parts = [];
        let cur = el;
        while (cur && cur !== document.body) {
            let seg = cur.tagName.toLowerCase();
            if (cur.id) {
                seg += `#${cur.id.replace(/([.:])/g, '\\$1')}`;
                parts.unshift(seg);
                break;
            }
            const parent = cur.parentElement;
            if (parent) {
                const siblings = Array.from(parent.children).filter((c) => c.tagName === cur.tagName);
                if (siblings.length > 1) {
                    seg += `:nth-of-type(${siblings.indexOf(cur) + 1})`;
                }
            }
            parts.unshift(seg);
            cur = parent;
        }
        return parts.join(' > ');
    }
    try {
        const container = findFirst(containerSelectors);
        if (!container)
            return null;
        const chatRoot = container;
        const messages = [];
        const flatEls = chatRoot.querySelectorAll('[data-flat-index]');
        const messageDebug = {
            at: Date.now(),
            flatNodes: flatEls.length,
            extracted: 0,
            dropped: {
                tool: 0,
                userNoise: 0,
                userEmpty: 0,
                assistantWorking: 0,
                assistantNotMeaningful: 0,
                assistantNoMarkdown: 0,
            },
            droppedSamples: [],
            messagePreviews: [],
        };
        function previewText(el, max = 90) {
            const md = el.querySelector('.markdown-root');
            const human = el.querySelector('.aislash-editor-input-readonly');
            const raw = (human?.textContent || md?.textContent || el.textContent || '')
                .trim()
                .replace(/\s+/g, ' ');
            return raw.slice(0, max);
        }
        function recordDrop(reason, el) {
            const key = reason;
            if (key in messageDebug.dropped)
                messageDebug.dropped[key]++;
            if (messageDebug.droppedSamples.length < 14) {
                messageDebug.droppedSamples.push({
                    reason,
                    preview: previewText(el),
                    flatIndex: el.getAttribute('data-flat-index') ?? undefined,
                });
            }
        }
        function todoStatusFromRow(row) {
            const cls = row.className?.toString() ?? '';
            if (cls.includes('completed') || cls.includes('done'))
                return 'completed';
            if (cls.includes('cancelled'))
                return 'cancelled';
            if (cls.includes('in-progress') ||
                cls.includes('in_progress') ||
                cls.includes('active') ||
                !!row.querySelector('[class*="loading"], [class*="spinner"], [class*="progress"], [class*="arrow-circle"], [class*="in-progress-circle"]')) {
                return 'in_progress';
            }
            if (row.querySelector('[class*="check"], [class*="completed"]'))
                return 'completed';
            return 'pending';
        }
        function todoStatusFromUiItem(row) {
            if (row.classList.contains('ui-todo-item--completed'))
                return 'completed';
            if (row.classList.contains('ui-todo-item--cancelled'))
                return 'cancelled';
            if (row.querySelector('.ui-todo-item__content--in-progress'))
                return 'in_progress';
            return 'pending';
        }
        function todoStatusFromPlanItem(row) {
            const ind = row.querySelector('.composer-plan-todo-indicator');
            if (!ind)
                return todoStatusFromRow(row);
            const cls = ind.className?.toString() ?? '';
            if (cls.includes('loading') || cls.includes('in-progress'))
                return 'in_progress';
            if (cls.includes('completed'))
                return 'completed';
            if (cls.includes('cancelled'))
                return 'cancelled';
            if (cls.includes('pending'))
                return 'pending';
            return 'pending';
        }
        function todoStatusFromToolbarItem(row) {
            if (row.querySelector('.composer-toolbar-todo-in-progress-circle, .composer-plan-todo-in-progress-circle')) {
                return 'in_progress';
            }
            return todoStatusFromRow(row);
        }
        function isInsideChatHistory(el) {
            return !!el.closest('[data-flat-index]');
        }
        function hasShortTodosHeader(panel) {
            for (const h of panel.querySelectorAll('[class*="collapsible"] [class*="header"], [class*="tool-call"] [class*="header"], span, div, button, .ui-todo-list-header')) {
                if (h.children.length > 3)
                    continue;
                const t = (h.textContent ?? '').trim();
                if (/^To-?dos(\s+\d+)?$/i.test(t) && t.length < 24)
                    return true;
                if (/^To-?dos\s/i.test(t) && t.length < 32)
                    return true;
            }
            return false;
        }
        function extractTodoHeaderMeta(panel) {
            let total;
            const countEl = panel.querySelector('.ui-todo-list-header__count, .composer-create-plan-todos-count, .todo-list-header-left-count');
            if (countEl) {
                const n = parseInt(countEl.textContent?.trim() || '', 10);
                if (!isNaN(n))
                    total = n;
            }
            if (total === undefined) {
                const header = panel.querySelector('.ui-todo-list-header, .composer-create-plan-todos-header, .todo-list-header-left-title');
                const m = (header?.textContent || panel.textContent || '').match(/\bTo-?dos\s*(\d+)/i);
                if (m)
                    total = parseInt(m[1], 10);
            }
            let viewAllPath;
            for (const btn of panel.querySelectorAll('button, a, [role="button"]')) {
                if (/view\s+all/i.test(btn.textContent || '')) {
                    viewAllPath = buildSelectorPath(btn);
                    break;
                }
            }
            return { total, viewAllPath };
        }
        function extractTodosFromPanel(panel, prefix) {
            const todos = [];
            const seen = new Set();
            const meta = extractTodoHeaderMeta(panel);
            function pushTodo(text, status, idx) {
                const t = text.trim().replace(/\s+/g, ' ');
                if (!t || t.length < 4 || t.length > 280)
                    return;
                if (/^to-?dos$/i.test(t) || /^to-?dos\s+\d+$/i.test(t))
                    return;
                if (/^view\s+all$/i.test(t))
                    return;
                if (/^\d+\s+more$/i.test(t))
                    return;
                if (seen.has(t))
                    return;
                seen.add(t);
                todos.push({ id: `todo-${prefix}-${idx}`, text: t, status });
            }
            const uiItems = panel.querySelectorAll('.ui-todo-item');
            if (uiItems.length) {
                uiItems.forEach((row, i) => {
                    const label = row.querySelector('.ui-todo-item__label')?.textContent?.trim() ||
                        row.textContent?.trim() ||
                        '';
                    pushTodo(label, todoStatusFromUiItem(row), i);
                });
                return { todos, ...meta };
            }
            const planItems = panel.querySelectorAll('.composer-create-plan-todo-item');
            if (planItems.length) {
                planItems.forEach((row, i) => {
                    if (row.querySelector('.composer-plan-todo-more-text'))
                        return;
                    const label = row.querySelector('.composer-create-plan-todo-content')?.textContent?.trim() ||
                        row.textContent?.trim().replace(/\s*more\s*$/i, '') ||
                        '';
                    pushTodo(label, todoStatusFromPlanItem(row), i);
                });
                return { todos, ...meta };
            }
            const toolbarItems = panel.querySelectorAll('.composer-toolbar-todo-item');
            if (toolbarItems.length) {
                toolbarItems.forEach((row, i) => {
                    const label = row.querySelector('.composer-toolbar-todo-item-text')?.textContent?.trim() ||
                        row.textContent?.trim() ||
                        '';
                    pushTodo(label, todoStatusFromToolbarItem(row), i);
                });
                return { todos, ...meta };
            }
            const rowSelectors = [
                '[class*="todo-item"]',
                '[class*="TodoItem"]',
                '[class*="task-item"]',
                '[data-todo-id]',
                '.ui-todo-list-item',
            ];
            for (const sel of rowSelectors) {
                panel.querySelectorAll(sel).forEach((row, i) => {
                    if (isInsideChatHistory(row) &&
                        row.closest('[data-message-kind]')?.getAttribute('data-message-kind') !== 'tool') {
                        return;
                    }
                    const label = row.querySelector('[class*="label"], [class*="title"], [class*="content"]')
                        ?.textContent?.trim() ||
                        row.textContent?.trim() ||
                        '';
                    pushTodo(label, todoStatusFromRow(row), i);
                });
                if (todos.length > 0)
                    return { todos, ...meta };
            }
            panel.querySelectorAll('li, [class*="item"], [class*="row"]').forEach((row, i) => {
                const text = row.textContent?.trim() ?? '';
                if (!text || /^to-?dos/i.test(text))
                    return;
                if (text.length > 280)
                    return;
                pushTodo(text, todoStatusFromRow(row), i);
            });
            return { todos, ...meta };
        }
        function extractTodosCursor() {
            const roots = new Set();
            const rootSelectors = [
                '.ui-todo-list-container',
                '.composer-create-plan-todos',
                '.composer-toolbar-todos-item-list',
                '.composer-plan-todos',
                '.todo-list-container',
            ];
            for (const sel of rootSelectors) {
                document.querySelectorAll(sel).forEach((el) => roots.add(el));
                chatRoot.querySelectorAll(sel).forEach((el) => roots.add(el));
            }
            let best = { todos: [] };
            for (const root of roots) {
                const hit = extractTodosFromPanel(root, 'cursor');
                if (hit.todos.length > best.todos.length) {
                    best = {
                        todos: hit.todos,
                        total: hit.total,
                        viewAllPath: hit.viewAllPath,
                    };
                }
            }
            return best;
        }
        let todos = [];
        let todosTotalCount;
        let todosViewAllSelectorPath;
        const cursorTodos = extractTodosCursor();
        if (cursorTodos.todos.length > 0) {
            todos = cursorTodos.todos;
            todosTotalCount = cursorTodos.total;
            todosViewAllSelectorPath = cursorTodos.viewAllPath;
        }
        else {
            const toolBlocks = Array.from(chatRoot.querySelectorAll('[data-flat-index][data-message-kind="tool"]'));
            for (let i = toolBlocks.length - 1; i >= 0; i--) {
                const block = toolBlocks[i];
                if (!hasShortTodosHeader(block))
                    continue;
                const hit = extractTodosFromPanel(block, `tool-${i}`);
                todos = hit.todos;
                todosTotalCount = hit.total;
                todosViewAllSelectorPath = hit.viewAllPath;
                if (todos.length > 0)
                    break;
            }
            if (todos.length === 0) {
                for (const panel of chatRoot.querySelectorAll('[class*="collapsible"], [class*="tool-call"]')) {
                    if (!hasShortTodosHeader(panel))
                        continue;
                    if (isInsideChatHistory(panel)) {
                        const kind = panel.closest('[data-flat-index]')?.getAttribute('data-message-kind');
                        if (kind && kind !== 'tool')
                            continue;
                    }
                    const hit = extractTodosFromPanel(panel, 'panel');
                    todos = hit.todos;
                    todosTotalCount = hit.total;
                    todosViewAllSelectorPath = hit.viewAllPath;
                    if (todos.length > 0)
                        break;
                }
            }
        }
        function getComposerScope() {
            const input = findFirst(inputSelectors);
            if (!input)
                return null;
            const agentPanel = input.closest('[class*="agent-panel"]');
            const tray = document.querySelector('[class*="ui-tray--queued"]');
            if (agentPanel && tray && agentPanel.contains(tray)) {
                return agentPanel;
            }
            const candidates = [
                agentPanel,
                input.closest('[class*="composer-panel"]'),
                input.closest('.composer-bar, [class*="composer-bar"]'),
                findFirst(containerSelectors),
            ];
            for (const el of candidates) {
                if (el?.querySelector('[class*="ui-tray--queued"], [class*="queue-item"], [class*="queue-sortable-row"]')) {
                    return el;
                }
            }
            return (input.closest('.composer-bar, [class*="composer-bar"], [class*="composer-panel"]') ||
                input.parentElement?.parentElement?.parentElement ||
                null);
        }
        function extractQueuedMessages(scope) {
            const items = [];
            const seen = new Set();
            function isA11yDragHint(text) {
                return (/to pick up a draggable item/i.test(text) ||
                    /press space again to drop/i.test(text) ||
                    /while dragging, use the arrow keys/i.test(text));
            }
            function removePathFor(el) {
                const legacy = el.querySelector('button[aria-label="Remove"]');
                if (legacy) {
                    const path = buildSelectorPath(legacy);
                    if (path)
                        return path;
                }
                const removeAction = el.querySelector('[data-queue-action="remove"]');
                if (removeAction) {
                    const clickTarget = removeAction.closest('button') ||
                        removeAction.querySelector('button, .anysphere-icon-button') ||
                        removeAction;
                    const path = buildSelectorPath(clickTarget);
                    if (path)
                        return path;
                }
                const trashIcon = el.querySelector('.codicon-trashcan');
                if (trashIcon) {
                    const clickTarget = trashIcon.closest('button') ||
                        trashIcon.closest('.anysphere-icon-button') ||
                        trashIcon.parentElement;
                    if (clickTarget) {
                        const path = buildSelectorPath(clickTarget);
                        if (path)
                            return path;
                    }
                }
                return undefined;
            }
            function extractQueuedRowText(row) {
                const textRoot = row.querySelector('[class*="ui-tray-row"]') ||
                    row.querySelector('[class*="queue-sortable-row"]') ||
                    row;
                const clone = textRoot.cloneNode(true);
                clone
                    .querySelectorAll('img, button, .anysphere-icon-button, [class*="queue-item-actions"], [class*="icon"], [aria-hidden="true"], [class*="image-pill"]')
                    .forEach((el) => el.remove());
                return (clone.textContent || '').trim().replace(/\s+/g, ' ');
            }
            function extractQueuedRowImages(row) {
                const seenImg = new Set();
                const out = [];
                for (const img of row.querySelectorAll('img.queue-row-thumbnail, img.image-pill-img, .image-pill-container img, img[alt="Attached image"], .queue-row-thumbnails img')) {
                    const src = img.getAttribute('src');
                    if (!src)
                        continue;
                    const path = normalizeImageSrc(src);
                    if (!path || seenImg.has(path))
                        continue;
                    seenImg.add(path);
                    out.push(path);
                }
                return out;
            }
            function rowHasQueueThumbnail(row) {
                return !!row.querySelector('.queue-row-thumbnails img, img.queue-row-thumbnail, .image-pill-container img, img.image-pill-img');
            }
            function normalizeQueuedKey(text) {
                return text.trim().replace(/\s+/g, ' ');
            }
            function mergeQueuedByText(list) {
                const merged = [];
                const idxByText = new Map();
                for (const item of list) {
                    const key = normalizeQueuedKey(item.text);
                    if (!key) {
                        merged.push(item);
                        continue;
                    }
                    const idx = idxByText.get(key);
                    if (idx === undefined) {
                        idxByText.set(key, merged.length);
                        merged.push(item);
                        continue;
                    }
                    const prev = merged[idx];
                    const images = [...new Set([...(prev.images ?? []), ...(item.images ?? [])])];
                    merged[idx] = {
                        ...prev,
                        images: images.length ? images : undefined,
                        hasImage: !!(prev.hasImage || item.hasImage || images.length),
                        removeSelectorPath: prev.removeSelectorPath ?? item.removeSelectorPath,
                    };
                }
                return merged;
            }
            function filterLeafQueueRows(rows) {
                return rows.filter((row) => !rows.some((other) => other !== row && other.contains(row)));
            }
            function pushQueuedRow(row, idx) {
                const images = extractQueuedRowImages(row);
                const hasThumb = rowHasQueueThumbnail(row);
                const t = extractQueuedRowText(row);
                if ((!t || t.length < 2) && images.length === 0 && !hasThumb)
                    return;
                if (t.length > 600)
                    return;
                if (t && isA11yDragHint(t))
                    return;
                if (/^\d+\s+queued$/i.test(t))
                    return;
                if (/^(queued|to\s+send|start\s+multitasking)$/i.test(t))
                    return;
                if (t && /\bqueued\b/i.test(t) && /to\s+send/i.test(t) && t.length < 48)
                    return;
                if (/^start\s+multitasking/i.test(t))
                    return;
                const dedupeKey = `${normalizeQueuedKey(t)}|${images.join(',')}`;
                if (seen.has(dedupeKey))
                    return;
                seen.add(dedupeKey);
                const removeSelectorPath = removePathFor(row);
                const queueItemId = row.getAttribute('data-queue-item-id')?.trim() || undefined;
                items.push({
                    id: `q-${idx}-${items.length}`,
                    text: t,
                    hasImage: images.length > 0 || hasThumb,
                    images: images.length ? images : undefined,
                    ...(queueItemId ? { queueItemId } : {}),
                    removeSelectorPath,
                });
            }
            function pushQueuedLine(text, idx) {
                const t = text.trim().replace(/\s+/g, ' ');
                if (!t || t.length < 2 || t.length > 600)
                    return;
                if (isA11yDragHint(t))
                    return;
                if (/^\d+\s+queued$/i.test(t))
                    return;
                if (/^(queued|to\s+send|start\s+multitasking)$/i.test(t))
                    return;
                if (/\bqueued\b/i.test(t) && /to\s+send/i.test(t) && t.length < 48)
                    return;
                if (/^start\s+multitasking/i.test(t))
                    return;
                if (seen.has(t))
                    return;
                seen.add(t);
                items.push({ id: `q-line-${idx}-${items.length}`, text: t });
            }
            const itemSelectors = [
                '.composer-toolbar-queue-item',
                '[class*="ui-tray--queued"] [class*="queue-sortable-row"]',
                '[class*="ui-tray--queued"] [class*="ui-tray-row"]',
                '[class*="queue-sortable-row"]',
                '[class*="ui-tray-row"]',
                '[class*="queued-message"]',
                '[class*="QueueItem"]',
                '[class*="composer-queue"]',
                '[data-queued-message]',
                '[class*="pending-message"]',
            ];
            for (const sel of itemSelectors) {
                const rows = filterLeafQueueRows(Array.from(scope.querySelectorAll(sel)));
                rows.forEach((row, i) => {
                    if (isInsideChatHistory(row))
                        return;
                    pushQueuedRow(row, i);
                });
                if (items.length > 0)
                    return mergeQueuedByText(items);
            }
            const queueItems = filterLeafQueueRows(Array.from(scope.querySelectorAll('[class*="queue-item"]')));
            queueItems.forEach((item, i) => {
                if (isInsideChatHistory(item))
                    return;
                const row = item.querySelector('[class*="queue-sortable-row"], [class*="ui-tray-row"]');
                pushQueuedRow(row ?? item, i);
            });
            if (items.length > 0)
                return mergeQueuedByText(items);
            for (const panel of scope.querySelectorAll('div, section')) {
                if (isInsideChatHistory(panel))
                    continue;
                const raw = panel.textContent?.trim() ?? '';
                if (raw.length > 400)
                    continue;
                const firstLine = raw.split('\n').map((l) => l.trim()).find(Boolean) ?? '';
                if (!/^\d+\s+Queued\b/i.test(firstLine))
                    continue;
                let foundRow = false;
                panel
                    .querySelectorAll('[class*="item"], [class*="row"], [class*="preview"], li')
                    .forEach((row, i) => {
                    if (isInsideChatHistory(row))
                        return;
                    const text = row.textContent?.trim() ?? '';
                    if (text.length < 4 || text === raw)
                        return;
                    if (/queued|multitasking/i.test(text) && text.length < 50)
                        return;
                    pushQueuedRow(row, i);
                    foundRow = true;
                });
                if (!foundRow) {
                    let afterHeader = false;
                    for (const line of raw.split('\n')) {
                        const l = line.trim();
                        if (!l)
                            continue;
                        if (/^\d+\s+Queued\b/i.test(l)) {
                            afterHeader = true;
                            continue;
                        }
                        if (/start\s+multitasking/i.test(l))
                            continue;
                        if (afterHeader)
                            pushQueuedLine(l, items.length);
                    }
                }
                if (items.length > 0)
                    return mergeQueuedByText(items);
            }
            return mergeQueuedByText(items);
        }
        let queuedMessages = [];
        const composerScope = getComposerScope();
        if (composerScope) {
            queuedMessages = extractQueuedMessages(composerScope);
        }
        function isNoiseChatText(text) {
            const t = text.trim().replace(/\s+/g, ' ');
            if (!t || t.length < 2)
                return true;
            if (/^If the available MCP tools do not fully support what the user asked you to do\b/i.test(t)) {
                return true;
            }
            if (/^(Editing|Edited|Ran|Thought\s+(briefly|for\s)|Explored|Listed|Grepped|Searched|Read|Loading|Planning|Generating|Running|Finished|Cancelled|Using image)\b/i.test(t))
                return true;
            if (/^Edited\s+.+\s*\+\d+/i.test(t))
                return true;
            if (/\.[a-z0-9]+\s*[+-]\d+/i.test(t) && t.length < 120)
                return true;
            if (/^(cd |npm |npx |curl |git |node )/i.test(t) && t.length < 160)
                return true;
            if (/^Thought\s*for\s*\d/i.test(t) && t.length < 40)
                return true;
            if (/^Thought\s+\w+$/i.test(t) && t.length < 40)
                return true;
            if (/^Explored\d/i.test(t))
                return true;
            if (matchBackgroundStatusLine(t))
                return true;
            return false;
        }
        function matchBackgroundStatusLine(text) {
            const t = text.trim().replace(/\s+/g, ' ');
            if (!t || t.length > 100)
                return undefined;
            if (/will resume when|background work finishes|background shell|resuming when|paused while|waiting for background|waiting for \d+ command/i.test(t)) {
                return t;
            }
            if (/^working\.?$/i.test(t))
                return t;
            return undefined;
        }
        function textImpliesAgentWorking(text) {
            return matchBackgroundStatusLine(text) !== undefined;
        }
        function isBackgroundStatusRow(row) {
            const md = row?.querySelector('.markdown-root');
            const rowText = (md?.textContent || row?.textContent || '').trim();
            const hit = matchBackgroundStatusLine(rowText);
            if (!hit)
                return undefined;
            if (isMeaningfulAssistantText(rowText))
                return undefined;
            return hit;
        }
        function isUserFacingAssistantProse(text) {
            const t = text.trim();
            if (!t)
                return false;
            if (/^##\s+\S/m.test(t))
                return true;
            if (/^\*\*[^*]{2,}\*\*/m.test(t) && t.length >= 60)
                return true;
            const tableRows = t.match(/^\|[^\n]+\|$/gm);
            if (tableRows && tableRows.length >= 2)
                return true;
            if (/^[-*]\s+\S/m.test(t) && t.length >= 100)
                return true;
            return false;
        }
        function isInternalReasoningOutline(text) {
            const raw = text.trim();
            if (!raw)
                return false;
            const cotLine = /^(?:Evaluating|Analyzing|Analysing|Examining|Investigating|Gathering|Considering|Reviewing|Checking|Assessing|Exploring|Looking at|Thinking about|Planning next|Outlining|Identifying|Determining|Clarifying|Noting|Comparing|Tracing|Preparing|Updating|Fixing|Implementing|Searching for|Reading|Reflecting on)\s+\S/i;
            const lines = raw
                .split(/\n+/)
                .map((l) => l.replace(/^\*\*|\*\*$/g, '').trim())
                .filter(Boolean);
            if (!lines.length)
                return false;
            const cot = lines.filter((l) => cotLine.test(l) && l.length < 160);
            if (lines.length === 1 && cot.length === 1)
                return true;
            if (cot.length >= 2 && cot.length >= Math.ceil(lines.length * 0.55))
                return true;
            if (cot.length >= 3)
                return true;
            return false;
        }
        function isAssistantReflectionText(text) {
            const raw = text.trim();
            if (!raw)
                return true;
            if (isInternalReasoningOutline(raw))
                return true;
            const t = raw.replace(/\s+/g, ' ');
            if (!t || isNoiseChatText(t))
                return true;
            if (isUserFacingAssistantProse(t))
                return false;
            if (/^Thought\s*for\s*\d/i.test(t) && t.length < 160)
                return true;
            if (/^(Exploring|Grepped|Searched|Listed|Read |Ran |Edited |Loading|Planning|Using image)/i.test(t)) {
                return true;
            }
            const toolHits = t.match(/\b(Explored|Grepped|Searched|Listed|Read )\b/gi);
            if (toolHits && toolHits.length >= 2)
                return true;
            return false;
        }
        function isMeaningfulAssistantText(text) {
            const t = text.trim();
            if (!t || isNoiseChatText(t) || isAssistantReflectionText(t))
                return false;
            if (t.length >= 20 && /\s/.test(t))
                return true;
            if (t.length >= 6 && /[.!?…]$/.test(t))
                return true;
            return t.length >= 50;
        }
        function isAssistantThinkingRow(el) {
            if (el.getAttribute('data-message-kind') === 'thinking')
                return true;
            if (el.querySelector('[class*="thought"], [class*="thinking"]'))
                return true;
            if (el.querySelector('.composer-tool-former-message, [class*="tool-call-header"], [class*="ui-tool-call"]') &&
                !el.querySelector('.markdown-root')) {
                return true;
            }
            return false;
        }
        function cleanUserText(text) {
            return text
                .replace(/^\[Image\]\s*$/gim, '')
                .replace(/<image_files>[\s\S]*?<\/image_files>/gi, '')
                .replace(/(?:^|\n)\s*The following images? (?:were |has been )?provid(?:ed|ied)[^\n]*(?:\n\s*\d+\.\s*[^\n]+)*/gi, '\n')
                .replace(/(?:^|\n)\s*These images can be copied for use in other locations\.?\s*/gi, '\n')
                .replace(/(?:^|\n\n?)If the available MCP tools do not fully support[\s\S]*?unless the user explicitly asks you to use the browser\.?\s*/gi, '\n')
                .replace(/<timestamp>[\s\S]*?<\/timestamp>/gi, '')
                .replace(/<user_query>\s*/gi, '')
                .replace(/<\/user_query>/gi, '')
                .replace(/([.!?…])(\d+\.\s*)/g, '$1\n$2')
                .replace(/([^\n\d\s])(\d+\.\s+)/g, '$1\n$2')
                .replace(/\n{3,}/g, '\n\n')
                .trim();
        }
        function normalizeImageSrc(src) {
            const raw = src.trim();
            if (!raw)
                return null;
            if (/^https?:\/\//i.test(raw))
                return raw;
            if (raw.startsWith('vscode-file://vscode-app')) {
                const rest = raw.slice('vscode-file://vscode-app'.length);
                const q = rest.indexOf('?');
                try {
                    return decodeURIComponent(q >= 0 ? rest.slice(0, q) : rest);
                }
                catch {
                    return null;
                }
            }
            if (raw.startsWith('file://')) {
                try {
                    return decodeURIComponent(raw.replace(/^file:\/\//, ''));
                }
                catch {
                    return null;
                }
            }
            return null;
        }
        function extractRowImages(row) {
            const seen = new Set();
            const out = [];
            for (const img of row.querySelectorAll('img.image-pill-img, .image-pill-container img, img[alt="Attached image"]')) {
                const src = img.getAttribute('src');
                if (!src)
                    continue;
                const path = normalizeImageSrc(src);
                if (!path || seen.has(path))
                    continue;
                seen.add(path);
                out.push(path);
            }
            return out;
        }
        function isToolNoiseElement(el, msgKind) {
            if (msgKind === 'tool')
                return true;
            // Row may contain tool chrome + prose; keep when human/assistant body exists.
            if (el.querySelector('.markdown-root, .aislash-editor-input-readonly, .composer-human-tiptap-readonly-editor, .composer-human-message-content, .composer-human-message')) {
                return false;
            }
            if (el.querySelector('.loading-indicator-v3'))
                return true;
            if (el.querySelector('.composer-tool-former-message'))
                return true;
            if (el.querySelector('.composer-terminal-tool-call-block-container'))
                return true;
            if (el.querySelector('.composer-edit-file-review-wrapper'))
                return true;
            if (el.querySelector('.ui-edit-tool-call__filename'))
                return true;
            if (el.querySelector('[data-tool-status]'))
                return true;
            if (el.querySelector('.ui-tool-call-line-action'))
                return true;
            return false;
        }
        let domSeqCounter = 0;
        flatEls.forEach((el) => {
            const idxRaw = el.getAttribute('data-flat-index') ?? '';
            const idxParsed = Number.parseInt(idxRaw, 10);
            const domSeq = domSeqCounter++;
            // Sort/display: Cursor data-flat-index is the real timeline; domSeq only tie-breaks.
            const attrFlatIndex = Number.isFinite(idxParsed) ? idxParsed : undefined;
            const flatIndex = attrFlatIndex ?? domSeq;
            const role = el.getAttribute('data-message-role') ?? '';
            const kind = el.getAttribute('data-message-kind') ?? '';
            const id = `${attrFlatIndex ?? flatIndex}-${role || 'x'}-${kind || 'x'}`;
            function extractPlanBlockFromFlat(row) {
                const panel = row.querySelector('.composer-create-plan-todos');
                if (!panel)
                    return null;
                const hit = extractTodosFromPanel(panel, `flat-${flatIndex}`);
                if (!hit.todos.length)
                    return null;
                if (!/\bBuild\b/i.test(row.textContent || ''))
                    return null;
                let buildTitle = '';
                const m = (row.textContent || '').match(/Build\s+([^\n]{4,120})/i);
                if (m)
                    buildTitle = m[1].replace(/^[\s⠇\u2800-\u28FF]+/, '').trim();
                if (!buildTitle)
                    buildTitle = 'Plan';
                const completedCount = hit.todos.filter((t) => t.status === 'completed').length;
                const totalCount = hit.total ?? hit.todos.length;
                let progressCompleted = completedCount;
                const prog = (row.textContent || '').match(/\b(\d+)\s*\/\s*(\d+)\b/);
                if (prog)
                    progressCompleted = parseInt(prog[1], 10);
                return {
                    buildTitle,
                    todos: hit.todos,
                    completedCount: progressCompleted,
                    totalCount,
                };
            }
            if (isToolNoiseElement(el, kind)) {
                const planFromTool = extractPlanBlockFromFlat(el);
                if (planFromTool) {
                    messages.push({
                        id,
                        role: 'assistant',
                        text: '',
                        planBlock: planFromTool,
                        flatIndex,
                        domSeq,
                    });
                    messageDebug.extracted++;
                    return;
                }
                recordDrop('tool', el);
                return;
            }
            if (isAssistantThinkingRow(el)) {
                recordDrop('assistantNotMeaningful', el);
                return;
            }
            const humanEl = el.querySelector('.aislash-editor-input-readonly, .composer-human-tiptap-readonly-editor, .composer-human-message-content, .composer-human-message');
            const mdRoot = el.querySelector('.markdown-root') ||
                el.querySelector('[class*="markdown-root"]') ||
                el.querySelector('.anysphere-markdown-container');
            const isHuman = role === 'human' || !!humanEl;
            if (isHuman) {
                const images = extractRowImages(el);
                const text = cleanUserText(humanEl?.textContent?.trim() ?? el.textContent?.trim() ?? '');
                const hasText = Boolean(text) && !isNoiseChatText(text);
                if (!hasText && images.length === 0) {
                    recordDrop(text && isNoiseChatText(text) ? 'userNoise' : 'userEmpty', el);
                    return;
                }
                if (text && isNoiseChatText(text) && images.length > 0) {
                    recordDrop('userNoise', el);
                }
                const displayText = hasText
                    ? text
                    : images.length > 0
                        ? 'Изображение'
                        : '';
                messages.push({
                    id,
                    role: 'user',
                    text: displayText,
                    images: images.length ? images : undefined,
                    flatIndex,
                    domSeq,
                });
                messageDebug.extracted++;
                return;
            }
            const rowText = (el.textContent || '').trim();
            const text = mdRoot?.textContent?.trim() ?? '';
            if (text && textImpliesAgentWorking(text)) {
                recordDrop('assistantWorking', el);
                return;
            }
            if (!mdRoot || !text) {
                const planOnly = extractPlanBlockFromFlat(el);
                if (planOnly) {
                    messages.push({
                        id,
                        role: 'assistant',
                        text: '',
                        planBlock: planOnly,
                        flatIndex,
                        domSeq,
                    });
                    messageDebug.extracted++;
                    return;
                }
                if (rowText && isAssistantReflectionText(rowText)) {
                    recordDrop('assistantNotMeaningful', el);
                }
                else {
                    recordDrop('assistantNoMarkdown', el);
                }
                return;
            }
            if (!isMeaningfulAssistantText(text)) {
                recordDrop('assistantNotMeaningful', el);
                return;
            }
            const planBlock = extractPlanBlockFromFlat(el) ?? undefined;
            messages.push({
                id,
                role: 'assistant',
                text,
                html: mdRoot.innerHTML || undefined,
                planBlock,
                flatIndex,
                domSeq,
            });
            messageDebug.extracted++;
        });
        function compareUserText(text) {
            return cleanUserText(text).replace(/\s+/g, ' ').trim();
        }
        function userTextDup(a, b) {
            const ta = compareUserText(a);
            const tb = compareUserText(b);
            if (!ta || !tb)
                return !ta && !tb;
            if (ta === tb)
                return true;
            const short = ta.length <= tb.length ? ta : tb;
            const long = ta.length <= tb.length ? tb : ta;
            if (short.length < 12)
                return false;
            if (long.includes(short)) {
                if (long.endsWith(short) || long.startsWith(short))
                    return true;
                if (short.length / long.length >= 0.4)
                    return true;
            }
            return false;
        }
        const dedupedMessages = [];
        for (const m of messages) {
            if (m.role !== 'user') {
                dedupedMessages.push(m);
                continue;
            }
            const dupIdx = dedupedMessages.findIndex((x) => x.role === 'user' && userTextDup(x.text, m.text));
            if (dupIdx >= 0) {
                const prev = dedupedMessages[dupIdx];
                const keep = prev.text.length >= m.text.length ? prev : m;
                const drop = prev.text.length >= m.text.length ? m : prev;
                dedupedMessages[dupIdx] = {
                    ...keep,
                    images: keep.images?.length || drop.images?.length
                        ? [...new Set([...(keep.images ?? []), ...(drop.images ?? [])])]
                        : undefined,
                    flatIndex: Math.min(prev.flatIndex ?? 0, m.flatIndex ?? 0),
                };
                continue;
            }
            dedupedMessages.push(m);
        }
        messages.length = 0;
        messages.push(...dedupedMessages);
        let containerComposerId = container.getAttribute('data-composer-id') ||
            container.closest('[data-composer-id]')?.getAttribute('data-composer-id') ||
            '';
        if (!containerComposerId && flatEls.length > 0) {
            containerComposerId =
                flatEls[0].closest('[data-composer-id]')?.getAttribute('data-composer-id') || '';
        }
        function cleanSidebarTitle(btn) {
            const label = btn.querySelector('.ui-sidebar-menu-button-label');
            let t = (label?.textContent || btn.textContent || '').trim().replace(/\s+/g, ' ');
            t = t.replace(/\d+\s*(?:s|m|h|d|w)\b/gi, '').replace(/\d+[smhdw]$/i, '').trim();
            return t.slice(0, 120);
        }
        /** Tab title from auxiliary bar (aria-label is usually the full name). */
        function cleanAuxiliaryTabTitle(raw, fromAriaLabel) {
            let t = raw.trim().replace(/\s+/g, ' ');
            t = t.replace(/\d+\s*(?:s|m|h|d|w)\b/gi, '').replace(/\d+[smhdw]$/i, '').trim();
            t = t.replace(/⌘[A-Z0-9]+$/i, '').trim();
            // VS Code puts editor-group context in aria-label, not on the visible tab chip.
            t = t.replace(/,\s*Chat Editors:\s*Editor Group\s*\d+\s*$/i, '').trim();
            if (!fromAriaLabel) {
                // Status suffix at end only — do not use /i on "Running" (would strip "running" in "Bot running on…").
                t = t.replace(/\s+(?:Edited|Thinking|Grepping|Running)\s*$/i, '').trim();
                t = t.replace(/\+\d[\d\-·\s\w]*(?:Files?|File)\d*\w*$/i, '').trim();
            }
            return t.slice(0, 120);
        }
        function pickAuxiliaryTabTitle(aria, visible) {
            const cleanedAria = aria ? cleanAuxiliaryTabTitle(aria, true) : '';
            const cleanedVisible = visible ? cleanAuxiliaryTabTitle(visible, false) : '';
            if (cleanedAria && cleanedVisible) {
                if (cleanedVisible.length > cleanedAria.length)
                    return cleanedVisible;
                if (cleanedAria.startsWith(cleanedVisible) ||
                    cleanedVisible.length < Math.min(cleanedAria.length, 10)) {
                    return cleanedAria;
                }
                return cleanedAria.length >= cleanedVisible.length ? cleanedAria : cleanedVisible;
            }
            return cleanedAria || cleanedVisible;
        }
        function isEditorAuxiliaryLayout() {
            if (document.querySelector('[class*="agent-panel"]'))
                return false;
            return !!document.querySelector('#workbench\\.parts\\.auxiliarybar');
        }
        function extractEditorAuxiliaryTabs() {
            if (!isEditorAuxiliaryLayout())
                return [];
            const composerBar = document.querySelector('div.composer-bar.editor[data-composer-id]') ||
                document.querySelector('.composer-bar[data-composer-id]') ||
                document.querySelector('div.composer-bar.editor, .composer-bar');
            const activeComposerId = composerBar?.getAttribute('data-composer-id') ||
                composerBar?.closest('[data-composer-id]')?.getAttribute('data-composer-id') ||
                '';
            const tabEls = [];
            for (const sel of editorAuxiliaryTabSelectors) {
                try {
                    document.querySelectorAll(sel).forEach((el) => tabEls.push(el));
                }
                catch {
                    /* skip */
                }
                if (tabEls.length)
                    break;
            }
            if (!tabEls.length)
                return [];
            const out = [];
            tabEls.forEach((cell, i) => {
                const aria = cell.getAttribute('aria-label')?.trim() ?? '';
                const visible = (cell.textContent || '').trim().replace(/\s+/g, ' ');
                const title = pickAuxiliaryTabTitle(aria, visible);
                const active = cell.classList.contains('active') ||
                    cell.classList.contains('selected') ||
                    cell.getAttribute('aria-selected') === 'true';
                if (!title)
                    return;
                if (/^marketplace$/i.test(title))
                    return;
                if (/^new agent$/i.test(title) && !active)
                    return;
                const resourceName = cell.getAttribute('data-resource-name')?.trim() || '';
                let composerId = cell.getAttribute('data-composer-id') ||
                    cell.closest('[data-composer-id]')?.getAttribute('data-composer-id') ||
                    '';
                if (resourceName.length >= 32) {
                    composerId = resourceName;
                }
                else if (active && activeComposerId) {
                    composerId = activeComposerId;
                }
                out.push({
                    id: composerId || `aux-tab-${i}`,
                    composerId: composerId || undefined,
                    title,
                    active,
                });
            });
            return out;
        }
        function readAgentBtnMeta(btn) {
            const title = cleanSidebarTitle(btn);
            if (!title || /^more$/i.test(title) || /^less$/i.test(title))
                return null;
            const composerId = btn.getAttribute('data-composer-id') ||
                btn.closest('li')?.getAttribute('data-composer-id') ||
                btn.closest('[data-composer-id]')?.getAttribute('data-composer-id') ||
                '';
            const active = btn.getAttribute('data-active') === 'true';
            const isWorking = !!btn.querySelector('.loading-indicator-v3, [class*="loading-indicator"]');
            const cls = btn.className?.toString() ?? '';
            const statusDot = btn.querySelector('.agent-status-dot');
            const dotCls = statusDot?.className?.toString() ?? '';
            // Cursor unread = blue `::after` on `.agent-status-dot--done-unseen` (not legacy `[class*="unread"]`).
            const hasUnread = cls.includes('unread') ||
                !!btn.querySelector('[class*="unread"]') ||
                dotCls.includes('done-unseen') ||
                dotCls.includes('unseen') ||
                !!btn.querySelector('.agent-status-dot--done-unseen');
            const needsAttention = !!btn.querySelector('.agent-status-dot--needs-attention');
            return { title, composerId, active, isWorking, hasUnread, needsAttention };
        }
        const tabs = [];
        const editorAuxTabs = extractEditorAuxiliaryTabs();
        if (editorAuxTabs.length > 0) {
            tabs.push(...editorAuxTabs);
        }
        const glassTabs = document.querySelectorAll('.glass-sidebar-agent-list-container li.ui-sidebar-menu-item > div.glass-sidebar-agent-menu-btn');
        if (tabs.length === 0 && glassTabs.length > 0) {
            glassTabs.forEach((cell, i) => {
                const meta = readAgentBtnMeta(cell);
                if (!meta)
                    return;
                tabs.push({
                    id: meta.composerId || `tab-${i}`,
                    composerId: meta.composerId || undefined,
                    title: meta.title,
                    active: meta.active,
                    isWorking: meta.isWorking,
                    hasUnread: meta.hasUnread,
                    needsAttention: meta.needsAttention,
                });
            });
        }
        else if (tabs.length === 0) {
            for (const sel of tabSelectors) {
                document.querySelectorAll(sel).forEach((cell, i) => {
                    const title = cell.getAttribute('aria-label') ??
                        cell.getAttribute('title') ??
                        cell.textContent?.trim() ??
                        `Chat ${i + 1}`;
                    const composerId = cell.getAttribute('data-composer-id') ||
                        cell.closest('[data-composer-id]')?.getAttribute('data-composer-id') ||
                        '';
                    const active = cell.classList.contains('active') ||
                        cell.getAttribute('aria-selected') === 'true' ||
                        cell.getAttribute('data-selected') === 'true' ||
                        cell.matches('.selected');
                    tabs.push({
                        id: composerId || `tab-${i}`,
                        composerId: composerId || undefined,
                        title: title.replace(/\s+/g, ' ').slice(0, 120),
                        active,
                    });
                });
                if (tabs.length)
                    break;
            }
        }
        const pendingApprovals = [];
        function isVisibleButton(btn) {
            const st = getComputedStyle(btn);
            if (st.display === 'none' || st.visibility === 'hidden' || Number(st.opacity) < 0.05) {
                return false;
            }
            const r = btn.getBoundingClientRect();
            return r.width >= 2 && r.height >= 2;
        }
        /** Real tool Accept/Run — only explicit approval row (not chat status / "Run in background"). */
        function isToolApprovalButton(btn) {
            return !!btn.closest('.ui-shell-tool-call__approval-row');
        }
        function isDeniedApprovalLabel(label) {
            const t = label.trim().toLowerCase();
            if (!t)
                return true;
            if (t === 'run in background' || t.includes('run in background'))
                return true;
            if (/waiting for \d+ command/.test(t))
                return true;
            if (/will resume when|background work finishes|background shell/.test(t))
                return true;
            return false;
        }
        function isMenuTrigger(btn) {
            const p = btn.getAttribute('aria-haspopup');
            return p === 'menu' || p === 'true' || p === 'listbox';
        }
        function cleanLabel(raw) {
            return raw.replace(/\s*(Shift\+)?⏎\s*/g, '').replace(/\s+/g, ' ').trim();
        }
        function extractPendingQuestionnaire() {
            function isAnswersTrayTitle(raw) {
                const t = (raw || '').replace(/\s+/g, ' ').trim().toLowerCase();
                if (!t)
                    return false;
                return t === 'answers' || t === 'ответы';
            }
            function isQuestionnaireTray(el) {
                return (el.classList.contains('ui-tray') &&
                    !!el.querySelector('.ui-tray-option') &&
                    !!el.querySelector('.ui-tray-actions'));
            }
            function findQuestionnaireRoot() {
                const scopes = [
                    document.querySelector('[class*="composer-panel"]'),
                    document.querySelector('.composer-bar')?.closest('[class*="composer"]'),
                    document.querySelector('[class*="agent-panel"]'),
                    document.body,
                ].filter((el) => el instanceof Element);
                for (const scope of scopes) {
                    const legacy = scope.querySelector('.composer-questionnaire-toolbar');
                    if (legacy)
                        return legacy;
                    for (const tray of scope.querySelectorAll('.ui-tray')) {
                        if (isQuestionnaireTray(tray))
                            return tray;
                    }
                }
                return (document.querySelector('.composer-questionnaire-toolbar') ||
                    [...document.querySelectorAll('.ui-tray')].find(isQuestionnaireTray) ||
                    null);
            }
            function optionSelected(optEl) {
                if (optEl.classList.contains('composer-questionnaire-toolbar-option-focused') ||
                    !!optEl.querySelector('.composer-questionnaire-toolbar-option-label-selected'))
                    return true;
                if (optEl.getAttribute('aria-checked') === 'true')
                    return true;
                const dataState = optEl.getAttribute('data-state');
                if (dataState === 'checked' || dataState === 'selected' || dataState === 'on')
                    return true;
                if (optEl.getAttribute('data-selected') === 'true')
                    return true;
                if (optEl.querySelector('[data-selected="true"], [aria-selected="true"]'))
                    return true;
                const cls = String(optEl.className || '');
                if (/\bui-tray-option--(?:selected|checked|focused|active)\b/.test(cls))
                    return true;
                if (/\bis-selected\b/.test(cls))
                    return true;
                if (/selected|checked/.test(cls) && !/freeform/.test(cls))
                    return true;
                if (/focused|active/.test(cls) && !/freeform/.test(cls) && optEl.matches(':focus'))
                    return true;
                if (optEl.getAttribute('aria-selected') === 'true' ||
                    optEl.getAttribute('aria-pressed') === 'true')
                    return true;
                if (optEl instanceof HTMLElement && optEl.classList.contains('ui-tray-option')) {
                    const cs = getComputedStyle(optEl);
                    const borderW = parseFloat(cs.borderTopWidth || '0');
                    if (borderW >= 0.5 && cs.borderTopStyle !== 'none') {
                        const tray = optEl.closest('.ui-tray');
                        if (tray) {
                            let bordered = 0;
                            for (const o of tray.querySelectorAll('.ui-tray-option')) {
                                const b = parseFloat(getComputedStyle(o).borderTopWidth || '0');
                                if (b >= 0.5 && getComputedStyle(o).borderTopStyle !== 'none')
                                    bordered++;
                            }
                            if (bordered === 1)
                                return true;
                        }
                    }
                }
                return false;
            }
            function parseTrayOption(optEl, qi, oi) {
                let letter = optEl.querySelector('.ui-tray-option__badge, .composer-questionnaire-toolbar-option-letter')
                    ?.textContent?.trim() || '';
                let label = optEl.querySelector('.ui-tray-option__label, .composer-questionnaire-toolbar-option-label')
                    ?.textContent?.trim() || '';
                if (!letter || !label) {
                    const raw = (optEl.textContent || '').replace(/\s+/g, ' ').trim();
                    const m = raw.match(/^([A-D])\s*(.*)$/i);
                    if (m) {
                        if (!letter)
                            letter = m[1].toUpperCase();
                        if (!label)
                            label = m[2].trim();
                    }
                    else if (!label) {
                        label = raw;
                    }
                }
                const freeform = optEl.classList.contains('questionnaire-freeform-option') ||
                    /^other\.?\.?\.?$/i.test(label.trim());
                return {
                    id: `q${qi}-o${oi}`,
                    letter,
                    label,
                    selected: optionSelected(optEl),
                    freeform: freeform || undefined,
                    selectorPath: buildSelectorPath(optEl),
                };
            }
            function extractActions(actionRoot) {
                const actions = [];
                actionRoot.querySelectorAll('button').forEach((btn) => {
                    const isDisabled = (btn instanceof HTMLButtonElement && btn.disabled) ||
                        btn.getAttribute('aria-disabled') === 'true' ||
                        btn.getAttribute('data-disabled') === 'true' ||
                        btn.getAttribute('data-state') === 'disabled';
                    if (isDisabled)
                        return;
                    const label = cleanLabel(btn.textContent || '');
                    if (!label)
                        return;
                    let type = 'other';
                    if (/^(skip|пропустить)$/i.test(label))
                        type = 'skip';
                    else if (/^(continue|next|продолжить|далее)$/i.test(label))
                        type = 'continue';
                    actions.push({ label, type, selectorPath: buildSelectorPath(btn) });
                });
                return actions;
            }
            const root = findQuestionnaireRoot();
            if (!root)
                return undefined;
            if (root.classList.contains('composer-questionnaire-toolbar')) {
                const title = root.querySelector('.composer-questionnaire-toolbar-title')?.textContent?.trim() ||
                    'Questions';
                const questions = [];
                let qEls = root.querySelectorAll('.composer-questionnaire-toolbar-question-active');
                if (!qEls.length) {
                    qEls = root.querySelectorAll('.composer-questionnaire-toolbar-question');
                }
                qEls.forEach((qEl, qi) => {
                    const prompt = qEl.querySelector('.composer-questionnaire-toolbar-question-label')?.textContent?.trim() ||
                        '';
                    const options = [];
                    qEl.querySelectorAll('.composer-questionnaire-toolbar-option').forEach((optEl, oi) => {
                        options.push(parseTrayOption(optEl, qi, oi));
                    });
                    if (prompt || options.length) {
                        questions.push({ id: `q${qi}`, prompt, options });
                    }
                });
                const actions = extractActions(root.querySelector('.composer-questionnaire-toolbar-actions') || root);
                if (!questions.length && !actions.length)
                    return undefined;
                return {
                    id: `questionnaire:${buildSelectorPath(root)}`,
                    title,
                    questions,
                    actions,
                };
            }
            function extractTrayPager(trayRoot, stepCount) {
                const right = trayRoot.querySelector('.ui-tray-header__right');
                const pagerText = (right?.textContent || '').replace(/\s+/g, ' ').trim();
                const m = pagerText.match(/(\d+)\s*of\s*(\d+)/i);
                let currentStepIndex = 0;
                let totalSteps = stepCount > 0 ? stepCount : 1;
                if (m) {
                    const page = parseInt(m[1], 10);
                    totalSteps = parseInt(m[2], 10);
                    currentStepIndex = Math.max(0, Math.min(totalSteps - 1, page - 1));
                }
                else if (stepCount > 1) {
                    const stepEls = trayRoot.querySelectorAll('.ui-tray-step');
                    const idx = [...stepEls].findIndex((step) => {
                        const opts = step.querySelectorAll('.ui-tray-option');
                        return [...opts].some((o) => !optionSelected(o));
                    });
                    currentStepIndex = idx >= 0 ? idx : stepCount - 1;
                    totalSteps = stepCount;
                }
                const navBtns = trayRoot.querySelectorAll('.ui-tray-header__nav-button');
                let navPrevSelectorPath;
                let navNextSelectorPath;
                if (navBtns.length >= 2) {
                    navPrevSelectorPath = buildSelectorPath(navBtns[0]);
                    navNextSelectorPath = buildSelectorPath(navBtns[1]);
                }
                return { currentStepIndex, totalSteps, navPrevSelectorPath, navNextSelectorPath };
            }
            const title = root.querySelector('.ui-tray-header__label')?.textContent?.trim() || 'Questions';
            if (isAnswersTrayTitle(title))
                return undefined;
            const questions = [];
            const steps = root.querySelectorAll('.ui-tray-step');
            if (steps.length) {
                steps.forEach((step, qi) => {
                    const prompt = step.querySelector('.ui-tray-step__title')?.textContent?.trim() || '';
                    const options = [];
                    step.querySelectorAll('.ui-tray-option').forEach((optEl, oi) => {
                        options.push(parseTrayOption(optEl, qi, oi));
                    });
                    if (prompt || options.length) {
                        questions.push({ id: `q${qi}`, prompt, options });
                    }
                });
            }
            else {
                const prompt = root.querySelector('.ui-tray-step__title')?.textContent?.trim() || '';
                const options = [];
                root.querySelectorAll('.ui-tray-option').forEach((optEl, oi) => {
                    options.push(parseTrayOption(optEl, 0, oi));
                });
                if (prompt || options.length) {
                    questions.push({ id: 'q0', prompt, options });
                }
            }
            const actions = extractActions(root.querySelector('.ui-tray-actions') || root);
            if (!questions.length && !actions.length)
                return undefined;
            if (!actions.some((a) => a.type === 'skip' || a.type === 'continue')) {
                const hasUnanswered = questions.some((q) => q.options.some((o) => !o.selected));
                if (!hasUnanswered)
                    return undefined;
            }
            const pager = extractTrayPager(root, steps.length || questions.length);
            return {
                id: `questionnaire:${buildSelectorPath(root)}`,
                title,
                questions,
                actions,
                currentStepIndex: pager.currentStepIndex,
                totalSteps: pager.totalSteps,
                navPrevSelectorPath: pager.navPrevSelectorPath,
                navNextSelectorPath: pager.navNextSelectorPath,
            };
        }
        for (const row of Array.from(container.querySelectorAll('.ui-shell-tool-call__approval-row'))) {
            const card = row.closest('.ui-tool-call-card') || row.closest('.ui-shell-tool-call');
            if (!card)
                continue;
            const actions = [];
            const runBtn = row.querySelector('button.ui-shell-tool-call__run-btn');
            if (runBtn && isVisibleButton(runBtn) && !isMenuTrigger(runBtn)) {
                actions.push({
                    label: cleanLabel(runBtn.textContent || '') || 'Run',
                    type: 'approve',
                    selectorPath: buildSelectorPath(runBtn),
                });
            }
            const skipBtn = row.querySelector('button.ui-shell-tool-call__skip-btn');
            if (skipBtn && isVisibleButton(skipBtn) && !isMenuTrigger(skipBtn)) {
                actions.push({
                    label: cleanLabel(skipBtn.textContent || '') || 'Skip',
                    type: 'reject',
                    selectorPath: buildSelectorPath(skipBtn),
                });
            }
            const approveAction = actions.find((a) => a.type === 'approve' || a.type === 'approve_all');
            if (!approveAction || isDeniedApprovalLabel(approveAction.label))
                continue;
            const cmd = card.querySelector('.ui-shell-tool-call__command')?.textContent?.trim();
            if (cmd && isDeniedApprovalLabel(cmd))
                continue;
            pendingApprovals.push({
                id: `tool:${buildSelectorPath(card)}`,
                description: (cmd || 'Pending approval').slice(0, 240),
                actions,
            });
        }
        let activeTab = tabs.find((t) => t.active);
        if (!activeTab) {
            const headerTitle = document.querySelector('span.auxiliary-bar-chat-title')?.textContent?.trim() ?? '';
            if (headerTitle) {
                const norm = headerTitle
                    .replace(/\s+/g, ' ')
                    .replace(/\d+\s*(?:s|m|h|d|w)\b/gi, '')
                    .replace(/\d+[smhdw]$/i, '')
                    .trim()
                    .toLowerCase();
                activeTab = tabs.find((t) => {
                    const tNorm = (t.title || '')
                        .replace(/\s+/g, ' ')
                        .replace(/\d+\s*(?:s|m|h|d|w)\b/gi, '')
                        .replace(/\d+[smhdw]$/i, '')
                        .trim()
                        .toLowerCase();
                    return tNorm === norm || tNorm.includes(norm) || norm.includes(tNorm);
                });
            }
        }
        const modeEl = document.querySelector('.composer-unified-dropdown[data-mode]');
        const mode = modeEl?.getAttribute('data-mode') ?? undefined;
        const model = document.querySelector('.composer-unified-dropdown-model')?.textContent?.trim() ??
            undefined;
        function composerScopes(r) {
            return [
                document.querySelector('[class*="agent-panel"]'),
                document.querySelector('[class*="composer-panel"]'),
                r.closest('.composer-bar'),
                document.querySelector('.composer-bar'),
                document.querySelector('[class*="composer-bar"]'),
                r,
            ].filter((el) => Boolean(el));
        }
        /** Keep in sync with bridge/src/generation-stop-dom.ts */
        function findGenerationStopButton() {
            const scopes = [
                document.querySelector('[class*="agent-panel"]'),
                document.querySelector('.composer-bar'),
                document.querySelector('[class*="composer-bar"]'),
                document,
            ].filter((el) => Boolean(el));
            const sels = [
                'button.ui-prompt-input-submit-button[data-state="stop"]',
                'button[aria-label="Stop generation"]',
                'button.ui-prompt-input-submit-button[aria-label="Stop generation"]',
                'button[data-state="stop"]',
                '.composer-button-area .anysphere-icon-button:has(.codicon-debug-stop)',
                '.send-with-mode .anysphere-icon-button:has(.codicon-debug-stop)',
            ];
            for (const scope of scopes) {
                for (const sel of sels) {
                    try {
                        const hit = scope.querySelector(sel);
                        if (!hit)
                            continue;
                        const btn = hit.classList.contains('codicon-debug-stop')
                            ? hit.closest('.anysphere-icon-button, button, [role="button"], a') || hit
                            : hit;
                        const st = getComputedStyle(btn);
                        if (st.display === 'none' || st.visibility === 'hidden' || Number(st.opacity) < 0.05) {
                            continue;
                        }
                        const r = btn.getBoundingClientRect();
                        if (r.width < 2 || r.height < 2)
                            continue;
                        if (btn.closest('.ui-shell-tool-call'))
                            continue;
                        const aria = (btn.getAttribute('aria-label') || '').trim().toLowerCase();
                        if (aria === 'stop command')
                            continue;
                        return btn;
                    }
                    catch {
                        /* skip */
                    }
                }
            }
            return null;
        }
        /** Active generation — Stop in composer (not shell «Stop command» in tool rows). */
        function detectAgentWorking(root) {
            if (findGenerationStopButton())
                return true;
            const title = document.querySelector('span.auxiliary-bar-chat-title')?.textContent?.trim() || '';
            if (/generat|working|thinking|running|в работе/i.test(title) && !/waiting|approval/i.test(title)) {
                return true;
            }
            return false;
        }
        function findBackgroundWorkStatusText(root) {
            const flats = root.querySelectorAll('[data-flat-index]');
            for (let i = flats.length - 1; i >= Math.max(0, flats.length - 3); i--) {
                const hit = isBackgroundStatusRow(flats[i]);
                if (hit)
                    return hit;
            }
            const composer = root.closest('.composer-bar') ||
                document.querySelector('[class*="composer-bar"]');
            if (!composer)
                return undefined;
            for (const el of composer.querySelectorAll('span, p, div')) {
                if (el.closest('[data-flat-index]'))
                    continue;
                if (el.closest('.composer-human-message, .markdown-root, .aislash-editor-input-readonly')) {
                    continue;
                }
                if (el.querySelector('span, p, div'))
                    continue;
                const t = (el.textContent || '').trim().replace(/\s+/g, ' ');
                const hit = matchBackgroundStatusLine(t);
                if (hit)
                    return hit;
            }
            return undefined;
        }
        const pendingQuestionnaire = extractPendingQuestionnaire();
        const backgroundStatusText = pendingApprovals.length === 0 && !pendingQuestionnaire
            ? findBackgroundWorkStatusText(container)
            : undefined;
        const hasActiveGeneration = detectAgentWorking(container);
        const agentWorking = pendingApprovals.length === 0 &&
            !pendingQuestionnaire &&
            hasActiveGeneration;
        let agentStatus = document.querySelector('span.auxiliary-bar-chat-title')?.textContent?.trim() ||
            undefined;
        let agentStatusMessage;
        if (pendingQuestionnaire)
            agentStatus = 'waiting_questionnaire';
        else if (pendingApprovals.length > 0)
            agentStatus = 'waiting_approval';
        else if (hasActiveGeneration)
            agentStatus = 'working';
        else if (backgroundStatusText) {
            agentStatus = 'background_shell';
            agentStatusMessage = backgroundStatusText;
        }
        const activeListTab = tabs.find((t) => t.active);
        if (activeListTab) {
            activeListTab.isWorking = hasActiveGeneration;
        }
        let contextPercent;
        let terminalCount;
        for (const el of Array.from(document.querySelectorAll('button, span, div'))) {
            const t = el.textContent?.trim() ?? '';
            if (contextPercent === undefined) {
                const m = t.match(/^(\d+)%\s*context$/i);
                if (m)
                    contextPercent = Number(m[1]);
            }
            if (terminalCount === undefined) {
                const tm = t.match(/^(\d+)\s+Terminals?$/i);
                if (tm)
                    terminalCount = Number(tm[1]);
            }
        }
        let workspace = '';
        try {
            const g = globalThis;
            const path = g.vscode?.context?.configuration?.()?.workspace?.uri?.path;
            if (path)
                workspace = path.split('/').filter(Boolean).pop() || '';
        }
        catch {
            /* ignore */
        }
        const sidebarRepos = [];
        const sidebarScroll = document.querySelector('[class*="glass-sidebar-scroll"]') ||
            document.querySelector('[class*="glass-sidebar-body"]') ||
            document.querySelector('[class*="glass-sidebar"]');
        if (sidebarScroll) {
            let section = null;
            for (const el of sidebarScroll.querySelectorAll('.ui-sidebar-section-head, li.ui-sidebar-menu-item > div.glass-sidebar-agent-menu-btn')) {
                if (el.classList.contains('ui-sidebar-section-head')) {
                    const headClone = el.cloneNode(true);
                    headClone
                        .querySelectorAll('button, [role="button"], .ui-icon-button')
                        .forEach((btn) => btn.remove());
                    const name = (headClone.textContent || '')
                        .trim()
                        .replace(/\s+/g, ' ')
                        .slice(0, 120);
                    if (!name)
                        continue;
                    let newChatSelectorPath;
                    const scopes = [el, el.parentElement].filter(Boolean);
                    const newChatSels = [
                        'button.ui-icon-button[aria-label*="New Agent" i]',
                        'button.ui-icon-button[aria-label*="New Chat" i]',
                        "[data-command-id='composer.createNewComposerTab']",
                        "[data-command-id*='createNewComposer']",
                        'button.codicon-add-two',
                        "button[aria-label*='New Chat' i]",
                        "button[aria-label*='New Agent' i]",
                    ];
                    outer: for (const scope of scopes) {
                        for (const sel of newChatSels) {
                            try {
                                const hit = scope.querySelector(sel);
                                if (!hit)
                                    continue;
                                const clickTarget = hit.closest('button') ||
                                    hit.closest('.anysphere-icon-button') ||
                                    hit;
                                const path = buildSelectorPath(clickTarget);
                                if (path) {
                                    newChatSelectorPath = path;
                                    break outer;
                                }
                            }
                            catch {
                                /* skip */
                            }
                        }
                        const icon = scope.querySelector('.codicon-add-two, .codicon-add');
                        if (icon) {
                            const clickTarget = icon.closest('button') ||
                                icon.closest('.anysphere-icon-button') ||
                                icon.parentElement;
                            if (clickTarget) {
                                const path = buildSelectorPath(clickTarget);
                                if (path) {
                                    newChatSelectorPath = path;
                                    break outer;
                                }
                            }
                        }
                    }
                    section = {
                        id: name,
                        name,
                        path: '',
                        agents: [],
                        ...(newChatSelectorPath ? { newChatSelectorPath } : {}),
                    };
                    sidebarRepos.push(section);
                    continue;
                }
                const meta = readAgentBtnMeta(el);
                if (!meta || !section)
                    continue;
                section.agents.push({
                    id: meta.composerId || `sidebar-${section.agents.length}`,
                    title: meta.title,
                    updatedAt: Date.now(),
                    messageCount: 0,
                    isWorking: meta.isWorking,
                    hasUnread: meta.hasUnread,
                    needsAttention: meta.needsAttention,
                });
            }
        }
        function extractComposerDraftText() {
            const input = findFirst(inputSelectors);
            if (!input)
                return undefined;
            const t = ((input instanceof HTMLElement ? input.innerText : '') ||
                input.textContent ||
                '')
                .replace(/\u200b/g, ' ')
                .replace(/\s+/g, ' ')
                .trim();
            return t || undefined;
        }
        function extractComposerDraftImages() {
            const scopes = [
                findFirst(containerSelectors)?.closest('[class*="agent-panel"]'),
                document.querySelector('[class*="agent-panel"]'),
                document.querySelector('[class*="composer-panel"]'),
                findFirst(containerSelectors),
            ].filter(Boolean);
            const seen = new Set();
            const out = [];
            for (const scope of scopes) {
                for (const img of scope.querySelectorAll('img.image-pill-img, .image-pill-container img, img[alt="Attached image"]')) {
                    if (img.closest('[data-flat-index]'))
                        continue;
                    const src = img.getAttribute('src');
                    if (!src)
                        continue;
                    const raw = src.trim();
                    let path = null;
                    if (/^https?:\/\//i.test(raw))
                        path = raw;
                    else if (raw.startsWith('vscode-file://vscode-app')) {
                        const rest = raw.slice('vscode-file://vscode-app'.length);
                        const q = rest.indexOf('?');
                        try {
                            path = decodeURIComponent(q >= 0 ? rest.slice(0, q) : rest);
                        }
                        catch {
                            path = null;
                        }
                    }
                    else if (raw.startsWith('file://')) {
                        try {
                            path = decodeURIComponent(raw.replace(/^file:\/\//, ''));
                        }
                        catch {
                            path = null;
                        }
                    }
                    if (!path || seen.has(path))
                        continue;
                    seen.add(path);
                    out.push(path);
                }
            }
            return out.length ? out : undefined;
        }
        const composerDraft = extractComposerDraftText();
        const composerDraftImages = extractComposerDraftImages();
        const activeChatTitle = document.querySelector('span.auxiliary-bar-chat-title')?.textContent?.trim() ||
            undefined;
        const resolvedComposerId = (() => {
            if (containerComposerId && /^[0-9a-f-]{36}$/i.test(containerComposerId)) {
                return containerComposerId;
            }
            return activeTab?.composerId || activeTab?.id || containerComposerId || undefined;
        })();
        messageDebug.extracted = messages.length;
        messageDebug.containerComposerId = containerComposerId || activeTab?.composerId;
        messageDebug.messagePreviews = messages.slice(-24).map((m) => ({
            id: m.id,
            role: m.role,
            len: m.text.length,
            flatIndex: m.flatIndex,
        }));
        return {
            workspace,
            tabs,
            sidebarRepos,
            activeTabId: activeTab?.id ?? tabs[0]?.id,
            activeComposerId: resolvedComposerId,
            activeChatTitle,
            messageDebug,
            messages,
            todos,
            todosTotalCount,
            todosViewAllSelectorPath,
            queuedMessages,
            pendingApprovals,
            pendingQuestionnaire,
            agentWorking,
            agentStatus,
            agentStatusMessage,
            contextPercent,
            terminalCount,
            mode,
            model,
            composerDraft,
            composerDraftImages,
        };
    }
    catch {
        return null;
    }
}
/**
 * Agents sidebar only (list view has no composer container).
 * Keeps `hasUnread` / working markers fresh when full extract returns null.
 */
export function agentsSidebarListExtraction(tabSelectors, editorAuxiliaryTabSelectors) {
    function buildSelectorPath(el) {
        const parts = [];
        let cur = el;
        while (cur && cur !== document.body) {
            let seg = cur.tagName.toLowerCase();
            if (cur.id) {
                seg += `#${cur.id.replace(/([.:])/g, '\\$1')}`;
                parts.unshift(seg);
                break;
            }
            const parent = cur.parentElement;
            if (parent) {
                const siblings = Array.from(parent.children).filter((c) => c.tagName === cur.tagName);
                if (siblings.length > 1) {
                    seg += `:nth-of-type(${siblings.indexOf(cur) + 1})`;
                }
            }
            parts.unshift(seg);
            cur = parent;
        }
        return parts.join(' > ');
    }
    function cleanSidebarTitle(btn) {
        const label = btn.querySelector('.ui-sidebar-menu-button-label');
        let t = (label?.textContent || btn.textContent || '').trim().replace(/\s+/g, ' ');
        t = t.replace(/\d+\s*(?:s|m|h|d|w)\b/gi, '').replace(/\d+[smhdw]$/i, '').trim();
        return t.slice(0, 120);
    }
    function readAgentBtnMeta(btn) {
        const title = cleanSidebarTitle(btn);
        if (!title || /^more$/i.test(title) || /^less$/i.test(title))
            return null;
        const composerId = btn.getAttribute('data-composer-id') ||
            btn.closest('li')?.getAttribute('data-composer-id') ||
            btn.closest('[data-composer-id]')?.getAttribute('data-composer-id') ||
            '';
        const active = btn.getAttribute('data-active') === 'true';
        const isWorking = !!btn.querySelector('.loading-indicator-v3, [class*="loading-indicator"]');
        const cls = btn.className?.toString() ?? '';
        const statusDot = btn.querySelector('.agent-status-dot');
        const dotCls = statusDot?.className?.toString() ?? '';
        const hasUnread = cls.includes('unread') ||
            !!btn.querySelector('[class*="unread"]') ||
            dotCls.includes('done-unseen') ||
            dotCls.includes('unseen') ||
            !!btn.querySelector('.agent-status-dot--done-unseen');
        const needsAttention = !!btn.querySelector('.agent-status-dot--needs-attention');
        return { title, composerId, active, isWorking, hasUnread, needsAttention };
    }
    try {
        let workspace = '';
        try {
            const g = globalThis;
            const path = g.vscode?.context?.configuration?.()?.workspace?.uri?.path;
            if (path)
                workspace = path.split('/').filter(Boolean).pop() || '';
        }
        catch {
            /* ignore */
        }
        const tabs = [];
        const glassTabs = document.querySelectorAll('.glass-sidebar-agent-list-container li.ui-sidebar-menu-item > div.glass-sidebar-agent-menu-btn, li.ui-sidebar-menu-item > div.glass-sidebar-agent-menu-btn');
        glassTabs.forEach((cell, i) => {
            const meta = readAgentBtnMeta(cell);
            if (!meta)
                return;
            tabs.push({
                id: meta.composerId || `tab-${i}`,
                composerId: meta.composerId || undefined,
                title: meta.title,
                active: meta.active,
                isWorking: meta.isWorking,
                hasUnread: meta.hasUnread,
                needsAttention: meta.needsAttention,
            });
        });
        const sidebarRepos = [];
        const sidebarScroll = document.querySelector('[class*="glass-sidebar-scroll"]') ||
            document.querySelector('[class*="glass-sidebar-body"]') ||
            document.querySelector('[class*="glass-sidebar"]');
        if (sidebarScroll) {
            let section = null;
            for (const el of sidebarScroll.querySelectorAll('.ui-sidebar-section-head, li.ui-sidebar-menu-item > div.glass-sidebar-agent-menu-btn')) {
                if (el.classList.contains('ui-sidebar-section-head')) {
                    const headClone = el.cloneNode(true);
                    headClone
                        .querySelectorAll('button, [role="button"], .ui-icon-button')
                        .forEach((btn) => btn.remove());
                    const name = (headClone.textContent || '').trim().replace(/\s+/g, ' ').slice(0, 120);
                    if (!name)
                        continue;
                    let newChatSelectorPath;
                    for (const sel of [
                        'button.ui-icon-button[aria-label*="New Agent" i]',
                        'button[aria-label*="New Agent" i]',
                    ]) {
                        try {
                            const hit = el.querySelector(sel);
                            if (!hit)
                                continue;
                            const path = buildSelectorPath(hit.closest('button') || hit.closest('.ui-icon-button') || hit);
                            if (path) {
                                newChatSelectorPath = path;
                                break;
                            }
                        }
                        catch {
                            /* skip */
                        }
                    }
                    section = {
                        id: name,
                        name,
                        path: '',
                        agents: [],
                        ...(newChatSelectorPath ? { newChatSelectorPath } : {}),
                    };
                    sidebarRepos.push(section);
                    continue;
                }
                const meta = readAgentBtnMeta(el);
                if (!meta || !section)
                    continue;
                section.agents.push({
                    id: meta.composerId || `sidebar-${section.agents.length}`,
                    title: meta.title,
                    updatedAt: Date.now(),
                    messageCount: 0,
                    isWorking: meta.isWorking,
                    hasUnread: meta.hasUnread,
                    needsAttention: meta.needsAttention,
                });
            }
        }
        if (!tabs.length && !sidebarRepos.length)
            return null;
        return { workspace, tabs, sidebarRepos };
    }
    catch {
        return null;
    }
}
function mergeSidebarTabMarkers(mainTabs, sidebarTabs) {
    const tabs = mainTabs ?? [];
    if (!sidebarTabs?.length)
        return tabs;
    const byTitle = new Map();
    for (const t of sidebarTabs) {
        byTitle.set(t.title.trim().toLowerCase().replace(/\s+/g, ' '), t);
    }
    return tabs.map((t) => {
        const side = byTitle.get(t.title.trim().toLowerCase().replace(/\s+/g, ' '));
        if (!side)
            return t;
        return {
            ...t,
            isWorking: t.isWorking === true || side.isWorking === true,
            hasUnread: t.hasUnread === true || side.hasUnread === true,
            needsAttention: t.needsAttention === true || side.needsAttention === true,
        };
    });
}
function listOnlyExtractedState(sidebar) {
    return {
        workspace: sidebar.workspace,
        tabs: sidebar.tabs,
        sidebarRepos: mergeSidebarRepoSections(sidebar.sidebarRepos),
        messages: [],
        todos: [],
        queuedMessages: [],
        pendingApprovals: [],
    };
}
export async function extractPageState(client, selectors) {
    const editorAuxiliaryTabSelectors = selectors.editorAuxiliaryTabList?.strategies ?? [
        '#workbench\\.parts\\.auxiliarybar div.tab[role="tab"]',
    ];
    const sidebar = (await client.callFunction(agentsSidebarListExtraction, selectors.chatTabList.strategies, editorAuxiliaryTabSelectors));
    const main = (await client.callFunction(extractionFunction, selectors.chatContainer.strategies, selectors.chatTabList.strategies, editorAuxiliaryTabSelectors, selectors.chatInput.strategies, selectors.approveButton.strategies, selectors.approveButton.textMatch ?? [], selectors.rejectButton.strategies, selectors.rejectButton.textMatch ?? []));
    if (!main) {
        if (!sidebar)
            return null;
        return listOnlyExtractedState(sidebar);
    }
    const sidebarRepos = mergeSidebarRepoSections(sidebar?.sidebarRepos?.length ? sidebar.sidebarRepos : (main.sidebarRepos ?? []));
    return {
        ...main,
        workspace: main.workspace || sidebar?.workspace,
        sidebarRepos,
        tabs: mergeSidebarTabMarkers(main.tabs, sidebar?.tabs),
    };
}
