openmagic 0.1.0 → 0.3.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.
- package/LICENSE +1 -1
- package/README.md +20 -14
- package/dist/cli.js +800 -76
- package/dist/cli.js.map +1 -1
- package/dist/toolbar/index.global.js +78 -13
- package/dist/toolbar/index.global.js.map +1 -1
- package/package.json +10 -2
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/proxy.ts","../src/security.ts","../src/server.ts","../src/config.ts","../src/filesystem.ts","../src/llm/registry.ts","../src/llm/prompts.ts","../src/llm/openai.ts","../src/llm/anthropic.ts","../src/llm/google.ts","../src/llm/proxy.ts","../src/detect.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport open from \"open\";\nimport { resolve } from \"node:path\";\nimport { createProxyServer } from \"./proxy.js\";\nimport { createOpenMagicServer } from \"./server.js\";\nimport { generateSessionToken } from \"./security.js\";\nimport { detectDevServer, findAvailablePort, isPortOpen } from \"./detect.js\";\nimport { loadConfig, saveConfig } from \"./config.js\";\n\nconst VERSION = \"0.1.0\";\n\nconst program = new Command();\n\nprogram\n .name(\"openmagic\")\n .description(\"AI-powered coding toolbar for any web application\")\n .version(VERSION)\n .option(\"-p, --port <port>\", \"Dev server port to proxy\", \"\")\n .option(\n \"-l, --listen <port>\",\n \"Port for the OpenMagic proxy\",\n \"4567\"\n )\n .option(\n \"-r, --root <paths...>\",\n \"Project root directories (defaults to cwd)\"\n )\n .option(\"--no-open\", \"Don't auto-open browser\")\n .option(\"--host <host>\", \"Dev server host\", \"127.0.0.1\")\n .action(async (opts) => {\n console.log(\"\");\n console.log(\n chalk.bold.magenta(\" ✨ OpenMagic\") + chalk.dim(` v${VERSION}`)\n );\n console.log(\"\");\n\n // Determine target dev server\n let targetPort: number;\n let targetHost = opts.host;\n\n if (opts.port) {\n targetPort = parseInt(opts.port, 10);\n const isRunning = await isPortOpen(targetPort);\n if (!isRunning) {\n console.log(\n chalk.yellow(\n ` ⚠ No server found at ${targetHost}:${targetPort}`\n )\n );\n console.log(\n chalk.dim(\n \" Start your dev server first, then run openmagic again.\"\n )\n );\n console.log(\"\");\n process.exit(1);\n }\n } else {\n console.log(chalk.dim(\" Scanning for dev server...\"));\n const detected = await detectDevServer();\n if (!detected) {\n console.log(\n chalk.yellow(\n \" ⚠ No dev server detected on common ports (3000, 5173, 8080, etc.)\"\n )\n );\n console.log(\"\");\n console.log(\n chalk.white(\" Specify the port manually:\")\n );\n console.log(\n chalk.cyan(\" npx openmagic --port 3000\")\n );\n console.log(\"\");\n process.exit(1);\n }\n targetPort = detected.port;\n targetHost = detected.host;\n }\n\n console.log(\n chalk.green(` ✓ Dev server found at ${targetHost}:${targetPort}`)\n );\n\n // Set up roots\n const roots = (opts.root || [process.cwd()]).map((r: string) =>\n resolve(r)\n );\n\n // Save roots to config\n const config = loadConfig();\n saveConfig({ ...config, roots, targetPort });\n\n // Generate session token\n const token = generateSessionToken();\n\n // Find available proxy port\n let proxyPort = parseInt(opts.listen, 10);\n if (await isPortOpen(proxyPort)) {\n proxyPort = await findAvailablePort(proxyPort);\n }\n\n // Start the OpenMagic server (serves toolbar + WebSocket)\n const { httpServer: omServer } = createOpenMagicServer(proxyPort, roots);\n omServer.listen(proxyPort + 1, \"127.0.0.1\", () => {\n // OpenMagic API/WS server running on proxyPort+1\n });\n\n // Start the proxy server\n const proxyServer = createProxyServer(\n targetHost,\n targetPort,\n proxyPort + 1\n );\n\n proxyServer.listen(proxyPort, \"127.0.0.1\", () => {\n console.log(\"\");\n console.log(\n chalk.bold.green(` 🚀 Proxy running at → `) +\n chalk.bold.underline.cyan(`http://localhost:${proxyPort}`)\n );\n console.log(\"\");\n console.log(\n chalk.dim(\" Open the URL above in your browser to start.\")\n );\n console.log(chalk.dim(\" Press Ctrl+C to stop.\"));\n console.log(\"\");\n\n if (opts.open !== false) {\n open(`http://localhost:${proxyPort}`).catch(() => {\n // Silently fail if browser can't be opened\n });\n }\n });\n\n // Handle WebSocket upgrades for OpenMagic\n proxyServer.on(\"upgrade\", (req, socket, head) => {\n if (req.url?.startsWith(\"/__openmagic__\")) {\n // Forward to OpenMagic WS server\n omServer.emit(\"upgrade\", req, socket, head);\n }\n // Otherwise, the proxy.ts handler forwards to dev server\n });\n\n // Graceful shutdown\n const shutdown = () => {\n console.log(\"\");\n console.log(chalk.dim(\" Shutting down OpenMagic...\"));\n proxyServer.close();\n omServer.close();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n });\n\nprogram.parse();\n","import http from \"node:http\";\nimport httpProxy from \"http-proxy\";\nimport { getSessionToken } from \"./security.js\";\n\nexport function createProxyServer(\n targetHost: string,\n targetPort: number,\n serverPort: number\n): http.Server {\n const proxy = httpProxy.createProxyServer({\n target: `http://${targetHost}:${targetPort}`,\n ws: true,\n selfHandleResponse: true,\n });\n\n const token = getSessionToken();\n\n proxy.on(\"proxyRes\", (proxyRes, req, res) => {\n const contentType = proxyRes.headers[\"content-type\"] || \"\";\n const isHtml = contentType.includes(\"text/html\");\n\n if (!isHtml) {\n // Pass through non-HTML responses unchanged\n res.writeHead(proxyRes.statusCode || 200, proxyRes.headers);\n proxyRes.pipe(res);\n return;\n }\n\n // For HTML responses, collect the body and inject the toolbar script\n const chunks: Buffer[] = [];\n proxyRes.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n proxyRes.on(\"end\", () => {\n let body = Buffer.concat(chunks).toString(\"utf-8\");\n\n // Inject toolbar script before </body> or at end\n const toolbarScript = buildInjectionScript(serverPort, token);\n if (body.includes(\"</body>\")) {\n body = body.replace(\"</body>\", `${toolbarScript}</body>`);\n } else if (body.includes(\"</html>\")) {\n body = body.replace(\"</html>\", `${toolbarScript}</html>`);\n } else {\n body += toolbarScript;\n }\n\n // Remove content-length since we modified the body\n const headers = { ...proxyRes.headers };\n delete headers[\"content-length\"];\n delete headers[\"content-encoding\"]; // Remove compression since we decoded it\n\n res.writeHead(proxyRes.statusCode || 200, headers);\n res.end(body);\n });\n });\n\n proxy.on(\"error\", (err, _req, res) => {\n console.error(\"[OpenMagic] Proxy error:\", err.message);\n if (res instanceof http.ServerResponse && !res.headersSent) {\n res.writeHead(502, { \"Content-Type\": \"text/plain\" });\n res.end(\n `OpenMagic proxy error: Could not connect to dev server at ${targetHost}:${targetPort}\\n\\nMake sure your dev server is running.`\n );\n }\n });\n\n const server = http.createServer((req, res) => {\n // Serve toolbar assets from /__openmagic__/ path\n if (req.url?.startsWith(\"/__openmagic__/\")) {\n handleToolbarAsset(req, res, serverPort);\n return;\n }\n\n // Proxy everything else to the dev server\n proxy.web(req, res);\n });\n\n // Handle WebSocket upgrades — forward to dev server (for HMR etc.)\n server.on(\"upgrade\", (req, socket, head) => {\n // Don't proxy OpenMagic WebSocket connections\n if (req.url?.startsWith(\"/__openmagic__\")) {\n return; // Let the WS server handle this\n }\n proxy.ws(req, socket, head);\n });\n\n return server;\n}\n\nfunction handleToolbarAsset(\n _req: http.IncomingMessage,\n res: http.ServerResponse,\n _serverPort: number\n): void {\n // The toolbar bundle is served inline via the injection script\n // This endpoint exists for potential future asset serving (icons, fonts, etc.)\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not found\");\n}\n\nfunction buildInjectionScript(serverPort: number, token: string): string {\n return `\n<script data-openmagic=\"true\">\n(function() {\n if (window.__OPENMAGIC_LOADED__) return;\n window.__OPENMAGIC_LOADED__ = true;\n window.__OPENMAGIC_CONFIG__ = {\n wsPort: ${serverPort},\n token: \"${token}\"\n };\n var script = document.createElement(\"script\");\n script.src = \"http://127.0.0.1:${serverPort}/__openmagic__/toolbar.js\";\n script.dataset.openmagic = \"true\";\n document.body.appendChild(script);\n})();\n</script>`;\n}\n","import { randomBytes } from \"node:crypto\";\n\nlet sessionToken: string | null = null;\n\nexport function generateSessionToken(): string {\n sessionToken = randomBytes(32).toString(\"hex\");\n return sessionToken;\n}\n\nexport function getSessionToken(): string {\n if (!sessionToken) {\n return generateSessionToken();\n }\n return sessionToken;\n}\n\nexport function validateToken(token: string): boolean {\n return token === sessionToken;\n}\n","import http from \"node:http\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { WebSocketServer, WebSocket } from \"ws\";\nimport { validateToken } from \"./security.js\";\nimport { loadConfig, saveConfig } from \"./config.js\";\nimport { readFileSafe, writeFileSafe, listFiles, getProjectTree } from \"./filesystem.js\";\nimport type {\n WsMessage,\n HandshakePayload,\n FsReadPayload,\n FsWritePayload,\n FsListPayload,\n LlmChatPayload,\n ConfigSetPayload,\n OpenMagicConfig,\n} from \"./shared-types.js\";\nimport { handleLlmChat } from \"./llm/proxy.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\ninterface ClientState {\n authenticated: boolean;\n}\n\nexport function createOpenMagicServer(\n proxyPort: number,\n roots: string[]\n): { httpServer: http.Server; wss: WebSocketServer } {\n const httpServer = http.createServer((req, res) => {\n // Serve toolbar bundle\n if (req.url === \"/__openmagic__/toolbar.js\") {\n serveToolbarBundle(res);\n return;\n }\n\n // Health check\n if (req.url === \"/__openmagic__/health\") {\n res.writeHead(200, {\n \"Content-Type\": \"application/json\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n res.end(JSON.stringify({ status: \"ok\", version: \"0.1.0\" }));\n return;\n }\n\n res.writeHead(404);\n res.end(\"Not found\");\n });\n\n const wss = new WebSocketServer({\n server: httpServer,\n path: \"/__openmagic__/ws\",\n });\n\n const clientStates = new WeakMap<WebSocket, ClientState>();\n\n wss.on(\"connection\", (ws) => {\n clientStates.set(ws, { authenticated: false });\n\n ws.on(\"message\", async (data) => {\n let msg: WsMessage;\n try {\n msg = JSON.parse(data.toString());\n } catch {\n sendError(ws, \"parse_error\", \"Invalid JSON\");\n return;\n }\n\n const state = clientStates.get(ws)!;\n\n // Require handshake first\n if (!state.authenticated && msg.type !== \"handshake\") {\n sendError(ws, \"auth_required\", \"Handshake required\");\n return;\n }\n\n try {\n await handleMessage(ws, msg, state, roots, proxyPort);\n } catch (e: unknown) {\n sendError(ws, \"internal_error\", (e as Error).message, msg.id);\n }\n });\n\n ws.on(\"close\", () => {\n clientStates.delete(ws);\n });\n });\n\n return { httpServer, wss };\n}\n\nasync function handleMessage(\n ws: WebSocket,\n msg: WsMessage,\n state: ClientState,\n roots: string[],\n _proxyPort: number\n): Promise<void> {\n switch (msg.type) {\n case \"handshake\": {\n const payload = msg.payload as HandshakePayload;\n if (!validateToken(payload.token)) {\n sendError(ws, \"auth_failed\", \"Invalid token\", msg.id);\n ws.close();\n return;\n }\n state.authenticated = true;\n const config = loadConfig();\n send(ws, {\n id: msg.id,\n type: \"handshake.ok\",\n payload: {\n version: \"0.1.0\",\n roots,\n config: {\n provider: config.provider,\n model: config.model,\n hasApiKey: !!config.apiKey,\n },\n },\n });\n break;\n }\n\n case \"fs.read\": {\n const payload = msg.payload as FsReadPayload;\n const result = readFileSafe(payload.path, roots);\n if (\"error\" in result) {\n sendError(ws, \"fs_error\", result.error, msg.id);\n } else {\n send(ws, {\n id: msg.id,\n type: \"fs.content\",\n payload: { path: payload.path, content: result.content },\n });\n }\n break;\n }\n\n case \"fs.write\": {\n const payload = msg.payload as FsWritePayload;\n const result = writeFileSafe(payload.path, payload.content, roots);\n send(ws, {\n id: msg.id,\n type: \"fs.written\",\n payload: { path: payload.path, ok: result.ok, error: result.error },\n });\n break;\n }\n\n case \"fs.list\": {\n const payload = msg.payload as FsListPayload | undefined;\n const root = payload?.root || roots[0];\n const files = listFiles(root, roots);\n send(ws, {\n id: msg.id,\n type: \"fs.tree\",\n payload: { files, projectTree: getProjectTree(roots) },\n });\n break;\n }\n\n case \"llm.chat\": {\n const payload = msg.payload as LlmChatPayload;\n const config = loadConfig();\n\n if (!config.apiKey) {\n sendError(ws, \"config_error\", \"API key not configured\", msg.id);\n return;\n }\n\n await handleLlmChat(\n {\n provider: payload.provider || config.provider || \"openai\",\n model: payload.model || config.model || \"gpt-4o\",\n apiKey: config.apiKey,\n messages: payload.messages,\n context: payload.context,\n },\n (chunk) => {\n send(ws, { id: msg.id, type: \"llm.chunk\", payload: { delta: chunk } });\n },\n (result) => {\n send(ws, { id: msg.id, type: \"llm.done\", payload: result });\n },\n (error) => {\n send(ws, { id: msg.id, type: \"llm.error\", payload: { message: error } });\n }\n );\n break;\n }\n\n case \"config.get\": {\n const config = loadConfig();\n send(ws, {\n id: msg.id,\n type: \"config.value\",\n payload: {\n provider: config.provider,\n model: config.model,\n hasApiKey: !!config.apiKey,\n roots: config.roots || roots,\n },\n });\n break;\n }\n\n case \"config.set\": {\n const payload = msg.payload as ConfigSetPayload;\n const updates: Partial<OpenMagicConfig> = {};\n if (payload.provider !== undefined) updates.provider = payload.provider;\n if (payload.model !== undefined) updates.model = payload.model;\n if (payload.apiKey !== undefined) updates.apiKey = payload.apiKey;\n if (payload.roots !== undefined) updates.roots = payload.roots;\n saveConfig(updates);\n send(ws, {\n id: msg.id,\n type: \"config.saved\",\n payload: { ok: true },\n });\n break;\n }\n\n default:\n sendError(ws, \"unknown_type\", `Unknown message type: ${msg.type}`, msg.id);\n }\n}\n\nfunction send(ws: WebSocket, msg: WsMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(msg));\n }\n}\n\nfunction sendError(\n ws: WebSocket,\n code: string,\n message: string,\n id?: string\n): void {\n send(ws, {\n id: id || \"error\",\n type: \"error\",\n payload: { code, message },\n });\n}\n\nfunction serveToolbarBundle(res: http.ServerResponse): void {\n // Try to serve the pre-built toolbar bundle\n const bundlePaths = [\n join(__dirname, \"toolbar\", \"index.global.js\"),\n join(__dirname, \"..\", \"dist\", \"toolbar\", \"index.global.js\"),\n ];\n\n for (const bundlePath of bundlePaths) {\n if (existsSync(bundlePath)) {\n const content = readFileSync(bundlePath, \"utf-8\");\n res.writeHead(200, {\n \"Content-Type\": \"application/javascript\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Cache-Control\": \"no-cache\",\n });\n res.end(content);\n return;\n }\n }\n\n // Fallback: serve a minimal placeholder that shows a \"build required\" message\n res.writeHead(200, {\n \"Content-Type\": \"application/javascript\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n res.end(`\n (function() {\n var div = document.createElement(\"div\");\n div.style.cssText = \"position:fixed;bottom:20px;right:20px;background:#1a1a2e;color:#e94560;padding:16px 24px;border-radius:12px;font-family:system-ui;font-size:14px;z-index:2147483647;box-shadow:0 4px 24px rgba(0,0,0,0.3);\";\n div.textContent = \"OpenMagic: Toolbar bundle not found. Run 'npm run build:toolbar' first.\";\n document.body.appendChild(div);\n })();\n `);\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { OpenMagicConfig } from \"./shared-types.js\";\n\nconst CONFIG_DIR = join(homedir(), \".openmagic\");\nconst CONFIG_FILE = join(CONFIG_DIR, \"config.json\");\n\nfunction ensureConfigDir(): void {\n if (!existsSync(CONFIG_DIR)) {\n mkdirSync(CONFIG_DIR, { recursive: true });\n }\n}\n\nexport function loadConfig(): Partial<OpenMagicConfig> {\n ensureConfigDir();\n if (!existsSync(CONFIG_FILE)) {\n return {};\n }\n try {\n const raw = readFileSync(CONFIG_FILE, \"utf-8\");\n return JSON.parse(raw);\n } catch {\n return {};\n }\n}\n\nexport function saveConfig(updates: Partial<OpenMagicConfig>): void {\n ensureConfigDir();\n const existing = loadConfig();\n const merged = { ...existing, ...updates };\n writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2), \"utf-8\");\n}\n\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n","import {\n readFileSync,\n writeFileSync,\n existsSync,\n statSync,\n readdirSync,\n copyFileSync,\n mkdirSync,\n} from \"node:fs\";\nimport { join, resolve, relative, dirname, extname } from \"node:path\";\nimport type { FileEntry } from \"./shared-types.js\";\n\nconst IGNORED_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \".next\",\n \".nuxt\",\n \".svelte-kit\",\n \"dist\",\n \"build\",\n \".cache\",\n \".turbo\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n \".DS_Store\",\n]);\n\nconst IGNORED_EXTENSIONS = new Set([\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".gif\",\n \".svg\",\n \".ico\",\n \".webp\",\n \".mp4\",\n \".mp3\",\n \".woff\",\n \".woff2\",\n \".ttf\",\n \".eot\",\n \".lock\",\n]);\n\nexport function isPathSafe(filePath: string, roots: string[]): boolean {\n const resolved = resolve(filePath);\n return roots.some((root) => {\n const resolvedRoot = resolve(root);\n return resolved.startsWith(resolvedRoot);\n });\n}\n\nexport function readFileSafe(\n filePath: string,\n roots: string[]\n): { content: string } | { error: string } {\n if (!isPathSafe(filePath, roots)) {\n return { error: \"Path is outside allowed roots\" };\n }\n if (!existsSync(filePath)) {\n return { error: \"File not found\" };\n }\n try {\n const content = readFileSync(filePath, \"utf-8\");\n return { content };\n } catch (e: unknown) {\n return { error: `Failed to read file: ${(e as Error).message}` };\n }\n}\n\nexport function writeFileSafe(\n filePath: string,\n content: string,\n roots: string[]\n): { ok: boolean; error?: string; backupPath?: string } {\n if (!isPathSafe(filePath, roots)) {\n return { ok: false, error: \"Path is outside allowed roots\" };\n }\n\n try {\n // Create backup\n let backupPath: string | undefined;\n if (existsSync(filePath)) {\n backupPath = filePath + \".openmagic-backup\";\n copyFileSync(filePath, backupPath);\n }\n\n // Ensure directory exists\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n writeFileSync(filePath, content, \"utf-8\");\n return { ok: true, backupPath };\n } catch (e: unknown) {\n return { ok: false, error: `Failed to write file: ${(e as Error).message}` };\n }\n}\n\nexport function listFiles(\n rootPath: string,\n roots: string[],\n maxDepth: number = 4\n): FileEntry[] {\n if (!isPathSafe(rootPath, roots)) {\n return [];\n }\n\n const entries: FileEntry[] = [];\n\n function walk(dir: string, depth: number): void {\n if (depth > maxDepth) return;\n\n let items: string[];\n try {\n items = readdirSync(dir);\n } catch {\n return;\n }\n\n for (const item of items) {\n if (IGNORED_DIRS.has(item)) continue;\n if (item.startsWith(\".\") && item !== \".env.example\") continue;\n\n const fullPath = join(dir, item);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n\n const relPath = relative(rootPath, fullPath);\n\n if (stat.isDirectory()) {\n entries.push({ path: relPath, type: \"dir\", name: item });\n walk(fullPath, depth + 1);\n } else if (stat.isFile()) {\n const ext = extname(item).toLowerCase();\n if (!IGNORED_EXTENSIONS.has(ext)) {\n entries.push({ path: relPath, type: \"file\", name: item });\n }\n }\n }\n }\n\n walk(rootPath, 0);\n return entries;\n}\n\nexport function getProjectTree(roots: string[]): string {\n const lines: string[] = [];\n for (const root of roots) {\n lines.push(`[${root}]`);\n const files = listFiles(root, roots, 3);\n for (const f of files) {\n const indent = f.path.split(\"/\").length - 1;\n const prefix = \" \".repeat(indent);\n const icon = f.type === \"dir\" ? \"/\" : \"\";\n lines.push(`${prefix}${f.name}${icon}`);\n }\n lines.push(\"\");\n }\n return lines.join(\"\\n\");\n}\n","import type { ProviderRegistry } from \"../shared-types.js\";\n\nexport const MODEL_REGISTRY: ProviderRegistry = {\n openai: {\n name: \"OpenAI\",\n models: [\n { id: \"gpt-4.1\", name: \"GPT-4.1\", vision: true, context: 1047576 },\n { id: \"gpt-4.1-mini\", name: \"GPT-4.1 Mini\", vision: true, context: 1047576 },\n { id: \"gpt-4.1-nano\", name: \"GPT-4.1 Nano\", vision: true, context: 1047576 },\n { id: \"gpt-4o\", name: \"GPT-4o\", vision: true, context: 128000 },\n { id: \"gpt-4o-mini\", name: \"GPT-4o Mini\", vision: true, context: 128000 },\n { id: \"o3\", name: \"o3 (Reasoning)\", vision: true, context: 200000 },\n { id: \"o4-mini\", name: \"o4-mini (Reasoning)\", vision: true, context: 200000 },\n ],\n apiBase: \"https://api.openai.com/v1\",\n keyPrefix: \"sk-\",\n keyPlaceholder: \"sk-...\",\n },\n anthropic: {\n name: \"Anthropic\",\n models: [\n { id: \"claude-opus-4-20250514\", name: \"Claude Opus 4\", vision: true, context: 200000 },\n { id: \"claude-sonnet-4-20250514\", name: \"Claude Sonnet 4\", vision: true, context: 200000 },\n { id: \"claude-haiku-4-20250514\", name: \"Claude Haiku 4\", vision: true, context: 200000 },\n ],\n apiBase: \"https://api.anthropic.com/v1\",\n keyPrefix: \"sk-ant-\",\n keyPlaceholder: \"sk-ant-...\",\n },\n google: {\n name: \"Google Gemini\",\n models: [\n { id: \"gemini-2.5-pro\", name: \"Gemini 2.5 Pro\", vision: true, context: 1048576 },\n { id: \"gemini-2.5-flash\", name: \"Gemini 2.5 Flash\", vision: true, context: 1048576 },\n { id: \"gemini-2.0-flash\", name: \"Gemini 2.0 Flash\", vision: true, context: 1048576 },\n ],\n apiBase: \"https://generativelanguage.googleapis.com/v1beta\",\n keyPrefix: \"AI\",\n keyPlaceholder: \"AIza...\",\n },\n deepseek: {\n name: \"DeepSeek\",\n models: [\n { id: \"deepseek-chat\", name: \"DeepSeek V3\", vision: false, context: 65536 },\n { id: \"deepseek-reasoner\", name: \"DeepSeek R1\", vision: false, context: 65536 },\n ],\n apiBase: \"https://api.deepseek.com/v1\",\n keyPrefix: \"sk-\",\n keyPlaceholder: \"sk-...\",\n },\n groq: {\n name: \"Groq\",\n models: [\n { id: \"llama-3.3-70b-versatile\", name: \"Llama 3.3 70B\", vision: false, context: 131072 },\n { id: \"llama-3.1-8b-instant\", name: \"Llama 3.1 8B\", vision: false, context: 131072 },\n { id: \"gemma2-9b-it\", name: \"Gemma 2 9B\", vision: false, context: 8192 },\n ],\n apiBase: \"https://api.groq.com/openai/v1\",\n keyPrefix: \"gsk_\",\n keyPlaceholder: \"gsk_...\",\n },\n mistral: {\n name: \"Mistral\",\n models: [\n { id: \"mistral-large-latest\", name: \"Mistral Large\", vision: false, context: 131072 },\n { id: \"mistral-small-latest\", name: \"Mistral Small\", vision: false, context: 131072 },\n { id: \"codestral-latest\", name: \"Codestral\", vision: false, context: 262144 },\n ],\n apiBase: \"https://api.mistral.ai/v1\",\n keyPrefix: \"\",\n keyPlaceholder: \"Enter API key...\",\n },\n xai: {\n name: \"xAI (Grok)\",\n models: [\n { id: \"grok-3\", name: \"Grok 3\", vision: true, context: 131072 },\n { id: \"grok-3-mini\", name: \"Grok 3 Mini\", vision: true, context: 131072 },\n ],\n apiBase: \"https://api.x.ai/v1\",\n keyPrefix: \"xai-\",\n keyPlaceholder: \"xai-...\",\n },\n ollama: {\n name: \"Ollama (Local)\",\n models: [],\n apiBase: \"http://localhost:11434/v1\",\n keyPrefix: \"\",\n keyPlaceholder: \"not required\",\n local: true,\n },\n openrouter: {\n name: \"OpenRouter\",\n models: [],\n apiBase: \"https://openrouter.ai/api/v1\",\n keyPrefix: \"sk-or-\",\n keyPlaceholder: \"sk-or-...\",\n },\n};\n","export const SYSTEM_PROMPT = `You are OpenMagic, an AI coding assistant embedded in a developer's web application. You help modify the codebase based on visual context from the running app.\n\n## Your Role\n- You can see the developer's running web application (DOM elements, screenshots, styles)\n- You propose code modifications to their source files\n- Your changes are applied directly to their codebase and reflected via hot reload\n\n## Response Format\nYou MUST respond with valid JSON in this exact format:\n\n\\`\\`\\`json\n{\n \"modifications\": [\n {\n \"file\": \"relative/path/to/file.tsx\",\n \"type\": \"edit\",\n \"search\": \"exact code to find (multi-line ok)\",\n \"replace\": \"replacement code\"\n }\n ],\n \"explanation\": \"Brief description of what was changed and why\"\n}\n\\`\\`\\`\n\n## Modification Types\n- \\`edit\\`: Replace existing code. \\`search\\` must match exactly in the file. \\`replace\\` is the new code.\n- \\`create\\`: Create a new file. Use \\`content\\` instead of search/replace.\n- \\`delete\\`: Delete a file. No search/replace/content needed.\n\n## Rules\n1. The \\`search\\` field must contain the EXACT text from the source file — copy it precisely, including whitespace and indentation\n2. Keep modifications minimal — change only what's needed\n3. If you need to read a file first, say so in the explanation and the developer can provide it\n4. For style changes, prefer modifying existing CSS/Tailwind classes over adding inline styles\n5. Always preserve the existing code style and conventions\n6. If the change involves multiple files, include all modifications in the array\n7. ALWAYS respond with the JSON format above, even for explanations (put them in the \"explanation\" field)\n8. If you cannot make the requested change, set modifications to an empty array and explain why`;\n\nexport function buildUserMessage(\n userPrompt: string,\n context: {\n selectedElement?: string;\n screenshot?: string;\n fileContent?: string;\n filePath?: string;\n networkLogs?: string;\n consoleLogs?: string;\n projectTree?: string;\n }\n): string {\n const parts: string[] = [];\n\n if (context.projectTree) {\n parts.push(`## Project Structure\\n\\`\\`\\`\\n${context.projectTree}\\n\\`\\`\\``);\n }\n\n if (context.filePath && context.fileContent) {\n parts.push(\n `## Source File: ${context.filePath}\\n\\`\\`\\`\\n${context.fileContent}\\n\\`\\`\\``\n );\n }\n\n if (context.selectedElement) {\n parts.push(`## Selected Element (DOM)\\n\\`\\`\\`html\\n${context.selectedElement}\\n\\`\\`\\``);\n }\n\n if (context.networkLogs) {\n parts.push(`## Recent Network Requests\\n\\`\\`\\`\\n${context.networkLogs}\\n\\`\\`\\``);\n }\n\n if (context.consoleLogs) {\n parts.push(`## Console Output\\n\\`\\`\\`\\n${context.consoleLogs}\\n\\`\\`\\``);\n }\n\n parts.push(`## User Request\\n${userPrompt}`);\n\n return parts.join(\"\\n\\n\");\n}\n","import type { ChatMessage, ContentPart, LlmContext } from \"../shared-types.js\";\nimport { MODEL_REGISTRY } from \"./registry.js\";\nimport { SYSTEM_PROMPT, buildUserMessage } from \"./prompts.js\";\n\ninterface OpenAICompatibleRequest {\n model: string;\n messages: Array<{\n role: string;\n content: string | Array<{ type: string; text?: string; image_url?: { url: string } }>;\n }>;\n stream: boolean;\n max_tokens?: number;\n}\n\nexport async function chatOpenAICompatible(\n provider: string,\n model: string,\n apiKey: string,\n messages: ChatMessage[],\n context: LlmContext,\n onChunk: (chunk: string) => void,\n onDone: (result: { content: string }) => void,\n onError: (error: string) => void\n): Promise<void> {\n const providerConfig = MODEL_REGISTRY[provider];\n if (!providerConfig) {\n onError(`Unknown provider: ${provider}`);\n return;\n }\n\n const apiBase = providerConfig.apiBase;\n const url = `${apiBase}/chat/completions`;\n\n // Build messages with context\n const apiMessages: OpenAICompatibleRequest[\"messages\"] = [\n { role: \"system\", content: SYSTEM_PROMPT },\n ];\n\n // Add context to the first user message\n for (const msg of messages) {\n if (msg.role === \"user\" && typeof msg.content === \"string\") {\n const contextParts: Parameters<typeof buildUserMessage>[1] = {};\n\n if (context.selectedElement) {\n contextParts.selectedElement = context.selectedElement.outerHTML;\n }\n if (context.files && context.files.length > 0) {\n contextParts.filePath = context.files[0].path;\n contextParts.fileContent = context.files[0].content;\n }\n if (context.projectTree) {\n contextParts.projectTree = context.projectTree;\n }\n if (context.networkLogs) {\n contextParts.networkLogs = context.networkLogs\n .map((l) => `${l.method} ${l.url} → ${l.status || \"pending\"}`)\n .join(\"\\n\");\n }\n if (context.consoleLogs) {\n contextParts.consoleLogs = context.consoleLogs\n .map((l) => `[${l.level}] ${l.args.join(\" \")}`)\n .join(\"\\n\");\n }\n\n const enrichedContent = buildUserMessage(msg.content, contextParts);\n\n // If we have a screenshot and the model supports vision, add it\n const modelInfo = providerConfig.models.find((m) => m.id === model);\n if (context.screenshot && modelInfo?.vision) {\n apiMessages.push({\n role: \"user\",\n content: [\n { type: \"text\", text: enrichedContent },\n {\n type: \"image_url\",\n image_url: { url: context.screenshot },\n },\n ],\n });\n } else {\n apiMessages.push({ role: \"user\", content: enrichedContent });\n }\n } else {\n apiMessages.push({\n role: msg.role,\n content: msg.content as string,\n });\n }\n }\n\n const body: OpenAICompatibleRequest = {\n model,\n messages: apiMessages,\n stream: true,\n max_tokens: 4096,\n };\n\n try {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n if (provider === \"ollama\") {\n // Ollama doesn't need auth\n } else {\n headers[\"Authorization\"] = `Bearer ${apiKey}`;\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n onError(`API error ${response.status}: ${errorText}`);\n return;\n }\n\n if (!response.body) {\n onError(\"No response body\");\n return;\n }\n\n // Stream SSE response\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let fullContent = \"\";\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const data = line.slice(6).trim();\n if (data === \"[DONE]\") continue;\n\n try {\n const parsed = JSON.parse(data);\n const delta = parsed.choices?.[0]?.delta?.content;\n if (delta) {\n fullContent += delta;\n onChunk(delta);\n }\n } catch {\n // Skip malformed chunks\n }\n }\n }\n\n onDone({ content: fullContent });\n } catch (e: unknown) {\n onError(`Request failed: ${(e as Error).message}`);\n }\n}\n","import type { ChatMessage, LlmContext } from \"../shared-types.js\";\nimport { SYSTEM_PROMPT, buildUserMessage } from \"./prompts.js\";\n\ninterface AnthropicMessage {\n role: \"user\" | \"assistant\";\n content: string | Array<{ type: string; text?: string; source?: { type: string; media_type: string; data: string } }>;\n}\n\nexport async function chatAnthropic(\n model: string,\n apiKey: string,\n messages: ChatMessage[],\n context: LlmContext,\n onChunk: (chunk: string) => void,\n onDone: (result: { content: string }) => void,\n onError: (error: string) => void\n): Promise<void> {\n const url = \"https://api.anthropic.com/v1/messages\";\n\n const apiMessages: AnthropicMessage[] = [];\n\n for (const msg of messages) {\n if (msg.role === \"system\") continue; // System prompt goes in system field\n\n if (msg.role === \"user\" && typeof msg.content === \"string\") {\n const contextParts: Parameters<typeof buildUserMessage>[1] = {};\n\n if (context.selectedElement) {\n contextParts.selectedElement = context.selectedElement.outerHTML;\n }\n if (context.files && context.files.length > 0) {\n contextParts.filePath = context.files[0].path;\n contextParts.fileContent = context.files[0].content;\n }\n if (context.projectTree) {\n contextParts.projectTree = context.projectTree;\n }\n if (context.networkLogs) {\n contextParts.networkLogs = context.networkLogs\n .map((l) => `${l.method} ${l.url} → ${l.status || \"pending\"}`)\n .join(\"\\n\");\n }\n if (context.consoleLogs) {\n contextParts.consoleLogs = context.consoleLogs\n .map((l) => `[${l.level}] ${l.args.join(\" \")}`)\n .join(\"\\n\");\n }\n\n const enrichedContent = buildUserMessage(msg.content, contextParts);\n\n // If screenshot available, use vision\n if (context.screenshot) {\n const base64Data = context.screenshot.replace(\n /^data:image\\/\\w+;base64,/,\n \"\"\n );\n apiMessages.push({\n role: \"user\",\n content: [\n { type: \"text\", text: enrichedContent },\n {\n type: \"image\",\n source: {\n type: \"base64\",\n media_type: \"image/png\",\n data: base64Data,\n },\n },\n ],\n });\n } else {\n apiMessages.push({ role: \"user\", content: enrichedContent });\n }\n } else {\n apiMessages.push({\n role: msg.role as \"user\" | \"assistant\",\n content: msg.content as string,\n });\n }\n }\n\n const body = {\n model,\n max_tokens: 4096,\n system: SYSTEM_PROMPT,\n messages: apiMessages,\n stream: true,\n };\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": \"2023-06-01\",\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n onError(`Anthropic API error ${response.status}: ${errorText}`);\n return;\n }\n\n if (!response.body) {\n onError(\"No response body\");\n return;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let fullContent = \"\";\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const data = line.slice(6).trim();\n\n try {\n const parsed = JSON.parse(data);\n if (parsed.type === \"content_block_delta\") {\n const delta = parsed.delta?.text;\n if (delta) {\n fullContent += delta;\n onChunk(delta);\n }\n }\n } catch {\n // Skip malformed chunks\n }\n }\n }\n\n onDone({ content: fullContent });\n } catch (e: unknown) {\n onError(`Request failed: ${(e as Error).message}`);\n }\n}\n","import type { ChatMessage, LlmContext } from \"../shared-types.js\";\nimport { SYSTEM_PROMPT, buildUserMessage } from \"./prompts.js\";\n\nexport async function chatGoogle(\n model: string,\n apiKey: string,\n messages: ChatMessage[],\n context: LlmContext,\n onChunk: (chunk: string) => void,\n onDone: (result: { content: string }) => void,\n onError: (error: string) => void\n): Promise<void> {\n const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent?key=${apiKey}&alt=sse`;\n\n const contents: Array<{\n role: string;\n parts: Array<{ text?: string; inline_data?: { mime_type: string; data: string } }>;\n }> = [];\n\n for (const msg of messages) {\n if (msg.role === \"system\") continue;\n\n const role = msg.role === \"assistant\" ? \"model\" : \"user\";\n\n if (msg.role === \"user\" && typeof msg.content === \"string\") {\n const contextParts: Parameters<typeof buildUserMessage>[1] = {};\n\n if (context.selectedElement) {\n contextParts.selectedElement = context.selectedElement.outerHTML;\n }\n if (context.files && context.files.length > 0) {\n contextParts.filePath = context.files[0].path;\n contextParts.fileContent = context.files[0].content;\n }\n if (context.projectTree) {\n contextParts.projectTree = context.projectTree;\n }\n\n const enrichedContent = buildUserMessage(msg.content, contextParts);\n\n const parts: Array<{ text?: string; inline_data?: { mime_type: string; data: string } }> = [\n { text: enrichedContent },\n ];\n\n if (context.screenshot) {\n const base64Data = context.screenshot.replace(\n /^data:image\\/\\w+;base64,/,\n \"\"\n );\n parts.push({\n inline_data: {\n mime_type: \"image/png\",\n data: base64Data,\n },\n });\n }\n\n contents.push({ role, parts });\n } else {\n contents.push({\n role,\n parts: [{ text: msg.content as string }],\n });\n }\n }\n\n const body = {\n system_instruction: {\n parts: [{ text: SYSTEM_PROMPT }],\n },\n contents,\n generationConfig: {\n maxOutputTokens: 4096,\n },\n };\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n onError(`Google API error ${response.status}: ${errorText}`);\n return;\n }\n\n if (!response.body) {\n onError(\"No response body\");\n return;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let fullContent = \"\";\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const data = line.slice(6).trim();\n\n try {\n const parsed = JSON.parse(data);\n const text = parsed.candidates?.[0]?.content?.parts?.[0]?.text;\n if (text) {\n fullContent += text;\n onChunk(text);\n }\n } catch {\n // Skip malformed chunks\n }\n }\n }\n\n onDone({ content: fullContent });\n } catch (e: unknown) {\n onError(`Request failed: ${(e as Error).message}`);\n }\n}\n","import type { ChatMessage, LlmContext, LlmResponse } from \"../shared-types.js\";\nimport { chatOpenAICompatible } from \"./openai.js\";\nimport { chatAnthropic } from \"./anthropic.js\";\nimport { chatGoogle } from \"./google.js\";\n\n// Providers that use OpenAI-compatible API format\nconst OPENAI_COMPATIBLE_PROVIDERS = new Set([\n \"openai\",\n \"deepseek\",\n \"groq\",\n \"mistral\",\n \"xai\",\n \"ollama\",\n \"openrouter\",\n]);\n\ninterface LlmChatParams {\n provider: string;\n model: string;\n apiKey: string;\n messages: ChatMessage[];\n context: LlmContext;\n}\n\nexport async function handleLlmChat(\n params: LlmChatParams,\n onChunk: (chunk: string) => void,\n onDone: (result: { content: string; modifications?: LlmResponse[\"modifications\"] }) => void,\n onError: (error: string) => void\n): Promise<void> {\n const { provider, model, apiKey, messages, context } = params;\n\n const wrappedOnDone = (result: { content: string }) => {\n // Try to parse modifications from the response\n let modifications: LlmResponse[\"modifications\"] | undefined;\n try {\n // Extract JSON from the response (it might be wrapped in markdown code blocks)\n const jsonMatch = result.content.match(/```json\\s*([\\s\\S]*?)```/) ||\n result.content.match(/\\{[\\s\\S]*\"modifications\"[\\s\\S]*\\}/);\n\n if (jsonMatch) {\n const jsonStr = jsonMatch[1] || jsonMatch[0];\n const parsed = JSON.parse(jsonStr) as LlmResponse;\n modifications = parsed.modifications;\n }\n } catch {\n // If parsing fails, just return the raw content\n }\n\n onDone({ content: result.content, modifications });\n };\n\n if (provider === \"anthropic\") {\n await chatAnthropic(model, apiKey, messages, context, onChunk, wrappedOnDone, onError);\n } else if (provider === \"google\") {\n await chatGoogle(model, apiKey, messages, context, onChunk, wrappedOnDone, onError);\n } else if (OPENAI_COMPATIBLE_PROVIDERS.has(provider)) {\n await chatOpenAICompatible(\n provider,\n model,\n apiKey,\n messages,\n context,\n onChunk,\n wrappedOnDone,\n onError\n );\n } else {\n onError(`Unsupported provider: ${provider}`);\n }\n}\n","import { createConnection } from \"node:net\";\n\nconst COMMON_DEV_PORTS = [\n 3000, // React (CRA), Next.js, Express\n 5173, // Vite\n 5174, // Vite (alternate)\n 4200, // Angular\n 8080, // Vue CLI, generic\n 8000, // Django, Python\n 8888, // Jupyter, generic\n 3001, // Common alternate\n 4000, // Phoenix, generic\n 1234, // Parcel\n];\n\nfunction checkPort(port: number, host: string = \"127.0.0.1\"): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = createConnection({ port, host, timeout: 500 });\n socket.on(\"connect\", () => {\n socket.destroy();\n resolve(true);\n });\n socket.on(\"error\", () => {\n socket.destroy();\n resolve(false);\n });\n socket.on(\"timeout\", () => {\n socket.destroy();\n resolve(false);\n });\n });\n}\n\nexport interface DetectedServer {\n port: number;\n host: string;\n}\n\nexport async function detectDevServer(): Promise<DetectedServer | null> {\n const checks = COMMON_DEV_PORTS.map(async (port) => {\n const isOpen = await checkPort(port);\n return isOpen ? port : null;\n });\n\n const results = await Promise.all(checks);\n const foundPort = results.find((p) => p !== null);\n\n if (foundPort) {\n return { port: foundPort, host: \"127.0.0.1\" };\n }\n\n return null;\n}\n\nexport async function isPortOpen(port: number): Promise<boolean> {\n return checkPort(port);\n}\n\nexport async function findAvailablePort(startPort: number): Promise<number> {\n let port = startPort;\n while (await isPortOpen(port)) {\n port++;\n if (port > startPort + 100) {\n throw new Error(`Could not find an available port near ${startPort}`);\n }\n }\n return port;\n}\n"],"mappings":"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","names":["resolve","http","readFileSync","existsSync","join","dirname","readFileSync","writeFileSync","existsSync","mkdirSync","join","dirname","http","join","existsSync","readFileSync","resolve","resolve"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/proxy.ts","../src/security.ts","../src/server.ts","../src/config.ts","../src/filesystem.ts","../src/llm/registry.ts","../src/llm/prompts.ts","../src/llm/openai.ts","../src/llm/anthropic.ts","../src/llm/google.ts","../src/llm/proxy.ts","../src/detect.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport open from \"open\";\nimport { resolve } from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport { createInterface } from \"node:readline\";\nimport { createProxyServer } from \"./proxy.js\";\nimport { createOpenMagicServer } from \"./server.js\";\nimport { generateSessionToken } from \"./security.js\";\nimport {\n detectDevServer,\n findAvailablePort,\n isPortOpen,\n detectDevScripts,\n getProjectName,\n} from \"./detect.js\";\nimport { loadConfig, saveConfig } from \"./config.js\";\n\nconst VERSION = \"0.3.0\";\n\nfunction ask(question: string): Promise<string> {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nfunction waitForPort(port: number, timeoutMs: number = 30000): Promise<boolean> {\n const start = Date.now();\n return new Promise((resolve) => {\n const check = async () => {\n if (await isPortOpen(port)) {\n resolve(true);\n return;\n }\n if (Date.now() - start > timeoutMs) {\n resolve(false);\n return;\n }\n setTimeout(check, 500);\n };\n check();\n });\n}\n\nconst program = new Command();\n\nprogram\n .name(\"openmagic\")\n .description(\"AI-powered coding toolbar for any web application\")\n .version(VERSION)\n .option(\"-p, --port <port>\", \"Dev server port to proxy\", \"\")\n .option(\n \"-l, --listen <port>\",\n \"Port for the OpenMagic proxy\",\n \"4567\"\n )\n .option(\n \"-r, --root <paths...>\",\n \"Project root directories (defaults to cwd)\"\n )\n .option(\"--no-open\", \"Don't auto-open browser\")\n .option(\"--host <host>\", \"Dev server host\", \"127.0.0.1\")\n .action(async (opts) => {\n console.log(\"\");\n console.log(\n chalk.bold.magenta(\" ✨ OpenMagic\") + chalk.dim(` v${VERSION}`)\n );\n console.log(\"\");\n\n let targetPort: number;\n let targetHost = opts.host;\n\n if (opts.port) {\n // User specified a port\n targetPort = parseInt(opts.port, 10);\n const isRunning = await isPortOpen(targetPort);\n if (!isRunning) {\n // Port specified but not running — offer to start it\n const started = await offerToStartDevServer(targetPort);\n if (!started) {\n process.exit(1);\n }\n }\n } else {\n // Auto-detect running dev server\n console.log(chalk.dim(\" Scanning for dev server...\"));\n const detected = await detectDevServer();\n\n if (detected) {\n targetPort = detected.port;\n targetHost = detected.host;\n } else {\n // No server running — try to detect and start from package.json\n const started = await offerToStartDevServer();\n if (!started) {\n process.exit(1);\n }\n // Re-detect after starting\n const redetected = await detectDevServer();\n if (!redetected) {\n console.log(chalk.red(\" ✗ Could not detect the dev server after starting.\"));\n console.log(chalk.dim(\" Try specifying the port: npx openmagic --port 3000\"));\n console.log(\"\");\n process.exit(1);\n }\n targetPort = redetected.port;\n targetHost = redetected.host;\n }\n }\n\n console.log(\n chalk.green(` ✓ Dev server running at ${targetHost}:${targetPort}`)\n );\n\n // Set up roots\n const roots = (opts.root || [process.cwd()]).map((r: string) =>\n resolve(r)\n );\n\n // Save roots to config\n const config = loadConfig();\n saveConfig({ ...config, roots, targetPort });\n\n // Generate session token\n const token = generateSessionToken();\n\n // Find available proxy port\n let proxyPort = parseInt(opts.listen, 10);\n if (await isPortOpen(proxyPort)) {\n proxyPort = await findAvailablePort(proxyPort);\n }\n\n // Start the OpenMagic server (serves toolbar + WebSocket)\n const { httpServer: omServer } = createOpenMagicServer(proxyPort, roots);\n omServer.listen(proxyPort + 1, \"127.0.0.1\", () => {\n // OpenMagic API/WS server running on proxyPort+1\n });\n\n // Start the proxy server\n const proxyServer = createProxyServer(\n targetHost,\n targetPort!,\n proxyPort + 1\n );\n\n proxyServer.listen(proxyPort, \"127.0.0.1\", () => {\n console.log(\"\");\n console.log(\n chalk.bold.green(` 🚀 Proxy running at → `) +\n chalk.bold.underline.cyan(`http://localhost:${proxyPort}`)\n );\n console.log(\"\");\n console.log(\n chalk.dim(\" Open the URL above in your browser to start.\")\n );\n console.log(chalk.dim(\" Press Ctrl+C to stop.\"));\n console.log(\"\");\n\n if (opts.open !== false) {\n open(`http://localhost:${proxyPort}`).catch(() => {\n // Silently fail if browser can't be opened\n });\n }\n });\n\n // Handle WebSocket upgrades for OpenMagic\n proxyServer.on(\"upgrade\", (req, socket, head) => {\n if (req.url?.startsWith(\"/__openmagic__\")) {\n omServer.emit(\"upgrade\", req, socket, head);\n }\n });\n\n // Graceful shutdown\n const shutdown = () => {\n console.log(\"\");\n console.log(chalk.dim(\" Shutting down OpenMagic...\"));\n proxyServer.close();\n omServer.close();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n });\n\n// --- Smart Dev Server Start ---\n\nasync function offerToStartDevServer(expectedPort?: number): Promise<boolean> {\n const projectName = getProjectName();\n const scripts = detectDevScripts();\n\n if (scripts.length === 0) {\n console.log(\n chalk.yellow(\" ⚠ No dev server detected and no dev scripts found in package.json\")\n );\n console.log(\"\");\n console.log(chalk.white(\" Start your dev server manually, then run:\"));\n console.log(chalk.cyan(\" npx openmagic --port <your-port>\"));\n console.log(\"\");\n return false;\n }\n\n // Pick the best script\n let chosen = scripts[0];\n if (scripts.length === 1) {\n // Only one option\n console.log(\n chalk.yellow(\" ⚠ No dev server detected.\")\n );\n console.log(\"\");\n console.log(\n chalk.white(` Found `) +\n chalk.cyan(`npm run ${chosen.name}`) +\n chalk.white(` in ${projectName}`) +\n chalk.dim(` (${chosen.framework})`)\n );\n console.log(chalk.dim(` → ${chosen.command}`));\n console.log(\"\");\n\n const answer = await ask(\n chalk.white(` Start it now? `) + chalk.dim(\"(Y/n) \")\n );\n\n if (answer.toLowerCase() === \"n\" || answer.toLowerCase() === \"no\") {\n console.log(\"\");\n console.log(chalk.dim(\" Start your dev server first, then run openmagic again.\"));\n console.log(\"\");\n return false;\n }\n } else {\n // Multiple scripts — let user pick\n console.log(\n chalk.yellow(\" ⚠ No dev server detected.\")\n );\n console.log(\"\");\n console.log(\n chalk.white(` Found ${scripts.length} dev scripts in ${projectName}:`)\n );\n console.log(\"\");\n\n scripts.forEach((s, i) => {\n console.log(\n chalk.cyan(` ${i + 1}) `) +\n chalk.white(`npm run ${s.name}`) +\n chalk.dim(` — ${s.framework} (port ${s.defaultPort})`)\n );\n console.log(chalk.dim(` ${s.command}`));\n });\n\n console.log(\"\");\n const answer = await ask(\n chalk.white(` Which one to start? `) +\n chalk.dim(`(1-${scripts.length}, or n to cancel) `)\n );\n\n if (answer.toLowerCase() === \"n\" || answer.toLowerCase() === \"no\" || answer === \"\") {\n console.log(\"\");\n console.log(chalk.dim(\" Start your dev server first, then run openmagic again.\"));\n console.log(\"\");\n return false;\n }\n\n const idx = parseInt(answer, 10) - 1;\n if (idx < 0 || idx >= scripts.length || isNaN(idx)) {\n // Default to first\n chosen = scripts[0];\n } else {\n chosen = scripts[idx];\n }\n }\n\n // Start the dev server\n const port = expectedPort || chosen.defaultPort;\n\n console.log(\"\");\n console.log(\n chalk.dim(` Starting `) +\n chalk.cyan(`npm run ${chosen.name}`) +\n chalk.dim(\"...\")\n );\n\n const child = spawn(\"npm\", [\"run\", chosen.name], {\n cwd: process.cwd(),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: false,\n shell: true,\n env: {\n ...process.env,\n PORT: String(port), // CRA, Express\n BROWSER: \"none\", // Prevent CRA from opening browser\n BROWSER_NONE: \"true\", // Some frameworks\n },\n });\n\n // Pipe child output with prefix\n child.stdout?.on(\"data\", (data: Buffer) => {\n const lines = data.toString().trim().split(\"\\n\");\n for (const line of lines) {\n if (line.trim()) {\n process.stdout.write(chalk.dim(` │ ${line}\\n`));\n }\n }\n });\n\n child.stderr?.on(\"data\", (data: Buffer) => {\n const lines = data.toString().trim().split(\"\\n\");\n for (const line of lines) {\n if (line.trim()) {\n process.stdout.write(chalk.dim(` │ ${line}\\n`));\n }\n }\n });\n\n child.on(\"error\", (err) => {\n console.log(chalk.red(` ✗ Failed to start: ${err.message}`));\n });\n\n child.on(\"exit\", (code) => {\n if (code !== null && code !== 0) {\n console.log(chalk.red(` ✗ Dev server exited with code ${code}`));\n }\n });\n\n // Clean up child on exit\n const cleanup = () => {\n try {\n child.kill(\"SIGTERM\");\n } catch {}\n };\n process.on(\"exit\", cleanup);\n process.on(\"SIGINT\", cleanup);\n process.on(\"SIGTERM\", cleanup);\n\n // Wait for the port to open\n console.log(\n chalk.dim(` Waiting for port ${port}...`)\n );\n\n const isUp = await waitForPort(port, 30000);\n\n if (!isUp) {\n console.log(\n chalk.yellow(` ⚠ Port ${port} didn't open after 30s.`)\n );\n console.log(\n chalk.dim(` The server might use a different port. Check the output above.`)\n );\n console.log(\"\");\n\n // Try to detect any port that opened\n const detected = await detectDevServer();\n if (detected) {\n console.log(\n chalk.green(` ✓ Found server on port ${detected.port} instead.`)\n );\n return true;\n }\n\n return false;\n }\n\n console.log(\"\");\n return true;\n}\n\nprogram.parse();\n","import http from \"node:http\";\nimport httpProxy from \"http-proxy\";\nimport { getSessionToken } from \"./security.js\";\n\nexport function createProxyServer(\n targetHost: string,\n targetPort: number,\n serverPort: number\n): http.Server {\n const proxy = httpProxy.createProxyServer({\n target: `http://${targetHost}:${targetPort}`,\n ws: true,\n selfHandleResponse: true,\n });\n\n const token = getSessionToken();\n\n proxy.on(\"proxyRes\", (proxyRes, req, res) => {\n const contentType = proxyRes.headers[\"content-type\"] || \"\";\n const isHtml = contentType.includes(\"text/html\");\n\n if (!isHtml) {\n // Pass through non-HTML responses unchanged\n res.writeHead(proxyRes.statusCode || 200, proxyRes.headers);\n proxyRes.pipe(res);\n return;\n }\n\n // For HTML responses, collect the body and inject the toolbar script\n const chunks: Buffer[] = [];\n proxyRes.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n proxyRes.on(\"end\", () => {\n let body = Buffer.concat(chunks).toString(\"utf-8\");\n\n // Inject toolbar script before </body> or at end\n const toolbarScript = buildInjectionScript(serverPort, token);\n if (body.includes(\"</body>\")) {\n body = body.replace(\"</body>\", `${toolbarScript}</body>`);\n } else if (body.includes(\"</html>\")) {\n body = body.replace(\"</html>\", `${toolbarScript}</html>`);\n } else {\n body += toolbarScript;\n }\n\n // Remove content-length since we modified the body\n const headers = { ...proxyRes.headers };\n delete headers[\"content-length\"];\n delete headers[\"content-encoding\"]; // Remove compression since we decoded it\n\n res.writeHead(proxyRes.statusCode || 200, headers);\n res.end(body);\n });\n });\n\n proxy.on(\"error\", (err, _req, res) => {\n console.error(\"[OpenMagic] Proxy error:\", err.message);\n if (res instanceof http.ServerResponse && !res.headersSent) {\n res.writeHead(502, { \"Content-Type\": \"text/plain\" });\n res.end(\n `OpenMagic proxy error: Could not connect to dev server at ${targetHost}:${targetPort}\\n\\nMake sure your dev server is running.`\n );\n }\n });\n\n const server = http.createServer((req, res) => {\n // Serve toolbar assets from /__openmagic__/ path\n if (req.url?.startsWith(\"/__openmagic__/\")) {\n handleToolbarAsset(req, res, serverPort);\n return;\n }\n\n // Proxy everything else to the dev server\n proxy.web(req, res);\n });\n\n // Handle WebSocket upgrades — forward to dev server (for HMR etc.)\n server.on(\"upgrade\", (req, socket, head) => {\n // Don't proxy OpenMagic WebSocket connections\n if (req.url?.startsWith(\"/__openmagic__\")) {\n return; // Let the WS server handle this\n }\n proxy.ws(req, socket, head);\n });\n\n return server;\n}\n\nfunction handleToolbarAsset(\n _req: http.IncomingMessage,\n res: http.ServerResponse,\n _serverPort: number\n): void {\n // The toolbar bundle is served inline via the injection script\n // This endpoint exists for potential future asset serving (icons, fonts, etc.)\n res.writeHead(404, { \"Content-Type\": \"text/plain\" });\n res.end(\"Not found\");\n}\n\nfunction buildInjectionScript(serverPort: number, token: string): string {\n return `\n<script data-openmagic=\"true\">\n(function() {\n if (window.__OPENMAGIC_LOADED__) return;\n window.__OPENMAGIC_LOADED__ = true;\n window.__OPENMAGIC_CONFIG__ = {\n wsPort: ${serverPort},\n token: \"${token}\"\n };\n var script = document.createElement(\"script\");\n script.src = \"http://127.0.0.1:${serverPort}/__openmagic__/toolbar.js\";\n script.dataset.openmagic = \"true\";\n document.body.appendChild(script);\n})();\n</script>`;\n}\n","import { randomBytes } from \"node:crypto\";\n\nlet sessionToken: string | null = null;\n\nexport function generateSessionToken(): string {\n sessionToken = randomBytes(32).toString(\"hex\");\n return sessionToken;\n}\n\nexport function getSessionToken(): string {\n if (!sessionToken) {\n return generateSessionToken();\n }\n return sessionToken;\n}\n\nexport function validateToken(token: string): boolean {\n return token === sessionToken;\n}\n","import http from \"node:http\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { WebSocketServer, WebSocket } from \"ws\";\nimport { validateToken } from \"./security.js\";\nimport { loadConfig, saveConfig } from \"./config.js\";\nimport { readFileSafe, writeFileSafe, listFiles, getProjectTree } from \"./filesystem.js\";\nimport type {\n WsMessage,\n HandshakePayload,\n FsReadPayload,\n FsWritePayload,\n FsListPayload,\n LlmChatPayload,\n ConfigSetPayload,\n OpenMagicConfig,\n} from \"./shared-types.js\";\nimport { handleLlmChat } from \"./llm/proxy.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\ninterface ClientState {\n authenticated: boolean;\n}\n\nexport function createOpenMagicServer(\n proxyPort: number,\n roots: string[]\n): { httpServer: http.Server; wss: WebSocketServer } {\n const httpServer = http.createServer((req, res) => {\n // Serve toolbar bundle\n if (req.url === \"/__openmagic__/toolbar.js\") {\n serveToolbarBundle(res);\n return;\n }\n\n // Health check\n if (req.url === \"/__openmagic__/health\") {\n res.writeHead(200, {\n \"Content-Type\": \"application/json\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n res.end(JSON.stringify({ status: \"ok\", version: \"0.3.0\" }));\n return;\n }\n\n res.writeHead(404);\n res.end(\"Not found\");\n });\n\n const wss = new WebSocketServer({\n server: httpServer,\n path: \"/__openmagic__/ws\",\n });\n\n const clientStates = new WeakMap<WebSocket, ClientState>();\n\n wss.on(\"connection\", (ws) => {\n clientStates.set(ws, { authenticated: false });\n\n ws.on(\"message\", async (data) => {\n let msg: WsMessage;\n try {\n msg = JSON.parse(data.toString());\n } catch {\n sendError(ws, \"parse_error\", \"Invalid JSON\");\n return;\n }\n\n const state = clientStates.get(ws)!;\n\n // Require handshake first\n if (!state.authenticated && msg.type !== \"handshake\") {\n sendError(ws, \"auth_required\", \"Handshake required\");\n return;\n }\n\n try {\n await handleMessage(ws, msg, state, roots, proxyPort);\n } catch (e: unknown) {\n sendError(ws, \"internal_error\", (e as Error).message, msg.id);\n }\n });\n\n ws.on(\"close\", () => {\n clientStates.delete(ws);\n });\n });\n\n return { httpServer, wss };\n}\n\nasync function handleMessage(\n ws: WebSocket,\n msg: WsMessage,\n state: ClientState,\n roots: string[],\n _proxyPort: number\n): Promise<void> {\n switch (msg.type) {\n case \"handshake\": {\n const payload = msg.payload as HandshakePayload;\n if (!validateToken(payload.token)) {\n sendError(ws, \"auth_failed\", \"Invalid token\", msg.id);\n ws.close();\n return;\n }\n state.authenticated = true;\n const config = loadConfig();\n send(ws, {\n id: msg.id,\n type: \"handshake.ok\",\n payload: {\n version: \"0.3.0\",\n roots,\n config: {\n provider: config.provider,\n model: config.model,\n hasApiKey: !!config.apiKey,\n },\n },\n });\n break;\n }\n\n case \"fs.read\": {\n const payload = msg.payload as FsReadPayload;\n const result = readFileSafe(payload.path, roots);\n if (\"error\" in result) {\n sendError(ws, \"fs_error\", result.error, msg.id);\n } else {\n send(ws, {\n id: msg.id,\n type: \"fs.content\",\n payload: { path: payload.path, content: result.content },\n });\n }\n break;\n }\n\n case \"fs.write\": {\n const payload = msg.payload as FsWritePayload;\n const result = writeFileSafe(payload.path, payload.content, roots);\n send(ws, {\n id: msg.id,\n type: \"fs.written\",\n payload: { path: payload.path, ok: result.ok, error: result.error },\n });\n break;\n }\n\n case \"fs.list\": {\n const payload = msg.payload as FsListPayload | undefined;\n const root = payload?.root || roots[0];\n const files = listFiles(root, roots);\n send(ws, {\n id: msg.id,\n type: \"fs.tree\",\n payload: { files, projectTree: getProjectTree(roots) },\n });\n break;\n }\n\n case \"llm.chat\": {\n const payload = msg.payload as LlmChatPayload;\n const config = loadConfig();\n\n if (!config.apiKey) {\n sendError(ws, \"config_error\", \"API key not configured\", msg.id);\n return;\n }\n\n await handleLlmChat(\n {\n provider: payload.provider || config.provider || \"openai\",\n model: payload.model || config.model || \"gpt-4o\",\n apiKey: config.apiKey,\n messages: payload.messages,\n context: payload.context,\n },\n (chunk) => {\n send(ws, { id: msg.id, type: \"llm.chunk\", payload: { delta: chunk } });\n },\n (result) => {\n send(ws, { id: msg.id, type: \"llm.done\", payload: result });\n },\n (error) => {\n send(ws, { id: msg.id, type: \"llm.error\", payload: { message: error } });\n }\n );\n break;\n }\n\n case \"config.get\": {\n const config = loadConfig();\n send(ws, {\n id: msg.id,\n type: \"config.value\",\n payload: {\n provider: config.provider,\n model: config.model,\n hasApiKey: !!config.apiKey,\n roots: config.roots || roots,\n },\n });\n break;\n }\n\n case \"config.set\": {\n const payload = msg.payload as ConfigSetPayload;\n const updates: Partial<OpenMagicConfig> = {};\n if (payload.provider !== undefined) updates.provider = payload.provider;\n if (payload.model !== undefined) updates.model = payload.model;\n if (payload.apiKey !== undefined) updates.apiKey = payload.apiKey;\n if (payload.roots !== undefined) updates.roots = payload.roots;\n saveConfig(updates);\n send(ws, {\n id: msg.id,\n type: \"config.saved\",\n payload: { ok: true },\n });\n break;\n }\n\n default:\n sendError(ws, \"unknown_type\", `Unknown message type: ${msg.type}`, msg.id);\n }\n}\n\nfunction send(ws: WebSocket, msg: WsMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(msg));\n }\n}\n\nfunction sendError(\n ws: WebSocket,\n code: string,\n message: string,\n id?: string\n): void {\n send(ws, {\n id: id || \"error\",\n type: \"error\",\n payload: { code, message },\n });\n}\n\nfunction serveToolbarBundle(res: http.ServerResponse): void {\n // Try to serve the pre-built toolbar bundle\n const bundlePaths = [\n join(__dirname, \"toolbar\", \"index.global.js\"),\n join(__dirname, \"..\", \"dist\", \"toolbar\", \"index.global.js\"),\n ];\n\n for (const bundlePath of bundlePaths) {\n if (existsSync(bundlePath)) {\n const content = readFileSync(bundlePath, \"utf-8\");\n res.writeHead(200, {\n \"Content-Type\": \"application/javascript\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Cache-Control\": \"no-cache\",\n });\n res.end(content);\n return;\n }\n }\n\n // Fallback: serve a minimal placeholder that shows a \"build required\" message\n res.writeHead(200, {\n \"Content-Type\": \"application/javascript\",\n \"Access-Control-Allow-Origin\": \"*\",\n });\n res.end(`\n (function() {\n var div = document.createElement(\"div\");\n div.style.cssText = \"position:fixed;bottom:20px;right:20px;background:#1a1a2e;color:#e94560;padding:16px 24px;border-radius:12px;font-family:system-ui;font-size:14px;z-index:2147483647;box-shadow:0 4px 24px rgba(0,0,0,0.3);\";\n div.textContent = \"OpenMagic: Toolbar bundle not found. Run 'npm run build:toolbar' first.\";\n document.body.appendChild(div);\n })();\n `);\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { OpenMagicConfig } from \"./shared-types.js\";\n\nconst CONFIG_DIR = join(homedir(), \".openmagic\");\nconst CONFIG_FILE = join(CONFIG_DIR, \"config.json\");\n\nfunction ensureConfigDir(): void {\n if (!existsSync(CONFIG_DIR)) {\n mkdirSync(CONFIG_DIR, { recursive: true });\n }\n}\n\nexport function loadConfig(): Partial<OpenMagicConfig> {\n ensureConfigDir();\n if (!existsSync(CONFIG_FILE)) {\n return {};\n }\n try {\n const raw = readFileSync(CONFIG_FILE, \"utf-8\");\n return JSON.parse(raw);\n } catch {\n return {};\n }\n}\n\nexport function saveConfig(updates: Partial<OpenMagicConfig>): void {\n ensureConfigDir();\n const existing = loadConfig();\n const merged = { ...existing, ...updates };\n writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2), \"utf-8\");\n}\n\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n","import {\n readFileSync,\n writeFileSync,\n existsSync,\n statSync,\n readdirSync,\n copyFileSync,\n mkdirSync,\n} from \"node:fs\";\nimport { join, resolve, relative, dirname, extname } from \"node:path\";\nimport type { FileEntry } from \"./shared-types.js\";\n\nconst IGNORED_DIRS = new Set([\n \"node_modules\",\n \".git\",\n \".next\",\n \".nuxt\",\n \".svelte-kit\",\n \"dist\",\n \"build\",\n \".cache\",\n \".turbo\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n \".DS_Store\",\n]);\n\nconst IGNORED_EXTENSIONS = new Set([\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".gif\",\n \".svg\",\n \".ico\",\n \".webp\",\n \".mp4\",\n \".mp3\",\n \".woff\",\n \".woff2\",\n \".ttf\",\n \".eot\",\n \".lock\",\n]);\n\nexport function isPathSafe(filePath: string, roots: string[]): boolean {\n const resolved = resolve(filePath);\n return roots.some((root) => {\n const resolvedRoot = resolve(root);\n return resolved.startsWith(resolvedRoot);\n });\n}\n\nexport function readFileSafe(\n filePath: string,\n roots: string[]\n): { content: string } | { error: string } {\n if (!isPathSafe(filePath, roots)) {\n return { error: \"Path is outside allowed roots\" };\n }\n if (!existsSync(filePath)) {\n return { error: \"File not found\" };\n }\n try {\n const content = readFileSync(filePath, \"utf-8\");\n return { content };\n } catch (e: unknown) {\n return { error: `Failed to read file: ${(e as Error).message}` };\n }\n}\n\nexport function writeFileSafe(\n filePath: string,\n content: string,\n roots: string[]\n): { ok: boolean; error?: string; backupPath?: string } {\n if (!isPathSafe(filePath, roots)) {\n return { ok: false, error: \"Path is outside allowed roots\" };\n }\n\n try {\n // Create backup\n let backupPath: string | undefined;\n if (existsSync(filePath)) {\n backupPath = filePath + \".openmagic-backup\";\n copyFileSync(filePath, backupPath);\n }\n\n // Ensure directory exists\n const dir = dirname(filePath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n writeFileSync(filePath, content, \"utf-8\");\n return { ok: true, backupPath };\n } catch (e: unknown) {\n return { ok: false, error: `Failed to write file: ${(e as Error).message}` };\n }\n}\n\nexport function listFiles(\n rootPath: string,\n roots: string[],\n maxDepth: number = 4\n): FileEntry[] {\n if (!isPathSafe(rootPath, roots)) {\n return [];\n }\n\n const entries: FileEntry[] = [];\n\n function walk(dir: string, depth: number): void {\n if (depth > maxDepth) return;\n\n let items: string[];\n try {\n items = readdirSync(dir);\n } catch {\n return;\n }\n\n for (const item of items) {\n if (IGNORED_DIRS.has(item)) continue;\n if (item.startsWith(\".\") && item !== \".env.example\") continue;\n\n const fullPath = join(dir, item);\n let stat;\n try {\n stat = statSync(fullPath);\n } catch {\n continue;\n }\n\n const relPath = relative(rootPath, fullPath);\n\n if (stat.isDirectory()) {\n entries.push({ path: relPath, type: \"dir\", name: item });\n walk(fullPath, depth + 1);\n } else if (stat.isFile()) {\n const ext = extname(item).toLowerCase();\n if (!IGNORED_EXTENSIONS.has(ext)) {\n entries.push({ path: relPath, type: \"file\", name: item });\n }\n }\n }\n }\n\n walk(rootPath, 0);\n return entries;\n}\n\nexport function getProjectTree(roots: string[]): string {\n const lines: string[] = [];\n for (const root of roots) {\n lines.push(`[${root}]`);\n const files = listFiles(root, roots, 3);\n for (const f of files) {\n const indent = f.path.split(\"/\").length - 1;\n const prefix = \" \".repeat(indent);\n const icon = f.type === \"dir\" ? \"/\" : \"\";\n lines.push(`${prefix}${f.name}${icon}`);\n }\n lines.push(\"\");\n }\n return lines.join(\"\\n\");\n}\n","import type { ProviderRegistry } from \"../shared-types.js\";\n\nexport const MODEL_REGISTRY: ProviderRegistry = {\n // ─── OpenAI ───────────────────────────────────────────────────\n openai: {\n name: \"OpenAI\",\n models: [\n // GPT-5.4 family (March 2026 — latest flagship)\n {\n id: \"gpt-5.4\",\n name: \"GPT-5.4\",\n vision: true,\n context: 1050000,\n maxOutput: 128000,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"none\", \"low\", \"medium\", \"high\", \"xhigh\"],\n defaultLevel: \"medium\",\n },\n },\n {\n id: \"gpt-5.4-pro\",\n name: \"GPT-5.4 Pro\",\n vision: true,\n context: 1050000,\n maxOutput: 128000,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"none\", \"low\", \"medium\", \"high\", \"xhigh\"],\n defaultLevel: \"high\",\n },\n },\n {\n id: \"gpt-5.4-mini\",\n name: \"GPT-5.4 Mini\",\n vision: true,\n context: 400000,\n maxOutput: 128000,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"none\", \"low\", \"medium\", \"high\"],\n defaultLevel: \"medium\",\n },\n },\n {\n id: \"gpt-5.4-nano\",\n name: \"GPT-5.4 Nano\",\n vision: true,\n context: 400000,\n maxOutput: 128000,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"none\", \"low\", \"medium\", \"high\"],\n defaultLevel: \"low\",\n },\n },\n // GPT-5.2 family (reasoning-focused)\n {\n id: \"gpt-5.2\",\n name: \"GPT-5.2 Thinking\",\n vision: true,\n context: 272000,\n maxOutput: 128000,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"none\", \"low\", \"medium\", \"high\", \"xhigh\"],\n defaultLevel: \"high\",\n },\n },\n {\n id: \"gpt-5.2-pro\",\n name: \"GPT-5.2 Pro\",\n vision: true,\n context: 272000,\n maxOutput: 128000,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"none\", \"low\", \"medium\", \"high\", \"xhigh\"],\n defaultLevel: \"high\",\n },\n },\n // o-series reasoning models\n {\n id: \"o3\",\n name: \"o3 (Reasoning)\",\n vision: true,\n context: 200000,\n maxOutput: 100000,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"low\", \"medium\", \"high\"],\n defaultLevel: \"medium\",\n },\n },\n {\n id: \"o4-mini\",\n name: \"o4-mini (Reasoning)\",\n vision: true,\n context: 200000,\n maxOutput: 100000,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"low\", \"medium\", \"high\"],\n defaultLevel: \"medium\",\n },\n },\n // GPT-4.1 family\n {\n id: \"gpt-4.1\",\n name: \"GPT-4.1\",\n vision: true,\n context: 1047576,\n maxOutput: 32768,\n },\n {\n id: \"gpt-4.1-mini\",\n name: \"GPT-4.1 Mini\",\n vision: true,\n context: 1047576,\n maxOutput: 32768,\n },\n {\n id: \"gpt-4.1-nano\",\n name: \"GPT-4.1 Nano\",\n vision: true,\n context: 1047576,\n maxOutput: 32768,\n },\n // Codex\n {\n id: \"codex-mini-latest\",\n name: \"Codex Mini\",\n vision: false,\n context: 192000,\n maxOutput: 100000,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"low\", \"medium\", \"high\"],\n defaultLevel: \"high\",\n },\n },\n ],\n apiBase: \"https://api.openai.com/v1\",\n keyPrefix: \"sk-\",\n keyPlaceholder: \"sk-...\",\n },\n\n // ─── Anthropic ────────────────────────────────────────────────\n anthropic: {\n name: \"Anthropic\",\n models: [\n // Claude 4.6 (latest — Feb 2026)\n {\n id: \"claude-opus-4-6\",\n name: \"Claude Opus 4.6\",\n vision: true,\n context: 1000000,\n maxOutput: 128000,\n thinking: {\n supported: true,\n paramName: \"budget_tokens\",\n paramType: \"budget\",\n defaultBudget: 10000,\n maxBudget: 128000,\n },\n },\n {\n id: \"claude-sonnet-4-6\",\n name: \"Claude Sonnet 4.6\",\n vision: true,\n context: 1000000,\n maxOutput: 64000,\n thinking: {\n supported: true,\n paramName: \"budget_tokens\",\n paramType: \"budget\",\n defaultBudget: 8000,\n maxBudget: 64000,\n },\n },\n // Claude 4.5\n {\n id: \"claude-haiku-4-5-20251001\",\n name: \"Claude Haiku 4.5\",\n vision: true,\n context: 200000,\n maxOutput: 64000,\n thinking: {\n supported: true,\n paramName: \"budget_tokens\",\n paramType: \"budget\",\n defaultBudget: 5000,\n maxBudget: 64000,\n },\n },\n {\n id: \"claude-sonnet-4-5-20250929\",\n name: \"Claude Sonnet 4.5\",\n vision: true,\n context: 1000000,\n maxOutput: 64000,\n thinking: {\n supported: true,\n paramName: \"budget_tokens\",\n paramType: \"budget\",\n defaultBudget: 8000,\n maxBudget: 64000,\n },\n },\n {\n id: \"claude-opus-4-5-20251101\",\n name: \"Claude Opus 4.5\",\n vision: true,\n context: 200000,\n maxOutput: 64000,\n thinking: {\n supported: true,\n paramName: \"budget_tokens\",\n paramType: \"budget\",\n defaultBudget: 10000,\n maxBudget: 64000,\n },\n },\n // Claude 4.0\n {\n id: \"claude-sonnet-4-20250514\",\n name: \"Claude Sonnet 4\",\n vision: true,\n context: 200000,\n maxOutput: 64000,\n thinking: {\n supported: true,\n paramName: \"budget_tokens\",\n paramType: \"budget\",\n defaultBudget: 8000,\n maxBudget: 64000,\n },\n },\n {\n id: \"claude-opus-4-20250514\",\n name: \"Claude Opus 4\",\n vision: true,\n context: 200000,\n maxOutput: 32000,\n thinking: {\n supported: true,\n paramName: \"budget_tokens\",\n paramType: \"budget\",\n defaultBudget: 10000,\n maxBudget: 32000,\n },\n },\n ],\n apiBase: \"https://api.anthropic.com/v1\",\n keyPrefix: \"sk-ant-\",\n keyPlaceholder: \"sk-ant-...\",\n },\n\n // ─── Google Gemini ────────────────────────────────────────────\n google: {\n name: \"Google Gemini\",\n models: [\n // Gemini 3.1 (latest — Feb-Mar 2026)\n {\n id: \"gemini-3.1-pro-preview\",\n name: \"Gemini 3.1 Pro\",\n vision: true,\n context: 1048576,\n maxOutput: 65536,\n thinking: {\n supported: true,\n paramName: \"thinking_level\",\n paramType: \"level\",\n levels: [\"none\", \"low\", \"medium\", \"high\"],\n defaultLevel: \"medium\",\n },\n },\n // Gemini 3.0\n {\n id: \"gemini-3-flash-preview\",\n name: \"Gemini 3 Flash\",\n vision: true,\n context: 1048576,\n maxOutput: 65536,\n thinking: {\n supported: true,\n paramName: \"thinking_level\",\n paramType: \"level\",\n levels: [\"none\", \"low\", \"medium\", \"high\"],\n defaultLevel: \"low\",\n },\n },\n {\n id: \"gemini-3.1-flash-lite-preview\",\n name: \"Gemini 3.1 Flash Lite\",\n vision: true,\n context: 1048576,\n maxOutput: 65536,\n },\n // Gemini 2.5\n {\n id: \"gemini-2.5-pro\",\n name: \"Gemini 2.5 Pro\",\n vision: true,\n context: 1048576,\n maxOutput: 65536,\n thinking: {\n supported: true,\n paramName: \"thinking_level\",\n paramType: \"level\",\n levels: [\"none\", \"low\", \"medium\", \"high\"],\n defaultLevel: \"medium\",\n },\n },\n {\n id: \"gemini-2.5-flash\",\n name: \"Gemini 2.5 Flash\",\n vision: true,\n context: 1048576,\n maxOutput: 65536,\n thinking: {\n supported: true,\n paramName: \"thinking_level\",\n paramType: \"level\",\n levels: [\"none\", \"low\", \"medium\", \"high\"],\n defaultLevel: \"low\",\n },\n },\n {\n id: \"gemini-2.5-flash-lite\",\n name: \"Gemini 2.5 Flash Lite\",\n vision: true,\n context: 1048576,\n maxOutput: 65536,\n },\n ],\n apiBase: \"https://generativelanguage.googleapis.com/v1beta\",\n keyPrefix: \"AI\",\n keyPlaceholder: \"AIza...\",\n },\n\n // ─── xAI (Grok) ──────────────────────────────────────────────\n xai: {\n name: \"xAI (Grok)\",\n models: [\n {\n id: \"grok-4.20-0309-reasoning\",\n name: \"Grok 4.20 Reasoning\",\n vision: true,\n context: 2000000,\n maxOutput: 128000,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"low\", \"medium\", \"high\"],\n defaultLevel: \"medium\",\n },\n },\n {\n id: \"grok-4.20-0309-non-reasoning\",\n name: \"Grok 4.20\",\n vision: true,\n context: 2000000,\n maxOutput: 128000,\n },\n {\n id: \"grok-4-1-fast-reasoning\",\n name: \"Grok 4.1 Fast Reasoning\",\n vision: true,\n context: 2000000,\n maxOutput: 128000,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"low\", \"medium\", \"high\"],\n defaultLevel: \"low\",\n },\n },\n {\n id: \"grok-4-1-fast-non-reasoning\",\n name: \"Grok 4.1 Fast\",\n vision: true,\n context: 2000000,\n maxOutput: 128000,\n },\n ],\n apiBase: \"https://api.x.ai/v1\",\n keyPrefix: \"xai-\",\n keyPlaceholder: \"xai-...\",\n },\n\n // ─── DeepSeek ─────────────────────────────────────────────────\n deepseek: {\n name: \"DeepSeek\",\n models: [\n {\n id: \"deepseek-chat\",\n name: \"DeepSeek V3.2\",\n vision: false,\n context: 128000,\n maxOutput: 8192,\n },\n {\n id: \"deepseek-reasoner\",\n name: \"DeepSeek R1\",\n vision: false,\n context: 128000,\n maxOutput: 8192,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"low\", \"medium\", \"high\"],\n defaultLevel: \"medium\",\n },\n },\n ],\n apiBase: \"https://api.deepseek.com/v1\",\n keyPrefix: \"sk-\",\n keyPlaceholder: \"sk-...\",\n },\n\n // ─── Mistral ──────────────────────────────────────────────────\n mistral: {\n name: \"Mistral\",\n models: [\n {\n id: \"mistral-large-3-25-12\",\n name: \"Mistral Large 3\",\n vision: true,\n context: 131072,\n maxOutput: 32768,\n },\n {\n id: \"mistral-small-4-0-26-03\",\n name: \"Mistral Small 4\",\n vision: true,\n context: 131072,\n maxOutput: 32768,\n },\n {\n id: \"mistral-small-3-2-25-06\",\n name: \"Mistral Small 3.2\",\n vision: true,\n context: 131072,\n maxOutput: 32768,\n },\n {\n id: \"codestral-2508\",\n name: \"Codestral\",\n vision: false,\n context: 262144,\n maxOutput: 32768,\n },\n {\n id: \"devstral-2-25-12\",\n name: \"Devstral 2\",\n vision: false,\n context: 131072,\n maxOutput: 32768,\n },\n {\n id: \"magistral-medium-1-2-25-09\",\n name: \"Magistral Medium (Reasoning)\",\n vision: false,\n context: 131072,\n maxOutput: 32768,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"low\", \"medium\", \"high\"],\n defaultLevel: \"medium\",\n },\n },\n {\n id: \"magistral-small-1-2-25-09\",\n name: \"Magistral Small (Reasoning)\",\n vision: false,\n context: 131072,\n maxOutput: 32768,\n thinking: {\n supported: true,\n paramName: \"reasoning_effort\",\n paramType: \"level\",\n levels: [\"low\", \"medium\", \"high\"],\n defaultLevel: \"medium\",\n },\n },\n ],\n apiBase: \"https://api.mistral.ai/v1\",\n keyPrefix: \"\",\n keyPlaceholder: \"Enter API key...\",\n },\n\n // ─── Groq ─────────────────────────────────────────────────────\n groq: {\n name: \"Groq\",\n models: [\n {\n id: \"meta-llama/llama-4-scout-17b-16e-instruct\",\n name: \"Llama 4 Scout 17B\",\n vision: true,\n context: 131072,\n maxOutput: 8192,\n },\n {\n id: \"llama-3.3-70b-versatile\",\n name: \"Llama 3.3 70B\",\n vision: false,\n context: 131072,\n maxOutput: 32768,\n },\n {\n id: \"llama-3.1-8b-instant\",\n name: \"Llama 3.1 8B Instant\",\n vision: false,\n context: 131072,\n maxOutput: 8192,\n },\n {\n id: \"qwen/qwen3-32b\",\n name: \"Qwen 3 32B\",\n vision: false,\n context: 131072,\n maxOutput: 8192,\n },\n ],\n apiBase: \"https://api.groq.com/openai/v1\",\n keyPrefix: \"gsk_\",\n keyPlaceholder: \"gsk_...\",\n },\n\n // ─── Ollama (Local) ───────────────────────────────────────────\n ollama: {\n name: \"Ollama (Local)\",\n models: [],\n apiBase: \"http://localhost:11434/v1\",\n keyPrefix: \"\",\n keyPlaceholder: \"not required\",\n local: true,\n },\n\n // ─── OpenRouter (200+ models) ─────────────────────────────────\n openrouter: {\n name: \"OpenRouter\",\n models: [],\n apiBase: \"https://openrouter.ai/api/v1\",\n keyPrefix: \"sk-or-\",\n keyPlaceholder: \"sk-or-...\",\n },\n};\n","export const SYSTEM_PROMPT = `You are OpenMagic, an AI coding assistant embedded in a developer's web application. You help modify the codebase based on visual context from the running app.\n\n## Your Role\n- You can see the developer's running web application (DOM elements, screenshots, styles)\n- You propose code modifications to their source files\n- Your changes are applied directly to their codebase and reflected via hot reload\n\n## Response Format\nYou MUST respond with valid JSON in this exact format:\n\n\\`\\`\\`json\n{\n \"modifications\": [\n {\n \"file\": \"relative/path/to/file.tsx\",\n \"type\": \"edit\",\n \"search\": \"exact code to find (multi-line ok)\",\n \"replace\": \"replacement code\"\n }\n ],\n \"explanation\": \"Brief description of what was changed and why\"\n}\n\\`\\`\\`\n\n## Modification Types\n- \\`edit\\`: Replace existing code. \\`search\\` must match exactly in the file. \\`replace\\` is the new code.\n- \\`create\\`: Create a new file. Use \\`content\\` instead of search/replace.\n- \\`delete\\`: Delete a file. No search/replace/content needed.\n\n## Rules\n1. The \\`search\\` field must contain the EXACT text from the source file — copy it precisely, including whitespace and indentation\n2. Keep modifications minimal — change only what's needed\n3. If you need to read a file first, say so in the explanation and the developer can provide it\n4. For style changes, prefer modifying existing CSS/Tailwind classes over adding inline styles\n5. Always preserve the existing code style and conventions\n6. If the change involves multiple files, include all modifications in the array\n7. ALWAYS respond with the JSON format above, even for explanations (put them in the \"explanation\" field)\n8. If you cannot make the requested change, set modifications to an empty array and explain why`;\n\nexport function buildUserMessage(\n userPrompt: string,\n context: {\n selectedElement?: string;\n screenshot?: string;\n fileContent?: string;\n filePath?: string;\n networkLogs?: string;\n consoleLogs?: string;\n projectTree?: string;\n }\n): string {\n const parts: string[] = [];\n\n if (context.projectTree) {\n parts.push(`## Project Structure\\n\\`\\`\\`\\n${context.projectTree}\\n\\`\\`\\``);\n }\n\n if (context.filePath && context.fileContent) {\n parts.push(\n `## Source File: ${context.filePath}\\n\\`\\`\\`\\n${context.fileContent}\\n\\`\\`\\``\n );\n }\n\n if (context.selectedElement) {\n parts.push(`## Selected Element (DOM)\\n\\`\\`\\`html\\n${context.selectedElement}\\n\\`\\`\\``);\n }\n\n if (context.networkLogs) {\n parts.push(`## Recent Network Requests\\n\\`\\`\\`\\n${context.networkLogs}\\n\\`\\`\\``);\n }\n\n if (context.consoleLogs) {\n parts.push(`## Console Output\\n\\`\\`\\`\\n${context.consoleLogs}\\n\\`\\`\\``);\n }\n\n parts.push(`## User Request\\n${userPrompt}`);\n\n return parts.join(\"\\n\\n\");\n}\n","import type { ChatMessage, ContentPart, LlmContext } from \"../shared-types.js\";\nimport { MODEL_REGISTRY } from \"./registry.js\";\nimport { SYSTEM_PROMPT, buildUserMessage } from \"./prompts.js\";\n\ninterface OpenAICompatibleRequest {\n model: string;\n messages: Array<{\n role: string;\n content: string | Array<{ type: string; text?: string; image_url?: { url: string } }>;\n }>;\n stream: boolean;\n max_tokens?: number;\n reasoning_effort?: string;\n}\n\nexport async function chatOpenAICompatible(\n provider: string,\n model: string,\n apiKey: string,\n messages: ChatMessage[],\n context: LlmContext,\n onChunk: (chunk: string) => void,\n onDone: (result: { content: string }) => void,\n onError: (error: string) => void\n): Promise<void> {\n const providerConfig = MODEL_REGISTRY[provider];\n if (!providerConfig) {\n onError(`Unknown provider: ${provider}`);\n return;\n }\n\n const apiBase = providerConfig.apiBase;\n const url = `${apiBase}/chat/completions`;\n\n // Build messages with context\n const apiMessages: OpenAICompatibleRequest[\"messages\"] = [\n { role: \"system\", content: SYSTEM_PROMPT },\n ];\n\n // Add context to the first user message\n for (const msg of messages) {\n if (msg.role === \"user\" && typeof msg.content === \"string\") {\n const contextParts: Parameters<typeof buildUserMessage>[1] = {};\n\n if (context.selectedElement) {\n contextParts.selectedElement = context.selectedElement.outerHTML;\n }\n if (context.files && context.files.length > 0) {\n contextParts.filePath = context.files[0].path;\n contextParts.fileContent = context.files[0].content;\n }\n if (context.projectTree) {\n contextParts.projectTree = context.projectTree;\n }\n if (context.networkLogs) {\n contextParts.networkLogs = context.networkLogs\n .map((l) => `${l.method} ${l.url} → ${l.status || \"pending\"}`)\n .join(\"\\n\");\n }\n if (context.consoleLogs) {\n contextParts.consoleLogs = context.consoleLogs\n .map((l) => `[${l.level}] ${l.args.join(\" \")}`)\n .join(\"\\n\");\n }\n\n const enrichedContent = buildUserMessage(msg.content, contextParts);\n\n // If we have a screenshot and the model supports vision, add it\n const modelInfo = providerConfig.models.find((m) => m.id === model);\n if (context.screenshot && modelInfo?.vision) {\n apiMessages.push({\n role: \"user\",\n content: [\n { type: \"text\", text: enrichedContent },\n {\n type: \"image_url\",\n image_url: { url: context.screenshot },\n },\n ],\n });\n } else {\n apiMessages.push({ role: \"user\", content: enrichedContent });\n }\n } else {\n apiMessages.push({\n role: msg.role,\n content: msg.content as string,\n });\n }\n }\n\n const body: OpenAICompatibleRequest = {\n model,\n messages: apiMessages,\n stream: true,\n max_tokens: 4096,\n };\n\n // Add thinking/reasoning config if the model supports it\n const modelInfo = providerConfig.models.find((m) => m.id === model);\n if (modelInfo?.thinking?.supported && modelInfo.thinking.paramType === \"level\") {\n body.reasoning_effort = modelInfo.thinking.defaultLevel || \"medium\";\n // Reasoning models typically need higher max_tokens\n body.max_tokens = Math.min(modelInfo.maxOutput, 16384);\n }\n\n try {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n if (provider === \"ollama\") {\n // Ollama doesn't need auth\n } else {\n headers[\"Authorization\"] = `Bearer ${apiKey}`;\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n onError(`API error ${response.status}: ${errorText}`);\n return;\n }\n\n if (!response.body) {\n onError(\"No response body\");\n return;\n }\n\n // Stream SSE response\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let fullContent = \"\";\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const data = line.slice(6).trim();\n if (data === \"[DONE]\") continue;\n\n try {\n const parsed = JSON.parse(data);\n const delta = parsed.choices?.[0]?.delta?.content;\n if (delta) {\n fullContent += delta;\n onChunk(delta);\n }\n } catch {\n // Skip malformed chunks\n }\n }\n }\n\n onDone({ content: fullContent });\n } catch (e: unknown) {\n onError(`Request failed: ${(e as Error).message}`);\n }\n}\n","import type { ChatMessage, LlmContext } from \"../shared-types.js\";\nimport { MODEL_REGISTRY } from \"./registry.js\";\nimport { SYSTEM_PROMPT, buildUserMessage } from \"./prompts.js\";\n\ninterface AnthropicMessage {\n role: \"user\" | \"assistant\";\n content: string | Array<{ type: string; text?: string; source?: { type: string; media_type: string; data: string } }>;\n}\n\nexport async function chatAnthropic(\n model: string,\n apiKey: string,\n messages: ChatMessage[],\n context: LlmContext,\n onChunk: (chunk: string) => void,\n onDone: (result: { content: string }) => void,\n onError: (error: string) => void\n): Promise<void> {\n const url = \"https://api.anthropic.com/v1/messages\";\n\n const apiMessages: AnthropicMessage[] = [];\n\n for (const msg of messages) {\n if (msg.role === \"system\") continue; // System prompt goes in system field\n\n if (msg.role === \"user\" && typeof msg.content === \"string\") {\n const contextParts: Parameters<typeof buildUserMessage>[1] = {};\n\n if (context.selectedElement) {\n contextParts.selectedElement = context.selectedElement.outerHTML;\n }\n if (context.files && context.files.length > 0) {\n contextParts.filePath = context.files[0].path;\n contextParts.fileContent = context.files[0].content;\n }\n if (context.projectTree) {\n contextParts.projectTree = context.projectTree;\n }\n if (context.networkLogs) {\n contextParts.networkLogs = context.networkLogs\n .map((l) => `${l.method} ${l.url} → ${l.status || \"pending\"}`)\n .join(\"\\n\");\n }\n if (context.consoleLogs) {\n contextParts.consoleLogs = context.consoleLogs\n .map((l) => `[${l.level}] ${l.args.join(\" \")}`)\n .join(\"\\n\");\n }\n\n const enrichedContent = buildUserMessage(msg.content, contextParts);\n\n // If screenshot available, use vision\n if (context.screenshot) {\n const base64Data = context.screenshot.replace(\n /^data:image\\/\\w+;base64,/,\n \"\"\n );\n apiMessages.push({\n role: \"user\",\n content: [\n { type: \"text\", text: enrichedContent },\n {\n type: \"image\",\n source: {\n type: \"base64\",\n media_type: \"image/png\",\n data: base64Data,\n },\n },\n ],\n });\n } else {\n apiMessages.push({ role: \"user\", content: enrichedContent });\n }\n } else {\n apiMessages.push({\n role: msg.role as \"user\" | \"assistant\",\n content: msg.content as string,\n });\n }\n }\n\n // Build body with optional extended thinking\n const providerConfig = MODEL_REGISTRY.anthropic;\n const modelInfo = providerConfig?.models.find((m) => m.id === model);\n const thinkingBudget = modelInfo?.thinking?.defaultBudget || 0;\n\n const body: Record<string, unknown> = {\n model,\n max_tokens: thinkingBudget > 0 ? Math.max(thinkingBudget + 4096, 16384) : 4096,\n system: SYSTEM_PROMPT,\n messages: apiMessages,\n stream: true,\n };\n\n // Add extended thinking if supported\n if (thinkingBudget > 0) {\n body.thinking = {\n type: \"enabled\",\n budget_tokens: thinkingBudget,\n };\n }\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": apiKey,\n \"anthropic-version\": \"2023-06-01\",\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n onError(`Anthropic API error ${response.status}: ${errorText}`);\n return;\n }\n\n if (!response.body) {\n onError(\"No response body\");\n return;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let fullContent = \"\";\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const data = line.slice(6).trim();\n\n try {\n const parsed = JSON.parse(data);\n if (parsed.type === \"content_block_delta\") {\n const delta = parsed.delta?.text;\n if (delta) {\n fullContent += delta;\n onChunk(delta);\n }\n }\n } catch {\n // Skip malformed chunks\n }\n }\n }\n\n onDone({ content: fullContent });\n } catch (e: unknown) {\n onError(`Request failed: ${(e as Error).message}`);\n }\n}\n","import type { ChatMessage, LlmContext } from \"../shared-types.js\";\nimport { MODEL_REGISTRY } from \"./registry.js\";\nimport { SYSTEM_PROMPT, buildUserMessage } from \"./prompts.js\";\n\nexport async function chatGoogle(\n model: string,\n apiKey: string,\n messages: ChatMessage[],\n context: LlmContext,\n onChunk: (chunk: string) => void,\n onDone: (result: { content: string }) => void,\n onError: (error: string) => void\n): Promise<void> {\n const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent?key=${apiKey}&alt=sse`;\n\n const contents: Array<{\n role: string;\n parts: Array<{ text?: string; inline_data?: { mime_type: string; data: string } }>;\n }> = [];\n\n for (const msg of messages) {\n if (msg.role === \"system\") continue;\n\n const role = msg.role === \"assistant\" ? \"model\" : \"user\";\n\n if (msg.role === \"user\" && typeof msg.content === \"string\") {\n const contextParts: Parameters<typeof buildUserMessage>[1] = {};\n\n if (context.selectedElement) {\n contextParts.selectedElement = context.selectedElement.outerHTML;\n }\n if (context.files && context.files.length > 0) {\n contextParts.filePath = context.files[0].path;\n contextParts.fileContent = context.files[0].content;\n }\n if (context.projectTree) {\n contextParts.projectTree = context.projectTree;\n }\n\n const enrichedContent = buildUserMessage(msg.content, contextParts);\n\n const parts: Array<{ text?: string; inline_data?: { mime_type: string; data: string } }> = [\n { text: enrichedContent },\n ];\n\n if (context.screenshot) {\n const base64Data = context.screenshot.replace(\n /^data:image\\/\\w+;base64,/,\n \"\"\n );\n parts.push({\n inline_data: {\n mime_type: \"image/png\",\n data: base64Data,\n },\n });\n }\n\n contents.push({ role, parts });\n } else {\n contents.push({\n role,\n parts: [{ text: msg.content as string }],\n });\n }\n }\n\n // Check for thinking support\n const providerConfig = MODEL_REGISTRY.google;\n const modelInfo = providerConfig?.models.find((m) => m.id === model);\n const thinkingLevel = modelInfo?.thinking?.defaultLevel;\n\n const generationConfig: Record<string, unknown> = {\n maxOutputTokens: 8192,\n };\n\n if (thinkingLevel && thinkingLevel !== \"none\") {\n generationConfig.thinking_level = thinkingLevel.toUpperCase();\n }\n\n const body = {\n system_instruction: {\n parts: [{ text: SYSTEM_PROMPT }],\n },\n contents,\n generationConfig,\n };\n\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n onError(`Google API error ${response.status}: ${errorText}`);\n return;\n }\n\n if (!response.body) {\n onError(\"No response body\");\n return;\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let fullContent = \"\";\n let buffer = \"\";\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n\n for (const line of lines) {\n if (!line.startsWith(\"data: \")) continue;\n const data = line.slice(6).trim();\n\n try {\n const parsed = JSON.parse(data);\n const text = parsed.candidates?.[0]?.content?.parts?.[0]?.text;\n if (text) {\n fullContent += text;\n onChunk(text);\n }\n } catch {\n // Skip malformed chunks\n }\n }\n }\n\n onDone({ content: fullContent });\n } catch (e: unknown) {\n onError(`Request failed: ${(e as Error).message}`);\n }\n}\n","import type { ChatMessage, LlmContext, LlmResponse } from \"../shared-types.js\";\nimport { chatOpenAICompatible } from \"./openai.js\";\nimport { chatAnthropic } from \"./anthropic.js\";\nimport { chatGoogle } from \"./google.js\";\n\n// Providers that use OpenAI-compatible API format\nconst OPENAI_COMPATIBLE_PROVIDERS = new Set([\n \"openai\",\n \"deepseek\",\n \"groq\",\n \"mistral\",\n \"xai\",\n \"ollama\",\n \"openrouter\",\n]);\n\ninterface LlmChatParams {\n provider: string;\n model: string;\n apiKey: string;\n messages: ChatMessage[];\n context: LlmContext;\n}\n\nexport async function handleLlmChat(\n params: LlmChatParams,\n onChunk: (chunk: string) => void,\n onDone: (result: { content: string; modifications?: LlmResponse[\"modifications\"] }) => void,\n onError: (error: string) => void\n): Promise<void> {\n const { provider, model, apiKey, messages, context } = params;\n\n const wrappedOnDone = (result: { content: string }) => {\n // Try to parse modifications from the response\n let modifications: LlmResponse[\"modifications\"] | undefined;\n try {\n // Extract JSON from the response (it might be wrapped in markdown code blocks)\n const jsonMatch = result.content.match(/```json\\s*([\\s\\S]*?)```/) ||\n result.content.match(/\\{[\\s\\S]*\"modifications\"[\\s\\S]*\\}/);\n\n if (jsonMatch) {\n const jsonStr = jsonMatch[1] || jsonMatch[0];\n const parsed = JSON.parse(jsonStr) as LlmResponse;\n modifications = parsed.modifications;\n }\n } catch {\n // If parsing fails, just return the raw content\n }\n\n onDone({ content: result.content, modifications });\n };\n\n if (provider === \"anthropic\") {\n await chatAnthropic(model, apiKey, messages, context, onChunk, wrappedOnDone, onError);\n } else if (provider === \"google\") {\n await chatGoogle(model, apiKey, messages, context, onChunk, wrappedOnDone, onError);\n } else if (OPENAI_COMPATIBLE_PROVIDERS.has(provider)) {\n await chatOpenAICompatible(\n provider,\n model,\n apiKey,\n messages,\n context,\n onChunk,\n wrappedOnDone,\n onError\n );\n } else {\n onError(`Unsupported provider: ${provider}`);\n }\n}\n","import { createConnection } from \"node:net\";\nimport { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst COMMON_DEV_PORTS = [\n 3000, // React (CRA), Next.js, Express\n 5173, // Vite\n 5174, // Vite (alternate)\n 4200, // Angular\n 8080, // Vue CLI, generic\n 8000, // Django, Python\n 8888, // Jupyter, generic\n 3001, // Common alternate\n 4000, // Phoenix, generic\n 1234, // Parcel\n 4321, // Astro\n 3333, // Remix\n 8081, // Metro (React Native)\n 9000, // generic\n];\n\nfunction checkPort(port: number, host: string = \"127.0.0.1\"): Promise<boolean> {\n return new Promise((resolve) => {\n const socket = createConnection({ port, host, timeout: 500 });\n socket.on(\"connect\", () => {\n socket.destroy();\n resolve(true);\n });\n socket.on(\"error\", () => {\n socket.destroy();\n resolve(false);\n });\n socket.on(\"timeout\", () => {\n socket.destroy();\n resolve(false);\n });\n });\n}\n\nexport interface DetectedServer {\n port: number;\n host: string;\n}\n\nexport async function detectDevServer(): Promise<DetectedServer | null> {\n const checks = COMMON_DEV_PORTS.map(async (port) => {\n const isOpen = await checkPort(port);\n return isOpen ? port : null;\n });\n\n const results = await Promise.all(checks);\n const foundPort = results.find((p) => p !== null);\n\n if (foundPort) {\n return { port: foundPort, host: \"127.0.0.1\" };\n }\n\n return null;\n}\n\nexport async function isPortOpen(port: number): Promise<boolean> {\n return checkPort(port);\n}\n\nexport async function findAvailablePort(startPort: number): Promise<number> {\n let port = startPort;\n while (await isPortOpen(port)) {\n port++;\n if (port > startPort + 100) {\n throw new Error(`Could not find an available port near ${startPort}`);\n }\n }\n return port;\n}\n\n// --- Package.json Dev Script Detection ---\n\nexport interface DevScript {\n name: string; // e.g. \"dev\", \"start\", \"serve\"\n command: string; // e.g. \"next dev\", \"vite\", \"ng serve\"\n framework: string; // e.g. \"Next.js\", \"Vite\", \"Angular\"\n defaultPort: number;\n}\n\nconst FRAMEWORK_PATTERNS: Array<{\n match: RegExp;\n framework: string;\n defaultPort: number;\n}> = [\n { match: /\\bnext\\b/, framework: \"Next.js\", defaultPort: 3000 },\n { match: /\\bvite\\b/, framework: \"Vite\", defaultPort: 5173 },\n { match: /\\bnuxt\\b/, framework: \"Nuxt\", defaultPort: 3000 },\n { match: /\\bng\\s+serve\\b/, framework: \"Angular\", defaultPort: 4200 },\n { match: /\\bvue-cli-service\\s+serve\\b/, framework: \"Vue CLI\", defaultPort: 8080 },\n { match: /\\bsvelte-kit\\b/, framework: \"SvelteKit\", defaultPort: 5173 },\n { match: /\\bastro\\b/, framework: \"Astro\", defaultPort: 4321 },\n { match: /\\bremix\\b/, framework: \"Remix\", defaultPort: 3000 },\n { match: /\\breact-scripts\\s+start\\b/, framework: \"Create React App\", defaultPort: 3000 },\n { match: /\\bparcel\\b/, framework: \"Parcel\", defaultPort: 1234 },\n { match: /\\bwebpack\\s+serve\\b|webpack-dev-server/, framework: \"Webpack\", defaultPort: 8080 },\n { match: /\\bgatsby\\b/, framework: \"Gatsby\", defaultPort: 8000 },\n { match: /\\bturborepo\\b|\\bturbo\\b.*dev/, framework: \"Turborepo\", defaultPort: 3000 },\n { match: /\\bexpo\\b/, framework: \"Expo\", defaultPort: 8081 },\n { match: /\\bnodemon\\b|\\bts-node\\b|\\bnode\\b/, framework: \"Node.js\", defaultPort: 3000 },\n { match: /\\bflask\\b/, framework: \"Flask\", defaultPort: 5000 },\n { match: /\\bdjango\\b|manage\\.py\\s+runserver/, framework: \"Django\", defaultPort: 8000 },\n { match: /\\brails\\b/, framework: \"Rails\", defaultPort: 3000 },\n { match: /\\bphp\\s+.*serve\\b|artisan\\s+serve/, framework: \"PHP/Laravel\", defaultPort: 8000 },\n];\n\nconst DEV_SCRIPT_NAMES = [\"dev\", \"start\", \"serve\", \"develop\", \"dev:start\", \"start:dev\"];\n\nexport function detectDevScripts(cwd: string = process.cwd()): DevScript[] {\n const pkgPath = join(cwd, \"package.json\");\n if (!existsSync(pkgPath)) return [];\n\n let pkg: any;\n try {\n pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n } catch {\n return [];\n }\n\n if (!pkg.scripts) return [];\n\n const scripts: DevScript[] = [];\n\n for (const name of DEV_SCRIPT_NAMES) {\n const command = pkg.scripts[name];\n if (!command) continue;\n\n // Detect framework from command\n let framework = \"Unknown\";\n let defaultPort = 3000;\n\n for (const pattern of FRAMEWORK_PATTERNS) {\n if (pattern.match.test(command)) {\n framework = pattern.framework;\n defaultPort = pattern.defaultPort;\n break;\n }\n }\n\n // Try to extract port from command (e.g., --port 4000, -p 8080)\n const portMatch = command.match(/(?:--port|-p)\\s+(\\d+)/);\n if (portMatch) {\n defaultPort = parseInt(portMatch[1], 10);\n }\n\n scripts.push({ name, command, framework, defaultPort });\n }\n\n return scripts;\n}\n\nexport function getProjectName(cwd: string = process.cwd()): string {\n const pkgPath = join(cwd, \"package.json\");\n if (!existsSync(pkgPath)) return \"this project\";\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n return pkg.name || \"this project\";\n } catch {\n return \"this project\";\n }\n}\n"],"mappings":"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","names":["resolve","http","readFileSync","existsSync","join","dirname","readFileSync","writeFileSync","existsSync","mkdirSync","join","modelInfo","dirname","http","join","existsSync","readFileSync","readFileSync","existsSync","join","resolve","resolve"]}
|