openmagic 0.17.1 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/toolbar/styles/toolbar.css.ts","../../src/toolbar/services/ws-client.ts","../../src/toolbar/services/dom-inspector.ts","../../src/toolbar/services/capture.ts","../../src/toolbar/services/context-builder.ts","../../src/toolbar/index.ts"],"sourcesContent":["export const TOOLBAR_CSS = `\n:host {\n all: initial;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #e0e0e0;\n line-height: 1.5;\n}\n\n* { box-sizing: border-box; margin: 0; padding: 0; }\n.om-hidden { display: none !important; }\n\n/* ── Unified Toolbar Container ────────────────────────── */\n.om-toolbar {\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: 2147483647;\n width: min(420px, calc(100vw - 40px));\n display: flex;\n flex-direction: column;\n background: #111125;\n border: 1px solid rgba(108, 92, 231, 0.18);\n border-radius: 14px;\n box-shadow: 0 6px 32px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.02);\n overflow: hidden;\n}\n\n/* Panel header */\n.om-panel-header {\n display: flex; align-items: center; gap: 6px;\n padding: 8px 12px;\n border-bottom: 1px solid rgba(255,255,255,0.04);\n background: rgba(108, 92, 231, 0.03);\n flex-shrink: 0;\n}\n.om-panel-title { font-size: 11px; font-weight: 600; color: #a29bfe; }\n.om-panel-version { font-size: 10px; color: #444; margin-left: auto; }\n.om-panel-close {\n background: none; border: none; color: #555; cursor: pointer;\n padding: 2px 4px; border-radius: 4px; line-height: 1;\n display: flex; align-items: center;\n}\n.om-panel-close:hover { color: #ccc; background: rgba(255,255,255,0.05); }\n\n/* ── Header Bar (brand + tools) ───────────────────────── */\n.om-toolbar-header {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 6px 10px 6px 5px;\n border-bottom: 1px solid rgba(255,255,255,0.04);\n background: rgba(108, 92, 231, 0.03);\n flex-shrink: 0;\n}\n\n.om-grab {\n display: flex; align-items: center; justify-content: center;\n width: 18px; height: 26px; color: #3a3a5a; cursor: grab;\n border-radius: 5px; transition: color 0.15s; flex-shrink: 0;\n}\n.om-grab:hover { color: #6c5ce7; }\n.om-grab:active { cursor: grabbing; color: #a29bfe; }\n\n.om-pill-brand {\n display: flex; align-items: center; gap: 5px;\n padding: 0 6px 0 4px; cursor: grab;\n}\n.om-pill-icon { color: #a29bfe; flex-shrink: 0; }\n.om-pill-text { font-size: 11px; font-weight: 700; color: #a29bfe; letter-spacing: 0.3px; white-space: nowrap; }\n\n.om-pill-divider { width: 1px; height: 18px; background: rgba(255,255,255,0.06); margin: 0 3px; flex-shrink: 0; }\n\n.om-pill-btn {\n background: none; border: none; color: #555; cursor: pointer;\n padding: 5px 6px; border-radius: 6px; line-height: 1;\n transition: background 0.15s, color 0.15s;\n display: flex; align-items: center; justify-content: center;\n}\n.om-pill-btn:hover { background: rgba(108, 92, 231, 0.15); color: #a29bfe; }\n.om-pill-btn.active { background: rgba(108, 92, 231, 0.25); color: #c4b5fd; }\n\n.om-status-dot {\n width: 7px; height: 7px; border-radius: 50%; margin-left: auto; flex-shrink: 0;\n}\n.om-status-dot.connected { background: #00b894; }\n.om-status-dot.disconnected { background: #e94560; }\n\n.om-update-dot {\n width: 7px; height: 7px; border-radius: 50%; background: #fdcb6e;\n margin-left: 4px; cursor: pointer; flex-shrink: 0;\n animation: om-pulse 2s ease infinite;\n}\n@keyframes om-pulse {\n 0%, 100% { box-shadow: 0 0 0 0 rgba(253,203,110,0.4); }\n 50% { box-shadow: 0 0 0 5px rgba(253,203,110,0); }\n}\n\n/* ── Panel (expandable area between header and prompt) ── */\n.om-panel {\n max-height: 420px;\n overflow: hidden;\n border-bottom: 1px solid rgba(255,255,255,0.04);\n animation: om-expand 0.15s ease;\n}\n@keyframes om-expand {\n from { max-height: 0; opacity: 0; }\n to { max-height: 420px; opacity: 1; }\n}\n\n.om-panel-body {\n overflow-y: auto; padding: 12px;\n max-height: 420px;\n}\n.om-panel-body::-webkit-scrollbar { width: 5px; }\n.om-panel-body::-webkit-scrollbar-track { background: transparent; }\n.om-panel-body::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 3px; }\n\n/* ── Prompt Row (always visible at bottom) ────────────── */\n.om-prompt-row {\n display: flex;\n align-items: center;\n padding: 6px;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.om-prompt-context {\n display: flex; gap: 3px; flex-shrink: 0;\n}\n.om-prompt-chip {\n display: flex; align-items: center; gap: 3px;\n padding: 3px 7px; background: rgba(108, 92, 231, 0.08);\n border: 1px solid rgba(108, 92, 231, 0.12);\n border-radius: 6px; font-size: 10px; color: #a29bfe;\n cursor: default; white-space: nowrap;\n}\n.om-prompt-chip-x {\n background: none; border: none; color: #a29bfe; cursor: pointer;\n font-size: 11px; line-height: 1; padding: 0 1px; opacity: 0.5;\n}\n.om-prompt-chip-x:hover { opacity: 1; }\n\n.om-prompt-input {\n flex: 1;\n background: rgba(255,255,255,0.04);\n border: 1px solid rgba(255,255,255,0.06);\n border-radius: 8px;\n color: #e0e0e0;\n font-size: 13px;\n font-family: inherit;\n padding: 7px 10px;\n outline: none;\n min-width: 0;\n transition: border-color 0.15s;\n}\n.om-prompt-input:focus { border-color: rgba(108, 92, 231, 0.4); }\n.om-prompt-input::placeholder { color: #3a3a5a; }\n\n.om-prompt-send {\n display: flex; align-items: center; justify-content: center;\n width: 30px; height: 30px; flex-shrink: 0;\n background: #6c5ce7; border: none; border-radius: 8px;\n color: white; cursor: pointer; transition: background 0.15s;\n}\n.om-prompt-send:hover { background: #7c6cf7; }\n.om-prompt-send:disabled { background: #2a2a4a; color: #444; cursor: not-allowed; }\n\n.om-prompt-attach {\n display: flex; align-items: center; justify-content: center;\n width: 28px; height: 28px; flex-shrink: 0;\n background: none; border: none; color: #555;\n cursor: pointer; border-radius: 6px; transition: color 0.15s, background 0.15s;\n}\n.om-prompt-attach:hover { color: #a29bfe; background: rgba(108, 92, 231, 0.1); }\n\n/* ── Attachments ──────────────────────────────────────── */\n.om-prompt-attachments {\n display: flex; gap: 6px; padding: 4px 8px; flex-wrap: wrap;\n border-bottom: 1px solid rgba(255,255,255,0.03);\n}\n.om-attachment-thumb {\n position: relative; width: 48px; height: 48px;\n border-radius: 6px; overflow: hidden;\n border: 1px solid rgba(255,255,255,0.08);\n}\n.om-attachment-thumb img {\n width: 100%; height: 100%; object-fit: cover;\n}\n.om-attachment-remove {\n position: absolute; top: 1px; right: 1px;\n width: 16px; height: 16px; display: flex;\n align-items: center; justify-content: center;\n background: rgba(0,0,0,0.7); border: none; border-radius: 50%;\n color: #fff; cursor: pointer; padding: 0; line-height: 1;\n}\n.om-attachment-remove svg { width: 10px; height: 10px; }\n\n/* ── Settings ─────────────────────────────────────────── */\n.om-settings { display: flex; flex-direction: column; gap: 12px; }\n\n.om-field { display: flex; flex-direction: column; gap: 5px; }\n.om-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: #555; }\n\n.om-select, .om-input {\n background: rgba(255,255,255,0.04);\n border: 1px solid rgba(255,255,255,0.08);\n border-radius: 8px;\n padding: 8px 10px;\n color: #e0e0e0;\n font-size: 13px;\n font-family: inherit;\n outline: none;\n width: 100%;\n transition: border-color 0.15s;\n}\n.om-select:focus, .om-input:focus { border-color: rgba(108, 92, 231, 0.4); }\n.om-select option { background: #111125; color: #e0e0e0; }\n\n.om-key-row { display: flex; gap: 6px; align-items: stretch; }\n.om-key-input { flex: 1; min-width: 0; -webkit-text-security: disc; }\n\n.om-key-configured {\n display: flex; align-items: center; gap: 6px;\n padding: 8px 10px; background: rgba(0, 184, 148, 0.06);\n border: 1px solid rgba(0, 184, 148, 0.12);\n border-radius: 8px; font-size: 12px; color: #00b894;\n}\n.om-key-configured span { flex: 1; }\n.om-btn-change-key {\n background: none; border: 1px solid rgba(255,255,255,0.08);\n color: #888; cursor: pointer; padding: 3px 8px;\n border-radius: 5px; font-size: 10px; font-family: inherit;\n transition: all 0.15s;\n}\n.om-btn-change-key:hover { color: #ccc; border-color: rgba(255,255,255,0.15); }\n.om-key-change-row { margin-top: 6px; }\n\n.om-btn-get-key {\n display: flex; align-items: center; gap: 4px;\n padding: 6px 9px; background: rgba(108, 92, 231, 0.08);\n border: 1px solid rgba(108, 92, 231, 0.15); border-radius: 8px;\n color: #a29bfe; font-size: 11px; font-weight: 600;\n font-family: inherit; cursor: pointer; white-space: nowrap;\n transition: all 0.15s;\n}\n.om-btn-get-key:hover { background: rgba(108, 92, 231, 0.15); color: #c4b5fd; }\n\n.om-btn {\n display: flex; align-items: center; justify-content: center; gap: 6px;\n background: #6c5ce7; border: none; color: white; cursor: pointer;\n padding: 8px 14px; border-radius: 8px;\n font-size: 13px; font-weight: 600; font-family: inherit;\n transition: background 0.15s;\n}\n.om-btn:hover { background: #7c6cf7; }\n.om-btn:disabled { background: #2a2a4a; color: #555; cursor: not-allowed; }\n.om-btn-saving { background: #4a3db0; }\n.om-btn-saved { background: #00b894; }\n\n.om-status { font-size: 11px; padding: 5px 8px; border-radius: 6px; text-align: center; display: flex; align-items: center; justify-content: center; gap: 4px; }\n.om-status-success { background: rgba(0, 184, 148, 0.06); color: #00b894; }\n.om-status-error { background: rgba(233, 69, 96, 0.06); color: #e94560; }\n\n.om-key-hint { font-size: 10px; color: #444; margin-top: 3px; }\n.om-key-hint a { color: #7c6cf7; cursor: pointer; text-decoration: none; }\n.om-key-hint a:hover { text-decoration: underline; }\n\n.om-update-banner {\n display: flex; align-items: center; gap: 6px; flex-wrap: wrap;\n padding: 7px 10px; margin-bottom: 10px;\n background: rgba(253, 203, 110, 0.04); border: 1px solid rgba(253, 203, 110, 0.12);\n border-radius: 8px; font-size: 11px; color: #fdcb6e;\n}\n.om-update-cmd {\n display: block; width: 100%; margin-top: 2px;\n padding: 4px 7px; background: rgba(0, 0, 0, 0.12); border-radius: 4px;\n font-family: 'SF Mono', 'Fira Code', Consolas, monospace;\n font-size: 11px; color: #fdcb6e; user-select: all;\n}\n\n/* ── Chat ─────────────────────────────────────────────── */\n.om-chat-messages {\n display: flex; flex-direction: column; gap: 8px;\n max-height: 380px;\n overflow-y: auto;\n}\n.om-chat-messages::-webkit-scrollbar { width: 4px; }\n.om-chat-messages::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.06); border-radius: 2px; }\n\n.om-msg {\n padding: 8px 11px; border-radius: 10px;\n font-size: 13px; line-height: 1.5;\n white-space: pre-wrap; word-break: break-word;\n}\n.om-msg-user { background: rgba(108, 92, 231, 0.08); color: #ccc; margin-left: 36px; border-bottom-right-radius: 3px; }\n.om-msg-assistant { background: rgba(255,255,255,0.02); color: #aaa; margin-right: 36px; border-bottom-left-radius: 3px; border: 1px solid rgba(255,255,255,0.03); }\n.om-msg-system { background: rgba(108, 92, 231, 0.05); color: #888; font-size: 11px; text-align: center; padding: 5px 8px; border-radius: 6px; }\n\n.om-chat-empty { color: #333; text-align: center; padding: 32px 16px; font-size: 12px; line-height: 1.6; }\n\n.om-spinner { width: 12px; height: 12px; border: 2px solid rgba(108,92,231,0.12); border-top-color: #6c5ce7; border-radius: 50%; animation: om-spin 0.6s linear infinite; display: inline-block; vertical-align: -1px; margin-right: 5px; }\n@keyframes om-spin { to { transform: rotate(360deg); } }\n\n.om-element-info {\n background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.03);\n border-radius: 6px; padding: 6px 8px;\n font-family: 'SF Mono', 'Fira Code', Consolas, monospace;\n font-size: 10px; color: #555; max-height: 60px; overflow-y: auto; margin-bottom: 6px;\n}\n\n/* ── Diff Cards ──────────────────────────────────────── */\n.om-diff-card { background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.06); border-radius: 8px; padding: 8px 10px; margin: 4px 0; font-size: 12px; }\n.om-diff-file { color: #a29bfe; font-size: 11px; font-weight: 600; margin-bottom: 6px; font-family: 'SF Mono', Consolas, monospace; }\n.om-diff-removed { background: rgba(233,69,96,0.08); color: #fab1a0; padding: 4px 8px; border-radius: 4px; font-family: 'SF Mono', Consolas, monospace; font-size: 11px; white-space: pre-wrap; word-break: break-all; margin-bottom: 4px; }\n.om-diff-added { background: rgba(0,184,148,0.08); color: #55efc4; padding: 4px 8px; border-radius: 4px; font-family: 'SF Mono', Consolas, monospace; font-size: 11px; white-space: pre-wrap; word-break: break-all; margin-bottom: 6px; }\n.om-diff-actions { display: flex; gap: 6px; }\n.om-btn-sm { padding: 4px 10px; font-size: 11px; border-radius: 6px; }\n.om-btn-secondary { background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.08); color: #888; cursor: pointer; font-family: inherit; }\n.om-btn-secondary:hover { background: rgba(255,255,255,0.08); color: #ccc; }\n.om-diff-applied { opacity: 0.5; }\n.om-diff-applied .om-diff-actions { display: none; }\n`;\n","type MessageHandler = (msg: any) => void;\n\nlet ws: WebSocket | null = null;\nlet handlers: Map<string, MessageHandler> = new Map();\nlet globalHandlers: ((msg: any) => void)[] = [];\nlet messageQueue: string[] = [];\nlet connected = false;\nlet shouldReconnect = false;\nlet reconnectTimer: ReturnType<typeof setTimeout> | null = null;\nlet reconnectAttempt = 0;\n\nfunction generateId(): string {\n return Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\nexport function connect(port: number, token: string): Promise<void> {\n shouldReconnect = true;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n\n const handshakeTimeout = setTimeout(() => {\n if (!settled) {\n settled = true;\n reject(new Error(\"Handshake timeout\"));\n ws?.close();\n }\n }, 10000);\n\n try {\n // Same-origin WebSocket — use page hostname and given port\n const wsHost = window.location.hostname || \"127.0.0.1\";\n const wsProto = window.location.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n ws = new WebSocket(`${wsProto}//${wsHost}:${port}/__openmagic__/ws`);\n\n ws.onopen = () => {\n // Send handshake directly (bypass send() which checks connected flag)\n const handshakeId = generateId();\n ws!.send(JSON.stringify({ id: handshakeId, type: \"handshake\", payload: { token } }));\n\n handlers.set(handshakeId, (msg) => {\n if (msg.type === \"handshake.ok\") {\n clearTimeout(handshakeTimeout);\n connected = true;\n reconnectAttempt = 0;\n // Flush queued messages\n for (const queued of messageQueue) {\n ws?.send(queued);\n }\n messageQueue = [];\n if (!settled) { settled = true; resolve(); }\n } else if (msg.type === \"error\") {\n clearTimeout(handshakeTimeout);\n if (!settled) { settled = true; reject(new Error(msg.payload?.message || \"Handshake failed\")); }\n }\n });\n };\n\n ws.onmessage = (event) => {\n try {\n const msg = JSON.parse(event.data);\n if (msg.id && handlers.has(msg.id)) {\n const handler = handlers.get(msg.id)!;\n handler(msg);\n if (msg.type === \"llm.done\" || msg.type === \"llm.error\" || !msg.type.startsWith(\"llm.\")) {\n handlers.delete(msg.id);\n }\n }\n for (const handler of globalHandlers) {\n handler(msg);\n }\n } catch {\n // Ignore parse errors\n }\n };\n\n ws.onclose = () => {\n const wasConnected = connected;\n connected = false;\n\n // Reject all pending handlers\n handlers.forEach((handler, id) => {\n handler({ type: \"error\", id, payload: { message: \"Connection lost\" } });\n });\n handlers.clear();\n\n if (!wasConnected && !settled) {\n // Connection closed before handshake completed\n clearTimeout(handshakeTimeout);\n settled = true;\n reject(new Error(\"WebSocket closed before handshake\"));\n return;\n }\n\n // Only reconnect if we were previously connected and should reconnect\n if (wasConnected && shouldReconnect && !reconnectTimer) {\n const delay = Math.min(2000 * Math.pow(1.5, reconnectAttempt), 30000);\n reconnectAttempt++;\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n connect(port, token).then(() => {\n // Notify toolbar of reconnection\n for (const handler of globalHandlers) {\n handler({ type: \"reconnected\", payload: {} });\n }\n }).catch(() => {});\n }, delay);\n }\n };\n\n ws.onerror = () => {\n if (!connected && !settled) {\n clearTimeout(handshakeTimeout);\n settled = true;\n reject(new Error(\"WebSocket connection failed\"));\n }\n };\n } catch (e) {\n clearTimeout(handshakeTimeout);\n if (!settled) { settled = true; reject(e); }\n }\n });\n}\n\nexport function send(msg: { id: string; type: string; payload?: any }): void {\n const data = JSON.stringify(msg);\n if (ws && ws.readyState === WebSocket.OPEN && connected) {\n ws.send(data);\n } else {\n messageQueue.push(data);\n }\n}\n\nexport function request(type: string, payload?: any): Promise<any> {\n return new Promise((resolve, reject) => {\n const id = generateId();\n const timeout = setTimeout(() => {\n handlers.delete(id);\n reject(new Error(\"Request timeout\"));\n }, 30000);\n\n handlers.set(id, (msg) => {\n clearTimeout(timeout);\n if (msg.type === \"error\") {\n reject(new Error(msg.payload?.message || \"Unknown error\"));\n } else {\n resolve(msg);\n }\n });\n\n send({ id, type, payload });\n });\n}\n\nexport function stream(\n type: string,\n payload: any,\n onChunk: (chunk: string) => void\n): Promise<any> {\n return new Promise((resolve, reject) => {\n const id = generateId();\n const timeout = setTimeout(() => {\n handlers.delete(id);\n reject(new Error(\"Stream timeout\"));\n }, 120000);\n\n handlers.set(id, (msg) => {\n if (msg.type === \"llm.chunk\") {\n onChunk(msg.payload?.delta || \"\");\n } else if (msg.type === \"llm.done\") {\n clearTimeout(timeout);\n handlers.delete(id);\n resolve(msg.payload);\n } else if (msg.type === \"llm.error\" || msg.type === \"error\") {\n clearTimeout(timeout);\n handlers.delete(id);\n reject(new Error(msg.payload?.message || \"Stream error\"));\n }\n });\n\n send({ id, type, payload });\n });\n}\n\nexport function onMessage(handler: (msg: any) => void): () => void {\n globalHandlers.push(handler);\n return () => {\n globalHandlers = globalHandlers.filter((h) => h !== handler);\n };\n}\n\nexport function isConnected(): boolean {\n return connected;\n}\n\nexport function disconnect(): void {\n shouldReconnect = false;\n if (reconnectTimer) {\n clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n if (ws) {\n ws.close();\n ws = null;\n }\n connected = false;\n}\n","export interface SelectedElement {\n tagName: string;\n id: string;\n className: string;\n textContent: string;\n outerHTML: string;\n cssSelector: string;\n xpath: string;\n computedStyles: Record<string, string>;\n rect: { x: number; y: number; width: number; height: number };\n}\n\nconst IMPORTANT_STYLES = [\n \"display\",\n \"position\",\n \"width\",\n \"height\",\n \"margin\",\n \"padding\",\n \"color\",\n \"background-color\",\n \"background\",\n \"font-size\",\n \"font-weight\",\n \"font-family\",\n \"border\",\n \"border-radius\",\n \"box-shadow\",\n \"flex-direction\",\n \"justify-content\",\n \"align-items\",\n \"gap\",\n \"grid-template-columns\",\n \"grid-template-rows\",\n \"overflow\",\n \"opacity\",\n \"z-index\",\n \"text-align\",\n \"line-height\",\n \"letter-spacing\",\n];\n\nexport function inspectElement(el: HTMLElement): SelectedElement {\n const computed = window.getComputedStyle(el);\n const styles: Record<string, string> = {};\n for (const prop of IMPORTANT_STYLES) {\n styles[prop] = computed.getPropertyValue(prop);\n }\n\n const rect = el.getBoundingClientRect();\n\n return {\n tagName: el.tagName.toLowerCase(),\n id: el.id || \"\",\n className: el.className || \"\",\n textContent: (el.textContent || \"\").trim().slice(0, 200),\n outerHTML: getCleanOuterHTML(el),\n cssSelector: getCssSelector(el),\n xpath: getXPath(el),\n computedStyles: styles,\n rect: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n },\n };\n}\n\nfunction getCleanOuterHTML(el: HTMLElement): string {\n const clone = el.cloneNode(true) as HTMLElement;\n\n // Remove script tags and large content\n const scripts = clone.querySelectorAll(\"script, style, svg\");\n scripts.forEach((s) => s.remove());\n\n // Truncate children if too many\n let html = clone.outerHTML;\n if (html.length > 2000) {\n // Just get the opening tag + first level children hints\n const tag = el.tagName.toLowerCase();\n const attrs = Array.from(el.attributes)\n .map((a) => `${a.name}=\"${a.value}\"`)\n .join(\" \");\n const childSummary = Array.from(el.children)\n .slice(0, 5)\n .map((c) => `<${c.tagName.toLowerCase()} .../>`)\n .join(\"\\n \");\n html = `<${tag} ${attrs}>\\n ${childSummary}\\n ${el.children.length > 5 ? `<!-- +${el.children.length - 5} more children -->` : \"\"}\\n</${tag}>`;\n }\n\n return html;\n}\n\nfunction getCssSelector(el: HTMLElement): string {\n if (el.id) return `#${CSS.escape(el.id)}`;\n\n const parts: string[] = [];\n let current: HTMLElement | null = el;\n\n while (current && current !== document.body) {\n let selector = current.tagName.toLowerCase();\n\n if (current.id) {\n parts.unshift(`#${CSS.escape(current.id)}`);\n break;\n }\n\n if (current.className && typeof current.className === \"string\") {\n const classes = current.className\n .trim()\n .split(/\\s+/)\n .filter((c) => !c.startsWith(\"__\") && c.length < 30)\n .slice(0, 2)\n .map((c) => CSS.escape(c));\n if (classes.length > 0) {\n selector += \".\" + classes.join(\".\");\n }\n }\n\n // Add nth-of-type if needed for uniqueness\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (s) => s.tagName === current!.tagName\n );\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n selector += `:nth-of-type(${index})`;\n }\n }\n\n parts.unshift(selector);\n current = current.parentElement;\n }\n\n return parts.join(\" > \");\n}\n\nfunction getXPath(el: HTMLElement): string {\n const parts: string[] = [];\n let current: Node | null = el;\n\n while (current && current !== document) {\n if (current.nodeType === Node.ELEMENT_NODE) {\n const element = current as HTMLElement;\n let index = 1;\n let sibling = element.previousElementSibling;\n while (sibling) {\n if (sibling.tagName === element.tagName) index++;\n sibling = sibling.previousElementSibling;\n }\n parts.unshift(`${element.tagName.toLowerCase()}[${index}]`);\n }\n current = current.parentNode;\n }\n\n return \"/\" + parts.join(\"/\");\n}\n\n// --- Highlight Overlay ---\n\nlet highlightEl: HTMLDivElement | null = null;\n\nexport function showHighlight(rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n}): void {\n if (!highlightEl) {\n highlightEl = document.createElement(\"div\");\n highlightEl.style.cssText = `\n position: fixed;\n pointer-events: none;\n z-index: 2147483646;\n border: 2px solid #6c5ce7;\n background: rgba(108, 92, 231, 0.1);\n transition: all 0.1s ease;\n `;\n highlightEl.dataset.openmagic = \"highlight\";\n document.body.appendChild(highlightEl);\n }\n\n highlightEl.style.left = `${rect.x}px`;\n highlightEl.style.top = `${rect.y}px`;\n highlightEl.style.width = `${rect.width}px`;\n highlightEl.style.height = `${rect.height}px`;\n highlightEl.style.display = \"block\";\n}\n\nexport function hideHighlight(): void {\n if (highlightEl) {\n highlightEl.style.display = \"none\";\n }\n}\n\n","// Simple screenshot capture using Canvas API\n// Falls back to a simpler approach if html-to-image isn't available\n\nexport async function captureScreenshot(\n target?: HTMLElement\n): Promise<string | null> {\n try {\n // Try using the Canvas approach for element capture\n if (target) {\n return await captureElementViaCanvas(target);\n }\n\n // Full page: use a simple canvas capture of the viewport\n return await captureViewport();\n } catch (e) {\n console.warn(\"[OpenMagic] Screenshot capture failed:\", e);\n return null;\n }\n}\n\nasync function captureViewport(): Promise<string | null> {\n // Create a canvas the size of the viewport\n const canvas = document.createElement(\"canvas\");\n const dpr = window.devicePixelRatio || 1;\n canvas.width = window.innerWidth * dpr;\n canvas.height = window.innerHeight * dpr;\n const ctx = canvas.getContext(\"2d\")!;\n ctx.scale(dpr, dpr);\n\n // We can't directly capture the viewport without html2canvas or similar\n // Instead, we use the SVG foreignObject approach (snapdom-like)\n try {\n const svgData = await elementToSvg(document.body);\n const img = await svgToImage(svgData, window.innerWidth, window.innerHeight);\n ctx.drawImage(img, 0, 0);\n return canvas.toDataURL(\"image/png\");\n } catch {\n return null;\n }\n}\n\nasync function captureElementViaCanvas(\n element: HTMLElement\n): Promise<string | null> {\n const rect = element.getBoundingClientRect();\n const canvas = document.createElement(\"canvas\");\n const dpr = window.devicePixelRatio || 1;\n canvas.width = rect.width * dpr;\n canvas.height = rect.height * dpr;\n const ctx = canvas.getContext(\"2d\")!;\n ctx.scale(dpr, dpr);\n\n try {\n const svgData = await elementToSvg(element);\n const img = await svgToImage(svgData, rect.width, rect.height);\n ctx.drawImage(img, 0, 0);\n return canvas.toDataURL(\"image/png\");\n } catch {\n return null;\n }\n}\n\nfunction elementToSvg(element: HTMLElement): Promise<string> {\n return new Promise((resolve) => {\n const clone = element.cloneNode(true) as HTMLElement;\n\n // Inline computed styles on the clone\n inlineStyles(element, clone);\n\n const rect = element.getBoundingClientRect();\n const width = rect.width;\n const height = rect.height;\n\n const foreignObject = `\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\">\n <foreignObject width=\"100%\" height=\"100%\">\n <div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"width:${width}px;height:${height}px;overflow:hidden;\">\n ${clone.outerHTML}\n </div>\n </foreignObject>\n </svg>`;\n\n resolve(foreignObject);\n });\n}\n\nfunction inlineStyles(source: HTMLElement, target: HTMLElement): void {\n const computed = window.getComputedStyle(source);\n let cssText = \"\";\n for (let i = 0; i < computed.length; i++) {\n const prop = computed[i];\n cssText += `${prop}:${computed.getPropertyValue(prop)};`;\n }\n target.style.cssText = cssText;\n\n const sourceChildren = source.children;\n const targetChildren = target.children;\n for (let i = 0; i < sourceChildren.length && i < targetChildren.length; i++) {\n inlineStyles(\n sourceChildren[i] as HTMLElement,\n targetChildren[i] as HTMLElement\n );\n }\n}\n\nfunction svgToImage(\n svgData: string,\n width: number,\n height: number\n): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n const blob = new Blob([svgData], { type: \"image/svg+xml;charset=utf-8\" });\n const url = URL.createObjectURL(blob);\n\n img.onload = () => {\n URL.revokeObjectURL(url);\n resolve(img);\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error(\"Failed to load SVG image\"));\n };\n\n img.width = width;\n img.height = height;\n img.src = url;\n });\n}\n","import type { SelectedElement } from \"./dom-inspector.js\";\n\n// --- Network Log Capture ---\n\ninterface NetworkEntry {\n method: string;\n url: string;\n status?: number;\n duration?: number;\n timestamp: number;\n}\n\nconst networkLogs: NetworkEntry[] = [];\nconst MAX_NETWORK_LOGS = 50;\n\nlet networkCaptureInstalled = false;\n\nexport function installNetworkCapture(): void {\n if (networkCaptureInstalled) return;\n networkCaptureInstalled = true;\n\n // Intercept fetch\n const originalFetch = window.fetch;\n window.fetch = async function (...args) {\n const request = new Request(...args);\n const entry: NetworkEntry = {\n method: request.method,\n url: request.url,\n timestamp: Date.now(),\n };\n\n try {\n const response = await originalFetch.apply(this, args);\n entry.status = response.status;\n entry.duration = Date.now() - entry.timestamp;\n addNetworkEntry(entry);\n return response;\n } catch (e) {\n entry.status = 0;\n entry.duration = Date.now() - entry.timestamp;\n addNetworkEntry(entry);\n throw e;\n }\n };\n\n // Intercept XMLHttpRequest\n const originalOpen = XMLHttpRequest.prototype.open;\n const originalSend = XMLHttpRequest.prototype.send;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string, ...rest: any[]) {\n (this as any).__om_method = method;\n (this as any).__om_url = url;\n (this as any).__om_start = Date.now();\n return originalOpen.apply(this, [method, url, ...rest] as any);\n };\n\n XMLHttpRequest.prototype.send = function (...args) {\n this.addEventListener(\"loadend\", () => {\n addNetworkEntry({\n method: (this as any).__om_method || \"GET\",\n url: (this as any).__om_url || \"\",\n status: this.status,\n duration: Date.now() - ((this as any).__om_start || Date.now()),\n timestamp: (this as any).__om_start || Date.now(),\n });\n });\n return originalSend.apply(this, args);\n };\n}\n\nfunction addNetworkEntry(entry: NetworkEntry): void {\n // Filter out OpenMagic's own requests\n if (entry.url.includes(\"__openmagic__\")) return;\n networkLogs.push(entry);\n if (networkLogs.length > MAX_NETWORK_LOGS) {\n networkLogs.shift();\n }\n}\n\nexport function getNetworkLogs(): NetworkEntry[] {\n return [...networkLogs];\n}\n\nexport function clearNetworkLogs(): void {\n networkLogs.length = 0;\n}\n\n// --- Console Log Capture ---\n\ninterface ConsoleEntry {\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\";\n args: string[];\n timestamp: number;\n}\n\nconst consoleLogs: ConsoleEntry[] = [];\nconst MAX_CONSOLE_LOGS = 100;\n\nlet consoleCaptureInstalled = false;\n\nexport function installConsoleCapture(): void {\n if (consoleCaptureInstalled) return;\n consoleCaptureInstalled = true;\n\n const levels: ConsoleEntry[\"level\"][] = [\"log\", \"warn\", \"error\", \"info\", \"debug\"];\n\n for (const level of levels) {\n const original = console[level];\n console[level] = function (...args: any[]) {\n consoleLogs.push({\n level,\n args: args.map((a) => {\n try {\n return typeof a === \"object\" ? JSON.stringify(a).slice(0, 500) : String(a);\n } catch {\n return String(a);\n }\n }),\n timestamp: Date.now(),\n });\n\n if (consoleLogs.length > MAX_CONSOLE_LOGS) {\n consoleLogs.shift();\n }\n\n original.apply(console, args);\n };\n }\n}\n\nexport function getConsoleLogs(): ConsoleEntry[] {\n return [...consoleLogs];\n}\n\nexport function clearConsoleLogs(): void {\n consoleLogs.length = 0;\n}\n\n// --- Context Builder ---\n\nexport function buildContext(\n selectedElement: SelectedElement | null,\n screenshot: string | null\n) {\n return {\n selectedElement: selectedElement\n ? {\n tagName: selectedElement.tagName,\n id: selectedElement.id,\n className: selectedElement.className,\n textContent: selectedElement.textContent,\n outerHTML: selectedElement.outerHTML,\n cssSelector: selectedElement.cssSelector,\n computedStyles: selectedElement.computedStyles,\n }\n : undefined,\n screenshot: screenshot || undefined,\n networkLogs: getNetworkLogs().map((l) => ({\n method: l.method,\n url: l.url,\n status: l.status,\n duration: l.duration,\n timestamp: l.timestamp,\n })),\n consoleLogs: getConsoleLogs().map((l) => ({\n level: l.level,\n args: l.args,\n timestamp: l.timestamp,\n })),\n };\n}\n","import { TOOLBAR_CSS } from \"./styles/toolbar.css.js\";\nimport * as ws from \"./services/ws-client.js\";\nimport { inspectElement, showHighlight, hideHighlight, type SelectedElement } from \"./services/dom-inspector.js\";\nimport { captureScreenshot } from \"./services/capture.js\";\nimport { installNetworkCapture, installConsoleCapture, buildContext, getNetworkLogs, getConsoleLogs } from \"./services/context-builder.js\";\n\n// ── SVG Icons (Lucide-style) ─────────────────────────────────────\nconst ICON = {\n sparkle: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.582a.5.5 0 0 1 0 .962L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\"/></svg>`,\n crosshair: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"22\" y1=\"12\" x2=\"18\" y2=\"12\"/><line x1=\"6\" y1=\"12\" x2=\"2\" y2=\"12\"/><line x1=\"12\" y1=\"6\" x2=\"12\" y2=\"2\"/><line x1=\"12\" y1=\"22\" x2=\"12\" y2=\"18\"/></svg>`,\n camera: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\"/><circle cx=\"12\" cy=\"13\" r=\"3\"/></svg>`,\n chat: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/></svg>`,\n settings: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>`,\n send: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"/><polygon points=\"22 2 15 22 11 13 2 9 22 2\"/></svg>`,\n x: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n externalLink: `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"/><polyline points=\"15 3 21 3 21 9\"/><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"/></svg>`,\n check: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polyline points=\"20 6 9 17 4 12\"/></svg>`,\n grip: `<svg width=\"7\" height=\"14\" viewBox=\"0 0 8 14\" fill=\"currentColor\"><circle cx=\"2\" cy=\"2\" r=\"1.2\"/><circle cx=\"6\" cy=\"2\" r=\"1.2\"/><circle cx=\"2\" cy=\"7\" r=\"1.2\"/><circle cx=\"6\" cy=\"7\" r=\"1.2\"/><circle cx=\"2\" cy=\"12\" r=\"1.2\"/><circle cx=\"6\" cy=\"12\" r=\"1.2\"/></svg>`,\n network: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/></svg>`,\n activity: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polyline points=\"22 12 18 12 15 21 9 3 6 12 2 12\"/></svg>`,\n paperclip: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\"/></svg>`,\n image: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\"/><circle cx=\"9\" cy=\"9\" r=\"2\"/><path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\"/></svg>`,\n};\n\n// ── Model Registry (inline for browser bundle) ───────────────────\nconst MODEL_REGISTRY: Record<string, { name: string; models: { id: string; name: string }[]; keyPlaceholder: string; local?: boolean; keyUrl?: string }> = {\n openai: { name: \"OpenAI\", keyUrl: \"https://platform.openai.com/api-keys\", keyPlaceholder: \"sk-...\", models: [\n { id: \"gpt-5.4\", name: \"GPT-5.4\" }, { id: \"gpt-5.4-mini\", name: \"GPT-5.4 Mini\" },\n { id: \"gpt-5.2\", name: \"GPT-5.2 Thinking\" }, { id: \"o3\", name: \"o3\" }, { id: \"o4-mini\", name: \"o4-mini\" },\n { id: \"gpt-4.1\", name: \"GPT-4.1\" }, { id: \"gpt-4.1-mini\", name: \"GPT-4.1 Mini\" },\n ]},\n anthropic: { name: \"Anthropic\", keyUrl: \"https://console.anthropic.com/settings/keys\", keyPlaceholder: \"sk-ant-...\", models: [\n { id: \"claude-opus-4-6\", name: \"Claude Opus 4.6\" }, { id: \"claude-sonnet-4-6\", name: \"Claude Sonnet 4.6\" },\n { id: \"claude-haiku-4-5-20251001\", name: \"Claude Haiku 4.5\" },\n ]},\n google: { name: \"Google Gemini\", keyUrl: \"https://aistudio.google.com/apikey\", keyPlaceholder: \"AIza...\", models: [\n { id: \"gemini-3.1-pro-preview\", name: \"Gemini 3.1 Pro\" }, { id: \"gemini-3-flash-preview\", name: \"Gemini 3 Flash\" },\n { id: \"gemini-2.5-pro\", name: \"Gemini 2.5 Pro\" }, { id: \"gemini-2.5-flash\", name: \"Gemini 2.5 Flash\" },\n ]},\n xai: { name: \"xAI (Grok)\", keyUrl: \"https://console.x.ai/team/default/api-keys\", keyPlaceholder: \"xai-...\", models: [\n { id: \"grok-4.20-0309-reasoning\", name: \"Grok 4.20 Reasoning\" }, { id: \"grok-4-1-fast-non-reasoning\", name: \"Grok 4.1 Fast\" },\n ]},\n deepseek: { name: \"DeepSeek\", keyUrl: \"https://platform.deepseek.com/api_keys\", keyPlaceholder: \"sk-...\", models: [\n { id: \"deepseek-chat\", name: \"DeepSeek V3.2\" }, { id: \"deepseek-reasoner\", name: \"DeepSeek R1\" },\n ]},\n mistral: { name: \"Mistral\", keyUrl: \"https://console.mistral.ai/api-keys\", keyPlaceholder: \"...\", models: [\n { id: \"mistral-large-3-25-12\", name: \"Mistral Large 3\" }, { id: \"codestral-2508\", name: \"Codestral\" }, { id: \"devstral-2-25-12\", name: \"Devstral 2\" },\n ]},\n groq: { name: \"Groq\", keyUrl: \"https://console.groq.com/keys\", keyPlaceholder: \"gsk_...\", models: [\n { id: \"meta-llama/llama-4-scout-17b-16e-instruct\", name: \"Llama 4 Scout\" }, { id: \"llama-3.3-70b-versatile\", name: \"Llama 3.3 70B\" },\n ]},\n minimax: { name: \"MiniMax\", keyUrl: \"https://platform.minimax.chat/user-center/basic-information/interface-key\", keyPlaceholder: \"MiniMax key...\", models: [\n { id: \"MiniMax-M2.7\", name: \"MiniMax M2.7\" }, { id: \"MiniMax-M2.5\", name: \"MiniMax M2.5\" },\n ]},\n moonshot: { name: \"Kimi (Moonshot)\", keyUrl: \"https://platform.moonshot.cn/console/api-keys\", keyPlaceholder: \"Moonshot key...\", models: [\n { id: \"kimi-k2.5\", name: \"Kimi K2.5\" }, { id: \"kimi-k2-thinking\", name: \"Kimi K2 Thinking\" },\n ]},\n qwen: { name: \"Qwen (Alibaba)\", keyUrl: \"https://dashscope.console.aliyun.com/apiKey\", keyPlaceholder: \"DashScope key...\", models: [\n { id: \"qwen3.5-plus\", name: \"Qwen 3.5 Plus\" }, { id: \"qwen-max\", name: \"Qwen Max\" },\n ]},\n zhipu: { name: \"Zhipu AI (GLM)\", keyUrl: \"https://open.bigmodel.cn/usercenter/apikeys\", keyPlaceholder: \"Zhipu key...\", models: [\n { id: \"glm-5\", name: \"GLM-5\" }, { id: \"glm-4.7\", name: \"GLM-4.7\" },\n ]},\n doubao: { name: \"Doubao (ByteDance)\", keyUrl: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey\", keyPlaceholder: \"Volcano key...\", models: [\n { id: \"doubao-seed-2-0-pro\", name: \"Doubao Seed 2.0 Pro\" }, { id: \"doubao-seed-2-0-code\", name: \"Doubao Seed 2.0 Code\" },\n ]},\n ollama: { name: \"Ollama (Local)\", keyPlaceholder: \"not required\", local: true, models: [] },\n openrouter: { name: \"OpenRouter\", keyUrl: \"https://openrouter.ai/settings/keys\", keyPlaceholder: \"sk-or-...\", models: [] },\n};\n\nfunction encodeBase64Utf8(value: string): string {\n const bytes = new TextEncoder().encode(value);\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 0x8000) {\n binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));\n }\n return btoa(binary);\n}\n\nfunction decodeBase64Utf8(value: string): string {\n const binary = atob(value);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return new TextDecoder().decode(bytes);\n}\n\nconst CURRENT_VERSION = \"0.17.1\";\n\n// ── State ────────────────────────────────────────────────────────\nconst state = {\n connected: false,\n panelOpen: false,\n activePanel: \"\" as \"\" | \"chat\" | \"settings\",\n selecting: false,\n selectedElement: null as SelectedElement | null,\n screenshot: null as string | null,\n messages: [] as { role: \"user\" | \"assistant\" | \"system\"; content: string }[],\n streaming: false,\n streamContent: \"\",\n provider: \"\",\n model: \"\",\n hasApiKey: false,\n configuredProviders: {} as Record<string, boolean>, // which providers have keys\n roots: [] as string[],\n updateAvailable: false,\n latestVersion: \"\",\n saveStatus: \"\" as \"\" | \"saving\" | \"saved\" | \"error\",\n networkCapture: false, // whether network panel is showing\n attachments: [] as string[], // base64 image data URLs attached to next message\n};\n\n// ── DOM refs (created once) ──────────────────────────────────────\nlet shadow: ShadowRoot;\nlet $toolbar: HTMLDivElement;\nlet $promptInput: HTMLInputElement;\nlet $promptCtx: HTMLDivElement;\nlet $panel: HTMLDivElement;\nlet $panelBody: HTMLDivElement;\n\n// ── Initialize ───────────────────────────────────────────────────\n// ── State Persistence (survives HMR page reloads) ────────────────\nfunction saveState() {\n try {\n sessionStorage.setItem(\"__om_state__\", JSON.stringify({\n messages: state.messages,\n provider: state.provider,\n model: state.model,\n panelOpen: state.panelOpen,\n activePanel: state.activePanel,\n }));\n } catch { /* quota exceeded or unavailable */ }\n}\n\nfunction restoreState() {\n try {\n const saved = JSON.parse(sessionStorage.getItem(\"__om_state__\") || \"{}\");\n if (saved.messages?.length) state.messages = saved.messages;\n if (saved.provider) state.provider = saved.provider;\n if (saved.model) state.model = saved.model;\n if (saved.panelOpen) { state.panelOpen = saved.panelOpen; state.activePanel = saved.activePanel || \"\"; }\n } catch { /* parse error or unavailable */ }\n}\n\nfunction init() {\n if (document.querySelector(\"openmagic-toolbar\")) return;\n\n // Restore chat history and settings from session storage (survives HMR)\n restoreState();\n\n const host = document.createElement(\"openmagic-toolbar\");\n host.dataset.openmagic = \"true\";\n shadow = host.attachShadow({ mode: \"closed\" });\n\n const style = document.createElement(\"style\");\n style.textContent = TOOLBAR_CSS;\n shadow.appendChild(style);\n\n const root = document.createElement(\"div\");\n shadow.appendChild(root);\n\n // Build DOM structure ONCE\n root.innerHTML = buildStaticDOM();\n\n // Cache refs\n $toolbar = root.querySelector(\".om-toolbar\")!;\n $promptInput = root.querySelector(\".om-prompt-input\")!;\n $promptCtx = root.querySelector(\".om-prompt-context\")!;\n $panel = root.querySelector(\".om-panel\")!;\n $panelBody = root.querySelector(\".om-panel-body\")!;\n\n document.body.appendChild(host);\n\n // Attach event delegation ONCE\n attachGlobalEvents(root);\n setupDraggable();\n\n // Restore persisted toolbar position\n try {\n const pos = JSON.parse(localStorage.getItem(\"__om_pos__\") || \"\");\n if (pos?.left && pos?.top) {\n $toolbar.style.left = pos.left;\n $toolbar.style.top = pos.top;\n $toolbar.style.right = \"auto\";\n $toolbar.style.bottom = \"auto\";\n }\n } catch {}\n\n installNetworkCapture();\n installConsoleCapture();\n checkForUpdates();\n\n // Connect to server — same origin (single port)\n const currentScript = document.querySelector('script[data-openmagic-token]') as HTMLScriptElement | null;\n const token = currentScript?.dataset.openmagicToken || (window as any).__OPENMAGIC_TOKEN__;\n const wsPort = parseInt(window.location.port, 10) || (window.location.protocol === \"https:\" ? 443 : 80);\n if (token) {\n ws.connect(wsPort, token)\n .then(() => {\n state.connected = true;\n updateStatusDot();\n return ws.request(\"config.get\");\n })\n .then((msg: any) => {\n // Merge server config with restored state (restored state takes precedence for provider/model)\n const serverProvider = msg.payload?.provider || \"\";\n const serverModel = msg.payload?.model || \"\";\n state.provider = state.provider || serverProvider;\n state.model = state.model || serverModel;\n state.configuredProviders = msg.payload?.apiKeys || {};\n state.hasApiKey = state.configuredProviders[state.provider] || false;\n state.roots = msg.payload?.roots || [];\n\n // Restore panel state if we had it open before refresh\n if (state.panelOpen && state.activePanel) {\n openPanel(state.activePanel as \"chat\" | \"settings\");\n } else if (!state.provider || (!state.hasApiKey && !Object.values(state.configuredProviders).some(Boolean))) {\n openPanel(\"settings\");\n }\n updatePillButtons();\n })\n .catch(() => {\n state.connected = false;\n updateStatusDot();\n });\n }\n}\n\nfunction buildStaticDOM(): string {\n return `\n <div class=\"om-toolbar\">\n <div class=\"om-toolbar-header\">\n <span class=\"om-grab\">${ICON.grip}</span>\n <span class=\"om-pill-brand\">\n <span class=\"om-pill-icon\">${ICON.sparkle}</span>\n <span class=\"om-pill-text\">OpenMagic</span>\n </span>\n <span class=\"om-pill-divider\"></span>\n <button class=\"om-pill-btn\" data-action=\"select\" title=\"Select element\">${ICON.crosshair}</button>\n <button class=\"om-pill-btn\" data-action=\"screenshot\" title=\"Screenshot\">${ICON.camera}</button>\n <button class=\"om-pill-btn\" data-action=\"network\" title=\"Network & Performance\">${ICON.activity}</button>\n <span class=\"om-pill-divider\"></span>\n <button class=\"om-pill-btn\" data-action=\"chat\" title=\"Chat\">${ICON.chat}</button>\n <button class=\"om-pill-btn\" data-action=\"settings\" title=\"Settings\">${ICON.settings}</button>\n <span class=\"om-status-dot disconnected\"></span>\n </div>\n <div class=\"om-panel om-hidden\">\n <div class=\"om-panel-header\">\n <span class=\"om-panel-title\"></span>\n <span class=\"om-panel-version\">v${CURRENT_VERSION}</span>\n <button class=\"om-panel-close\" data-action=\"close-panel\">${ICON.x}</button>\n </div>\n <div class=\"om-panel-body\"></div>\n </div>\n <div class=\"om-prompt-attachments\"></div>\n <div class=\"om-prompt-row\">\n <div class=\"om-prompt-context\"></div>\n <button class=\"om-prompt-attach\" data-action=\"attach-image\" title=\"Attach image\">${ICON.paperclip}</button>\n <input class=\"om-prompt-input\" type=\"text\" placeholder=\"Describe what to change...\" autocomplete=\"off\" />\n <button class=\"om-prompt-send\" data-action=\"prompt-send\">${ICON.send}</button>\n <input type=\"file\" class=\"om-file-input om-hidden\" accept=\"image/*\" multiple />\n </div>\n </div>`;\n}\n\n// ── Event Delegation (attached ONCE) ─────────────────────────────\nfunction attachGlobalEvents(root: HTMLElement) {\n // Click delegation\n root.addEventListener(\"click\", (e) => {\n const target = (e.target as HTMLElement).closest(\"[data-action]\") as HTMLElement | null;\n if (!target) return;\n e.preventDefault();\n e.stopPropagation();\n const action = target.dataset.action!;\n handleAction(action, target);\n });\n\n // Change delegation (dropdowns)\n root.addEventListener(\"change\", (e) => {\n const target = e.target as HTMLSelectElement;\n const field = target.dataset.field;\n if (!field) return;\n\n if (field === \"provider\") {\n state.provider = target.value;\n state.model = MODEL_REGISTRY[state.provider]?.models[0]?.id || \"\";\n state.hasApiKey = state.configuredProviders[state.provider] || MODEL_REGISTRY[state.provider]?.local || false;\n state.saveStatus = \"\";\n refreshPanelContent();\n } else if (field === \"model\") {\n state.model = target.value;\n }\n });\n\n // Prompt input: Enter to send\n $promptInput.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n sendPrompt();\n }\n });\n\n // File input change handler\n const fileInput = root.querySelector(\".om-file-input\") as HTMLInputElement;\n if (fileInput) {\n fileInput.addEventListener(\"change\", () => {\n handleFileSelect(fileInput.files);\n fileInput.value = \"\"; // Reset so same file can be selected again\n });\n }\n\n // Drag and drop on prompt area\n const promptRow = root.querySelector(\".om-prompt-row\");\n if (promptRow) {\n promptRow.addEventListener(\"dragover\", (e) => {\n e.preventDefault();\n (promptRow as HTMLElement).style.borderColor = \"rgba(108, 92, 231, 0.5)\";\n });\n promptRow.addEventListener(\"dragleave\", () => {\n (promptRow as HTMLElement).style.borderColor = \"\";\n });\n promptRow.addEventListener(\"drop\", (e) => {\n e.preventDefault();\n (promptRow as HTMLElement).style.borderColor = \"\";\n const dt = (e as DragEvent).dataTransfer;\n if (dt?.files?.length) handleFileSelect(dt.files);\n });\n\n // Also handle paste with images\n $promptInput.addEventListener(\"paste\", (e) => {\n const items = (e as ClipboardEvent).clipboardData?.items;\n if (!items) return;\n for (let i = 0; i < items.length; i++) {\n if (items[i].type.startsWith(\"image/\")) {\n const file = items[i].getAsFile();\n if (file) {\n const dt = new DataTransfer();\n dt.items.add(file);\n handleFileSelect(dt.files);\n }\n }\n }\n });\n }\n\n // Listen for reconnection events\n ws.onMessage((msg: any) => {\n if (msg.type === \"reconnected\") {\n state.connected = true;\n updateStatusDot();\n }\n });\n}\n\nfunction resolveFilePath(rel: string): string {\n return state.roots.length > 0 ? state.roots[0] + \"/\" + rel : rel;\n}\n\nasync function applyDiff(target: HTMLElement) {\n const file = target.dataset.file;\n const searchB64 = target.dataset.search;\n const replaceB64 = target.dataset.replace;\n if (!file || !searchB64 || !replaceB64) return;\n\n let search: string, replace: string;\n try {\n search = decodeBase64Utf8(searchB64);\n replace = decodeBase64Utf8(replaceB64);\n } catch {\n state.messages.push({ role: \"system\", content: `Failed to decode diff data for ${file}` });\n refreshPanelContent();\n return;\n }\n\n const card = target.closest(\".om-diff-card\") as HTMLElement | null;\n const filePath = resolveFilePath(file);\n\n // Show applying state\n if (card) {\n const actions = card.querySelector(\".om-diff-actions\");\n if (actions) actions.innerHTML = '<span class=\"om-spinner\"></span> Applying...';\n }\n\n try {\n const fileResult = await ws.request(\"fs.read\", { path: filePath });\n const content = fileResult?.payload?.content;\n\n if (!content) {\n state.messages.push({ role: \"system\", content: `Could not read ${file} — file may not exist at ${filePath}` });\n } else {\n const occurrences = content.split(search).length - 1;\n if (occurrences === 0) {\n state.messages.push({ role: \"system\", content: `No matching code found in ${file}. The file may have changed since the suggestion was made.` });\n } else if (occurrences > 1) {\n state.messages.push({ role: \"system\", content: `Found ${occurrences} matches in ${file} — expected exactly 1. Edit not applied for safety.` });\n } else {\n const writeResult = await ws.request(\"fs.write\", { path: filePath, content: content.replace(search, replace) });\n if (writeResult?.payload?.ok === false) {\n state.messages.push({ role: \"system\", content: `Write failed: ${file} - ${writeResult.payload?.error || \"unknown\"}` });\n } else {\n const idx = card?.dataset.diffIdx;\n if (idx !== undefined) {\n state.messages[parseInt(idx)] = { role: \"system\", content: `Applied change to ${file}` };\n } else {\n state.messages.push({ role: \"system\", content: `Applied change to ${file}` });\n }\n }\n }\n }\n } catch (e: any) {\n state.messages.push({ role: \"system\", content: `Failed to apply: ${file} — ${e.message}` });\n }\n\n refreshPanelContent();\n scrollChatToBottom();\n}\n\nfunction rejectDiff(target: HTMLElement) {\n const idx = target.dataset.idx;\n if (idx !== undefined) {\n const i = parseInt(idx);\n const parts = state.messages[i]?.content.split(\"__\");\n const file = parts?.[3] || \"file\";\n state.messages[i] = { role: \"system\", content: `Rejected change to ${file}` };\n }\n refreshPanelContent();\n scrollChatToBottom();\n}\n\nfunction handleAction(action: string, target: HTMLElement) {\n switch (action) {\n case \"select\": toggleSelectMode(); break;\n case \"screenshot\": takeScreenshot(); break;\n case \"chat\": togglePanel(\"chat\"); break;\n case \"settings\": togglePanel(\"settings\"); break;\n case \"close-panel\": closePanel(); break;\n case \"prompt-send\": sendPrompt(); break;\n case \"save-settings\": saveSettings(); break;\n case \"get-key\": {\n const url = target.dataset.url;\n if (url) window.open(url, \"_blank\", \"noopener\");\n break;\n }\n case \"change-key\": {\n // Show the hidden key input field\n const changeRow = shadow.querySelector(\"[data-key-change]\");\n if (changeRow) changeRow.classList.remove(\"om-hidden\");\n target.style.display = \"none\";\n break;\n }\n case \"network\": togglePanel(\"chat\"); captureNetworkProfile(); break;\n case \"attach-image\": triggerFileAttach(); break;\n case \"remove-attachment\": {\n const idx = parseInt(target.dataset.idx || \"0\", 10);\n state.attachments.splice(idx, 1);\n renderAttachments();\n break;\n }\n case \"apply-diff\": applyDiff(target); break;\n case \"reject-diff\": rejectDiff(target); break;\n case \"clear-element\": state.selectedElement = null; updatePromptContext(); break;\n case \"clear-screenshot\": state.screenshot = null; updatePromptContext(); break;\n }\n}\n\n// ── Targeted UI Updates (no full DOM rebuild) ────────────────────\n\nfunction updateStatusDot() {\n const dot = shadow.querySelector(\".om-status-dot\");\n if (dot) {\n dot.className = `om-status-dot ${state.connected ? \"connected\" : \"disconnected\"}`;\n }\n}\n\nfunction updatePillButtons() {\n shadow.querySelectorAll(\".om-pill-btn\").forEach((btn) => {\n const action = (btn as HTMLElement).dataset.action;\n btn.classList.toggle(\"active\", action === state.activePanel || (action === \"select\" && state.selecting));\n });\n}\n\nfunction updatePromptContext() {\n const chips: string[] = [];\n if (state.selectedElement) {\n chips.push(`<span class=\"om-prompt-chip\">${state.selectedElement.tagName}${state.selectedElement.id ? \"#\" + state.selectedElement.id : \"\"} <button class=\"om-prompt-chip-x\" data-action=\"clear-element\">${ICON.x}</button></span>`);\n }\n if (state.screenshot) {\n chips.push(`<span class=\"om-prompt-chip\">Screenshot <button class=\"om-prompt-chip-x\" data-action=\"clear-screenshot\">${ICON.x}</button></span>`);\n }\n if (state.attachments.length) {\n chips.push(`<span class=\"om-prompt-chip\">${state.attachments.length} image${state.attachments.length > 1 ? \"s\" : \"\"}</span>`);\n }\n $promptCtx.innerHTML = chips.join(\"\");\n}\n\n// ── Panel Management ─────────────────────────────────────────────\n\nfunction openPanel(panel: \"chat\" | \"settings\") {\n state.panelOpen = true;\n state.activePanel = panel;\n $panel.classList.remove(\"om-hidden\");\n const title = shadow.querySelector(\".om-panel-title\");\n if (title) title.textContent = panel === \"settings\" ? \"Settings\" : \"Chat\";\n refreshPanelContent();\n updatePillButtons();\n}\n\nfunction closePanel() {\n state.panelOpen = false;\n state.activePanel = \"\";\n $panel.classList.add(\"om-hidden\");\n updatePillButtons();\n}\n\nfunction togglePanel(panel: \"chat\" | \"settings\") {\n if (state.panelOpen && state.activePanel === panel) {\n closePanel();\n } else {\n openPanel(panel);\n }\n}\n\nfunction refreshPanelContent() {\n if (state.activePanel === \"settings\") {\n $panelBody.innerHTML = renderSettingsHTML();\n } else if (state.activePanel === \"chat\") {\n $panelBody.innerHTML = renderChatHTML();\n scrollChatToBottom();\n }\n saveState();\n}\n\n// ── Settings Renderer ────────────────────────────────────────────\n\nfunction renderSettingsHTML(): string {\n const providerOpts = Object.entries(MODEL_REGISTRY)\n .map(([k, p]) => {\n const configured = state.configuredProviders[k] || p.local;\n const indicator = configured ? \" \\u2713\" : \"\";\n return `<option value=\"${k}\" ${state.provider === k ? \"selected\" : \"\"}>${p.name}${indicator}</option>`;\n }).join(\"\");\n\n const prov = MODEL_REGISTRY[state.provider];\n const modelOpts = prov\n ? prov.models.map(m => `<option value=\"${m.id}\" ${state.model === m.id ? \"selected\" : \"\"}>${m.name}</option>`).join(\"\")\n : '<option value=\"\">Select provider first</option>';\n\n const isLocal = prov?.local || false;\n const keyUrl = prov?.keyUrl || \"\";\n const keyPh = prov?.keyPlaceholder || \"Enter API key...\";\n const providerHasKey = state.configuredProviders[state.provider] || false;\n\n const updateBanner = state.updateAvailable\n ? `<div class=\"om-update-banner\">v${state.latestVersion} available <code class=\"om-update-cmd\">npx openmagic@latest</code></div>` : \"\";\n\n // Show connected status if current provider has a key\n const statusHtml = (providerHasKey || isLocal)\n ? `<div class=\"om-status om-status-success\">${ICON.check} ${prov?.name || \"Provider\"} connected</div>` : \"\";\n\n const saveBtnText = state.saveStatus === \"saving\" ? '<span class=\"om-spinner\"></span> Saving...'\n : state.saveStatus === \"saved\" ? `${ICON.check} Saved` : \"Save\";\n const saveBtnClass = state.saveStatus === \"saving\" ? \"om-btn om-btn-saving\"\n : state.saveStatus === \"saved\" ? \"om-btn om-btn-saved\" : \"om-btn\";\n const saveBtnDisabled = state.saveStatus === \"saving\" ? \"disabled\" : \"\";\n\n // API key section: show \"configured\" state if key exists, with option to change\n let keySection = \"\";\n if (!isLocal && state.provider) {\n if (providerHasKey) {\n keySection = `\n <div class=\"om-field\">\n <label class=\"om-label\">API Key</label>\n <div class=\"om-key-configured\">\n ${ICON.check} <span>Key configured</span>\n <button class=\"om-btn-change-key\" data-action=\"change-key\">Change</button>\n </div>\n <div class=\"om-key-change-row om-hidden\" data-key-change>\n <div class=\"om-key-row\">\n <input type=\"text\" class=\"om-input om-key-input\" data-field=\"apiKey\" placeholder=\"${keyPh}\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" data-lpignore=\"true\" data-1p-ignore=\"true\" data-form-type=\"other\" />\n ${keyUrl ? `<button class=\"om-btn-get-key\" data-action=\"get-key\" data-url=\"${keyUrl}\">${ICON.externalLink} Get key</button>` : \"\"}\n </div>\n </div>\n </div>`;\n } else {\n keySection = `\n <div class=\"om-field\">\n <label class=\"om-label\">API Key</label>\n <div class=\"om-key-row\">\n <input type=\"text\" class=\"om-input om-key-input\" data-field=\"apiKey\" placeholder=\"${keyPh}\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" data-lpignore=\"true\" data-1p-ignore=\"true\" data-form-type=\"other\" />\n ${keyUrl ? `<button class=\"om-btn-get-key\" data-action=\"get-key\" data-url=\"${keyUrl}\">${ICON.externalLink} Get key</button>` : \"\"}\n </div>\n ${keyUrl ? `<div class=\"om-key-hint\"><a data-action=\"get-key\" data-url=\"${keyUrl}\">Get your ${prov?.name || \"\"} API key here</a></div>` : \"\"}\n </div>`;\n }\n }\n\n return `\n ${updateBanner}\n <div class=\"om-settings\">\n <div class=\"om-field\">\n <label class=\"om-label\">Provider</label>\n <select class=\"om-select\" data-field=\"provider\"><option value=\"\">Select Provider...</option>${providerOpts}</select>\n </div>\n <div class=\"om-field\">\n <label class=\"om-label\">Model</label>\n <select class=\"om-select\" data-field=\"model\"><option value=\"\">Select Model...</option>${modelOpts}</select>\n </div>\n ${keySection}\n <button class=\"${saveBtnClass}\" data-action=\"save-settings\" ${saveBtnDisabled}>${saveBtnText}</button>\n ${statusHtml}\n </div>`;\n}\n\n// ── Chat Renderer ────────────────────────────────────────────────\n\nfunction renderChatHTML(): string {\n if (!state.provider || (!state.hasApiKey && !MODEL_REGISTRY[state.provider]?.local)) {\n return `<div class=\"om-status om-status-error\">Configure your provider in Settings first</div>`;\n }\n\n const msgs = state.messages.map((m, i) => {\n if (m.content.startsWith(\"__DIFF__\")) {\n try {\n const diff = JSON.parse(decodeBase64Utf8(m.content.slice(8)));\n const searchB64 = encodeBase64Utf8(diff.search);\n const replaceB64 = encodeBase64Utf8(diff.replace);\n return `<div class=\"om-diff-card\" data-diff-idx=\"${i}\">\n <div class=\"om-diff-file\">${escapeHtml(diff.file)}</div>\n <div class=\"om-diff-removed\">${escapeHtml(diff.search.slice(0, 200))}</div>\n <div class=\"om-diff-added\">${escapeHtml(diff.replace.slice(0, 200))}</div>\n <div class=\"om-diff-actions\">\n <button class=\"om-btn om-btn-sm\" data-action=\"apply-diff\" data-file=\"${escapeHtml(diff.file)}\" data-search=\"${searchB64}\" data-replace=\"${replaceB64}\">Apply</button>\n <button class=\"om-btn-secondary om-btn-sm\" data-action=\"reject-diff\" data-idx=\"${i}\">Reject</button>\n </div>\n </div>`;\n } catch {\n return `<div class=\"om-msg om-msg-system\">Malformed diff data</div>`;\n }\n }\n return `<div class=\"om-msg om-msg-${m.role}\">${escapeHtml(m.content)}</div>`;\n }).join(\"\");\n\n const streamHtml = state.streaming\n ? `<div class=\"om-msg om-msg-assistant\"><span class=\"om-spinner\"></span>${escapeHtml(state.streamContent)}</div>` : \"\";\n\n const empty = !state.messages.length && !state.streaming\n ? `<div class=\"om-chat-empty\">Select an element or type below to start</div>` : \"\";\n\n return `<div class=\"om-chat-messages\">${empty}${msgs}${streamHtml}</div>`;\n}\n\nfunction scrollChatToBottom() {\n requestAnimationFrame(() => {\n const el = $panelBody.querySelector(\".om-chat-messages\");\n if (el) el.scrollTop = el.scrollHeight;\n });\n}\n\n// ── Save Settings ────────────────────────────────────────────────\n\nasync function saveSettings() {\n const apiKeyInput = $panelBody.querySelector('[data-field=\"apiKey\"]') as HTMLInputElement;\n const apiKey = apiKeyInput?.value || \"\";\n\n if (!state.provider) {\n state.saveStatus = \"error\";\n updateSaveButton();\n setTimeout(() => { state.saveStatus = \"\"; refreshPanelContent(); }, 2000);\n return;\n }\n\n // Check WebSocket connection\n if (!ws.isConnected()) {\n state.saveStatus = \"error\";\n updateSaveButton();\n const btn = $panelBody.querySelector('[data-action=\"save-settings\"]');\n if (btn) btn.innerHTML = \"Not connected - check terminal\";\n setTimeout(() => { state.saveStatus = \"\"; refreshPanelContent(); }, 3000);\n return;\n }\n\n const payload: any = { provider: state.provider, model: state.model };\n if (apiKey) payload.apiKey = apiKey;\n\n state.saveStatus = \"saving\";\n updateSaveButton();\n\n try {\n // Race against a 8s local timeout (don't wait 30s)\n const result = await Promise.race([\n ws.request(\"config.set\", payload),\n new Promise((_, reject) => setTimeout(() => reject(new Error(\"Save timed out\")), 8000)),\n ]);\n // Mark this provider as configured\n if (apiKey && state.provider) {\n state.configuredProviders[state.provider] = true;\n }\n state.hasApiKey = !!(apiKey || state.configuredProviders[state.provider]);\n state.saveStatus = \"saved\";\n updateSaveButton();\n\n // Auto-transition to chat after 1.2s\n setTimeout(() => {\n state.saveStatus = \"\";\n if (state.activePanel === \"settings\") {\n openPanel(\"chat\");\n }\n }, 1200);\n } catch (e: any) {\n state.saveStatus = \"error\";\n const btn = $panelBody.querySelector('[data-action=\"save-settings\"]');\n const msg = (e?.message || \"\").includes(\"timeout\") ? \"Connection timeout - is the CLI running?\"\n : (e?.message || \"\").includes(\"connected\") ? \"Not connected to OpenMagic server\"\n : `Save failed: ${e?.message || \"Unknown error\"}`;\n if (btn) {\n btn.innerHTML = msg;\n btn.className = \"om-btn\";\n (btn as HTMLButtonElement).disabled = false;\n }\n setTimeout(() => { state.saveStatus = \"\"; refreshPanelContent(); }, 4000);\n }\n}\n\nfunction updateSaveButton() {\n const btn = $panelBody.querySelector('[data-action=\"save-settings\"]');\n if (!btn) return;\n if (state.saveStatus === \"saving\") {\n btn.innerHTML = '<span class=\"om-spinner\"></span> Saving...';\n btn.className = \"om-btn om-btn-saving\";\n (btn as HTMLButtonElement).disabled = true;\n } else if (state.saveStatus === \"saved\") {\n btn.innerHTML = `${ICON.check} Saved`;\n btn.className = \"om-btn om-btn-saved\";\n (btn as HTMLButtonElement).disabled = false;\n } else if (state.saveStatus === \"error\") {\n btn.innerHTML = \"Save failed - try again\";\n btn.className = \"om-btn\";\n (btn as HTMLButtonElement).disabled = false;\n } else {\n btn.innerHTML = \"Save\";\n btn.className = \"om-btn\";\n (btn as HTMLButtonElement).disabled = false;\n }\n}\n\n// ── Send Prompt ──────────────────────────────────────────────────\n\nasync function sendPrompt() {\n const text = $promptInput.value.trim();\n if (!text || state.streaming) return;\n\n if (!state.provider || (!state.hasApiKey && !MODEL_REGISTRY[state.provider]?.local)) {\n openPanel(\"settings\");\n return;\n }\n\n // Add user message\n state.messages.push({ role: \"user\", content: text });\n state.streaming = true;\n state.streamContent = \"\";\n $promptInput.value = \"\";\n\n // Open chat panel\n openPanel(\"chat\");\n\n // Build context — includes page info, selected element, screenshot, network/console logs\n const context: any = buildContext(state.selectedElement, state.screenshot);\n context.pageUrl = window.location.href;\n context.pageTitle = document.title;\n\n // Include image attachments (for vision-capable models)\n if (state.attachments.length > 0) {\n // Use the first attachment as the screenshot if none is captured\n if (!context.screenshot) {\n context.screenshot = state.attachments[0];\n }\n // Store all attachments for multi-image models\n context.attachments = [...state.attachments];\n }\n\n // Grounding: read project tree + score and read relevant source files\n const MAX_GROUNDED_FILES = 4;\n const MAX_GROUNDED_CHARS = 24000;\n const TEXT_RE = /\\.(?:[cm]?[jt]sx?|svelte|vue|astro|html?|css|scss|less|php|py)$/i;\n\n try {\n const treeResult = await ws.request(\"fs.list\", {});\n if (treeResult?.payload?.projectTree) {\n context.projectTree = treeResult.payload.projectTree;\n }\n\n // Score files by relevance to the prompt + selected element\n const allFiles = (treeResult?.payload?.files || []) as Array<{ path: string; type: string }>;\n const textFiles = allFiles.filter((f: { path: string; type: string }) => f.type === \"file\" && TEXT_RE.test(f.path));\n\n // Extract search tokens from prompt and selected element\n const searchTokens = [text, state.selectedElement?.tagName, state.selectedElement?.id, state.selectedElement?.className, state.selectedElement?.textContent]\n .filter(Boolean).join(\" \").toLowerCase().split(/[^a-z0-9_-]+/).filter((t: string) => t.length >= 2);\n\n const scored = textFiles.map((f: { path: string; type: string }) => {\n let score = 0;\n const lower = f.path.toLowerCase();\n for (const token of searchTokens) { if (lower.includes(token)) score += 5; }\n if (/(component|page|route|app|src|view|template)/.test(lower)) score += 2;\n return { ...f, score };\n }).sort((a: { score: number }, b: { score: number }) => b.score - a.score);\n\n // Read top scored files\n const files: Array<{ path: string; content: string }> = [];\n let totalChars = 0;\n for (const f of scored.slice(0, MAX_GROUNDED_FILES)) {\n if (totalChars >= MAX_GROUNDED_CHARS) break;\n try {\n const root = state.roots[0] || \"\";\n const result = await ws.request(\"fs.read\", { path: root ? `${root}/${f.path}` : f.path });\n const content = String(result?.payload?.content || \"\");\n if (!content) continue;\n const trimmed = content.slice(0, Math.min(8000, MAX_GROUNDED_CHARS - totalChars));\n files.push({ path: f.path, content: trimmed });\n totalChars += trimmed.length;\n } catch { /* skip unreadable files */ }\n }\n if (files.length) context.files = files;\n } catch { /* grounding is best-effort */ }\n\n try {\n const result = await ws.stream(\n \"llm.chat\",\n {\n provider: state.provider,\n model: state.model,\n messages: state.messages.map(m => ({ role: m.role, content: m.content })),\n context,\n },\n (chunk: string) => {\n state.streamContent += chunk;\n // Update the streaming message in-place\n const msgEl = $panelBody.querySelector(\".om-msg-assistant:last-child\");\n if (msgEl) {\n msgEl.innerHTML = `<span class=\"om-spinner\"></span>${escapeHtml(state.streamContent)}`;\n scrollChatToBottom();\n }\n }\n );\n\n state.messages.push({ role: \"assistant\", content: state.streamContent || result?.content || \"\" });\n\n // Show diff previews for approval instead of auto-applying\n if (result?.modifications?.length) {\n for (const mod of result.modifications) {\n if (mod.type === \"edit\" && mod.file && mod.search && mod.replace) {\n const diffId = Math.random().toString(36).slice(2);\n const diffPayload = JSON.stringify({ id: diffId, file: mod.file, search: mod.search, replace: mod.replace });\n state.messages.push({\n role: \"system\",\n content: `__DIFF__${encodeBase64Utf8(diffPayload)}`,\n });\n }\n }\n }\n } catch (e: any) {\n state.messages.push({ role: \"system\", content: `Error: ${e.message}` });\n }\n\n state.streaming = false;\n state.streamContent = \"\";\n state.attachments = [];\n renderAttachments();\n refreshPanelContent();\n scrollChatToBottom();\n}\n\n// ── Network & Profiling ──────────────────────────────────────────\n\nfunction captureNetworkProfile() {\n // Capture performance timing\n const perf = window.performance;\n const navEntry = perf.getEntriesByType(\"navigation\")[0] as PerformanceNavigationTiming | undefined;\n const paintEntries = perf.getEntriesByType(\"paint\");\n const resources = perf.getEntriesByType(\"resource\").slice(-20) as PerformanceResourceTiming[];\n\n const networkLogs = getNetworkLogs();\n const consoleLogs = getConsoleLogs();\n\n // Build a summary message\n const lines: string[] = [];\n lines.push(\"--- Network & Performance Capture ---\");\n\n if (navEntry) {\n lines.push(`Page load: ${Math.round(navEntry.loadEventEnd - navEntry.startTime)}ms`);\n lines.push(`DOM ready: ${Math.round(navEntry.domContentLoadedEventEnd - navEntry.startTime)}ms`);\n lines.push(`TTFB: ${Math.round(navEntry.responseStart - navEntry.startTime)}ms`);\n }\n\n const fcp = paintEntries.find(e => e.name === \"first-contentful-paint\");\n if (fcp) lines.push(`FCP: ${Math.round(fcp.startTime)}ms`);\n\n if (networkLogs.length) {\n lines.push(`\\nRecent requests (${networkLogs.length}):`);\n for (const log of networkLogs.slice(-15)) {\n lines.push(` ${log.method} ${log.url.slice(0, 80)} → ${log.status || \"pending\"} (${log.duration || \"?\"}ms)`);\n }\n }\n\n if (consoleLogs.length) {\n const errors = consoleLogs.filter(l => l.level === \"error\");\n const warns = consoleLogs.filter(l => l.level === \"warn\");\n if (errors.length) lines.push(`\\nConsole errors: ${errors.length}`);\n if (warns.length) lines.push(`Console warnings: ${warns.length}`);\n }\n\n if (resources.length) {\n const slowest = [...resources].sort((a, b) => b.duration - a.duration).slice(0, 5);\n lines.push(`\\nSlowest resources:`);\n for (const r of slowest) {\n lines.push(` ${Math.round(r.duration)}ms — ${r.name.split(\"/\").pop()?.slice(0, 50)}`);\n }\n }\n\n // Add as a system message in the chat\n state.messages.push({ role: \"system\", content: lines.join(\"\\n\") });\n refreshPanelContent();\n scrollChatToBottom();\n updatePromptContext();\n}\n\n// ── File Attachments ─────────────────────────────────────────────\n\nfunction triggerFileAttach() {\n const input = shadow.querySelector(\".om-file-input\") as HTMLInputElement;\n if (input) input.click();\n}\n\nfunction handleFileSelect(files: FileList | null) {\n if (!files) return;\n for (let i = 0; i < files.length && state.attachments.length < 5; i++) {\n const file = files[i];\n if (!file.type.startsWith(\"image/\")) continue;\n if (file.size > 10 * 1024 * 1024) continue; // 10MB max\n const reader = new FileReader();\n reader.onload = () => {\n if (typeof reader.result === \"string\") {\n state.attachments.push(reader.result);\n renderAttachments();\n }\n };\n reader.readAsDataURL(file);\n }\n}\n\nfunction renderAttachments() {\n const container = shadow.querySelector(\".om-prompt-attachments\");\n if (!container) return;\n if (!state.attachments.length) {\n container.innerHTML = \"\";\n container.classList.add(\"om-hidden\");\n return;\n }\n container.classList.remove(\"om-hidden\");\n container.innerHTML = state.attachments.map((a, i) =>\n `<div class=\"om-attachment-thumb\">\n <img src=\"${a}\" alt=\"attachment\" />\n <button class=\"om-attachment-remove\" data-action=\"remove-attachment\" data-idx=\"${i}\">${ICON.x}</button>\n </div>`\n ).join(\"\");\n}\n\n// ── Select Mode ──────────────────────────────────────────────────\n\nlet selectHandler: ((e: MouseEvent) => void) | null = null;\nlet hoverHandler: ((e: MouseEvent) => void) | null = null;\n\nfunction toggleSelectMode() {\n state.selecting ? exitSelectMode() : enterSelectMode();\n}\n\nfunction enterSelectMode() {\n state.selecting = true;\n document.body.style.cursor = \"crosshair\";\n updatePillButtons();\n\n hoverHandler = (e: MouseEvent) => {\n const t = e.target as HTMLElement;\n if (t.closest(\"openmagic-toolbar\") || t.dataset?.openmagic) return;\n const r = t.getBoundingClientRect();\n showHighlight({ x: r.x, y: r.y, width: r.width, height: r.height });\n };\n\n selectHandler = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const t = e.target as HTMLElement;\n if (t.closest(\"openmagic-toolbar\") || t.dataset?.openmagic) return;\n state.selectedElement = inspectElement(t);\n exitSelectMode();\n updatePromptContext();\n $promptInput.focus();\n };\n\n // ESC to cancel\n const escHandler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n exitSelectMode();\n }\n };\n\n document.addEventListener(\"mousemove\", hoverHandler, true);\n document.addEventListener(\"click\", selectHandler, true);\n document.addEventListener(\"keydown\", escHandler, true);\n\n // Store for cleanup\n (enterSelectMode as any)._escHandler = escHandler;\n}\n\nfunction exitSelectMode() {\n state.selecting = false;\n document.body.style.cursor = \"\";\n hideHighlight();\n if (hoverHandler) { document.removeEventListener(\"mousemove\", hoverHandler, true); hoverHandler = null; }\n if (selectHandler) { document.removeEventListener(\"click\", selectHandler, true); selectHandler = null; }\n const escH = (enterSelectMode as any)._escHandler;\n if (escH) { document.removeEventListener(\"keydown\", escH, true); (enterSelectMode as any)._escHandler = null; }\n updatePillButtons();\n}\n\nasync function takeScreenshot() {\n // If element is selected, try element screenshot first\n let target: HTMLElement | undefined;\n try {\n const sel = state.selectedElement?.cssSelector?.trim();\n if (sel) target = (document.querySelector(sel) as HTMLElement) || undefined;\n } catch { /* stale or invalid selector */ }\n const ss = await captureScreenshot(target || undefined);\n if (ss) {\n state.screenshot = ss;\n updatePromptContext();\n $promptInput.focus();\n }\n}\n\n// ── Draggable (setup ONCE) ───────────────────────────────────────\n\nfunction setupDraggable() {\n let active = false, startX = 0, startY = 0, origX = 0, origY = 0;\n\n $toolbar.addEventListener(\"mousedown\", (e) => {\n const t = e.target as HTMLElement;\n if (t.closest(\"[data-action]\")) return;\n if (!t.closest(\".om-grab\") && !t.closest(\".om-pill-brand\")) return;\n active = true;\n startX = e.clientX; startY = e.clientY;\n const r = $toolbar.getBoundingClientRect();\n origX = r.left; origY = r.top;\n e.preventDefault();\n });\n\n document.addEventListener(\"mousemove\", (e) => {\n if (!active) return;\n $toolbar.style.left = (origX + e.clientX - startX) + \"px\";\n $toolbar.style.top = (origY + e.clientY - startY) + \"px\";\n $toolbar.style.right = \"auto\";\n $toolbar.style.bottom = \"auto\";\n });\n\n document.addEventListener(\"mouseup\", () => {\n if (active) {\n active = false;\n // Persist position\n try {\n localStorage.setItem(\"__om_pos__\", JSON.stringify({\n left: $toolbar.style.left,\n top: $toolbar.style.top,\n }));\n } catch {}\n }\n });\n}\n\n// ── Helpers ──────────────────────────────────────────────────────\n\nfunction escapeHtml(text: string): string {\n const d = document.createElement(\"div\");\n d.textContent = text;\n return d.innerHTML;\n}\n\nfunction checkForUpdates() {\n fetch(\"https://registry.npmjs.org/openmagic/latest\", {\n headers: { Accept: \"application/json\" },\n signal: AbortSignal.timeout(5000),\n }).then(r => r.ok ? r.json() : null).then(d => {\n if (!d?.version) return;\n const l = d.version.split(\".\").map(Number), c = CURRENT_VERSION.split(\".\").map(Number);\n for (let i = 0; i < 3; i++) { if ((l[i]||0) > (c[i]||0)) { state.updateAvailable = true; state.latestVersion = d.version; showUpdateDot(); return; } if ((l[i]||0) < (c[i]||0)) return; }\n }).catch(() => {});\n}\n\nfunction showUpdateDot() {\n const existing = shadow.querySelector(\".om-update-dot\");\n if (existing) return;\n const dot = document.createElement(\"span\");\n dot.className = \"om-update-dot\";\n dot.title = `v${state.latestVersion} available`;\n dot.addEventListener(\"click\", () => openPanel(\"settings\"));\n const header = shadow.querySelector(\".om-toolbar-header\");\n if (header) header.appendChild(dot);\n}\n\n// ── Boot ─────────────────────────────────────────────────────────\nif (typeof window !== \"undefined\") {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", init);\n } else {\n init();\n }\n}\n"],"mappings":";wCAAO,IAAMA,GAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["TOOLBAR_CSS","ws","handlers","globalHandlers","messageQueue","connected","shouldReconnect","reconnectTimer","reconnectAttempt","generateId","connect","port","token","resolve","reject","settled","handshakeTimeout","wsHost","wsProto","handshakeId","msg","queued","event","handler","wasConnected","id","delay","e","send","data","request","type","payload","timeout","stream","onChunk","onMessage","h","isConnected","IMPORTANT_STYLES","inspectElement","el","computed","styles","prop","rect","getCleanOuterHTML","getCssSelector","getXPath","clone","html","tag","attrs","a","childSummary","c","parts","current","selector","classes","parent","siblings","s","index","element","sibling","highlightEl","showHighlight","hideHighlight","captureScreenshot","target","captureElementViaCanvas","captureViewport","e","canvas","dpr","ctx","svgData","elementToSvg","img","svgToImage","element","rect","resolve","clone","inlineStyles","width","height","foreignObject","source","computed","cssText","prop","sourceChildren","targetChildren","reject","blob","url","networkLogs","networkCaptureInstalled","installNetworkCapture","originalFetch","args","request","entry","response","addNetworkEntry","e","originalOpen","originalSend","method","url","rest","networkLogs","getNetworkLogs","consoleLogs","MAX_CONSOLE_LOGS","consoleCaptureInstalled","installConsoleCapture","levels","level","original","args","a","getConsoleLogs","buildContext","selectedElement","screenshot","getNetworkLogs","l","getConsoleLogs","ICON","MODEL_REGISTRY","encodeBase64Utf8","value","bytes","binary","i","decodeBase64Utf8","CURRENT_VERSION","state","shadow","$toolbar","$promptInput","$promptCtx","$panel","$panelBody","saveState","restoreState","saved","init","host","style","TOOLBAR_CSS","root","buildStaticDOM","attachGlobalEvents","setupDraggable","pos","installNetworkCapture","installConsoleCapture","checkForUpdates","token","wsPort","connect","updateStatusDot","request","msg","serverProvider","serverModel","openPanel","updatePillButtons","e","target","action","handleAction","field","refreshPanelContent","sendPrompt","fileInput","handleFileSelect","promptRow","dt","items","file","onMessage","resolveFilePath","rel","applyDiff","searchB64","replaceB64","search","replace","card","filePath","actions","content","occurrences","writeResult","idx","scrollChatToBottom","rejectDiff","toggleSelectMode","takeScreenshot","togglePanel","closePanel","saveSettings","url","changeRow","captureNetworkProfile","triggerFileAttach","renderAttachments","updatePromptContext","dot","btn","chips","panel","title","renderSettingsHTML","renderChatHTML","providerOpts","k","p","indicator","prov","modelOpts","m","isLocal","keyUrl","keyPh","providerHasKey","updateBanner","statusHtml","saveBtnText","saveBtnClass","saveBtnDisabled","keySection","msgs","diff","escapeHtml","streamHtml","el","apiKey","updateSaveButton","isConnected","payload","result","_","reject","text","context","buildContext","MAX_GROUNDED_FILES","MAX_GROUNDED_CHARS","TEXT_RE","treeResult","textFiles","f","searchTokens","t","scored","score","lower","a","b","files","totalChars","trimmed","stream","chunk","msgEl","mod","diffId","diffPayload","perf","navEntry","paintEntries","resources","networkLogs","getNetworkLogs","consoleLogs","getConsoleLogs","lines","fcp","log","errors","l","warns","slowest","r","input","reader","container","selectHandler","hoverHandler","exitSelectMode","enterSelectMode","showHighlight","inspectElement","escHandler","hideHighlight","escH","sel","ss","captureScreenshot","active","startX","startY","origX","origY","d","c","showUpdateDot","header"]}
1
+ {"version":3,"sources":["../../src/toolbar/styles/toolbar.css.ts","../../src/toolbar/services/ws-client.ts","../../src/toolbar/services/dom-inspector.ts","../../src/toolbar/services/capture.ts","../../src/toolbar/services/context-builder.ts","../../src/toolbar/index.ts"],"sourcesContent":["export const TOOLBAR_CSS = `\n:host {\n all: initial;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n font-size: 14px;\n color: #e0e0e0;\n line-height: 1.5;\n}\n\n* { box-sizing: border-box; margin: 0; padding: 0; }\n.om-hidden { display: none !important; }\n\n/* ── Unified Toolbar Container ────────────────────────── */\n.om-toolbar {\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: 2147483647;\n width: min(420px, calc(100vw - 40px));\n display: flex;\n flex-direction: column;\n background: #111125;\n border: 1px solid rgba(108, 92, 231, 0.18);\n border-radius: 14px;\n box-shadow: 0 6px 32px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255,255,255,0.02);\n overflow: hidden;\n}\n\n/* Panel header */\n.om-panel-header {\n display: flex; align-items: center; gap: 6px;\n padding: 8px 12px;\n border-bottom: 1px solid rgba(255,255,255,0.04);\n background: rgba(108, 92, 231, 0.03);\n flex-shrink: 0;\n}\n.om-panel-title { font-size: 11px; font-weight: 600; color: #a29bfe; }\n.om-panel-version { font-size: 10px; color: #444; margin-left: auto; }\n.om-panel-close {\n background: none; border: none; color: #555; cursor: pointer;\n padding: 2px 4px; border-radius: 4px; line-height: 1;\n display: flex; align-items: center;\n}\n.om-panel-close:hover { color: #ccc; background: rgba(255,255,255,0.05); }\n\n/* ── Header Bar (brand + tools) ───────────────────────── */\n.om-toolbar-header {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 6px 10px 6px 5px;\n border-bottom: 1px solid rgba(255,255,255,0.04);\n background: rgba(108, 92, 231, 0.03);\n flex-shrink: 0;\n}\n\n.om-grab {\n display: flex; align-items: center; justify-content: center;\n width: 18px; height: 26px; color: #3a3a5a; cursor: grab;\n border-radius: 5px; transition: color 0.15s; flex-shrink: 0;\n}\n.om-grab:hover { color: #6c5ce7; }\n.om-grab:active { cursor: grabbing; color: #a29bfe; }\n\n.om-pill-brand {\n display: flex; align-items: center; gap: 5px;\n padding: 0 6px 0 4px; cursor: grab;\n}\n.om-pill-icon { color: #a29bfe; flex-shrink: 0; }\n.om-pill-text { font-size: 11px; font-weight: 700; color: #a29bfe; letter-spacing: 0.3px; white-space: nowrap; }\n\n.om-pill-divider { width: 1px; height: 18px; background: rgba(255,255,255,0.06); margin: 0 3px; flex-shrink: 0; }\n\n.om-pill-btn {\n background: none; border: none; color: #555; cursor: pointer;\n padding: 5px 6px; border-radius: 6px; line-height: 1;\n transition: background 0.15s, color 0.15s;\n display: flex; align-items: center; justify-content: center;\n}\n.om-pill-btn:hover { background: rgba(108, 92, 231, 0.15); color: #a29bfe; }\n.om-pill-btn.active { background: rgba(108, 92, 231, 0.25); color: #c4b5fd; }\n\n.om-status-dot {\n width: 7px; height: 7px; border-radius: 50%; margin-left: auto; flex-shrink: 0;\n}\n.om-status-dot.connected { background: #00b894; }\n.om-status-dot.disconnected { background: #e94560; }\n\n.om-update-dot {\n width: 7px; height: 7px; border-radius: 50%; background: #fdcb6e;\n margin-left: 4px; cursor: pointer; flex-shrink: 0;\n animation: om-pulse 2s ease infinite;\n}\n@keyframes om-pulse {\n 0%, 100% { box-shadow: 0 0 0 0 rgba(253,203,110,0.4); }\n 50% { box-shadow: 0 0 0 5px rgba(253,203,110,0); }\n}\n\n/* ── Panel (expandable area between header and prompt) ── */\n.om-panel {\n max-height: 420px;\n overflow: hidden;\n border-bottom: 1px solid rgba(255,255,255,0.04);\n animation: om-expand 0.15s ease;\n}\n@keyframes om-expand {\n from { max-height: 0; opacity: 0; }\n to { max-height: 420px; opacity: 1; }\n}\n\n.om-panel-body {\n overflow-y: auto; padding: 12px;\n max-height: 420px;\n}\n.om-panel-body::-webkit-scrollbar { width: 5px; }\n.om-panel-body::-webkit-scrollbar-track { background: transparent; }\n.om-panel-body::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 3px; }\n\n/* ── Prompt Row (always visible at bottom) ────────────── */\n.om-prompt-row {\n display: flex;\n align-items: center;\n padding: 6px;\n gap: 4px;\n flex-shrink: 0;\n}\n\n.om-prompt-context {\n display: flex; gap: 3px; flex-shrink: 0;\n}\n.om-prompt-chip {\n display: flex; align-items: center; gap: 3px;\n padding: 3px 7px; background: rgba(108, 92, 231, 0.08);\n border: 1px solid rgba(108, 92, 231, 0.12);\n border-radius: 6px; font-size: 10px; color: #a29bfe;\n cursor: default; white-space: nowrap;\n}\n.om-prompt-chip-x {\n background: none; border: none; color: #a29bfe; cursor: pointer;\n font-size: 11px; line-height: 1; padding: 0 1px; opacity: 0.5;\n}\n.om-prompt-chip-x:hover { opacity: 1; }\n\n.om-prompt-input {\n flex: 1;\n background: rgba(255,255,255,0.04);\n border: 1px solid rgba(255,255,255,0.06);\n border-radius: 8px;\n color: #e0e0e0;\n font-size: 13px;\n font-family: inherit;\n padding: 7px 10px;\n outline: none;\n min-width: 0;\n transition: border-color 0.15s;\n}\n.om-prompt-input:focus { border-color: rgba(108, 92, 231, 0.4); }\n.om-prompt-input::placeholder { color: #3a3a5a; }\n\n.om-prompt-send {\n display: flex; align-items: center; justify-content: center;\n width: 30px; height: 30px; flex-shrink: 0;\n background: #6c5ce7; border: none; border-radius: 8px;\n color: white; cursor: pointer; transition: background 0.15s;\n}\n.om-prompt-send:hover { background: #7c6cf7; }\n.om-prompt-send:disabled { background: #2a2a4a; color: #444; cursor: not-allowed; }\n\n.om-prompt-attach {\n display: flex; align-items: center; justify-content: center;\n width: 28px; height: 28px; flex-shrink: 0;\n background: none; border: none; color: #555;\n cursor: pointer; border-radius: 6px; transition: color 0.15s, background 0.15s;\n}\n.om-prompt-attach:hover { color: #a29bfe; background: rgba(108, 92, 231, 0.1); }\n\n/* ── Attachments ──────────────────────────────────────── */\n.om-prompt-attachments {\n display: flex; gap: 6px; padding: 4px 8px; flex-wrap: wrap;\n border-bottom: 1px solid rgba(255,255,255,0.03);\n}\n.om-attachment-thumb {\n position: relative; width: 48px; height: 48px;\n border-radius: 6px; overflow: hidden;\n border: 1px solid rgba(255,255,255,0.08);\n}\n.om-attachment-thumb img {\n width: 100%; height: 100%; object-fit: cover;\n}\n.om-attachment-remove {\n position: absolute; top: 1px; right: 1px;\n width: 16px; height: 16px; display: flex;\n align-items: center; justify-content: center;\n background: rgba(0,0,0,0.7); border: none; border-radius: 50%;\n color: #fff; cursor: pointer; padding: 0; line-height: 1;\n}\n.om-attachment-remove svg { width: 10px; height: 10px; }\n\n/* ── Settings ─────────────────────────────────────────── */\n.om-settings { display: flex; flex-direction: column; gap: 12px; }\n\n.om-field { display: flex; flex-direction: column; gap: 5px; }\n.om-label { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: #555; }\n\n.om-select, .om-input {\n background: rgba(255,255,255,0.04);\n border: 1px solid rgba(255,255,255,0.08);\n border-radius: 8px;\n padding: 8px 10px;\n color: #e0e0e0;\n font-size: 13px;\n font-family: inherit;\n outline: none;\n width: 100%;\n transition: border-color 0.15s;\n}\n.om-select:focus, .om-input:focus { border-color: rgba(108, 92, 231, 0.4); }\n.om-select option { background: #111125; color: #e0e0e0; }\n\n.om-key-row { display: flex; gap: 6px; align-items: stretch; }\n.om-key-input { flex: 1; min-width: 0; -webkit-text-security: disc; }\n\n.om-key-configured {\n display: flex; align-items: center; gap: 6px;\n padding: 8px 10px; background: rgba(0, 184, 148, 0.06);\n border: 1px solid rgba(0, 184, 148, 0.12);\n border-radius: 8px; font-size: 12px; color: #00b894;\n}\n.om-key-configured span { flex: 1; }\n.om-btn-change-key {\n background: none; border: 1px solid rgba(255,255,255,0.08);\n color: #888; cursor: pointer; padding: 3px 8px;\n border-radius: 5px; font-size: 10px; font-family: inherit;\n transition: all 0.15s;\n}\n.om-btn-change-key:hover { color: #ccc; border-color: rgba(255,255,255,0.15); }\n.om-key-change-row { margin-top: 6px; }\n\n.om-btn-get-key {\n display: flex; align-items: center; gap: 4px;\n padding: 6px 9px; background: rgba(108, 92, 231, 0.08);\n border: 1px solid rgba(108, 92, 231, 0.15); border-radius: 8px;\n color: #a29bfe; font-size: 11px; font-weight: 600;\n font-family: inherit; cursor: pointer; white-space: nowrap;\n transition: all 0.15s;\n}\n.om-btn-get-key:hover { background: rgba(108, 92, 231, 0.15); color: #c4b5fd; }\n\n.om-btn {\n display: flex; align-items: center; justify-content: center; gap: 6px;\n background: #6c5ce7; border: none; color: white; cursor: pointer;\n padding: 8px 14px; border-radius: 8px;\n font-size: 13px; font-weight: 600; font-family: inherit;\n transition: background 0.15s;\n}\n.om-btn:hover { background: #7c6cf7; }\n.om-btn:disabled { background: #2a2a4a; color: #555; cursor: not-allowed; }\n.om-btn-saving { background: #4a3db0; }\n.om-btn-saved { background: #00b894; }\n\n.om-status { font-size: 11px; padding: 5px 8px; border-radius: 6px; text-align: center; display: flex; align-items: center; justify-content: center; gap: 4px; }\n.om-status-success { background: rgba(0, 184, 148, 0.06); color: #00b894; }\n.om-status-error { background: rgba(233, 69, 96, 0.06); color: #e94560; }\n\n.om-key-hint { font-size: 10px; color: #444; margin-top: 3px; }\n.om-key-hint a { color: #7c6cf7; cursor: pointer; text-decoration: none; }\n.om-key-hint a:hover { text-decoration: underline; }\n\n.om-update-banner {\n display: flex; align-items: center; gap: 6px; flex-wrap: wrap;\n padding: 7px 10px; margin-bottom: 10px;\n background: rgba(253, 203, 110, 0.04); border: 1px solid rgba(253, 203, 110, 0.12);\n border-radius: 8px; font-size: 11px; color: #fdcb6e;\n}\n.om-update-cmd {\n display: block; width: 100%; margin-top: 2px;\n padding: 4px 7px; background: rgba(0, 0, 0, 0.12); border-radius: 4px;\n font-family: 'SF Mono', 'Fira Code', Consolas, monospace;\n font-size: 11px; color: #fdcb6e; user-select: all;\n}\n\n/* ── Chat ─────────────────────────────────────────────── */\n.om-chat-messages {\n display: flex; flex-direction: column; gap: 8px;\n max-height: 380px;\n overflow-y: auto;\n}\n.om-chat-messages::-webkit-scrollbar { width: 4px; }\n.om-chat-messages::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.06); border-radius: 2px; }\n\n.om-msg {\n padding: 8px 11px; border-radius: 10px;\n font-size: 13px; line-height: 1.5;\n white-space: pre-wrap; word-break: break-word;\n}\n.om-msg-user { background: rgba(108, 92, 231, 0.08); color: #ccc; margin-left: 36px; border-bottom-right-radius: 3px; }\n.om-msg-assistant { background: rgba(255,255,255,0.02); color: #aaa; margin-right: 36px; border-bottom-left-radius: 3px; border: 1px solid rgba(255,255,255,0.03); }\n.om-msg-system { background: rgba(108, 92, 231, 0.05); color: #888; font-size: 11px; text-align: center; padding: 5px 8px; border-radius: 6px; }\n\n.om-chat-empty { color: #333; text-align: center; padding: 32px 16px; font-size: 12px; line-height: 1.6; }\n\n.om-spinner { width: 12px; height: 12px; border: 2px solid rgba(108,92,231,0.12); border-top-color: #6c5ce7; border-radius: 50%; animation: om-spin 0.6s linear infinite; display: inline-block; vertical-align: -1px; margin-right: 5px; }\n@keyframes om-spin { to { transform: rotate(360deg); } }\n\n.om-element-info {\n background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.03);\n border-radius: 6px; padding: 6px 8px;\n font-family: 'SF Mono', 'Fira Code', Consolas, monospace;\n font-size: 10px; color: #555; max-height: 60px; overflow-y: auto; margin-bottom: 6px;\n}\n\n/* ── Diff Cards ──────────────────────────────────────── */\n.om-diff-card { background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.06); border-radius: 8px; padding: 8px 10px; margin: 4px 0; font-size: 12px; }\n.om-diff-file { color: #a29bfe; font-size: 11px; font-weight: 600; margin-bottom: 6px; font-family: 'SF Mono', Consolas, monospace; }\n.om-diff-removed { background: rgba(233,69,96,0.08); color: #fab1a0; padding: 4px 8px; border-radius: 4px; font-family: 'SF Mono', Consolas, monospace; font-size: 11px; white-space: pre-wrap; word-break: break-all; margin-bottom: 4px; }\n.om-diff-added { background: rgba(0,184,148,0.08); color: #55efc4; padding: 4px 8px; border-radius: 4px; font-family: 'SF Mono', Consolas, monospace; font-size: 11px; white-space: pre-wrap; word-break: break-all; margin-bottom: 6px; }\n.om-diff-actions { display: flex; gap: 6px; }\n.om-btn-sm { padding: 4px 10px; font-size: 11px; border-radius: 6px; }\n.om-btn-secondary { background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.08); color: #888; cursor: pointer; font-family: inherit; }\n.om-btn-secondary:hover { background: rgba(255,255,255,0.08); color: #ccc; }\n.om-diff-applied { opacity: 0.5; }\n.om-diff-applied .om-diff-actions { display: none; }\n`;\n","type MessageHandler = (msg: any) => void;\n\nlet ws: WebSocket | null = null;\nlet handlers: Map<string, MessageHandler> = new Map();\nlet globalHandlers: ((msg: any) => void)[] = [];\nlet messageQueue: string[] = [];\nlet connected = false;\nlet shouldReconnect = false;\nlet reconnectTimer: ReturnType<typeof setTimeout> | null = null;\nlet reconnectAttempt = 0;\n\nfunction generateId(): string {\n return Math.random().toString(36).slice(2) + Date.now().toString(36);\n}\n\nexport function connect(port: number, token: string): Promise<void> {\n shouldReconnect = true;\n\n return new Promise((resolve, reject) => {\n let settled = false;\n\n const handshakeTimeout = setTimeout(() => {\n if (!settled) {\n settled = true;\n reject(new Error(\"Handshake timeout\"));\n ws?.close();\n }\n }, 10000);\n\n try {\n // Same-origin WebSocket — use page hostname and given port\n const wsHost = window.location.hostname || \"127.0.0.1\";\n const wsProto = window.location.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n ws = new WebSocket(`${wsProto}//${wsHost}:${port}/__openmagic__/ws`);\n\n ws.onopen = () => {\n // Send handshake directly (bypass send() which checks connected flag)\n const handshakeId = generateId();\n ws!.send(JSON.stringify({ id: handshakeId, type: \"handshake\", payload: { token } }));\n\n handlers.set(handshakeId, (msg) => {\n if (msg.type === \"handshake.ok\") {\n clearTimeout(handshakeTimeout);\n connected = true;\n reconnectAttempt = 0;\n // Flush queued messages\n for (const queued of messageQueue) {\n ws?.send(queued);\n }\n messageQueue = [];\n if (!settled) { settled = true; resolve(); }\n } else if (msg.type === \"error\") {\n clearTimeout(handshakeTimeout);\n if (!settled) { settled = true; reject(new Error(msg.payload?.message || \"Handshake failed\")); }\n }\n });\n };\n\n ws.onmessage = (event) => {\n try {\n const msg = JSON.parse(event.data);\n if (msg.id && handlers.has(msg.id)) {\n const handler = handlers.get(msg.id)!;\n handler(msg);\n if (msg.type === \"llm.done\" || msg.type === \"llm.error\" || !msg.type.startsWith(\"llm.\")) {\n handlers.delete(msg.id);\n }\n }\n for (const handler of globalHandlers) {\n handler(msg);\n }\n } catch {\n // Ignore parse errors\n }\n };\n\n ws.onclose = () => {\n const wasConnected = connected;\n connected = false;\n\n // Reject all pending handlers\n handlers.forEach((handler, id) => {\n handler({ type: \"error\", id, payload: { message: \"Connection lost\" } });\n });\n handlers.clear();\n\n if (!wasConnected && !settled) {\n // Connection closed before handshake completed\n clearTimeout(handshakeTimeout);\n settled = true;\n reject(new Error(\"WebSocket closed before handshake\"));\n return;\n }\n\n // Only reconnect if we were previously connected and should reconnect\n if (wasConnected && shouldReconnect && !reconnectTimer) {\n const delay = Math.min(2000 * Math.pow(1.5, reconnectAttempt), 30000);\n reconnectAttempt++;\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n connect(port, token).then(() => {\n // Notify toolbar of reconnection\n for (const handler of globalHandlers) {\n handler({ type: \"reconnected\", payload: {} });\n }\n }).catch(() => {});\n }, delay);\n }\n };\n\n ws.onerror = () => {\n if (!connected && !settled) {\n clearTimeout(handshakeTimeout);\n settled = true;\n reject(new Error(\"WebSocket connection failed\"));\n }\n };\n } catch (e) {\n clearTimeout(handshakeTimeout);\n if (!settled) { settled = true; reject(e); }\n }\n });\n}\n\nexport function send(msg: { id: string; type: string; payload?: any }): void {\n const data = JSON.stringify(msg);\n if (ws && ws.readyState === WebSocket.OPEN && connected) {\n ws.send(data);\n } else {\n messageQueue.push(data);\n }\n}\n\nexport function request(type: string, payload?: any): Promise<any> {\n return new Promise((resolve, reject) => {\n const id = generateId();\n const timeout = setTimeout(() => {\n handlers.delete(id);\n reject(new Error(\"Request timeout\"));\n }, 30000);\n\n handlers.set(id, (msg) => {\n clearTimeout(timeout);\n if (msg.type === \"error\") {\n reject(new Error(msg.payload?.message || \"Unknown error\"));\n } else {\n resolve(msg);\n }\n });\n\n send({ id, type, payload });\n });\n}\n\nexport function stream(\n type: string,\n payload: any,\n onChunk: (chunk: string) => void\n): Promise<any> {\n return new Promise((resolve, reject) => {\n const id = generateId();\n const timeout = setTimeout(() => {\n handlers.delete(id);\n reject(new Error(\"Stream timeout\"));\n }, 120000);\n\n handlers.set(id, (msg) => {\n if (msg.type === \"llm.chunk\") {\n onChunk(msg.payload?.delta || \"\");\n } else if (msg.type === \"llm.done\") {\n clearTimeout(timeout);\n handlers.delete(id);\n resolve(msg.payload);\n } else if (msg.type === \"llm.error\" || msg.type === \"error\") {\n clearTimeout(timeout);\n handlers.delete(id);\n reject(new Error(msg.payload?.message || \"Stream error\"));\n }\n });\n\n send({ id, type, payload });\n });\n}\n\nexport function onMessage(handler: (msg: any) => void): () => void {\n globalHandlers.push(handler);\n return () => {\n globalHandlers = globalHandlers.filter((h) => h !== handler);\n };\n}\n\nexport function isConnected(): boolean {\n return connected;\n}\n\nexport function disconnect(): void {\n shouldReconnect = false;\n if (reconnectTimer) {\n clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n if (ws) {\n ws.close();\n ws = null;\n }\n connected = false;\n}\n","export interface SelectedElement {\n tagName: string;\n id: string;\n className: string;\n textContent: string;\n outerHTML: string;\n cssSelector: string;\n xpath: string;\n computedStyles: Record<string, string>;\n ancestry: string[];\n componentHint: string;\n rect: { x: number; y: number; width: number; height: number };\n}\n\nconst IMPORTANT_STYLES = [\n \"display\",\n \"position\",\n \"width\",\n \"height\",\n \"margin\",\n \"padding\",\n \"color\",\n \"background-color\",\n \"background\",\n \"font-size\",\n \"font-weight\",\n \"font-family\",\n \"border\",\n \"border-radius\",\n \"box-shadow\",\n \"flex-direction\",\n \"justify-content\",\n \"align-items\",\n \"gap\",\n \"grid-template-columns\",\n \"grid-template-rows\",\n \"overflow\",\n \"opacity\",\n \"z-index\",\n \"text-align\",\n \"line-height\",\n \"letter-spacing\",\n];\n\nexport function inspectElement(el: HTMLElement): SelectedElement {\n const computed = window.getComputedStyle(el);\n const styles: Record<string, string> = {};\n for (const prop of IMPORTANT_STYLES) {\n styles[prop] = computed.getPropertyValue(prop);\n }\n\n const rect = el.getBoundingClientRect();\n\n return {\n tagName: el.tagName.toLowerCase(),\n id: el.id || \"\",\n className: el.className || \"\",\n textContent: (el.textContent || \"\").trim().slice(0, 200),\n outerHTML: getCleanOuterHTML(el),\n cssSelector: getCssSelector(el),\n xpath: getXPath(el),\n computedStyles: styles,\n ancestry: getAncestry(el),\n componentHint: getComponentHint(el),\n rect: {\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n },\n };\n}\n\nfunction getAncestry(el: HTMLElement, depth: number = 5): string[] {\n const result: string[] = [];\n let current = el.parentElement;\n while (current && current !== document.body && result.length < depth) {\n const tag = current.tagName.toLowerCase();\n const cls = (typeof current.className === \"string\" ? current.className : \"\")\n .split(/\\s+/).filter(c => c.length > 1 && !c.startsWith(\"_\")).slice(0, 3).join(\".\");\n result.push(cls ? `${tag}.${cls}` : tag);\n current = current.parentElement;\n }\n return result;\n}\n\nfunction getComponentHint(el: HTMLElement): string {\n // Try to find component name from data attributes or React fiber\n let current: HTMLElement | null = el;\n while (current && current !== document.body) {\n // Check common framework data attributes\n const dataComponent = current.getAttribute(\"data-component\")\n || current.getAttribute(\"data-testid\")\n || current.getAttribute(\"data-cy\");\n if (dataComponent) return dataComponent;\n\n // React: check __reactFiber or __reactInternalInstance\n const keys = Object.keys(current);\n for (const key of keys) {\n if (key.startsWith(\"__reactFiber\") || key.startsWith(\"__reactInternalInstance\")) {\n try {\n const fiber = (current as any)[key];\n const name = fiber?.type?.name || fiber?.type?.displayName\n || fiber?.return?.type?.name || fiber?.return?.type?.displayName;\n if (name && name !== \"div\" && name !== \"span\" && name.length > 1) return name;\n } catch {}\n }\n }\n\n current = current.parentElement;\n }\n return \"\";\n}\n\nfunction getCleanOuterHTML(el: HTMLElement): string {\n const clone = el.cloneNode(true) as HTMLElement;\n\n // Remove script tags and large content\n const scripts = clone.querySelectorAll(\"script, style, svg\");\n scripts.forEach((s) => s.remove());\n\n // Truncate children if too many\n let html = clone.outerHTML;\n if (html.length > 2000) {\n // Just get the opening tag + first level children hints\n const tag = el.tagName.toLowerCase();\n const attrs = Array.from(el.attributes)\n .map((a) => `${a.name}=\"${a.value}\"`)\n .join(\" \");\n const childSummary = Array.from(el.children)\n .slice(0, 5)\n .map((c) => `<${c.tagName.toLowerCase()} .../>`)\n .join(\"\\n \");\n html = `<${tag} ${attrs}>\\n ${childSummary}\\n ${el.children.length > 5 ? `<!-- +${el.children.length - 5} more children -->` : \"\"}\\n</${tag}>`;\n }\n\n return html;\n}\n\nfunction getCssSelector(el: HTMLElement): string {\n if (el.id) return `#${CSS.escape(el.id)}`;\n\n const parts: string[] = [];\n let current: HTMLElement | null = el;\n\n while (current && current !== document.body) {\n let selector = current.tagName.toLowerCase();\n\n if (current.id) {\n parts.unshift(`#${CSS.escape(current.id)}`);\n break;\n }\n\n if (current.className && typeof current.className === \"string\") {\n const classes = current.className\n .trim()\n .split(/\\s+/)\n .filter((c) => !c.startsWith(\"__\") && c.length < 30)\n .slice(0, 2)\n .map((c) => CSS.escape(c));\n if (classes.length > 0) {\n selector += \".\" + classes.join(\".\");\n }\n }\n\n // Add nth-of-type if needed for uniqueness\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (s) => s.tagName === current!.tagName\n );\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n selector += `:nth-of-type(${index})`;\n }\n }\n\n parts.unshift(selector);\n current = current.parentElement;\n }\n\n return parts.join(\" > \");\n}\n\nfunction getXPath(el: HTMLElement): string {\n const parts: string[] = [];\n let current: Node | null = el;\n\n while (current && current !== document) {\n if (current.nodeType === Node.ELEMENT_NODE) {\n const element = current as HTMLElement;\n let index = 1;\n let sibling = element.previousElementSibling;\n while (sibling) {\n if (sibling.tagName === element.tagName) index++;\n sibling = sibling.previousElementSibling;\n }\n parts.unshift(`${element.tagName.toLowerCase()}[${index}]`);\n }\n current = current.parentNode;\n }\n\n return \"/\" + parts.join(\"/\");\n}\n\n// --- Highlight Overlay ---\n\nlet highlightEl: HTMLDivElement | null = null;\n\nexport function showHighlight(rect: {\n x: number;\n y: number;\n width: number;\n height: number;\n}): void {\n if (!highlightEl) {\n highlightEl = document.createElement(\"div\");\n highlightEl.style.cssText = `\n position: fixed;\n pointer-events: none;\n z-index: 2147483646;\n border: 2px solid #6c5ce7;\n background: rgba(108, 92, 231, 0.1);\n transition: all 0.1s ease;\n `;\n highlightEl.dataset.openmagic = \"highlight\";\n document.body.appendChild(highlightEl);\n }\n\n highlightEl.style.left = `${rect.x}px`;\n highlightEl.style.top = `${rect.y}px`;\n highlightEl.style.width = `${rect.width}px`;\n highlightEl.style.height = `${rect.height}px`;\n highlightEl.style.display = \"block\";\n}\n\nexport function hideHighlight(): void {\n if (highlightEl) {\n highlightEl.style.display = \"none\";\n }\n}\n\n","// Simple screenshot capture using Canvas API\n// Falls back to a simpler approach if html-to-image isn't available\n\nexport async function captureScreenshot(\n target?: HTMLElement\n): Promise<string | null> {\n try {\n // Try using the Canvas approach for element capture\n if (target) {\n return await captureElementViaCanvas(target);\n }\n\n // Full page: use a simple canvas capture of the viewport\n return await captureViewport();\n } catch (e) {\n console.warn(\"[OpenMagic] Screenshot capture failed:\", e);\n return null;\n }\n}\n\nasync function captureViewport(): Promise<string | null> {\n // Create a canvas the size of the viewport\n const canvas = document.createElement(\"canvas\");\n const dpr = window.devicePixelRatio || 1;\n canvas.width = window.innerWidth * dpr;\n canvas.height = window.innerHeight * dpr;\n const ctx = canvas.getContext(\"2d\")!;\n ctx.scale(dpr, dpr);\n\n // We can't directly capture the viewport without html2canvas or similar\n // Instead, we use the SVG foreignObject approach (snapdom-like)\n try {\n const svgData = await elementToSvg(document.body);\n const img = await svgToImage(svgData, window.innerWidth, window.innerHeight);\n ctx.drawImage(img, 0, 0);\n return canvas.toDataURL(\"image/png\");\n } catch {\n return null;\n }\n}\n\nasync function captureElementViaCanvas(\n element: HTMLElement\n): Promise<string | null> {\n const rect = element.getBoundingClientRect();\n const canvas = document.createElement(\"canvas\");\n const dpr = window.devicePixelRatio || 1;\n canvas.width = rect.width * dpr;\n canvas.height = rect.height * dpr;\n const ctx = canvas.getContext(\"2d\")!;\n ctx.scale(dpr, dpr);\n\n try {\n const svgData = await elementToSvg(element);\n const img = await svgToImage(svgData, rect.width, rect.height);\n ctx.drawImage(img, 0, 0);\n return canvas.toDataURL(\"image/png\");\n } catch {\n return null;\n }\n}\n\nfunction elementToSvg(element: HTMLElement): Promise<string> {\n return new Promise((resolve) => {\n const clone = element.cloneNode(true) as HTMLElement;\n\n // Inline computed styles on the clone\n inlineStyles(element, clone);\n\n const rect = element.getBoundingClientRect();\n const width = rect.width;\n const height = rect.height;\n\n const foreignObject = `\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\">\n <foreignObject width=\"100%\" height=\"100%\">\n <div xmlns=\"http://www.w3.org/1999/xhtml\" style=\"width:${width}px;height:${height}px;overflow:hidden;\">\n ${clone.outerHTML}\n </div>\n </foreignObject>\n </svg>`;\n\n resolve(foreignObject);\n });\n}\n\nfunction inlineStyles(source: HTMLElement, target: HTMLElement): void {\n const computed = window.getComputedStyle(source);\n let cssText = \"\";\n for (let i = 0; i < computed.length; i++) {\n const prop = computed[i];\n cssText += `${prop}:${computed.getPropertyValue(prop)};`;\n }\n target.style.cssText = cssText;\n\n const sourceChildren = source.children;\n const targetChildren = target.children;\n for (let i = 0; i < sourceChildren.length && i < targetChildren.length; i++) {\n inlineStyles(\n sourceChildren[i] as HTMLElement,\n targetChildren[i] as HTMLElement\n );\n }\n}\n\nfunction svgToImage(\n svgData: string,\n width: number,\n height: number\n): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n const blob = new Blob([svgData], { type: \"image/svg+xml;charset=utf-8\" });\n const url = URL.createObjectURL(blob);\n\n img.onload = () => {\n URL.revokeObjectURL(url);\n resolve(img);\n };\n img.onerror = () => {\n URL.revokeObjectURL(url);\n reject(new Error(\"Failed to load SVG image\"));\n };\n\n img.width = width;\n img.height = height;\n img.src = url;\n });\n}\n","import type { SelectedElement } from \"./dom-inspector.js\";\n\n// --- Network Log Capture ---\n\ninterface NetworkEntry {\n method: string;\n url: string;\n status?: number;\n duration?: number;\n timestamp: number;\n}\n\nconst networkLogs: NetworkEntry[] = [];\nconst MAX_NETWORK_LOGS = 50;\n\nlet networkCaptureInstalled = false;\n\nexport function installNetworkCapture(): void {\n if (networkCaptureInstalled) return;\n networkCaptureInstalled = true;\n\n // Intercept fetch\n const originalFetch = window.fetch;\n window.fetch = async function (...args) {\n const request = new Request(...args);\n const entry: NetworkEntry = {\n method: request.method,\n url: request.url,\n timestamp: Date.now(),\n };\n\n try {\n const response = await originalFetch.apply(this, args);\n entry.status = response.status;\n entry.duration = Date.now() - entry.timestamp;\n addNetworkEntry(entry);\n return response;\n } catch (e) {\n entry.status = 0;\n entry.duration = Date.now() - entry.timestamp;\n addNetworkEntry(entry);\n throw e;\n }\n };\n\n // Intercept XMLHttpRequest\n const originalOpen = XMLHttpRequest.prototype.open;\n const originalSend = XMLHttpRequest.prototype.send;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string, ...rest: any[]) {\n (this as any).__om_method = method;\n (this as any).__om_url = url;\n (this as any).__om_start = Date.now();\n return originalOpen.apply(this, [method, url, ...rest] as any);\n };\n\n XMLHttpRequest.prototype.send = function (...args) {\n this.addEventListener(\"loadend\", () => {\n addNetworkEntry({\n method: (this as any).__om_method || \"GET\",\n url: (this as any).__om_url || \"\",\n status: this.status,\n duration: Date.now() - ((this as any).__om_start || Date.now()),\n timestamp: (this as any).__om_start || Date.now(),\n });\n });\n return originalSend.apply(this, args);\n };\n}\n\nfunction addNetworkEntry(entry: NetworkEntry): void {\n // Filter out OpenMagic's own requests\n if (entry.url.includes(\"__openmagic__\")) return;\n networkLogs.push(entry);\n if (networkLogs.length > MAX_NETWORK_LOGS) {\n networkLogs.shift();\n }\n}\n\nexport function getNetworkLogs(): NetworkEntry[] {\n return [...networkLogs];\n}\n\nexport function clearNetworkLogs(): void {\n networkLogs.length = 0;\n}\n\n// --- Console Log Capture ---\n\ninterface ConsoleEntry {\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\";\n args: string[];\n timestamp: number;\n}\n\nconst consoleLogs: ConsoleEntry[] = [];\nconst MAX_CONSOLE_LOGS = 100;\n\nlet consoleCaptureInstalled = false;\n\nexport function installConsoleCapture(): void {\n if (consoleCaptureInstalled) return;\n consoleCaptureInstalled = true;\n\n const levels: ConsoleEntry[\"level\"][] = [\"log\", \"warn\", \"error\", \"info\", \"debug\"];\n\n for (const level of levels) {\n const original = console[level];\n console[level] = function (...args: any[]) {\n consoleLogs.push({\n level,\n args: args.map((a) => {\n try {\n return typeof a === \"object\" ? JSON.stringify(a).slice(0, 500) : String(a);\n } catch {\n return String(a);\n }\n }),\n timestamp: Date.now(),\n });\n\n if (consoleLogs.length > MAX_CONSOLE_LOGS) {\n consoleLogs.shift();\n }\n\n original.apply(console, args);\n };\n }\n}\n\nexport function getConsoleLogs(): ConsoleEntry[] {\n return [...consoleLogs];\n}\n\nexport function clearConsoleLogs(): void {\n consoleLogs.length = 0;\n}\n\n// --- Context Builder ---\n\nexport function buildContext(\n selectedElement: SelectedElement | null,\n screenshot: string | null\n) {\n return {\n selectedElement: selectedElement\n ? {\n tagName: selectedElement.tagName,\n id: selectedElement.id,\n className: selectedElement.className,\n textContent: selectedElement.textContent,\n outerHTML: selectedElement.outerHTML,\n cssSelector: selectedElement.cssSelector,\n computedStyles: selectedElement.computedStyles,\n }\n : undefined,\n screenshot: screenshot || undefined,\n networkLogs: getNetworkLogs().map((l) => ({\n method: l.method,\n url: l.url,\n status: l.status,\n duration: l.duration,\n timestamp: l.timestamp,\n })),\n consoleLogs: getConsoleLogs().map((l) => ({\n level: l.level,\n args: l.args,\n timestamp: l.timestamp,\n })),\n };\n}\n","import { TOOLBAR_CSS } from \"./styles/toolbar.css.js\";\nimport * as ws from \"./services/ws-client.js\";\nimport { inspectElement, showHighlight, hideHighlight, type SelectedElement } from \"./services/dom-inspector.js\";\nimport { captureScreenshot } from \"./services/capture.js\";\nimport { installNetworkCapture, installConsoleCapture, buildContext, getNetworkLogs, getConsoleLogs } from \"./services/context-builder.js\";\n\n// ── SVG Icons (Lucide-style) ─────────────────────────────────────\nconst ICON = {\n sparkle: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.582a.5.5 0 0 1 0 .962L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\"/></svg>`,\n crosshair: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"22\" y1=\"12\" x2=\"18\" y2=\"12\"/><line x1=\"6\" y1=\"12\" x2=\"2\" y2=\"12\"/><line x1=\"12\" y1=\"6\" x2=\"12\" y2=\"2\"/><line x1=\"12\" y1=\"22\" x2=\"12\" y2=\"18\"/></svg>`,\n camera: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\"/><circle cx=\"12\" cy=\"13\" r=\"3\"/></svg>`,\n chat: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/></svg>`,\n settings: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>`,\n send: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"/><polygon points=\"22 2 15 22 11 13 2 9 22 2\"/></svg>`,\n x: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"/><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"/></svg>`,\n externalLink: `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"/><polyline points=\"15 3 21 3 21 9\"/><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"/></svg>`,\n check: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polyline points=\"20 6 9 17 4 12\"/></svg>`,\n grip: `<svg width=\"7\" height=\"14\" viewBox=\"0 0 8 14\" fill=\"currentColor\"><circle cx=\"2\" cy=\"2\" r=\"1.2\"/><circle cx=\"6\" cy=\"2\" r=\"1.2\"/><circle cx=\"2\" cy=\"7\" r=\"1.2\"/><circle cx=\"6\" cy=\"7\" r=\"1.2\"/><circle cx=\"2\" cy=\"12\" r=\"1.2\"/><circle cx=\"6\" cy=\"12\" r=\"1.2\"/></svg>`,\n network: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/></svg>`,\n activity: `<svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polyline points=\"22 12 18 12 15 21 9 3 6 12 2 12\"/></svg>`,\n paperclip: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\"/></svg>`,\n image: `<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\"/><circle cx=\"9\" cy=\"9\" r=\"2\"/><path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\"/></svg>`,\n};\n\n// ── Model Registry (inline for browser bundle) ───────────────────\nconst MODEL_REGISTRY: Record<string, { name: string; models: { id: string; name: string }[]; keyPlaceholder: string; local?: boolean; keyUrl?: string }> = {\n openai: { name: \"OpenAI\", keyUrl: \"https://platform.openai.com/api-keys\", keyPlaceholder: \"sk-...\", models: [\n { id: \"gpt-5.4\", name: \"GPT-5.4\" }, { id: \"gpt-5.4-mini\", name: \"GPT-5.4 Mini\" },\n { id: \"gpt-5.2\", name: \"GPT-5.2 Thinking\" }, { id: \"o3\", name: \"o3\" }, { id: \"o4-mini\", name: \"o4-mini\" },\n { id: \"gpt-4.1\", name: \"GPT-4.1\" }, { id: \"gpt-4.1-mini\", name: \"GPT-4.1 Mini\" },\n ]},\n anthropic: { name: \"Anthropic\", keyUrl: \"https://console.anthropic.com/settings/keys\", keyPlaceholder: \"sk-ant-...\", models: [\n { id: \"claude-opus-4-6\", name: \"Claude Opus 4.6\" }, { id: \"claude-sonnet-4-6\", name: \"Claude Sonnet 4.6\" },\n { id: \"claude-haiku-4-5-20251001\", name: \"Claude Haiku 4.5\" },\n ]},\n google: { name: \"Google Gemini\", keyUrl: \"https://aistudio.google.com/apikey\", keyPlaceholder: \"AIza...\", models: [\n { id: \"gemini-3.1-pro-preview\", name: \"Gemini 3.1 Pro\" }, { id: \"gemini-3-flash-preview\", name: \"Gemini 3 Flash\" },\n { id: \"gemini-2.5-pro\", name: \"Gemini 2.5 Pro\" }, { id: \"gemini-2.5-flash\", name: \"Gemini 2.5 Flash\" },\n ]},\n xai: { name: \"xAI (Grok)\", keyUrl: \"https://console.x.ai/team/default/api-keys\", keyPlaceholder: \"xai-...\", models: [\n { id: \"grok-4.20-0309-reasoning\", name: \"Grok 4.20 Reasoning\" }, { id: \"grok-4-1-fast-non-reasoning\", name: \"Grok 4.1 Fast\" },\n ]},\n deepseek: { name: \"DeepSeek\", keyUrl: \"https://platform.deepseek.com/api_keys\", keyPlaceholder: \"sk-...\", models: [\n { id: \"deepseek-chat\", name: \"DeepSeek V3.2\" }, { id: \"deepseek-reasoner\", name: \"DeepSeek R1\" },\n ]},\n mistral: { name: \"Mistral\", keyUrl: \"https://console.mistral.ai/api-keys\", keyPlaceholder: \"...\", models: [\n { id: \"mistral-large-3-25-12\", name: \"Mistral Large 3\" }, { id: \"codestral-2508\", name: \"Codestral\" }, { id: \"devstral-2-25-12\", name: \"Devstral 2\" },\n ]},\n groq: { name: \"Groq\", keyUrl: \"https://console.groq.com/keys\", keyPlaceholder: \"gsk_...\", models: [\n { id: \"meta-llama/llama-4-scout-17b-16e-instruct\", name: \"Llama 4 Scout\" }, { id: \"llama-3.3-70b-versatile\", name: \"Llama 3.3 70B\" },\n ]},\n minimax: { name: \"MiniMax\", keyUrl: \"https://platform.minimax.chat/user-center/basic-information/interface-key\", keyPlaceholder: \"MiniMax key...\", models: [\n { id: \"MiniMax-M2.7\", name: \"MiniMax M2.7\" }, { id: \"MiniMax-M2.5\", name: \"MiniMax M2.5\" },\n ]},\n moonshot: { name: \"Kimi (Moonshot)\", keyUrl: \"https://platform.moonshot.cn/console/api-keys\", keyPlaceholder: \"Moonshot key...\", models: [\n { id: \"kimi-k2.5\", name: \"Kimi K2.5\" }, { id: \"kimi-k2-thinking\", name: \"Kimi K2 Thinking\" },\n ]},\n qwen: { name: \"Qwen (Alibaba)\", keyUrl: \"https://dashscope.console.aliyun.com/apiKey\", keyPlaceholder: \"DashScope key...\", models: [\n { id: \"qwen3.5-plus\", name: \"Qwen 3.5 Plus\" }, { id: \"qwen-max\", name: \"Qwen Max\" },\n ]},\n zhipu: { name: \"Zhipu AI (GLM)\", keyUrl: \"https://open.bigmodel.cn/usercenter/apikeys\", keyPlaceholder: \"Zhipu key...\", models: [\n { id: \"glm-5\", name: \"GLM-5\" }, { id: \"glm-4.7\", name: \"GLM-4.7\" },\n ]},\n doubao: { name: \"Doubao (ByteDance)\", keyUrl: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey\", keyPlaceholder: \"Volcano key...\", models: [\n { id: \"doubao-seed-2-0-pro\", name: \"Doubao Seed 2.0 Pro\" }, { id: \"doubao-seed-2-0-code\", name: \"Doubao Seed 2.0 Code\" },\n ]},\n ollama: { name: \"Ollama (Local)\", keyPlaceholder: \"not required\", local: true, models: [] },\n openrouter: { name: \"OpenRouter\", keyUrl: \"https://openrouter.ai/settings/keys\", keyPlaceholder: \"sk-or-...\", models: [] },\n};\n\nfunction encodeBase64Utf8(value: string): string {\n const bytes = new TextEncoder().encode(value);\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 0x8000) {\n binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));\n }\n return btoa(binary);\n}\n\nfunction decodeBase64Utf8(value: string): string {\n const binary = atob(value);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return new TextDecoder().decode(bytes);\n}\n\nconst CURRENT_VERSION = \"0.18.0\";\n\n// ── State ────────────────────────────────────────────────────────\nconst state = {\n connected: false,\n panelOpen: false,\n activePanel: \"\" as \"\" | \"chat\" | \"settings\",\n selecting: false,\n selectedElement: null as SelectedElement | null,\n screenshot: null as string | null,\n messages: [] as { role: \"user\" | \"assistant\" | \"system\"; content: string }[],\n streaming: false,\n streamContent: \"\",\n provider: \"\",\n model: \"\",\n hasApiKey: false,\n configuredProviders: {} as Record<string, boolean>, // which providers have keys\n roots: [] as string[],\n updateAvailable: false,\n latestVersion: \"\",\n saveStatus: \"\" as \"\" | \"saving\" | \"saved\" | \"error\",\n networkCapture: false, // whether network panel is showing\n attachments: [] as string[], // base64 image data URLs attached to next message\n};\n\n// ── DOM refs (created once) ──────────────────────────────────────\nlet shadow: ShadowRoot;\nlet $toolbar: HTMLDivElement;\nlet $promptInput: HTMLInputElement;\nlet $promptCtx: HTMLDivElement;\nlet $panel: HTMLDivElement;\nlet $panelBody: HTMLDivElement;\n\n// ── Initialize ───────────────────────────────────────────────────\n// ── State Persistence (survives HMR page reloads) ────────────────\nfunction saveState() {\n try {\n sessionStorage.setItem(\"__om_state__\", JSON.stringify({\n messages: state.messages,\n provider: state.provider,\n model: state.model,\n panelOpen: state.panelOpen,\n activePanel: state.activePanel,\n }));\n } catch { /* quota exceeded or unavailable */ }\n}\n\nfunction restoreState() {\n try {\n const saved = JSON.parse(sessionStorage.getItem(\"__om_state__\") || \"{}\");\n if (saved.messages?.length) state.messages = saved.messages;\n if (saved.provider) state.provider = saved.provider;\n if (saved.model) state.model = saved.model;\n if (saved.panelOpen) { state.panelOpen = saved.panelOpen; state.activePanel = saved.activePanel || \"\"; }\n } catch { /* parse error or unavailable */ }\n}\n\nfunction init() {\n if (document.querySelector(\"openmagic-toolbar\")) return;\n\n // Restore chat history and settings from session storage (survives HMR)\n restoreState();\n\n const host = document.createElement(\"openmagic-toolbar\");\n host.dataset.openmagic = \"true\";\n shadow = host.attachShadow({ mode: \"closed\" });\n\n const style = document.createElement(\"style\");\n style.textContent = TOOLBAR_CSS;\n shadow.appendChild(style);\n\n const root = document.createElement(\"div\");\n shadow.appendChild(root);\n\n // Build DOM structure ONCE\n root.innerHTML = buildStaticDOM();\n\n // Cache refs\n $toolbar = root.querySelector(\".om-toolbar\")!;\n $promptInput = root.querySelector(\".om-prompt-input\")!;\n $promptCtx = root.querySelector(\".om-prompt-context\")!;\n $panel = root.querySelector(\".om-panel\")!;\n $panelBody = root.querySelector(\".om-panel-body\")!;\n\n document.body.appendChild(host);\n\n // Attach event delegation ONCE\n attachGlobalEvents(root);\n setupDraggable();\n\n // Restore persisted toolbar position\n try {\n const pos = JSON.parse(localStorage.getItem(\"__om_pos__\") || \"\");\n if (pos?.left && pos?.top) {\n $toolbar.style.left = pos.left;\n $toolbar.style.top = pos.top;\n $toolbar.style.right = \"auto\";\n $toolbar.style.bottom = \"auto\";\n }\n } catch {}\n\n installNetworkCapture();\n installConsoleCapture();\n checkForUpdates();\n\n // Connect to server — same origin (single port)\n const currentScript = document.querySelector('script[data-openmagic-token]') as HTMLScriptElement | null;\n const token = currentScript?.dataset.openmagicToken || (window as any).__OPENMAGIC_TOKEN__;\n const wsPort = parseInt(window.location.port, 10) || (window.location.protocol === \"https:\" ? 443 : 80);\n if (token) {\n ws.connect(wsPort, token)\n .then(() => {\n state.connected = true;\n updateStatusDot();\n return ws.request(\"config.get\");\n })\n .then((msg: any) => {\n // Merge server config with restored state (restored state takes precedence for provider/model)\n const serverProvider = msg.payload?.provider || \"\";\n const serverModel = msg.payload?.model || \"\";\n state.provider = state.provider || serverProvider;\n state.model = state.model || serverModel;\n state.configuredProviders = msg.payload?.apiKeys || {};\n state.hasApiKey = state.configuredProviders[state.provider] || false;\n state.roots = msg.payload?.roots || [];\n\n // Restore panel state if we had it open before refresh\n if (state.panelOpen && state.activePanel) {\n openPanel(state.activePanel as \"chat\" | \"settings\");\n } else if (!state.provider || (!state.hasApiKey && !Object.values(state.configuredProviders).some(Boolean))) {\n openPanel(\"settings\");\n }\n updatePillButtons();\n })\n .catch(() => {\n state.connected = false;\n updateStatusDot();\n });\n }\n}\n\nfunction buildStaticDOM(): string {\n return `\n <div class=\"om-toolbar\">\n <div class=\"om-toolbar-header\">\n <span class=\"om-grab\">${ICON.grip}</span>\n <span class=\"om-pill-brand\">\n <span class=\"om-pill-icon\">${ICON.sparkle}</span>\n <span class=\"om-pill-text\">OpenMagic</span>\n </span>\n <span class=\"om-pill-divider\"></span>\n <button class=\"om-pill-btn\" data-action=\"select\" title=\"Select element\">${ICON.crosshair}</button>\n <button class=\"om-pill-btn\" data-action=\"screenshot\" title=\"Screenshot\">${ICON.camera}</button>\n <button class=\"om-pill-btn\" data-action=\"network\" title=\"Network & Performance\">${ICON.activity}</button>\n <span class=\"om-pill-divider\"></span>\n <button class=\"om-pill-btn\" data-action=\"chat\" title=\"Chat\">${ICON.chat}</button>\n <button class=\"om-pill-btn\" data-action=\"settings\" title=\"Settings\">${ICON.settings}</button>\n <span class=\"om-status-dot disconnected\"></span>\n </div>\n <div class=\"om-panel om-hidden\">\n <div class=\"om-panel-header\">\n <span class=\"om-panel-title\"></span>\n <span class=\"om-panel-version\">v${CURRENT_VERSION}</span>\n <button class=\"om-panel-close\" data-action=\"close-panel\">${ICON.x}</button>\n </div>\n <div class=\"om-panel-body\"></div>\n </div>\n <div class=\"om-prompt-attachments\"></div>\n <div class=\"om-prompt-row\">\n <div class=\"om-prompt-context\"></div>\n <button class=\"om-prompt-attach\" data-action=\"attach-image\" title=\"Attach image\">${ICON.paperclip}</button>\n <input class=\"om-prompt-input\" type=\"text\" placeholder=\"Describe what to change...\" autocomplete=\"off\" />\n <button class=\"om-prompt-send\" data-action=\"prompt-send\">${ICON.send}</button>\n <input type=\"file\" class=\"om-file-input om-hidden\" accept=\"image/*\" multiple />\n </div>\n </div>`;\n}\n\n// ── Event Delegation (attached ONCE) ─────────────────────────────\nfunction attachGlobalEvents(root: HTMLElement) {\n // Click delegation\n root.addEventListener(\"click\", (e) => {\n const target = (e.target as HTMLElement).closest(\"[data-action]\") as HTMLElement | null;\n if (!target) return;\n e.preventDefault();\n e.stopPropagation();\n const action = target.dataset.action!;\n handleAction(action, target);\n });\n\n // Change delegation (dropdowns)\n root.addEventListener(\"change\", (e) => {\n const target = e.target as HTMLSelectElement;\n const field = target.dataset.field;\n if (!field) return;\n\n if (field === \"provider\") {\n state.provider = target.value;\n state.model = MODEL_REGISTRY[state.provider]?.models[0]?.id || \"\";\n state.hasApiKey = state.configuredProviders[state.provider] || MODEL_REGISTRY[state.provider]?.local || false;\n state.saveStatus = \"\";\n refreshPanelContent();\n } else if (field === \"model\") {\n state.model = target.value;\n }\n });\n\n // Prompt input: Enter to send\n $promptInput.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n sendPrompt();\n }\n });\n\n // File input change handler\n const fileInput = root.querySelector(\".om-file-input\") as HTMLInputElement;\n if (fileInput) {\n fileInput.addEventListener(\"change\", () => {\n handleFileSelect(fileInput.files);\n fileInput.value = \"\"; // Reset so same file can be selected again\n });\n }\n\n // Drag and drop on prompt area\n const promptRow = root.querySelector(\".om-prompt-row\");\n if (promptRow) {\n promptRow.addEventListener(\"dragover\", (e) => {\n e.preventDefault();\n (promptRow as HTMLElement).style.borderColor = \"rgba(108, 92, 231, 0.5)\";\n });\n promptRow.addEventListener(\"dragleave\", () => {\n (promptRow as HTMLElement).style.borderColor = \"\";\n });\n promptRow.addEventListener(\"drop\", (e) => {\n e.preventDefault();\n (promptRow as HTMLElement).style.borderColor = \"\";\n const dt = (e as DragEvent).dataTransfer;\n if (dt?.files?.length) handleFileSelect(dt.files);\n });\n\n // Also handle paste with images\n $promptInput.addEventListener(\"paste\", (e) => {\n const items = (e as ClipboardEvent).clipboardData?.items;\n if (!items) return;\n for (let i = 0; i < items.length; i++) {\n if (items[i].type.startsWith(\"image/\")) {\n const file = items[i].getAsFile();\n if (file) {\n const dt = new DataTransfer();\n dt.items.add(file);\n handleFileSelect(dt.files);\n }\n }\n }\n });\n }\n\n // Listen for reconnection events\n ws.onMessage((msg: any) => {\n if (msg.type === \"reconnected\") {\n state.connected = true;\n updateStatusDot();\n }\n });\n}\n\nfunction resolveFilePath(rel: string): string {\n return state.roots.length > 0 ? state.roots[0] + \"/\" + rel : rel;\n}\n\nasync function applyDiff(target: HTMLElement) {\n const file = target.dataset.file;\n const searchB64 = target.dataset.search;\n const replaceB64 = target.dataset.replace;\n if (!file || !searchB64 || !replaceB64) return;\n\n let search: string, replace: string;\n try {\n search = decodeBase64Utf8(searchB64);\n replace = decodeBase64Utf8(replaceB64);\n } catch {\n state.messages.push({ role: \"system\", content: `Failed to decode diff data for ${file}` });\n refreshPanelContent();\n return;\n }\n\n const card = target.closest(\".om-diff-card\") as HTMLElement | null;\n const filePath = resolveFilePath(file);\n\n // Show applying state\n if (card) {\n const actions = card.querySelector(\".om-diff-actions\");\n if (actions) actions.innerHTML = '<span class=\"om-spinner\"></span> Applying...';\n }\n\n try {\n const fileResult = await ws.request(\"fs.read\", { path: filePath });\n const content = fileResult?.payload?.content;\n\n if (!content) {\n state.messages.push({ role: \"system\", content: `Could not read ${file} — file may not exist at ${filePath}` });\n } else {\n const occurrences = content.split(search).length - 1;\n if (occurrences === 0) {\n state.messages.push({ role: \"system\", content: `No matching code found in ${file}. The file may have changed since the suggestion was made.` });\n } else if (occurrences > 1) {\n state.messages.push({ role: \"system\", content: `Found ${occurrences} matches in ${file} — expected exactly 1. Edit not applied for safety.` });\n } else {\n const writeResult = await ws.request(\"fs.write\", { path: filePath, content: content.replace(search, replace) });\n if (writeResult?.payload?.ok === false) {\n state.messages.push({ role: \"system\", content: `Write failed: ${file} - ${writeResult.payload?.error || \"unknown\"}` });\n } else {\n const idx = card?.dataset.diffIdx;\n if (idx !== undefined) {\n state.messages[parseInt(idx)] = { role: \"system\", content: `Applied change to ${file}` };\n } else {\n state.messages.push({ role: \"system\", content: `Applied change to ${file}` });\n }\n }\n }\n }\n } catch (e: any) {\n state.messages.push({ role: \"system\", content: `Failed to apply: ${file} — ${e.message}` });\n }\n\n refreshPanelContent();\n scrollChatToBottom();\n}\n\nfunction rejectDiff(target: HTMLElement) {\n const idx = target.dataset.idx;\n if (idx !== undefined) {\n const i = parseInt(idx);\n const parts = state.messages[i]?.content.split(\"__\");\n const file = parts?.[3] || \"file\";\n state.messages[i] = { role: \"system\", content: `Rejected change to ${file}` };\n }\n refreshPanelContent();\n scrollChatToBottom();\n}\n\nfunction handleAction(action: string, target: HTMLElement) {\n switch (action) {\n case \"select\": toggleSelectMode(); break;\n case \"screenshot\": takeScreenshot(); break;\n case \"chat\": togglePanel(\"chat\"); break;\n case \"settings\": togglePanel(\"settings\"); break;\n case \"close-panel\": closePanel(); break;\n case \"prompt-send\": sendPrompt(); break;\n case \"save-settings\": saveSettings(); break;\n case \"get-key\": {\n const url = target.dataset.url;\n if (url) window.open(url, \"_blank\", \"noopener\");\n break;\n }\n case \"change-key\": {\n // Show the hidden key input field\n const changeRow = shadow.querySelector(\"[data-key-change]\");\n if (changeRow) changeRow.classList.remove(\"om-hidden\");\n target.style.display = \"none\";\n break;\n }\n case \"network\": togglePanel(\"chat\"); captureNetworkProfile(); break;\n case \"attach-image\": triggerFileAttach(); break;\n case \"remove-attachment\": {\n const idx = parseInt(target.dataset.idx || \"0\", 10);\n state.attachments.splice(idx, 1);\n renderAttachments();\n break;\n }\n case \"apply-diff\": applyDiff(target); break;\n case \"reject-diff\": rejectDiff(target); break;\n case \"clear-element\": state.selectedElement = null; updatePromptContext(); break;\n case \"clear-screenshot\": state.screenshot = null; updatePromptContext(); break;\n }\n}\n\n// ── Targeted UI Updates (no full DOM rebuild) ────────────────────\n\nfunction updateStatusDot() {\n const dot = shadow.querySelector(\".om-status-dot\");\n if (dot) {\n dot.className = `om-status-dot ${state.connected ? \"connected\" : \"disconnected\"}`;\n }\n}\n\nfunction updatePillButtons() {\n shadow.querySelectorAll(\".om-pill-btn\").forEach((btn) => {\n const action = (btn as HTMLElement).dataset.action;\n btn.classList.toggle(\"active\", action === state.activePanel || (action === \"select\" && state.selecting));\n });\n}\n\nfunction updatePromptContext() {\n const chips: string[] = [];\n if (state.selectedElement) {\n chips.push(`<span class=\"om-prompt-chip\">${state.selectedElement.tagName}${state.selectedElement.id ? \"#\" + state.selectedElement.id : \"\"} <button class=\"om-prompt-chip-x\" data-action=\"clear-element\">${ICON.x}</button></span>`);\n }\n if (state.screenshot) {\n chips.push(`<span class=\"om-prompt-chip\">Screenshot <button class=\"om-prompt-chip-x\" data-action=\"clear-screenshot\">${ICON.x}</button></span>`);\n }\n if (state.attachments.length) {\n chips.push(`<span class=\"om-prompt-chip\">${state.attachments.length} image${state.attachments.length > 1 ? \"s\" : \"\"}</span>`);\n }\n $promptCtx.innerHTML = chips.join(\"\");\n}\n\n// ── Panel Management ─────────────────────────────────────────────\n\nfunction openPanel(panel: \"chat\" | \"settings\") {\n state.panelOpen = true;\n state.activePanel = panel;\n $panel.classList.remove(\"om-hidden\");\n const title = shadow.querySelector(\".om-panel-title\");\n if (title) title.textContent = panel === \"settings\" ? \"Settings\" : \"Chat\";\n refreshPanelContent();\n updatePillButtons();\n}\n\nfunction closePanel() {\n state.panelOpen = false;\n state.activePanel = \"\";\n $panel.classList.add(\"om-hidden\");\n updatePillButtons();\n}\n\nfunction togglePanel(panel: \"chat\" | \"settings\") {\n if (state.panelOpen && state.activePanel === panel) {\n closePanel();\n } else {\n openPanel(panel);\n }\n}\n\nfunction refreshPanelContent() {\n if (state.activePanel === \"settings\") {\n $panelBody.innerHTML = renderSettingsHTML();\n } else if (state.activePanel === \"chat\") {\n $panelBody.innerHTML = renderChatHTML();\n scrollChatToBottom();\n }\n saveState();\n}\n\n// ── Settings Renderer ────────────────────────────────────────────\n\nfunction renderSettingsHTML(): string {\n const providerOpts = Object.entries(MODEL_REGISTRY)\n .map(([k, p]) => {\n const configured = state.configuredProviders[k] || p.local;\n const indicator = configured ? \" \\u2713\" : \"\";\n return `<option value=\"${k}\" ${state.provider === k ? \"selected\" : \"\"}>${p.name}${indicator}</option>`;\n }).join(\"\");\n\n const prov = MODEL_REGISTRY[state.provider];\n const modelOpts = prov\n ? prov.models.map(m => `<option value=\"${m.id}\" ${state.model === m.id ? \"selected\" : \"\"}>${m.name}</option>`).join(\"\")\n : '<option value=\"\">Select provider first</option>';\n\n const isLocal = prov?.local || false;\n const keyUrl = prov?.keyUrl || \"\";\n const keyPh = prov?.keyPlaceholder || \"Enter API key...\";\n const providerHasKey = state.configuredProviders[state.provider] || false;\n\n const updateBanner = state.updateAvailable\n ? `<div class=\"om-update-banner\">v${state.latestVersion} available <code class=\"om-update-cmd\">npx openmagic@latest</code></div>` : \"\";\n\n // Show connected status if current provider has a key\n const statusHtml = (providerHasKey || isLocal)\n ? `<div class=\"om-status om-status-success\">${ICON.check} ${prov?.name || \"Provider\"} connected</div>` : \"\";\n\n const saveBtnText = state.saveStatus === \"saving\" ? '<span class=\"om-spinner\"></span> Saving...'\n : state.saveStatus === \"saved\" ? `${ICON.check} Saved` : \"Save\";\n const saveBtnClass = state.saveStatus === \"saving\" ? \"om-btn om-btn-saving\"\n : state.saveStatus === \"saved\" ? \"om-btn om-btn-saved\" : \"om-btn\";\n const saveBtnDisabled = state.saveStatus === \"saving\" ? \"disabled\" : \"\";\n\n // API key section: show \"configured\" state if key exists, with option to change\n let keySection = \"\";\n if (!isLocal && state.provider) {\n if (providerHasKey) {\n keySection = `\n <div class=\"om-field\">\n <label class=\"om-label\">API Key</label>\n <div class=\"om-key-configured\">\n ${ICON.check} <span>Key configured</span>\n <button class=\"om-btn-change-key\" data-action=\"change-key\">Change</button>\n </div>\n <div class=\"om-key-change-row om-hidden\" data-key-change>\n <div class=\"om-key-row\">\n <input type=\"text\" class=\"om-input om-key-input\" data-field=\"apiKey\" placeholder=\"${keyPh}\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" data-lpignore=\"true\" data-1p-ignore=\"true\" data-form-type=\"other\" />\n ${keyUrl ? `<button class=\"om-btn-get-key\" data-action=\"get-key\" data-url=\"${keyUrl}\">${ICON.externalLink} Get key</button>` : \"\"}\n </div>\n </div>\n </div>`;\n } else {\n keySection = `\n <div class=\"om-field\">\n <label class=\"om-label\">API Key</label>\n <div class=\"om-key-row\">\n <input type=\"text\" class=\"om-input om-key-input\" data-field=\"apiKey\" placeholder=\"${keyPh}\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" data-lpignore=\"true\" data-1p-ignore=\"true\" data-form-type=\"other\" />\n ${keyUrl ? `<button class=\"om-btn-get-key\" data-action=\"get-key\" data-url=\"${keyUrl}\">${ICON.externalLink} Get key</button>` : \"\"}\n </div>\n ${keyUrl ? `<div class=\"om-key-hint\"><a data-action=\"get-key\" data-url=\"${keyUrl}\">Get your ${prov?.name || \"\"} API key here</a></div>` : \"\"}\n </div>`;\n }\n }\n\n return `\n ${updateBanner}\n <div class=\"om-settings\">\n <div class=\"om-field\">\n <label class=\"om-label\">Provider</label>\n <select class=\"om-select\" data-field=\"provider\"><option value=\"\">Select Provider...</option>${providerOpts}</select>\n </div>\n <div class=\"om-field\">\n <label class=\"om-label\">Model</label>\n <select class=\"om-select\" data-field=\"model\"><option value=\"\">Select Model...</option>${modelOpts}</select>\n </div>\n ${keySection}\n <button class=\"${saveBtnClass}\" data-action=\"save-settings\" ${saveBtnDisabled}>${saveBtnText}</button>\n ${statusHtml}\n </div>`;\n}\n\n// ── Chat Renderer ────────────────────────────────────────────────\n\nfunction renderChatHTML(): string {\n if (!state.provider || (!state.hasApiKey && !MODEL_REGISTRY[state.provider]?.local)) {\n return `<div class=\"om-status om-status-error\">Configure your provider in Settings first</div>`;\n }\n\n const msgs = state.messages.map((m, i) => {\n if (m.content.startsWith(\"__DIFF__\")) {\n try {\n const diff = JSON.parse(decodeBase64Utf8(m.content.slice(8)));\n const searchB64 = encodeBase64Utf8(diff.search);\n const replaceB64 = encodeBase64Utf8(diff.replace);\n return `<div class=\"om-diff-card\" data-diff-idx=\"${i}\">\n <div class=\"om-diff-file\">${escapeHtml(diff.file)}</div>\n <div class=\"om-diff-removed\">${escapeHtml(diff.search.slice(0, 200))}</div>\n <div class=\"om-diff-added\">${escapeHtml(diff.replace.slice(0, 200))}</div>\n <div class=\"om-diff-actions\">\n <button class=\"om-btn om-btn-sm\" data-action=\"apply-diff\" data-file=\"${escapeHtml(diff.file)}\" data-search=\"${searchB64}\" data-replace=\"${replaceB64}\">Apply</button>\n <button class=\"om-btn-secondary om-btn-sm\" data-action=\"reject-diff\" data-idx=\"${i}\">Reject</button>\n </div>\n </div>`;\n } catch {\n return `<div class=\"om-msg om-msg-system\">Malformed diff data</div>`;\n }\n }\n return `<div class=\"om-msg om-msg-${m.role}\">${escapeHtml(m.content)}</div>`;\n }).join(\"\");\n\n const streamHtml = state.streaming\n ? `<div class=\"om-msg om-msg-assistant\"><span class=\"om-spinner\"></span>${escapeHtml(state.streamContent)}</div>` : \"\";\n\n const empty = !state.messages.length && !state.streaming\n ? `<div class=\"om-chat-empty\">Select an element or type below to start</div>` : \"\";\n\n return `<div class=\"om-chat-messages\">${empty}${msgs}${streamHtml}</div>`;\n}\n\nfunction scrollChatToBottom() {\n requestAnimationFrame(() => {\n const el = $panelBody.querySelector(\".om-chat-messages\");\n if (el) el.scrollTop = el.scrollHeight;\n });\n}\n\n// ── Save Settings ────────────────────────────────────────────────\n\nasync function saveSettings() {\n const apiKeyInput = $panelBody.querySelector('[data-field=\"apiKey\"]') as HTMLInputElement;\n const apiKey = apiKeyInput?.value || \"\";\n\n if (!state.provider) {\n state.saveStatus = \"error\";\n updateSaveButton();\n setTimeout(() => { state.saveStatus = \"\"; refreshPanelContent(); }, 2000);\n return;\n }\n\n // Check WebSocket connection\n if (!ws.isConnected()) {\n state.saveStatus = \"error\";\n updateSaveButton();\n const btn = $panelBody.querySelector('[data-action=\"save-settings\"]');\n if (btn) btn.innerHTML = \"Not connected - check terminal\";\n setTimeout(() => { state.saveStatus = \"\"; refreshPanelContent(); }, 3000);\n return;\n }\n\n const payload: any = { provider: state.provider, model: state.model };\n if (apiKey) payload.apiKey = apiKey;\n\n state.saveStatus = \"saving\";\n updateSaveButton();\n\n try {\n // Race against a 8s local timeout (don't wait 30s)\n const result = await Promise.race([\n ws.request(\"config.set\", payload),\n new Promise((_, reject) => setTimeout(() => reject(new Error(\"Save timed out\")), 8000)),\n ]);\n // Mark this provider as configured\n if (apiKey && state.provider) {\n state.configuredProviders[state.provider] = true;\n }\n state.hasApiKey = !!(apiKey || state.configuredProviders[state.provider]);\n state.saveStatus = \"saved\";\n updateSaveButton();\n\n // Auto-transition to chat after 1.2s\n setTimeout(() => {\n state.saveStatus = \"\";\n if (state.activePanel === \"settings\") {\n openPanel(\"chat\");\n }\n }, 1200);\n } catch (e: any) {\n state.saveStatus = \"error\";\n const btn = $panelBody.querySelector('[data-action=\"save-settings\"]');\n const msg = (e?.message || \"\").includes(\"timeout\") ? \"Connection timeout - is the CLI running?\"\n : (e?.message || \"\").includes(\"connected\") ? \"Not connected to OpenMagic server\"\n : `Save failed: ${e?.message || \"Unknown error\"}`;\n if (btn) {\n btn.innerHTML = msg;\n btn.className = \"om-btn\";\n (btn as HTMLButtonElement).disabled = false;\n }\n setTimeout(() => { state.saveStatus = \"\"; refreshPanelContent(); }, 4000);\n }\n}\n\nfunction updateSaveButton() {\n const btn = $panelBody.querySelector('[data-action=\"save-settings\"]');\n if (!btn) return;\n if (state.saveStatus === \"saving\") {\n btn.innerHTML = '<span class=\"om-spinner\"></span> Saving...';\n btn.className = \"om-btn om-btn-saving\";\n (btn as HTMLButtonElement).disabled = true;\n } else if (state.saveStatus === \"saved\") {\n btn.innerHTML = `${ICON.check} Saved`;\n btn.className = \"om-btn om-btn-saved\";\n (btn as HTMLButtonElement).disabled = false;\n } else if (state.saveStatus === \"error\") {\n btn.innerHTML = \"Save failed - try again\";\n btn.className = \"om-btn\";\n (btn as HTMLButtonElement).disabled = false;\n } else {\n btn.innerHTML = \"Save\";\n btn.className = \"om-btn\";\n (btn as HTMLButtonElement).disabled = false;\n }\n}\n\n// ── Send Prompt ──────────────────────────────────────────────────\n\nasync function sendPrompt() {\n const text = $promptInput.value.trim();\n if (!text || state.streaming) return;\n\n if (!state.provider || (!state.hasApiKey && !MODEL_REGISTRY[state.provider]?.local)) {\n openPanel(\"settings\");\n return;\n }\n\n // Add user message\n state.messages.push({ role: \"user\", content: text });\n state.streaming = true;\n state.streamContent = \"\";\n $promptInput.value = \"\";\n\n // Open chat panel\n openPanel(\"chat\");\n\n // Build context — includes page info, selected element, screenshot, network/console logs\n const context: any = buildContext(state.selectedElement, state.screenshot);\n context.pageUrl = window.location.href;\n context.pageTitle = document.title;\n\n // Include image attachments (for vision-capable models)\n if (state.attachments.length > 0) {\n // Use the first attachment as the screenshot if none is captured\n if (!context.screenshot) {\n context.screenshot = state.attachments[0];\n }\n // Store all attachments for multi-image models\n context.attachments = [...state.attachments];\n }\n\n // Grounding: read project tree + score and read relevant source files\n const MAX_GROUNDED_FILES = 5;\n const MAX_GROUNDED_CHARS = 32000;\n const TEXT_RE = /\\.(?:[cm]?[jt]sx?|svelte|vue|astro|html?|css|scss|less|php|py)$/i;\n\n try {\n const treeResult = await ws.request(\"fs.list\", {});\n if (treeResult?.payload?.projectTree) {\n context.projectTree = treeResult.payload.projectTree;\n }\n\n const allFiles = (treeResult?.payload?.files || []) as Array<{ path: string; type: string }>;\n const textFiles = allFiles.filter((f: { path: string; type: string }) => f.type === \"file\" && TEXT_RE.test(f.path));\n\n // Build search tokens from multiple sources\n const tokenSources: string[] = [text];\n\n // Add element metadata\n if (state.selectedElement) {\n if (state.selectedElement.id) tokenSources.push(state.selectedElement.id);\n if (state.selectedElement.className) tokenSources.push(state.selectedElement.className);\n if (state.selectedElement.textContent) tokenSources.push(state.selectedElement.textContent.slice(0, 100));\n if ((state.selectedElement as any).componentHint) tokenSources.push((state.selectedElement as any).componentHint);\n // Add ancestry class/component names\n if ((state.selectedElement as any).ancestry) {\n for (const a of (state.selectedElement as any).ancestry) {\n tokenSources.push(a);\n }\n }\n }\n\n const searchTokens = tokenSources\n .filter(Boolean).join(\" \").toLowerCase()\n .split(/[^a-z0-9_-]+/)\n .filter((t: string) => t.length >= 2 && ![\"the\", \"to\", \"in\", \"of\", \"and\", \"div\", \"span\", \"class\", \"style\"].includes(t));\n\n // Extract URL route segments (highest signal for finding the right page component)\n const pathname = window.location.pathname;\n const routeTokens = pathname.split(\"/\").filter((s: string) => s.length > 1 && !/^\\d+$/.test(s));\n\n const scored = textFiles.map((f: { path: string; type: string }) => {\n let score = 0;\n const lower = f.path.toLowerCase();\n\n // Route match: files matching URL path get highest priority (+15)\n for (const rt of routeTokens) {\n if (lower.includes(rt.toLowerCase())) score += 15;\n }\n\n // Component hint match (+12)\n if ((state.selectedElement as any)?.componentHint) {\n const hint = (state.selectedElement as any).componentHint.toLowerCase();\n if (lower.includes(hint)) score += 12;\n }\n\n // Token match from prompt/element (+5)\n for (const token of searchTokens) {\n if (lower.includes(token)) score += 5;\n }\n\n // Framework patterns (+3)\n if (/(component|page|route|layout|template|view)/.test(lower)) score += 3;\n // Page/route files for current route get extra (+5)\n if (/page\\.[jt]sx?$|layout\\.[jt]sx?$|\\+page\\.svelte$/.test(lower)) score += 5;\n\n return { ...f, score };\n }).sort((a: { score: number }, b: { score: number }) => b.score - a.score);\n\n // Read top scored files\n const files: Array<{ path: string; content: string }> = [];\n let totalChars = 0;\n for (const f of scored.slice(0, MAX_GROUNDED_FILES)) {\n if (f.score <= 0) break; // Only read files with positive relevance\n if (totalChars >= MAX_GROUNDED_CHARS) break;\n try {\n const root = state.roots[0] || \"\";\n const result = await ws.request(\"fs.read\", { path: root ? `${root}/${f.path}` : f.path });\n const content = String(result?.payload?.content || \"\");\n if (!content) continue;\n const trimmed = content.slice(0, Math.min(8000, MAX_GROUNDED_CHARS - totalChars));\n files.push({ path: f.path, content: trimmed });\n totalChars += trimmed.length;\n } catch { /* skip unreadable files */ }\n }\n if (files.length) context.files = files;\n } catch { /* grounding is best-effort */ }\n\n try {\n const result = await ws.stream(\n \"llm.chat\",\n {\n provider: state.provider,\n model: state.model,\n messages: state.messages.map(m => ({ role: m.role, content: m.content })),\n context,\n },\n (chunk: string) => {\n state.streamContent += chunk;\n // Update the streaming message in-place\n const msgEl = $panelBody.querySelector(\".om-msg-assistant:last-child\");\n if (msgEl) {\n msgEl.innerHTML = `<span class=\"om-spinner\"></span>${escapeHtml(state.streamContent)}`;\n scrollChatToBottom();\n }\n }\n );\n\n state.messages.push({ role: \"assistant\", content: state.streamContent || result?.content || \"\" });\n\n // Show diff previews for approval instead of auto-applying\n if (result?.modifications?.length) {\n for (const mod of result.modifications) {\n if (mod.type === \"edit\" && mod.file && mod.search && mod.replace) {\n const diffId = Math.random().toString(36).slice(2);\n const diffPayload = JSON.stringify({ id: diffId, file: mod.file, search: mod.search, replace: mod.replace });\n state.messages.push({\n role: \"system\",\n content: `__DIFF__${encodeBase64Utf8(diffPayload)}`,\n });\n }\n }\n }\n } catch (e: any) {\n state.messages.push({ role: \"system\", content: `Error: ${e.message}` });\n }\n\n state.streaming = false;\n state.streamContent = \"\";\n state.attachments = [];\n renderAttachments();\n refreshPanelContent();\n scrollChatToBottom();\n}\n\n// ── Network & Profiling ──────────────────────────────────────────\n\nfunction captureNetworkProfile() {\n // Capture performance timing\n const perf = window.performance;\n const navEntry = perf.getEntriesByType(\"navigation\")[0] as PerformanceNavigationTiming | undefined;\n const paintEntries = perf.getEntriesByType(\"paint\");\n const resources = perf.getEntriesByType(\"resource\").slice(-20) as PerformanceResourceTiming[];\n\n const networkLogs = getNetworkLogs();\n const consoleLogs = getConsoleLogs();\n\n // Build a summary message\n const lines: string[] = [];\n lines.push(\"--- Network & Performance Capture ---\");\n\n if (navEntry) {\n lines.push(`Page load: ${Math.round(navEntry.loadEventEnd - navEntry.startTime)}ms`);\n lines.push(`DOM ready: ${Math.round(navEntry.domContentLoadedEventEnd - navEntry.startTime)}ms`);\n lines.push(`TTFB: ${Math.round(navEntry.responseStart - navEntry.startTime)}ms`);\n }\n\n const fcp = paintEntries.find(e => e.name === \"first-contentful-paint\");\n if (fcp) lines.push(`FCP: ${Math.round(fcp.startTime)}ms`);\n\n if (networkLogs.length) {\n lines.push(`\\nRecent requests (${networkLogs.length}):`);\n for (const log of networkLogs.slice(-15)) {\n lines.push(` ${log.method} ${log.url.slice(0, 80)} → ${log.status || \"pending\"} (${log.duration || \"?\"}ms)`);\n }\n }\n\n if (consoleLogs.length) {\n const errors = consoleLogs.filter(l => l.level === \"error\");\n const warns = consoleLogs.filter(l => l.level === \"warn\");\n if (errors.length) lines.push(`\\nConsole errors: ${errors.length}`);\n if (warns.length) lines.push(`Console warnings: ${warns.length}`);\n }\n\n if (resources.length) {\n const slowest = [...resources].sort((a, b) => b.duration - a.duration).slice(0, 5);\n lines.push(`\\nSlowest resources:`);\n for (const r of slowest) {\n lines.push(` ${Math.round(r.duration)}ms — ${r.name.split(\"/\").pop()?.slice(0, 50)}`);\n }\n }\n\n // Add as a system message in the chat\n state.messages.push({ role: \"system\", content: lines.join(\"\\n\") });\n refreshPanelContent();\n scrollChatToBottom();\n updatePromptContext();\n}\n\n// ── File Attachments ─────────────────────────────────────────────\n\nfunction triggerFileAttach() {\n const input = shadow.querySelector(\".om-file-input\") as HTMLInputElement;\n if (input) input.click();\n}\n\nfunction handleFileSelect(files: FileList | null) {\n if (!files) return;\n for (let i = 0; i < files.length && state.attachments.length < 5; i++) {\n const file = files[i];\n if (!file.type.startsWith(\"image/\")) continue;\n if (file.size > 10 * 1024 * 1024) continue; // 10MB max\n const reader = new FileReader();\n reader.onload = () => {\n if (typeof reader.result === \"string\") {\n state.attachments.push(reader.result);\n renderAttachments();\n }\n };\n reader.readAsDataURL(file);\n }\n}\n\nfunction renderAttachments() {\n const container = shadow.querySelector(\".om-prompt-attachments\");\n if (!container) return;\n if (!state.attachments.length) {\n container.innerHTML = \"\";\n container.classList.add(\"om-hidden\");\n return;\n }\n container.classList.remove(\"om-hidden\");\n container.innerHTML = state.attachments.map((a, i) =>\n `<div class=\"om-attachment-thumb\">\n <img src=\"${a}\" alt=\"attachment\" />\n <button class=\"om-attachment-remove\" data-action=\"remove-attachment\" data-idx=\"${i}\">${ICON.x}</button>\n </div>`\n ).join(\"\");\n}\n\n// ── Select Mode ──────────────────────────────────────────────────\n\nlet selectHandler: ((e: MouseEvent) => void) | null = null;\nlet hoverHandler: ((e: MouseEvent) => void) | null = null;\n\nfunction toggleSelectMode() {\n state.selecting ? exitSelectMode() : enterSelectMode();\n}\n\nfunction enterSelectMode() {\n state.selecting = true;\n document.body.style.cursor = \"crosshair\";\n updatePillButtons();\n\n hoverHandler = (e: MouseEvent) => {\n const t = e.target as HTMLElement;\n if (t.closest(\"openmagic-toolbar\") || t.dataset?.openmagic) return;\n const r = t.getBoundingClientRect();\n showHighlight({ x: r.x, y: r.y, width: r.width, height: r.height });\n };\n\n selectHandler = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const t = e.target as HTMLElement;\n if (t.closest(\"openmagic-toolbar\") || t.dataset?.openmagic) return;\n state.selectedElement = inspectElement(t);\n exitSelectMode();\n updatePromptContext();\n $promptInput.focus();\n };\n\n // ESC to cancel\n const escHandler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n exitSelectMode();\n }\n };\n\n document.addEventListener(\"mousemove\", hoverHandler, true);\n document.addEventListener(\"click\", selectHandler, true);\n document.addEventListener(\"keydown\", escHandler, true);\n\n // Store for cleanup\n (enterSelectMode as any)._escHandler = escHandler;\n}\n\nfunction exitSelectMode() {\n state.selecting = false;\n document.body.style.cursor = \"\";\n hideHighlight();\n if (hoverHandler) { document.removeEventListener(\"mousemove\", hoverHandler, true); hoverHandler = null; }\n if (selectHandler) { document.removeEventListener(\"click\", selectHandler, true); selectHandler = null; }\n const escH = (enterSelectMode as any)._escHandler;\n if (escH) { document.removeEventListener(\"keydown\", escH, true); (enterSelectMode as any)._escHandler = null; }\n updatePillButtons();\n}\n\nasync function takeScreenshot() {\n // If element is selected, try element screenshot first\n let target: HTMLElement | undefined;\n try {\n const sel = state.selectedElement?.cssSelector?.trim();\n if (sel) target = (document.querySelector(sel) as HTMLElement) || undefined;\n } catch { /* stale or invalid selector */ }\n const ss = await captureScreenshot(target || undefined);\n if (ss) {\n state.screenshot = ss;\n updatePromptContext();\n $promptInput.focus();\n }\n}\n\n// ── Draggable (setup ONCE) ───────────────────────────────────────\n\nfunction setupDraggable() {\n let active = false, startX = 0, startY = 0, origX = 0, origY = 0;\n\n $toolbar.addEventListener(\"mousedown\", (e) => {\n const t = e.target as HTMLElement;\n if (t.closest(\"[data-action]\")) return;\n if (!t.closest(\".om-grab\") && !t.closest(\".om-pill-brand\")) return;\n active = true;\n startX = e.clientX; startY = e.clientY;\n const r = $toolbar.getBoundingClientRect();\n origX = r.left; origY = r.top;\n e.preventDefault();\n });\n\n document.addEventListener(\"mousemove\", (e) => {\n if (!active) return;\n $toolbar.style.left = (origX + e.clientX - startX) + \"px\";\n $toolbar.style.top = (origY + e.clientY - startY) + \"px\";\n $toolbar.style.right = \"auto\";\n $toolbar.style.bottom = \"auto\";\n });\n\n document.addEventListener(\"mouseup\", () => {\n if (active) {\n active = false;\n // Persist position\n try {\n localStorage.setItem(\"__om_pos__\", JSON.stringify({\n left: $toolbar.style.left,\n top: $toolbar.style.top,\n }));\n } catch {}\n }\n });\n}\n\n// ── Helpers ──────────────────────────────────────────────────────\n\nfunction escapeHtml(text: string): string {\n const d = document.createElement(\"div\");\n d.textContent = text;\n return d.innerHTML;\n}\n\nfunction checkForUpdates() {\n fetch(\"https://registry.npmjs.org/openmagic/latest\", {\n headers: { Accept: \"application/json\" },\n signal: AbortSignal.timeout(5000),\n }).then(r => r.ok ? r.json() : null).then(d => {\n if (!d?.version) return;\n const l = d.version.split(\".\").map(Number), c = CURRENT_VERSION.split(\".\").map(Number);\n for (let i = 0; i < 3; i++) { if ((l[i]||0) > (c[i]||0)) { state.updateAvailable = true; state.latestVersion = d.version; showUpdateDot(); return; } if ((l[i]||0) < (c[i]||0)) return; }\n }).catch(() => {});\n}\n\nfunction showUpdateDot() {\n const existing = shadow.querySelector(\".om-update-dot\");\n if (existing) return;\n const dot = document.createElement(\"span\");\n dot.className = \"om-update-dot\";\n dot.title = `v${state.latestVersion} available`;\n dot.addEventListener(\"click\", () => openPanel(\"settings\"));\n const header = shadow.querySelector(\".om-toolbar-header\");\n if (header) header.appendChild(dot);\n}\n\n// ── Boot ─────────────────────────────────────────────────────────\nif (typeof window !== \"undefined\") {\n if (document.readyState === \"loading\") {\n document.addEventListener(\"DOMContentLoaded\", init);\n } else {\n init();\n }\n}\n"],"mappings":";wCAAO,IAAMA,GAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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","names":["TOOLBAR_CSS","ws","handlers","globalHandlers","messageQueue","connected","shouldReconnect","reconnectTimer","reconnectAttempt","generateId","connect","port","token","resolve","reject","settled","handshakeTimeout","wsHost","wsProto","handshakeId","msg","queued","event","handler","wasConnected","id","delay","e","send","data","request","type","payload","timeout","stream","onChunk","onMessage","h","isConnected","IMPORTANT_STYLES","inspectElement","el","computed","styles","prop","rect","getCleanOuterHTML","getCssSelector","getXPath","getAncestry","getComponentHint","depth","result","current","tag","cls","c","dataComponent","keys","key","fiber","name","clone","html","attrs","a","childSummary","parts","selector","classes","parent","siblings","s","index","element","sibling","highlightEl","showHighlight","hideHighlight","captureScreenshot","target","captureElementViaCanvas","captureViewport","e","canvas","dpr","ctx","svgData","elementToSvg","img","svgToImage","element","rect","resolve","clone","inlineStyles","width","height","foreignObject","source","computed","cssText","prop","sourceChildren","targetChildren","reject","blob","url","networkLogs","networkCaptureInstalled","installNetworkCapture","originalFetch","args","request","entry","response","addNetworkEntry","e","originalOpen","originalSend","method","url","rest","networkLogs","getNetworkLogs","consoleLogs","MAX_CONSOLE_LOGS","consoleCaptureInstalled","installConsoleCapture","levels","level","original","args","a","getConsoleLogs","buildContext","selectedElement","screenshot","getNetworkLogs","l","getConsoleLogs","ICON","MODEL_REGISTRY","encodeBase64Utf8","value","bytes","binary","i","decodeBase64Utf8","CURRENT_VERSION","state","shadow","$toolbar","$promptInput","$promptCtx","$panel","$panelBody","saveState","restoreState","saved","init","host","style","TOOLBAR_CSS","root","buildStaticDOM","attachGlobalEvents","setupDraggable","pos","installNetworkCapture","installConsoleCapture","checkForUpdates","token","wsPort","connect","updateStatusDot","request","msg","serverProvider","serverModel","openPanel","updatePillButtons","e","target","action","handleAction","field","refreshPanelContent","sendPrompt","fileInput","handleFileSelect","promptRow","dt","items","file","onMessage","resolveFilePath","rel","applyDiff","searchB64","replaceB64","search","replace","card","filePath","actions","content","occurrences","writeResult","idx","scrollChatToBottom","rejectDiff","toggleSelectMode","takeScreenshot","togglePanel","closePanel","saveSettings","url","changeRow","captureNetworkProfile","triggerFileAttach","renderAttachments","updatePromptContext","dot","btn","chips","panel","title","renderSettingsHTML","renderChatHTML","providerOpts","k","p","indicator","prov","modelOpts","m","isLocal","keyUrl","keyPh","providerHasKey","updateBanner","statusHtml","saveBtnText","saveBtnClass","saveBtnDisabled","keySection","msgs","diff","escapeHtml","streamHtml","el","apiKey","updateSaveButton","isConnected","payload","result","_","reject","text","context","buildContext","MAX_GROUNDED_FILES","MAX_GROUNDED_CHARS","TEXT_RE","treeResult","textFiles","f","tokenSources","a","searchTokens","t","routeTokens","s","scored","score","lower","rt","hint","b","files","totalChars","trimmed","stream","chunk","msgEl","mod","diffId","diffPayload","perf","navEntry","paintEntries","resources","networkLogs","getNetworkLogs","consoleLogs","getConsoleLogs","lines","fcp","log","errors","l","warns","slowest","r","input","reader","container","selectHandler","hoverHandler","exitSelectMode","enterSelectMode","showHighlight","inspectElement","escHandler","hideHighlight","escH","sel","ss","captureScreenshot","active","startX","startY","origX","origY","d","c","showUpdateDot","header"]}