openmagic 0.9.0 → 0.10.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: 420px;\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/* ── 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/* ── 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-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","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 reconnectTimer: ReturnType<typeof setTimeout> | null = null;\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 return new Promise((resolve, reject) => {\n try {\n ws = new WebSocket(`ws://127.0.0.1:${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 // Wait for handshake.ok\n handlers.set(handshakeId, (msg) => {\n if (msg.type === \"handshake.ok\") {\n connected = true;\n // Flush queued messages\n for (const queued of messageQueue) {\n ws?.send(queued);\n }\n messageQueue = [];\n resolve();\n } else if (msg.type === \"error\") {\n 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\n // Route to specific handler if exists\n if (msg.id && handlers.has(msg.id)) {\n const handler = handlers.get(msg.id)!;\n handler(msg);\n // Don't delete handler for streaming responses\n if (msg.type === \"llm.done\" || msg.type === \"llm.error\" || !msg.type.startsWith(\"llm.\")) {\n handlers.delete(msg.id);\n }\n }\n\n // Notify global handlers\n for (const handler of globalHandlers) {\n handler(msg);\n }\n } catch {\n // Ignore parse errors\n }\n };\n\n ws.onclose = () => {\n connected = false;\n // Reconnect after 2 seconds\n if (!reconnectTimer) {\n reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n connect(port, token).catch(() => {});\n }, 2000);\n }\n };\n\n ws.onerror = () => {\n // Will trigger onclose\n };\n } catch (e) {\n 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); // 2 min timeout for LLM responses\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 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 `#${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(`#${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 if (classes.length > 0) {\n selector += \".\" + classes.join(\".\");\n }\n }\n\n // Add nth-child 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-child(${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\nexport function removeHighlight(): void {\n if (highlightEl) {\n highlightEl.remove();\n highlightEl = null;\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 } 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};\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\nconst CURRENT_VERSION = \"0.9.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 roots: [] as string[],\n updateAvailable: false,\n latestVersion: \"\",\n saveStatus: \"\" as \"\" | \"saving\" | \"saved\" | \"error\",\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 ───────────────────────────────────────────────────\nfunction init() {\n if (document.querySelector(\"openmagic-toolbar\")) return;\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 installNetworkCapture();\n installConsoleCapture();\n checkForUpdates();\n\n // Connect to server\n const config = (window as any).__OPENMAGIC_CONFIG__;\n if (config) {\n ws.connect(config.wsPort, config.token)\n .then(() => {\n state.connected = true;\n updateStatusDot();\n return ws.request(\"config.get\");\n })\n .then((msg: any) => {\n state.provider = msg.payload?.provider || \"\";\n state.model = msg.payload?.model || \"\";\n state.hasApiKey = msg.payload?.hasApiKey || false;\n state.roots = msg.payload?.roots || [];\n if (!state.provider || !state.hasApiKey) {\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 <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-body\"></div>\n </div>\n <div class=\"om-prompt-row\">\n <div class=\"om-prompt-context\"></div>\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 </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 = \"\";\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\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 \"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 $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 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}\n\n// ── Settings Renderer ────────────────────────────────────────────\n\nfunction renderSettingsHTML(): string {\n const providerOpts = Object.entries(MODEL_REGISTRY)\n .map(([k, p]) => `<option value=\"${k}\" ${state.provider === k ? \"selected\" : \"\"}>${p.name}</option>`).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\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 const statusHtml = state.hasApiKey\n ? `<div class=\"om-status om-status-success\">${ICON.check} 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 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 <div class=\"om-field ${isLocal ? \"om-hidden\" : \"\"}\">\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 <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.hasApiKey || !state.provider) {\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 =>\n `<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 state.hasApiKey = !!(apiKey || state.hasApiKey);\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.hasApiKey || !state.provider) {\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\n // Add current page context\n context.pageUrl = window.location.href;\n context.pageTitle = document.title;\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 // Apply code modifications if any\n if (result?.modifications?.length) {\n for (const mod of result.modifications) {\n if (mod.type === \"edit\" && mod.file && mod.search && mod.replace) {\n try {\n const fileResult = await ws.request(\"fs.read\", { path: resolveFilePath(mod.file) });\n const content = fileResult.payload?.content;\n if (content?.includes(mod.search)) {\n await ws.request(\"fs.write\", { path: resolveFilePath(mod.file), content: content.replace(mod.search, mod.replace) });\n state.messages.push({ role: \"system\", content: `Applied change to ${mod.file}` });\n }\n } catch (e: any) {\n state.messages.push({ role: \"system\", content: `Failed: ${mod.file} - ${e.message}` });\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 refreshPanelContent();\n scrollChatToBottom();\n}\n\nfunction resolveFilePath(rel: string): string {\n return state.roots.length > 0 ? state.roots[0] + \"/\" + rel : rel;\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 document.addEventListener(\"mousemove\", hoverHandler, true);\n document.addEventListener(\"click\", selectHandler, true);\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 updatePillButtons();\n}\n\nasync function takeScreenshot() {\n const ss = await captureScreenshot();\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\", () => { active = false; });\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,EAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","reconnectTimer","generateId","connect","port","token","resolve","reject","handshakeId","msg","queued","event","handler","e","send","data","request","type","payload","id","timeout","stream","onChunk","isConnected","connected","IMPORTANT_STYLES","inspectElement","el","computed","styles","prop","rect","getCleanOuterHTML","getCssSelector","getXPath","clone","s","html","tag","attrs","a","childSummary","c","parts","current","selector","classes","parent","siblings","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","i","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","CURRENT_VERSION","state","shadow","$toolbar","$promptInput","$promptCtx","$panel","$panelBody","init","host","style","TOOLBAR_CSS","root","buildStaticDOM","attachGlobalEvents","setupDraggable","installNetworkCapture","installConsoleCapture","checkForUpdates","config","connect","updateStatusDot","request","msg","openPanel","updatePillButtons","e","target","action","handleAction","field","refreshPanelContent","sendPrompt","toggleSelectMode","takeScreenshot","togglePanel","closePanel","saveSettings","url","updatePromptContext","dot","btn","chips","panel","title","renderSettingsHTML","renderChatHTML","scrollChatToBottom","providerOpts","k","p","prov","modelOpts","m","isLocal","keyUrl","keyPh","updateBanner","statusHtml","saveBtnText","saveBtnClass","saveBtnDisabled","msgs","escapeHtml","streamHtml","el","apiKey","updateSaveButton","isConnected","payload","result","_","reject","text","context","buildContext","stream","chunk","msgEl","mod","content","resolveFilePath","rel","selectHandler","hoverHandler","exitSelectMode","enterSelectMode","r","showHighlight","inspectElement","hideHighlight","ss","captureScreenshot","active","startX","startY","origX","origY","t","d","l","c","i","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: 420px;\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/* ── 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/* ── 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-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","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;\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 ws = new WebSocket(`ws://127.0.0.1:${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 // 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 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 reconnectTimer = setTimeout(() => {\n reconnectTimer = null;\n connect(port, token).catch(() => {});\n }, 2000);\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\nexport function removeHighlight(): void {\n if (highlightEl) {\n highlightEl.remove();\n highlightEl = null;\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 } 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};\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\nconst CURRENT_VERSION = \"0.10.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 roots: [] as string[],\n updateAvailable: false,\n latestVersion: \"\",\n saveStatus: \"\" as \"\" | \"saving\" | \"saved\" | \"error\",\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 ───────────────────────────────────────────────────\nfunction init() {\n if (document.querySelector(\"openmagic-toolbar\")) return;\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 installNetworkCapture();\n installConsoleCapture();\n checkForUpdates();\n\n // Connect to server\n const config = (window as any).__OPENMAGIC_CONFIG__;\n if (config) {\n ws.connect(config.wsPort, config.token)\n .then(() => {\n state.connected = true;\n updateStatusDot();\n return ws.request(\"config.get\");\n })\n .then((msg: any) => {\n state.provider = msg.payload?.provider || \"\";\n state.model = msg.payload?.model || \"\";\n state.hasApiKey = msg.payload?.hasApiKey || false;\n state.roots = msg.payload?.roots || [];\n if (!state.provider || !state.hasApiKey) {\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 <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-row\">\n <div class=\"om-prompt-context\"></div>\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 </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 = \"\";\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\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 \"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 $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}\n\n// ── Settings Renderer ────────────────────────────────────────────\n\nfunction renderSettingsHTML(): string {\n const providerOpts = Object.entries(MODEL_REGISTRY)\n .map(([k, p]) => `<option value=\"${k}\" ${state.provider === k ? \"selected\" : \"\"}>${p.name}</option>`).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\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 const statusHtml = state.hasApiKey\n ? `<div class=\"om-status om-status-success\">${ICON.check} 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 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 <div class=\"om-field ${isLocal ? \"om-hidden\" : \"\"}\">\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 <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 =>\n `<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 state.hasApiKey = !!(apiKey || state.hasApiKey);\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\n // Add current page context\n context.pageUrl = window.location.href;\n context.pageTitle = document.title;\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 // Apply code modifications if any\n if (result?.modifications?.length) {\n for (const mod of result.modifications) {\n if (mod.type === \"edit\" && mod.file && mod.search && mod.replace) {\n try {\n const fileResult = await ws.request(\"fs.read\", { path: resolveFilePath(mod.file) });\n const content = fileResult.payload?.content;\n if (content?.includes(mod.search)) {\n const writeResult = await ws.request(\"fs.write\", { path: resolveFilePath(mod.file), content: content.replace(mod.search, mod.replace) });\n if (writeResult?.payload?.ok === false) {\n state.messages.push({ role: \"system\", content: `Write failed: ${mod.file} - ${writeResult.payload.error || \"unknown\"}` });\n } else {\n state.messages.push({ role: \"system\", content: `Applied change to ${mod.file}` });\n }\n }\n } catch (e: any) {\n state.messages.push({ role: \"system\", content: `Failed: ${mod.file} - ${e.message}` });\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 refreshPanelContent();\n scrollChatToBottom();\n}\n\nfunction resolveFilePath(rel: string): string {\n return state.roots.length > 0 ? state.roots[0] + \"/\" + rel : rel;\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 document.addEventListener(\"mousemove\", hoverHandler, true);\n document.addEventListener(\"click\", selectHandler, true);\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 updatePillButtons();\n}\n\nasync function takeScreenshot() {\n const ss = await captureScreenshot();\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\", () => { active = false; });\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,EAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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","generateId","connect","port","token","resolve","reject","settled","handshakeTimeout","handshakeId","msg","queued","event","handler","wasConnected","e","send","data","request","type","payload","id","timeout","stream","onChunk","isConnected","connected","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","i","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","CURRENT_VERSION","state","shadow","$toolbar","$promptInput","$promptCtx","$panel","$panelBody","init","host","style","TOOLBAR_CSS","root","buildStaticDOM","attachGlobalEvents","setupDraggable","installNetworkCapture","installConsoleCapture","checkForUpdates","config","connect","updateStatusDot","request","msg","openPanel","updatePillButtons","e","target","action","handleAction","field","refreshPanelContent","sendPrompt","toggleSelectMode","takeScreenshot","togglePanel","closePanel","saveSettings","url","updatePromptContext","dot","btn","chips","panel","title","renderSettingsHTML","renderChatHTML","scrollChatToBottom","providerOpts","k","p","prov","modelOpts","m","isLocal","keyUrl","keyPh","updateBanner","statusHtml","saveBtnText","saveBtnClass","saveBtnDisabled","msgs","escapeHtml","streamHtml","el","apiKey","updateSaveButton","isConnected","payload","result","_","reject","text","context","buildContext","stream","chunk","msgEl","mod","content","resolveFilePath","writeResult","rel","selectHandler","hoverHandler","exitSelectMode","enterSelectMode","r","showHighlight","inspectElement","hideHighlight","ss","captureScreenshot","active","startX","startY","origX","origY","t","d","l","c","i","showUpdateDot","header"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openmagic",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "AI-powered coding toolbar for any web application. Select elements, capture context, and let AI modify your codebase in real-time.",
5
5
  "type": "module",
6
6
  "bin": {