viyv-browser-mcp 0.2.0 → 0.2.1
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/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1071,7 +1071,7 @@ async function callExtensionTool(tool, input) {
|
|
|
1071
1071
|
if (tool === "switch_browser") {
|
|
1072
1072
|
return handleSwitchBrowser();
|
|
1073
1073
|
}
|
|
1074
|
-
if (!extensionSocket || extensionSocket.destroyed
|
|
1074
|
+
if (!extensionSocket || extensionSocket.destroyed) {
|
|
1075
1075
|
return {
|
|
1076
1076
|
content: [
|
|
1077
1077
|
{
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/server.ts","../../shared/src/constants.ts","../src/agent-session.ts","../src/event-bridge.ts","../src/health.ts","../src/native-host/compression.ts","../src/tools/index.ts","../src/tools/advanced/gif-creator.ts","../src/tools/advanced/resize-window.ts","../src/tools/advanced/shortcuts-execute.ts","../src/tools/advanced/shortcuts-list.ts","../src/tools/advanced/switch-browser.ts","../src/tools/advanced/update-plan.ts","../src/tools/advanced/upload-image.ts","../src/tools/core/click.ts","../src/tools/core/drag.ts","../src/tools/core/find.ts","../src/tools/core/form-input.ts","../src/tools/core/get-page-text.ts","../src/tools/core/handle-dialog.ts","../src/tools/core/hover.ts","../src/tools/core/javascript-exec.ts","../src/tools/core/key.ts","../src/tools/core/navigate.ts","../src/tools/core/read-page.ts","../src/tools/core/screenshot.ts","../src/tools/core/scroll.ts","../src/tools/core/type.ts","../src/tools/core/wait-for.ts","../src/tools/debug/read-console-messages.ts","../src/tools/debug/read-network-requests.ts","../src/tools/tabs/select-tab.ts","../src/tools/tabs/tab-close.ts","../src/tools/tabs/tabs-context.ts","../src/tools/tabs/tabs-create.ts","../src/tools/viyv/agent-tab-assign.ts","../src/tools/viyv/agent-tab-list.ts","../src/tools/viyv/artifact-from-page.ts","../src/tools/viyv/browser-event-subscribe.ts","../src/tools/viyv/browser-event-unsubscribe.ts","../src/tools/viyv/browser-health.ts","../src/tools/viyv/page-data-extract.ts","../src/native-host/bridge.ts","../src/native-host/transport.ts","../src/setup.ts"],"sourcesContent":["/**\n * @viyv/browser-mcp CLI entry point.\n *\n * Two modes:\n * viyv-browser-mcp → MCP Server mode (stdio transport + Unix socket)\n * viyv-browser-mcp --native-host → Native Messaging Host mode (Chrome bridge)\n * viyv-browser-mcp setup → Register Native Messaging Host manifest\n */\n\nimport { existsSync, readdirSync } from 'node:fs'\nimport { startMcpServer } from './server.js'\nimport { startBridge } from './native-host/bridge.js'\nimport { runSetup } from './setup.js'\n\nconst args = process.argv.slice(2)\n\nif (args.includes('setup')) {\n // Setup mode: register Native Messaging Host\n const extensionIdIdx = args.indexOf('--extension-id')\n const extensionId = extensionIdIdx >= 0 ? args[extensionIdIdx + 1] : undefined\n runSetup({ extensionId })\n} else if (args.includes('--native-host')) {\n // Native Messaging Host mode: bridge Chrome ↔ MCP Server\n // Socket may not exist yet (MCP Server starts when AI client connects).\n // Wait and retry until the socket appears.\n const SOCKET_PATH = '/tmp/viyv-browser.sock'\n const POLL_INTERVAL = 2000\n const MAX_WAIT = 120_000\n\n function waitForSocket() {\n const start = Date.now()\n\n function poll() {\n const socketPath = findSocketPath()\n if (socketPath) {\n process.stderr.write(\n `[viyv-browser:native-host] Found socket at ${socketPath}\\n`,\n )\n startBridge({\n socketPath,\n onError: (error) => {\n process.stderr.write(`[viyv-browser:native-host] Error: ${error.message}\\n`)\n },\n })\n return\n }\n\n if (Date.now() - start > MAX_WAIT) {\n process.stderr.write(\n `[viyv-browser:native-host] MCP server socket not found after ${MAX_WAIT / 1000}s. Exiting.\\n`,\n )\n process.exit(1)\n }\n\n process.stderr.write(\n `[viyv-browser:native-host] Waiting for MCP server socket (${SOCKET_PATH})...\\n`,\n )\n setTimeout(poll, POLL_INTERVAL)\n }\n\n poll()\n }\n\n waitForSocket()\n} else {\n // MCP Server mode (default) — fixed path so bridge can always find it on reconnect\n const socketPath = '/tmp/viyv-browser.sock'\n const agentNameIdx = args.indexOf('--agent-name')\n const agentName = agentNameIdx >= 0 ? args[agentNameIdx + 1] : undefined\n\n const transportIdx = args.indexOf('--transport')\n const transportMode = transportIdx >= 0 ? args[transportIdx + 1] : 'stdio'\n if (transportMode !== 'stdio' && transportMode !== 'sse') {\n process.stderr.write(\n `[viyv-browser:mcp] Invalid transport: \"${transportMode}\". Must be \"stdio\" or \"sse\".\\n`,\n )\n process.exit(1)\n }\n const portIdx = args.indexOf('--port')\n const port = portIdx >= 0 ? Number(args[portIdx + 1]) : undefined\n\n startMcpServer(socketPath, agentName, { transport: transportMode, port })\n}\n\nfunction findSocketPath(): string | null {\n const envSocket = process.env.VIYV_BROWSER_SOCKET\n if (envSocket) return envSocket\n\n // Check fixed socket path first\n const fixedPath = '/tmp/viyv-browser.sock'\n if (existsSync(fixedPath)) return fixedPath\n\n // Fallback: scan for legacy PID-based sockets\n try {\n const tmpFiles = readdirSync('/tmp')\n const socketFile = tmpFiles.find((f) => f.startsWith('viyv-browser-') && f.endsWith('.sock'))\n if (socketFile) return `/tmp/${socketFile}`\n } catch {\n // Ignore\n }\n\n return null\n}\n","/**\n * MCP Server for viyv-browser.\n * Communicates with viyv Daemon via stdio (JSON-RPC) or SSE (HTTP),\n * and with Chrome Extension via Unix socket <-> Native Messaging bridge.\n */\n\nimport { randomUUID } from 'node:crypto'\nimport { existsSync, unlinkSync } from 'node:fs'\nimport http from 'node:http'\nimport { type Server as NetServer, type Socket, createServer } from 'node:net'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { type BrowserEventType, MCP_SERVER, PROTOCOL_VERSION, TIMEOUTS } from '@viyv-browser/shared'\nimport {\n closeSession,\n createSession,\n getDefaultAgentId,\n setDefaultAgentId,\n touchSession,\n} from './agent-session.js'\nimport {\n addEventListener,\n addSubscription,\n processEvent,\n removeEventListener,\n removeSubscription,\n removeSubscriptionsByAgent,\n} from './event-bridge.js'\nimport { isExtensionConnected, recordHeartbeat, setExtensionConnected } from './health.js'\nimport { decompressPayload } from './native-host/compression.js'\nimport { allTools } from './tools/index.js'\n\ninterface PendingRequest {\n resolve: (result: Record<string, unknown>) => void\n reject: (error: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\nconst pendingRequests = new Map<string, PendingRequest>()\nlet extensionSocket: Socket | null = null\n\nexport interface McpServerOptions {\n transport?: 'stdio' | 'sse'\n port?: number\n}\n\n/**\n * Creates a fully configured McpServer with all tools registered and event forwarding.\n * Each SSE session needs its own McpServer instance (McpServer.connect() can only be called once).\n */\nfunction createConfiguredMcpServer(): McpServer {\n const server = new McpServer({\n name: MCP_SERVER.NAME,\n version: MCP_SERVER.VERSION,\n })\n\n // Register all tools -- pass Zod shape directly (FIX #1: MCP SDK expects Zod, not JSON Schema)\n for (const tool of allTools) {\n const shape = tool.inputSchema._def.shape?.() ?? {}\n server.tool(tool.name, tool.description, shape, async (params) => {\n const result = await callExtensionTool(tool.name, params as Record<string, unknown>)\n\n // BUG-4 FIX: Sync event subscriptions with MCP server's event-bridge\n if (tool.name === 'browser_event_subscribe' && result.content[0]) {\n try {\n const parsed = JSON.parse(result.content[0].text)\n if (parsed.subscriptionId) {\n const p = params as Record<string, unknown>\n addSubscription({\n id: parsed.subscriptionId,\n agentId: getDefaultAgentId(),\n eventTypes: (p.eventTypes as BrowserEventType[]) ?? [],\n urlPattern: p.urlPattern as string | undefined,\n createdAt: Date.now(),\n })\n }\n } catch {\n /* ignore parse errors */\n }\n } else if (tool.name === 'browser_event_unsubscribe' && result.content[0]) {\n try {\n const parsed = JSON.parse(result.content[0].text)\n if (parsed.subscriptionId) {\n removeSubscription(parsed.subscriptionId)\n }\n } catch {\n /* ignore parse errors */\n }\n }\n\n return result\n })\n }\n\n // Forward browser events through MCP logging notification\n const listener = (event: Record<string, unknown>) => {\n server\n .sendLoggingMessage({\n level: 'info',\n data: event,\n })\n .catch(() => {\n // Ignore send errors for events (client may not be listening)\n })\n }\n addEventListener(listener)\n\n // Clean up listener when transport closes\n server.server.onclose = () => {\n removeEventListener(listener)\n }\n\n return server\n}\n\nexport async function startMcpServer(\n socketPath: string,\n agentName?: string,\n options?: McpServerOptions,\n): Promise<void> {\n if (agentName) {\n setDefaultAgentId(agentName)\n }\n\n // -- Unix Socket Server (for Native Host connections) -- shared by both transports\n const socketServer = createSocketServer(socketPath)\n\n if (options?.transport === 'sse') {\n // -- SSE mode: HTTP server, one McpServer per SSE session --\n const sessions = new Map<string, { transport: SSEServerTransport; server: McpServer }>()\n\n const httpServer = http.createServer()\n\n httpServer.on('request', (req, res) => {\n handleSseRequest(req, res, sessions).catch((error) => {\n process.stderr.write(`[viyv-browser:mcp] SSE request error: ${(error as Error).message}\\n`)\n if (!res.headersSent) {\n res.writeHead(500).end('Internal server error')\n }\n })\n })\n\n const listenPort = options.port ?? 0\n httpServer.listen(listenPort, '127.0.0.1', () => {\n const addr = httpServer.address()\n const port = typeof addr === 'object' ? addr?.port : listenPort\n process.stdout.write(`${JSON.stringify({ port })}\\n`)\n process.stderr.write(`[viyv-browser:mcp] SSE server listening on 127.0.0.1:${port}\\n`)\n })\n\n process.stderr.write(`[viyv-browser:mcp] MCP Server started (SSE), socket: ${socketPath}\\n`)\n\n // Graceful shutdown: close SSE sessions async, then sync cleanup\n let shuttingDown = false\n const shutdown = async () => {\n if (shuttingDown) return\n shuttingDown = true\n for (const { server: s } of sessions.values()) {\n await s.close().catch(() => {})\n }\n httpServer.close(() => {})\n socketServer.close(() => {})\n cleanupSocket(socketPath)\n process.exit(0)\n }\n process.on('SIGINT', () => {\n shutdown()\n })\n process.on('SIGTERM', () => {\n shutdown()\n })\n\n // Sync fallback for unexpected exit (e.g. uncaughtException)\n // shutdown() already handled close — only clean up socket file here\n process.on('exit', () => {\n cleanupSocket(socketPath)\n })\n } else {\n // -- stdio mode (default) --\n const server = createConfiguredMcpServer()\n const transport = new StdioServerTransport()\n await server.connect(transport)\n\n process.stderr.write(`[viyv-browser:mcp] MCP Server started (stdio), socket: ${socketPath}\\n`)\n\n process.on('SIGINT', () => process.exit(0))\n process.on('SIGTERM', () => process.exit(0))\n\n process.on('exit', () => {\n socketServer.close()\n cleanupSocket(socketPath)\n })\n }\n}\n\nasync function handleSseRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n sessions: Map<string, { transport: SSEServerTransport; server: McpServer }>,\n): Promise<void> {\n if (req.method === 'GET' && req.url === '/sse') {\n // New SSE session\n const transport = new SSEServerTransport('/message', res)\n const mcpServer = createConfiguredMcpServer()\n\n transport.onclose = () => {\n sessions.delete(transport.sessionId)\n }\n\n // Fallback: clean up session if HTTP connection closes without transport.onclose\n res.on('close', () => {\n if (sessions.has(transport.sessionId)) {\n sessions.delete(transport.sessionId)\n transport.close()\n }\n })\n\n await mcpServer.connect(transport)\n\n // Register session only after connect succeeds\n sessions.set(transport.sessionId, { transport, server: mcpServer })\n } else if (req.method === 'POST' && req.url?.startsWith('/message')) {\n // Route POST to the correct session\n const url = new URL(req.url, `http://${req.headers.host ?? 'localhost'}`)\n const sessionId = url.searchParams.get('sessionId')\n const session = sessionId ? sessions.get(sessionId) : null\n\n if (session) {\n await session.transport.handlePostMessage(req, res)\n } else {\n res.writeHead(404).end('Session not found')\n }\n } else {\n res.writeHead(404).end()\n }\n}\n\nfunction createSocketServer(socketPath: string): NetServer {\n cleanupSocket(socketPath)\n\n const server = createServer((socket) => {\n // FIX #6: Clean up old connection before accepting new one\n if (extensionSocket && !extensionSocket.destroyed) {\n process.stderr.write('[viyv-browser:mcp] Replacing existing extension connection\\n')\n extensionSocket.destroy()\n }\n\n process.stderr.write('[viyv-browser:mcp] Extension connected via Unix socket\\n')\n extensionSocket = socket\n setExtensionConnected(true)\n\n // NM3: Send session_init with protocol version on connection\n const agentId = getDefaultAgentId()\n createSession(agentId)\n const initMsg = {\n id: randomUUID(),\n type: 'session_init',\n agentId,\n protocolVersion: PROTOCOL_VERSION,\n timestamp: Date.now(),\n }\n socket.write(`${JSON.stringify(initMsg)}\\n`)\n\n // TCP stream fragmentation fix: line-based buffer\n let lineBuffer = ''\n\n socket.on('data', (data) => {\n lineBuffer += data.toString('utf-8')\n const lines = lineBuffer.split('\\n')\n lineBuffer = lines.pop() ?? '' // Keep incomplete last line\n for (const line of lines) {\n if (!line) continue\n try {\n let parsed = JSON.parse(line)\n // NM5: Handle compressed messages from Native Host\n if (parsed.type === 'compressed' && typeof parsed.data === 'string') {\n const decompressed = decompressPayload(parsed.data, true)\n parsed = JSON.parse(decompressed)\n }\n handleExtensionMessage(parsed)\n } catch (error) {\n process.stderr.write(`[viyv-browser:mcp] Parse error: ${(error as Error).message}\\n`)\n }\n }\n })\n\n socket.on('close', () => {\n process.stderr.write('[viyv-browser:mcp] Extension disconnected\\n')\n // Only clear if this is still the active socket\n if (extensionSocket === socket) {\n extensionSocket = null\n setExtensionConnected(false)\n }\n\n // Reject all pending requests on disconnect\n for (const [id, pending] of pendingRequests) {\n clearTimeout(pending.timer)\n pendingRequests.delete(id)\n pending.resolve({\n error: {\n code: 'EXTENSION_NOT_CONNECTED',\n message: 'Extension disconnected while request was pending',\n },\n })\n }\n })\n\n socket.on('error', (error) => {\n process.stderr.write(`[viyv-browser:mcp] Socket error: ${error.message}\\n`)\n })\n })\n\n server.listen(socketPath, () => {\n process.stderr.write(`[viyv-browser:mcp] Unix socket listening on ${socketPath}\\n`)\n })\n\n return server\n}\n\n// FIX #8: Validate message structure before processing\nfunction handleExtensionMessage(message: unknown) {\n if (!message || typeof message !== 'object') return\n const msg = message as Record<string, unknown>\n\n const type = typeof msg.type === 'string' ? msg.type : null\n const id = typeof msg.id === 'string' ? msg.id : null\n if (!type) return\n\n if (type === 'tool_result' && id) {\n const pending = pendingRequests.get(id)\n if (pending) {\n clearTimeout(pending.timer)\n pendingRequests.delete(id)\n\n if (msg.success) {\n pending.resolve((msg.result as Record<string, unknown>) ?? {})\n } else {\n const err = msg.error as Record<string, unknown> | undefined\n const code = typeof err?.code === 'string' ? err.code : 'UNKNOWN'\n const errMsg = typeof err?.message === 'string' ? err.message : 'Unknown error'\n pending.reject(new Error(`[${code}] ${errMsg}`))\n }\n }\n } else if (type === 'session_heartbeat') {\n recordHeartbeat()\n // NM6: Touch session on heartbeat\n const hbAgentId = typeof msg.agentId === 'string' ? msg.agentId : null\n if (hbAgentId) touchSession(hbAgentId)\n } else if (type === 'session_close') {\n // NH2: Clean up session resources on close\n const closeAgentId = typeof msg.agentId === 'string' ? msg.agentId : null\n if (closeAgentId) {\n closeSession(closeAgentId)\n // L2 FIX: Clean up stale event subscriptions for this agent\n removeSubscriptionsByAgent(closeAgentId)\n process.stderr.write(`[viyv-browser:mcp] Session closed and cleaned up: ${closeAgentId}\\n`)\n }\n } else if (type === 'session_recovery') {\n // NH2: Handle session recovery after SW restart\n const recoveryAgentId = typeof msg.agentId === 'string' ? msg.agentId : null\n if (recoveryAgentId) {\n createSession(recoveryAgentId)\n process.stderr.write(`[viyv-browser:mcp] Session recovered: ${recoveryAgentId}\\n`)\n }\n } else if (type === 'session_init') {\n // L3 FIX: Verify Extension's protocol version (bidirectional check)\n const remoteVersion = typeof msg.protocolVersion === 'string' ? msg.protocolVersion : null\n if (remoteVersion && remoteVersion !== PROTOCOL_VERSION) {\n process.stderr.write(\n `[viyv-browser:mcp] Protocol version mismatch: local=${PROTOCOL_VERSION}, remote=${remoteVersion}\\n`,\n )\n }\n } else if (type === 'browser_event') {\n process.stderr.write(`[viyv-browser:mcp] Browser event: ${String(msg.eventType)}\\n`)\n processEvent({\n eventType: msg.eventType as import('@viyv-browser/shared').BrowserEventType,\n agentId: String(msg.agentId ?? ''),\n tabId: Number(msg.tabId ?? 0),\n url: String(msg.url ?? ''),\n payload: (msg.payload as Record<string, unknown>) ?? {},\n sequenceNumber: Number(msg.sequenceNumber ?? 0),\n })\n }\n}\n\nasync function callExtensionTool(\n tool: string,\n input: Record<string, unknown>,\n): Promise<{ content: Array<{ type: string; text: string }> }> {\n // switch_browser is handled server-side: disconnect and wait for reconnection\n if (tool === 'switch_browser') {\n return handleSwitchBrowser()\n }\n\n if (!extensionSocket || extensionSocket.destroyed || !isExtensionConnected()) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: {\n code: 'EXTENSION_NOT_CONNECTED',\n message:\n 'Chrome Extension is not connected. Please open Chrome and click the Viyv Browser extension icon.',\n },\n }),\n },\n ],\n }\n }\n\n const requestId = randomUUID()\n const agentId = getDefaultAgentId()\n\n // NM6: Touch session to record activity\n touchSession(agentId)\n\n // Capture socket reference before entering Promise to avoid null race\n const sock = extensionSocket\n\n // Per-tool timeout: wait_for gets the tool's timeout + 5s buffer\n let toolTimeout = TIMEOUTS.MCP_TOOL\n if (tool === 'wait_for' && typeof input.timeout === 'number') {\n toolTimeout = input.timeout + 5000\n }\n\n return new Promise((resolve) => {\n // M3 FIX: Define error listener before timer so removeErrorListener is callable from timeout\n const onError = () => {\n const pending = pendingRequests.get(requestId)\n if (pending) {\n clearTimeout(pending.timer)\n pendingRequests.delete(requestId)\n resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: {\n code: 'EXTENSION_NOT_CONNECTED',\n message: 'Socket write failed',\n },\n }),\n },\n ],\n })\n }\n }\n\n const removeErrorListener = () => {\n sock.removeListener('error', onError)\n }\n\n const timer = setTimeout(() => {\n pendingRequests.delete(requestId)\n removeErrorListener()\n resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: {\n code: 'TIMEOUT',\n message: `Tool '${tool}' timed out after ${toolTimeout}ms`,\n },\n }),\n },\n ],\n })\n }, toolTimeout)\n\n pendingRequests.set(requestId, {\n resolve: (result) => {\n removeErrorListener()\n resolve({\n content: [{ type: 'text', text: JSON.stringify(result) }],\n })\n },\n reject: (error) => {\n removeErrorListener()\n resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: { code: 'CDP_ERROR', message: error.message },\n }),\n },\n ],\n })\n },\n timer,\n })\n\n // FIX #7: Handle socket write errors\n const request = {\n id: requestId,\n type: 'tool_call',\n agentId,\n tool,\n input,\n timestamp: Date.now(),\n }\n\n const written = sock.write(`${JSON.stringify(request)}\\n`)\n if (!written) {\n // Backpressure -- wait for drain but don't block\n sock.once('drain', () => {\n // Buffer flushed, nothing to do\n })\n }\n\n sock.once('error', onError)\n })\n}\n\nasync function handleSwitchBrowser(): Promise<{\n content: Array<{ type: string; text: string }>\n}> {\n const SWITCH_TIMEOUT = 60_000\n\n // Close existing connection gracefully\n if (extensionSocket && !extensionSocket.destroyed) {\n process.stderr.write('[viyv-browser:mcp] switch_browser: closing current connection\\n')\n extensionSocket.destroy()\n extensionSocket = null\n setExtensionConnected(false)\n }\n\n // Wait for a new connection\n process.stderr.write('[viyv-browser:mcp] switch_browser: waiting for new browser connection...\\n')\n return new Promise((resolve) => {\n const checkInterval = setInterval(() => {\n if (extensionSocket && !extensionSocket.destroyed && isExtensionConnected()) {\n clearInterval(checkInterval)\n clearTimeout(timer)\n resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n switched: true,\n message: 'Successfully connected to new browser instance.',\n }),\n },\n ],\n })\n }\n }, 500)\n\n const timer = setTimeout(() => {\n clearInterval(checkInterval)\n resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: {\n code: 'TIMEOUT',\n message: `No new browser connected within ${SWITCH_TIMEOUT / 1000}s. Please open Chrome and click the Viyv Browser extension icon.`,\n },\n }),\n },\n ],\n })\n }, SWITCH_TIMEOUT)\n })\n}\n\nfunction cleanupSocket(socketPath: string) {\n if (existsSync(socketPath)) {\n try {\n unlinkSync(socketPath)\n } catch {\n // Ignore -- may be cleaned up by another process\n }\n }\n}\n","/** Protocol version for compatibility checks */\nexport const PROTOCOL_VERSION = '1.0.0'\n\n/** Native Messaging host name (must match manifest) */\nexport const NATIVE_HOST_NAME = 'com.viyv.browser'\n\n/** Extension ID (will be assigned by CWS) */\nexport const EXTENSION_ID = '' // Set after CWS registration\n\n// ── Timeouts (ms) ──\n\nexport const TIMEOUTS = {\n /** Overall MCP tool timeout */\n MCP_TOOL: 30_000,\n /** Native Messaging request timeout */\n NATIVE_MESSAGE: 15_000,\n /** CDP command timeout */\n CDP_COMMAND: 10_000,\n /** Screenshot capture timeout */\n SCREENSHOT: 5_000,\n /** Navigation timeout */\n NAVIGATION: 30_000,\n /** Chunk reassembly timeout */\n CHUNK_REASSEMBLY: 10_000,\n /** Default wait_for timeout */\n WAIT_FOR: 30_000,\n /** Heartbeat interval */\n HEARTBEAT: 30_000,\n /** CDP idle detach delay */\n CDP_IDLE_DETACH: 5_000,\n /** Tab lock TTL (deadlock prevention) */\n TAB_LOCK_TTL: 60_000,\n} as const\n\n// ── Limits ──\n\nexport const LIMITS = {\n /** Native Messaging max message size (Chrome limit) */\n NATIVE_MESSAGE_MAX_BYTES: 1024 * 1024,\n /** Chunk size for large payloads */\n CHUNK_SIZE: 768 * 1024,\n /** A11y tree max elements */\n A11Y_MAX_ELEMENTS: 5000,\n /** A11y tree default depth */\n A11Y_DEFAULT_DEPTH: 8,\n /** A11y tree default max chars */\n A11Y_DEFAULT_MAX_CHARS: 50_000,\n /** Event buffer max entries */\n EVENT_BUFFER_MAX: 1000,\n /** Event buffer max bytes */\n EVENT_BUFFER_MAX_BYTES: 10 * 1024 * 1024,\n /** Message buffer during disconnection */\n MESSAGE_BUFFER_MAX: 1000,\n /** Default screenshot JPEG quality */\n SCREENSHOT_JPEG_QUALITY: 80,\n /** Console buffer per tab */\n CONSOLE_BUFFER_MAX: 1000,\n /** Network buffer per tab */\n NETWORK_BUFFER_MAX: 1000,\n} as const\n\n// ── Reconnection ──\n\nexport const RECONNECT = {\n /** Initial delay (ms) */\n INITIAL_DELAY: 1000,\n /** Max delay (ms) */\n MAX_DELAY: 30_000,\n /** Backoff multiplier */\n MULTIPLIER: 2,\n} as const\n\n// ── Keep-alive ──\n\nexport const KEEP_ALIVE = {\n /** Alarm name for backup keep-alive */\n ALARM_NAME: 'viyv-browser-keepalive',\n /** Alarm period (minutes) - minimum for Chrome alarms */\n ALARM_PERIOD_MIN: 0.5,\n} as const\n\n// ── MCP Server ──\n\nexport const MCP_SERVER = {\n /** Server name for MCP protocol */\n NAME: 'viyv-browser',\n /** Server version */\n VERSION: '0.1.0',\n /** Unix socket path template */\n SOCKET_PATH_TEMPLATE: '/tmp/viyv-browser-{pid}.sock',\n} as const\n","/**\n * Multi-agent session management.\n * Tracks which agents are connected and their session tokens.\n */\n\nimport { randomUUID } from 'node:crypto'\n\ninterface AgentSessionInfo {\n agentId: string\n sessionToken: string\n agentName: string\n status: 'active' | 'idle' | 'disconnected'\n lastActivity: number\n createdAt: number\n}\n\nconst sessions = new Map<string, AgentSessionInfo>()\nlet configuredDefaultAgentId = 'default'\n\nexport function setDefaultAgentId(id: string): void {\n configuredDefaultAgentId = id\n}\n\nexport function createSession(agentId: string, agentName?: string): AgentSessionInfo {\n const existing = sessions.get(agentId)\n if (existing) {\n existing.lastActivity = Date.now()\n existing.status = 'active'\n return existing\n }\n\n const session: AgentSessionInfo = {\n agentId,\n sessionToken: randomUUID(),\n agentName: agentName ?? agentId,\n status: 'active',\n lastActivity: Date.now(),\n createdAt: Date.now(),\n }\n\n sessions.set(agentId, session)\n return session\n}\n\nexport function getSession(agentId: string): AgentSessionInfo | undefined {\n return sessions.get(agentId)\n}\n\nexport function validateSession(agentId: string, sessionToken: string): boolean {\n const session = sessions.get(agentId)\n return session?.sessionToken === sessionToken\n}\n\nexport function touchSession(agentId: string): void {\n const session = sessions.get(agentId)\n if (session) {\n session.lastActivity = Date.now()\n }\n}\n\nexport function closeSession(agentId: string): void {\n sessions.delete(agentId)\n}\n\nexport function listSessions(): AgentSessionInfo[] {\n return Array.from(sessions.values())\n}\n\nexport function getDefaultAgentId(): string {\n // Return the first active session, or create a default\n const active = Array.from(sessions.values()).find((s) => s.status === 'active')\n if (active) return active.agentId\n\n const defaultSession = createSession(configuredDefaultAgentId)\n return defaultSession.agentId\n}\n\nconst STALE_SESSION_TTL = 5 * 60 * 1000 // 5 minutes\nconst CLEANUP_INTERVAL = 60 * 1000 // Check every minute\n\nexport function cleanupStaleSessions(): number {\n const now = Date.now()\n let cleaned = 0\n for (const [agentId, session] of sessions) {\n if (now - session.lastActivity > STALE_SESSION_TTL) {\n sessions.delete(agentId)\n cleaned++\n }\n }\n if (cleaned > 0) {\n process.stderr.write(\n `[viyv-browser:mcp] Cleaned up ${cleaned} stale session(s)\\n`,\n )\n }\n return cleaned\n}\n\n// Periodic stale session cleanup\nconst cleanupTimer = setInterval(cleanupStaleSessions, CLEANUP_INTERVAL)\ncleanupTimer.unref() // Don't prevent process from exiting\n","/**\n * Event bridge: forwards browser events from Extension to stdout\n * for consumption by viyv Daemon EventTriggerManager.\n */\n\nimport type { BrowserEventType, EventSubscription } from '@viyv-browser/shared'\n\nconst subscriptions = new Map<string, EventSubscription>()\nconst eventListeners = new Set<(event: Record<string, unknown>) => void>()\n\nexport function addEventListener(cb: (event: Record<string, unknown>) => void) {\n eventListeners.add(cb)\n}\n\nexport function removeEventListener(cb: (event: Record<string, unknown>) => void) {\n eventListeners.delete(cb)\n}\n\nexport function addSubscription(sub: EventSubscription): void {\n subscriptions.set(sub.id, sub)\n}\n\nexport function removeSubscription(subId: string): boolean {\n return subscriptions.delete(subId)\n}\n\n// L2 FIX: Remove all subscriptions for an agent on session close\nexport function removeSubscriptionsByAgent(agentId: string): number {\n let removed = 0\n for (const [id, sub] of subscriptions) {\n if (sub.agentId === agentId) {\n subscriptions.delete(id)\n removed++\n }\n }\n return removed\n}\n\nexport function getSubscriptions(agentId?: string): EventSubscription[] {\n const subs = Array.from(subscriptions.values())\n if (agentId) return subs.filter((s) => s.agentId === agentId)\n return subs\n}\n\nexport function processEvent(event: {\n eventType: BrowserEventType\n agentId: string\n tabId: number\n url: string\n payload: Record<string, unknown>\n sequenceNumber: number\n}): void {\n // Check subscriptions\n for (const sub of subscriptions.values()) {\n if (sub.agentId !== event.agentId) continue\n if (!sub.eventTypes.includes(event.eventType)) continue\n if (sub.urlPattern && !event.url.includes(sub.urlPattern)) continue\n\n // Forward to all listeners\n const payload = {\n type: 'browser_event',\n subscriptionId: sub.id,\n ...event,\n timestamp: Date.now(),\n }\n for (const listener of eventListeners) {\n listener(payload)\n }\n }\n}\n","/**\n * Health check for MCP Server ↔ Extension connection.\n */\n\nlet extensionConnected = false\nlet lastHeartbeat: number | null = null\n\nexport function setExtensionConnected(connected: boolean) {\n extensionConnected = connected\n if (connected) lastHeartbeat = Date.now()\n}\n\nexport function recordHeartbeat() {\n lastHeartbeat = Date.now()\n}\n\nconst HEARTBEAT_STALENESS_MS = 60_000\n\nexport function isExtensionConnected(): boolean {\n if (!extensionConnected) return false\n // Also verify heartbeat is within staleness threshold\n if (lastHeartbeat !== null && Date.now() - lastHeartbeat > HEARTBEAT_STALENESS_MS) {\n return false\n }\n return true\n}\n\nexport function getHealthStatus() {\n return {\n extensionConnected,\n lastHeartbeat,\n uptime: process.uptime(),\n memoryUsage: process.memoryUsage().heapUsed,\n }\n}\n","/**\n * Compression utilities for large payloads.\n * Used when messages approach the 1MB Native Messaging limit.\n */\n\nimport { gzipSync, gunzipSync } from 'node:zlib'\nimport type { ChunkedMessage } from '@viyv-browser/shared'\n\nconst CHUNK_SIZE = 768 * 1024 // 768KB per chunk\n\n// Use shared ChunkedMessage as the canonical type\nexport type ChunkedPayload = ChunkedMessage\n\nexport function compressPayload(data: string): { compressed: string; wasCompressed: boolean } {\n const original = Buffer.from(data, 'utf-8')\n const gzipped = gzipSync(original)\n\n if (gzipped.length < original.length) {\n return { compressed: gzipped.toString('base64'), wasCompressed: true }\n }\n return { compressed: data, wasCompressed: false }\n}\n\nexport function decompressPayload(data: string, isCompressed: boolean): string {\n if (!isCompressed) return data\n const buf = Buffer.from(data, 'base64')\n return gunzipSync(buf).toString('utf-8')\n}\n\nexport function chunkPayload(\n requestId: string,\n agentId: string,\n data: string,\n compressed: boolean,\n): ChunkedPayload[] {\n const totalSize = data.length\n const totalChunks = Math.ceil(totalSize / CHUNK_SIZE)\n const chunks: ChunkedPayload[] = []\n\n for (let i = 0; i < totalChunks; i++) {\n chunks.push({\n type: 'chunk',\n requestId,\n agentId,\n chunkIndex: i,\n totalChunks,\n totalSize,\n compressed,\n data: data.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE),\n })\n }\n\n return chunks\n}\n\n// FIX #20: Guard against empty chunks array\nexport function reassembleChunks(chunks: ChunkedPayload[]): string {\n if (chunks.length === 0) {\n throw new Error('Cannot reassemble: no chunks provided')\n }\n\n const sorted = [...chunks].sort((a, b) => a.chunkIndex - b.chunkIndex)\n\n if (sorted.length !== sorted[0].totalChunks) {\n throw new Error(\n `Incomplete chunks: got ${sorted.length}, expected ${sorted[0].totalChunks}`,\n )\n }\n\n const data = sorted.map((c) => c.data).join('')\n return decompressPayload(data, sorted[0].compressed)\n}\n","/**\n * Tool registry: defines all MCP tools and their schemas.\n */\n\nimport { z } from 'zod'\n\nimport { GIF_CREATOR_DESCRIPTION } from './advanced/gif-creator.js'\nimport { RESIZE_WINDOW_DESCRIPTION } from './advanced/resize-window.js'\nimport { SHORTCUTS_EXECUTE_DESCRIPTION } from './advanced/shortcuts-execute.js'\nimport { SHORTCUTS_LIST_DESCRIPTION } from './advanced/shortcuts-list.js'\nimport { SWITCH_BROWSER_DESCRIPTION } from './advanced/switch-browser.js'\nimport { UPDATE_PLAN_DESCRIPTION } from './advanced/update-plan.js'\nimport { UPLOAD_IMAGE_DESCRIPTION } from './advanced/upload-image.js'\nimport { CLICK_DESCRIPTION } from './core/click.js'\nimport { DRAG_DESCRIPTION } from './core/drag.js'\nimport { FIND_DESCRIPTION } from './core/find.js'\nimport { FORM_INPUT_DESCRIPTION } from './core/form-input.js'\nimport { GET_PAGE_TEXT_DESCRIPTION } from './core/get-page-text.js'\nimport { HANDLE_DIALOG_DESCRIPTION } from './core/handle-dialog.js'\nimport { HOVER_DESCRIPTION } from './core/hover.js'\nimport { JAVASCRIPT_EXEC_DESCRIPTION } from './core/javascript-exec.js'\nimport { KEY_DESCRIPTION } from './core/key.js'\nimport { NAVIGATE_DESCRIPTION } from './core/navigate.js'\nimport { READ_PAGE_DESCRIPTION } from './core/read-page.js'\nimport { SCREENSHOT_DESCRIPTION } from './core/screenshot.js'\nimport { SCROLL_DESCRIPTION } from './core/scroll.js'\nimport { TYPE_DESCRIPTION } from './core/type.js'\nimport { WAIT_FOR_DESCRIPTION } from './core/wait-for.js'\nimport { READ_CONSOLE_MESSAGES_DESCRIPTION } from './debug/read-console-messages.js'\nimport { READ_NETWORK_REQUESTS_DESCRIPTION } from './debug/read-network-requests.js'\nimport { SELECT_TAB_DESCRIPTION } from './tabs/select-tab.js'\nimport { TAB_CLOSE_DESCRIPTION } from './tabs/tab-close.js'\nimport { TABS_CONTEXT_DESCRIPTION } from './tabs/tabs-context.js'\nimport { TABS_CREATE_DESCRIPTION } from './tabs/tabs-create.js'\nimport { AGENT_TAB_ASSIGN_DESCRIPTION } from './viyv/agent-tab-assign.js'\nimport { AGENT_TAB_LIST_DESCRIPTION } from './viyv/agent-tab-list.js'\nimport { ARTIFACT_FROM_PAGE_DESCRIPTION } from './viyv/artifact-from-page.js'\nimport { BROWSER_EVENT_SUBSCRIBE_DESCRIPTION } from './viyv/browser-event-subscribe.js'\nimport { BROWSER_EVENT_UNSUBSCRIBE_DESCRIPTION } from './viyv/browser-event-unsubscribe.js'\nimport { BROWSER_HEALTH_DESCRIPTION } from './viyv/browser-health.js'\nimport { PAGE_DATA_EXTRACT_DESCRIPTION } from './viyv/page-data-extract.js'\n\nexport interface ToolDefinition {\n name: string\n description: string\n inputSchema: z.ZodType\n}\n\n// ── Core Browser Tools ──\n\nexport const navigateTool: ToolDefinition = {\n name: 'navigate',\n description: NAVIGATE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID to navigate'),\n url: z.string().describe('URL to navigate to, or \"back\"/\"forward\" for history'),\n }),\n}\n\nexport const screenshotTool: ToolDefinition = {\n name: 'screenshot',\n description: SCREENSHOT_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID to capture'),\n format: z.enum(['jpeg', 'png']).optional().describe('Image format (default: jpeg)'),\n quality: z.number().min(1).max(100).optional().describe('JPEG quality (default: 80)'),\n region: z\n .tuple([z.number(), z.number(), z.number(), z.number()])\n .optional()\n .describe('Capture region [x0, y0, x1, y1]'),\n }),\n}\n\nexport const clickTool: ToolDefinition = {\n name: 'click',\n description: CLICK_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n coordinate: z\n .tuple([z.number(), z.number()])\n .optional()\n .describe('Click position [x, y]'),\n ref: z.string().optional().describe('Element reference ID'),\n action: z\n .enum(['left_click', 'right_click', 'double_click', 'triple_click'])\n .optional()\n .describe('Click type (default: left_click)'),\n modifiers: z.string().optional().describe('Modifier keys (e.g., \"ctrl+shift\")'),\n }),\n}\n\nexport const typeTool: ToolDefinition = {\n name: 'type',\n description: TYPE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n text: z.string().describe('Text to type'),\n }),\n}\n\nexport const keyTool: ToolDefinition = {\n name: 'key',\n description: KEY_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n keys: z.string().describe('Space-separated keys (e.g., \"Enter\", \"ctrl+a\")'),\n repeat: z.number().min(1).max(100).optional().describe('Repeat count'),\n }),\n}\n\nexport const scrollTool: ToolDefinition = {\n name: 'scroll',\n description: SCROLL_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n coordinate: z\n .tuple([z.number(), z.number()])\n .optional()\n .describe('Scroll position [x, y] (required for directional scroll)'),\n direction: z\n .enum(['up', 'down', 'left', 'right'])\n .optional()\n .describe('Scroll direction (required for directional scroll)'),\n amount: z.number().min(1).max(10).optional().describe('Scroll amount (default: 3)'),\n ref: z.string().optional().describe('Element reference ID to scroll into view'),\n }),\n}\n\nexport const hoverTool: ToolDefinition = {\n name: 'hover',\n description: HOVER_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n coordinate: z.tuple([z.number(), z.number()]).optional().describe('Hover position [x, y]'),\n ref: z.string().optional().describe('Element reference ID'),\n }),\n}\n\nexport const dragTool: ToolDefinition = {\n name: 'drag',\n description: DRAG_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n startCoordinate: z.tuple([z.number(), z.number()]).describe('Start position [x, y]'),\n endCoordinate: z.tuple([z.number(), z.number()]).describe('End position [x, y]'),\n }),\n}\n\nexport const readPageTool: ToolDefinition = {\n name: 'read_page',\n description: READ_PAGE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n filter: z\n .enum(['interactive', 'all'])\n .optional()\n .describe('Filter: \"interactive\" for buttons/links/inputs, \"all\" for everything'),\n depth: z.number().min(1).max(20).optional().describe('Max tree depth (default: 8)'),\n refId: z.string().optional().describe('Focus on a specific element by ref'),\n maxChars: z.number().optional().describe('Max output characters (default: 50000)'),\n }),\n}\n\nexport const findTool: ToolDefinition = {\n name: 'find',\n description: FIND_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n query: z.string().describe('Natural language description of what to find'),\n }),\n}\n\nexport const formInputTool: ToolDefinition = {\n name: 'form_input',\n description: FORM_INPUT_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n ref: z.string().describe('Element reference ID'),\n value: z.union([z.string(), z.boolean(), z.number()]).describe('Value to set'),\n }),\n}\n\nexport const javascriptExecTool: ToolDefinition = {\n name: 'javascript_exec',\n description: JAVASCRIPT_EXEC_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n code: z.string().describe('JavaScript code to execute'),\n }),\n}\n\nexport const waitForTool: ToolDefinition = {\n name: 'wait_for',\n description: WAIT_FOR_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n selector: z.string().optional().describe('CSS selector to wait for'),\n navigation: z.boolean().optional().describe('Wait for navigation to complete'),\n timeout: z.number().optional().describe('Timeout in ms (default: 30000)'),\n }),\n}\n\nexport const getPageTextTool: ToolDefinition = {\n name: 'get_page_text',\n description: GET_PAGE_TEXT_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n }),\n}\n\nexport const handleDialogTool: ToolDefinition = {\n name: 'handle_dialog',\n description: HANDLE_DIALOG_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n action: z.enum(['accept', 'dismiss']).describe('Dialog action'),\n text: z.string().optional().describe('Text for prompt dialog'),\n }),\n}\n\n// ── Tab Management Tools ──\n\nexport const tabsContextTool: ToolDefinition = {\n name: 'tabs_context',\n description: TABS_CONTEXT_DESCRIPTION,\n inputSchema: z.object({\n createIfEmpty: z\n .boolean()\n .optional()\n .describe('Create a new tab group if none exists'),\n }),\n}\n\nexport const tabsCreateTool: ToolDefinition = {\n name: 'tabs_create',\n description: TABS_CREATE_DESCRIPTION,\n inputSchema: z.object({\n url: z.string().optional().describe('URL to open in the new tab'),\n }),\n}\n\nexport const tabCloseTool: ToolDefinition = {\n name: 'tab_close',\n description: TAB_CLOSE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID to close'),\n }),\n}\n\nexport const selectTabTool: ToolDefinition = {\n name: 'select_tab',\n description: SELECT_TAB_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID to focus'),\n }),\n}\n\n// ── Debug Tools ──\n\nexport const readConsoleMessagesTool: ToolDefinition = {\n name: 'read_console_messages',\n description: READ_CONSOLE_MESSAGES_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n pattern: z.string().optional().describe('Regex pattern to filter messages'),\n onlyErrors: z.boolean().optional().describe('Only return errors'),\n limit: z.number().optional().describe('Max messages to return (default: 100)'),\n clear: z.boolean().optional().describe('Clear messages after reading'),\n }),\n}\n\nexport const readNetworkRequestsTool: ToolDefinition = {\n name: 'read_network_requests',\n description: READ_NETWORK_REQUESTS_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n urlPattern: z.string().optional().describe('URL pattern to filter requests'),\n limit: z.number().optional().describe('Max requests to return (default: 100)'),\n clear: z.boolean().optional().describe('Clear requests after reading'),\n }),\n}\n\n// ── Advanced Tools ──\n\nexport const gifCreatorTool: ToolDefinition = {\n name: 'gif_creator',\n description: GIF_CREATOR_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n action: z\n .enum(['start_recording', 'stop_recording', 'export', 'clear'])\n .describe('GIF action'),\n filename: z.string().optional().describe('Filename for export'),\n options: z\n .object({\n showClickIndicators: z.boolean().optional(),\n showDragPaths: z.boolean().optional(),\n showActionLabels: z.boolean().optional(),\n showProgressBar: z.boolean().optional(),\n showWatermark: z.boolean().optional(),\n quality: z.number().min(1).max(30).optional(),\n })\n .optional()\n .describe('GIF rendering options'),\n download: z.boolean().optional().describe('Download the GIF'),\n }),\n}\n\nexport const uploadImageTool: ToolDefinition = {\n name: 'upload_image',\n description: UPLOAD_IMAGE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n imageId: z.string().describe('Image ID from a previous screenshot'),\n ref: z.string().optional().describe('Element reference for file input'),\n coordinate: z\n .tuple([z.number(), z.number()])\n .optional()\n .describe('Coordinates for drag & drop'),\n }),\n}\n\nexport const updatePlanTool: ToolDefinition = {\n name: 'update_plan',\n description: UPDATE_PLAN_DESCRIPTION,\n inputSchema: z.object({\n domains: z.array(z.string()).describe('Domains to visit'),\n approach: z.array(z.string()).describe('Steps in the plan'),\n }),\n}\n\nexport const resizeWindowTool: ToolDefinition = {\n name: 'resize_window',\n description: RESIZE_WINDOW_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n width: z.number().describe('Window width in pixels'),\n height: z.number().describe('Window height in pixels'),\n }),\n}\n\nexport const shortcutsListTool: ToolDefinition = {\n name: 'shortcuts_list',\n description: SHORTCUTS_LIST_DESCRIPTION,\n inputSchema: z.object({\n tabId: z\n .number()\n .optional()\n .describe('Tab ID (used to identify the tab group context)'),\n }),\n}\n\nexport const shortcutsExecuteTool: ToolDefinition = {\n name: 'shortcuts_execute',\n description: SHORTCUTS_EXECUTE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID to execute the shortcut on'),\n command: z.string().optional().describe('Command name of the shortcut'),\n shortcutId: z.string().optional().describe('ID of the shortcut'),\n }),\n}\n\nexport const switchBrowserTool: ToolDefinition = {\n name: 'switch_browser',\n description: SWITCH_BROWSER_DESCRIPTION,\n inputSchema: z.object({}),\n}\n\n// ── viyv Integration Tools ──\n\nexport const agentTabAssignTool: ToolDefinition = {\n name: 'agent_tab_assign',\n description: AGENT_TAB_ASSIGN_DESCRIPTION,\n inputSchema: z.object({\n agentId: z.string().describe('Agent ID'),\n agentName: z.string().describe('Display name'),\n color: z.string().optional().describe('Tab group color'),\n }),\n}\n\nexport const agentTabListTool: ToolDefinition = {\n name: 'agent_tab_list',\n description: AGENT_TAB_LIST_DESCRIPTION,\n inputSchema: z.object({}),\n}\n\nexport const browserEventSubscribeTool: ToolDefinition = {\n name: 'browser_event_subscribe',\n description: BROWSER_EVENT_SUBSCRIBE_DESCRIPTION,\n inputSchema: z.object({\n eventTypes: z.array(z.string()).describe('Event types to subscribe to'),\n urlPattern: z.string().optional().describe('URL pattern filter'),\n conditions: z.record(z.unknown()).optional().describe('Additional conditions'),\n }),\n}\n\nexport const browserEventUnsubscribeTool: ToolDefinition = {\n name: 'browser_event_unsubscribe',\n description: BROWSER_EVENT_UNSUBSCRIBE_DESCRIPTION,\n inputSchema: z.object({\n subscriptionId: z.string().describe('Subscription ID'),\n }),\n}\n\nexport const artifactFromPageTool: ToolDefinition = {\n name: 'artifact_from_page',\n description: ARTIFACT_FROM_PAGE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n type: z.string().describe('Artifact type (text, html, screenshot)'),\n title: z.string().optional().describe('Artifact title'),\n }),\n}\n\nexport const pageDataExtractTool: ToolDefinition = {\n name: 'page_data_extract',\n description: PAGE_DATA_EXTRACT_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n schema: z.record(z.unknown()).describe('Data extraction schema'),\n selector: z.string().optional().describe('CSS selector to scope extraction'),\n }),\n}\n\nexport const browserHealthTool: ToolDefinition = {\n name: 'browser_health',\n description: BROWSER_HEALTH_DESCRIPTION,\n inputSchema: z.object({}),\n}\n\n// ── All Tools ──\n\nexport const allTools: ToolDefinition[] = [\n // Core (15)\n navigateTool,\n screenshotTool,\n clickTool,\n typeTool,\n keyTool,\n scrollTool,\n hoverTool,\n dragTool,\n readPageTool,\n findTool,\n formInputTool,\n javascriptExecTool,\n waitForTool,\n getPageTextTool,\n handleDialogTool,\n // Tabs (4)\n tabsContextTool,\n tabsCreateTool,\n tabCloseTool,\n selectTabTool,\n // Debug (2)\n readConsoleMessagesTool,\n readNetworkRequestsTool,\n // Advanced (7)\n gifCreatorTool,\n uploadImageTool,\n updatePlanTool,\n resizeWindowTool,\n shortcutsListTool,\n shortcutsExecuteTool,\n switchBrowserTool,\n // viyv Integration (7)\n agentTabAssignTool,\n agentTabListTool,\n browserEventSubscribeTool,\n browserEventUnsubscribeTool,\n artifactFromPageTool,\n pageDataExtractTool,\n browserHealthTool,\n]\n","export const GIF_CREATOR_DESCRIPTION = `Record a GIF of browser activity.\nCaptures a sequence of screenshots over a specified duration\nand assembles them into an animated GIF. Useful for documenting\nvisual interactions or creating shareable recordings of workflows.`\n","export const RESIZE_WINDOW_DESCRIPTION = `Resize the browser window to specified dimensions.\nSets the width and height of the browser viewport, useful for\ntesting responsive layouts or ensuring consistent screenshot\ndimensions across different operations.`\n","export const SHORTCUTS_EXECUTE_DESCRIPTION = `Execute a shortcut or workflow by command name or ID.\n\nRuns the specified shortcut in the side panel using the current tab.\nLook up by command name or shortcutId. Use shortcuts_list first\nto see available shortcuts.`\n","export const SHORTCUTS_LIST_DESCRIPTION = `List all available shortcuts and workflows.\n\nReturns registered shortcuts with their commands, descriptions,\nand whether they are workflows. Shortcuts can be executed using\nthe shortcuts_execute tool.`\n","export const SWITCH_BROWSER_DESCRIPTION = `Switch to a different Chrome browser instance.\n\nDisconnects the current Extension connection and waits for a new\nChrome browser to connect (up to 60s). The user should click\n\"Connect\" in the desired browser's extension.`\n","export const UPDATE_PLAN_DESCRIPTION = `Present a step-by-step plan to the user for review.\nDisplays the proposed sequence of actions the agent intends to take,\nallowing the user to approve, modify, or reject the plan before\nexecution begins.`\n","export const UPLOAD_IMAGE_DESCRIPTION = `Upload an image to a file input element on the page.\nAccepts a local file path or base64-encoded image data and\nprogrammatically sets it on the target file input. Supports\ncommon image formats including PNG, JPEG, GIF, and WebP.`\n","export const CLICK_DESCRIPTION = `Click at coordinates or on a referenced element.\n\nProvide either coordinate [x, y] or ref (element reference from read_page/find).\nActions: left_click (default), right_click, double_click, triple_click.\nSupports modifier keys: ctrl, shift, alt, cmd (e.g., \"ctrl+shift\").`\n","export const DRAG_DESCRIPTION = `Drag from one coordinate to another.\n\nPerforms mousedown at start, mousemove to end, then mouseup.`\n","export const FIND_DESCRIPTION = `Find elements on the page using a natural language query.\nSearches the DOM for elements matching the given description,\nreturning references that can be used for subsequent interactions\nsuch as clicking, typing, or extracting content.`\n","export const FORM_INPUT_DESCRIPTION = `Set a value in a form element identified by its ref.\nSupports text inputs, textareas, selects, checkboxes, and radio buttons.\nThe ref must be obtained from a prior find or snapshot operation\nto ensure the correct element is targeted.`\n","export const GET_PAGE_TEXT_DESCRIPTION = `Extract readable text content from the current page.\nStrips away HTML tags, scripts, and styles to return a clean\ntext representation of the visible page content, suitable for\nanalysis, summarization, or further processing.`\n","export const HANDLE_DIALOG_DESCRIPTION = `Handle JavaScript dialogs such as alert, confirm, and prompt.\nAllows accepting or dismissing the dialog, and optionally providing\ninput text for prompt dialogs. Must be called while a dialog\nis actively displayed on the page.`\n","export const HOVER_DESCRIPTION = `Move mouse to coordinates or element without clicking.\n\nUseful for revealing tooltips, dropdown menus, or triggering hover states.`\n","export const JAVASCRIPT_EXEC_DESCRIPTION = `Execute arbitrary JavaScript code in the page context.\nThe script runs in the main world of the active page and can access\nthe DOM, window object, and any page-level APIs. Returns the\nserialized result of the last evaluated expression.`\n","export const KEY_DESCRIPTION = `Press keyboard key(s).\n\nSpace-separated key names. Supports keyboard shortcuts.\nExamples: \"Enter\", \"Tab\", \"Backspace\", \"ctrl+a\", \"cmd+c\".\nUse repeat parameter for repeated presses (e.g., arrow keys).`\n","export const NAVIGATE_DESCRIPTION = `Navigate to a URL, or go forward/back in browser history.\n\nUse \"back\" to go back in history, \"forward\" to go forward.\nProvide a full URL (with protocol) to navigate to a new page.\nWaits for page load to complete before returning.`\n","export const READ_PAGE_DESCRIPTION = `Get accessibility tree representation of page elements.\n\nSupports:\n- filter: \"interactive\" for buttons/links/inputs only, \"all\" for everything\n- depth: max tree depth (1-20, default 8)\n- refId: focus on a specific element subtree\n- maxChars: limit output size (default 50000)\n\nReturns elements with ref IDs that can be used with click, form_input, etc.`\n","export const SCREENSHOT_DESCRIPTION = `Take a screenshot of a tab.\n\nReturns base64-encoded image data.\nDefault format is JPEG with quality 80 (optimized for Native Messaging 1MB limit).\nUse PNG for lossless screenshots when needed.\nOptionally capture a specific region [x0, y0, x1, y1].`\n","export const SCROLL_DESCRIPTION = `Scroll in a direction at given coordinates, or scroll an element into view by ref.\n\nTwo modes:\n1. Directional scroll: provide coordinate + direction (+ optional amount 1-10, default 3).\n2. Scroll to element: provide ref (element reference ID from read_page/find). Scrolls the element into view using smooth scrolling.`\n","export const TYPE_DESCRIPTION = `Type text into the currently focused element.\n\nEach character is typed individually with keyDown/keyUp events.\nFor special keys (Enter, Tab, etc.), use the 'key' tool instead.`\n","export const WAIT_FOR_DESCRIPTION = `Wait for a specified condition before proceeding.\nSupports waiting for a CSS selector to appear in the DOM,\nfor a navigation event to complete, or for a fixed timeout duration.\nUseful for synchronizing with asynchronous page updates.`\n","export const READ_CONSOLE_MESSAGES_DESCRIPTION = `Read console messages captured from the page.\nReturns log, warning, error, and info messages that have been\nemitted by page scripts. Supports filtering by log level\nand limiting the number of returned entries.`\n","export const READ_NETWORK_REQUESTS_DESCRIPTION = `Read network requests captured from the page.\nReturns details of HTTP requests and responses including URL, method,\nstatus code, headers, and timing information. Supports filtering\nby URL pattern or resource type.`\n","export const SELECT_TAB_DESCRIPTION = `Switch focus to a specific tab by its identifier.\nMakes the target tab the active tab in the agent's group,\nbringing it to the foreground for subsequent operations\nsuch as navigation, clicking, or content extraction.`\n","export const TAB_CLOSE_DESCRIPTION = `Close a tab by its identifier.\nRemoves the specified tab from the browser and the agent's tab group.\nIf the closed tab was active, focus shifts to the nearest remaining\ntab in the group.`\n","export const TABS_CONTEXT_DESCRIPTION = `Get information about the current agent tab group.\nReturns the list of tabs belonging to the agent's assigned group,\nincluding each tab's ID, URL, title, and active status.\nUseful for understanding the current browsing context.`\n","export const TABS_CREATE_DESCRIPTION = `Create a new tab within the agent's tab group.\nOpens a new tab with an optional URL and automatically assigns it\nto the current agent's group. The new tab becomes the active tab\nunless otherwise specified.`\n","export const AGENT_TAB_ASSIGN_DESCRIPTION = `Assign a tab group to a specific agent.\nBinds an existing Chrome tab group to the calling agent, granting\nexclusive control over all tabs within the group. Prevents other\nagents from interfering with the assigned tabs.`\n","export const AGENT_TAB_LIST_DESCRIPTION = `List all agent-to-tab-group mappings.\nReturns a summary of which agents are assigned to which tab groups,\nincluding the group ID, agent identifier, and the number of tabs\nin each group.`\n","export const ARTIFACT_FROM_PAGE_DESCRIPTION = `Save the current page as a persistent artifact.\nCaptures the page content as HTML, PDF, or screenshot and stores it\nas a named artifact for later reference. Artifacts can be retrieved\nby other tools or returned to the user as output.`\n","export const BROWSER_EVENT_SUBSCRIBE_DESCRIPTION = `Subscribe to browser events for real-time monitoring.\nRegisters a listener for specified event types such as navigation,\ntab updates, DOM changes, or network activity. Events are queued\nand delivered on subsequent polling or callback.`\n","export const BROWSER_EVENT_UNSUBSCRIBE_DESCRIPTION = `Unsubscribe from previously registered browser events.\nRemoves the event listener for the specified subscription ID,\nstopping further event delivery. Cleans up associated resources\nand flushes any remaining queued events.`\n","export const BROWSER_HEALTH_DESCRIPTION = `Check the health status of the browser connection.\nVerifies that the browser process is running, the CDP connection\nis active, and the agent's tab group is accessible. Returns\ndiagnostic information useful for troubleshooting connectivity issues.`\n","export const PAGE_DATA_EXTRACT_DESCRIPTION = `Extract structured data from the current page.\nParses the page content according to a provided schema or natural\nlanguage description, returning well-formed JSON. Supports extracting\ntables, lists, key-value pairs, and other structured patterns.`\n","/**\n * Bridge between Native Messaging Host and MCP Server via Unix socket.\n *\n * When running as --native-host:\n * Chrome <-> stdin/stdout (Native Messaging) <-> this bridge <-> Unix socket <-> MCP Server\n */\n\nimport { createConnection, type Socket } from 'node:net'\nimport { createMessageReader, writeMessage } from './transport.js'\nimport { compressPayload, decompressPayload } from './compression.js'\nimport { RECONNECT, LIMITS } from '@viyv-browser/shared'\n\nconst MAX_BUFFER_SIZE = 1000\n\nexport interface BridgeOptions {\n socketPath: string\n onError?: (error: Error) => void\n}\n\nexport function startBridge(options: BridgeOptions): void {\n const { socketPath, onError } = options\n let socket: Socket | null = null\n let reconnecting = false\n let retryCount = 0\n\n // FIX #2: Actual message buffer for messages received while socket is disconnected\n const pendingMessages: unknown[] = []\n\n function flushBuffer() {\n if (!socket || socket.destroyed) return\n while (pendingMessages.length > 0) {\n const msg = pendingMessages[0] // FIX NL3: Peek first, don't shift until write succeeds\n try {\n const written = socket.write(`${JSON.stringify(msg)}\\n`)\n pendingMessages.shift() // Safe to remove after successful write call\n if (!written) {\n // Backpressure: wait for drain before continuing flush\n socket.once('drain', () => flushBuffer())\n return\n }\n } catch (error) {\n // Message stays in buffer for retry on reconnection\n onError?.(error as Error)\n return\n }\n }\n }\n\n function connectSocket() {\n socket = createConnection(socketPath)\n\n socket.on('connect', () => {\n process.stderr.write(\n `[viyv-browser:native-host] Connected to MCP server at ${socketPath}\\n`,\n )\n retryCount = 0 // Reset backoff on successful connection\n flushBuffer()\n })\n\n // Messages from MCP Server -> Chrome (via stdout)\n // TCP stream fragmentation fix: line-based buffer\n let lineBuffer = ''\n\n socket.on('data', (data) => {\n lineBuffer += data.toString('utf-8')\n const lines = lineBuffer.split('\\n')\n lineBuffer = lines.pop() ?? '' // Keep incomplete last line\n for (const line of lines) {\n if (!line) continue\n try {\n let message = JSON.parse(line)\n // NM5: Decompress incoming compressed messages from MCP Server\n if (message.type === 'compressed' && typeof message.data === 'string') {\n const decompressed = decompressPayload(message.data, true)\n message = JSON.parse(decompressed)\n }\n writeMessage(process.stdout, message)\n } catch (error) {\n onError?.(error as Error)\n }\n }\n })\n\n socket.on('error', (error) => {\n process.stderr.write(\n `[viyv-browser:native-host] Socket error: ${error.message}\\n`,\n )\n onError?.(error)\n })\n\n socket.on('close', () => {\n process.stderr.write('[viyv-browser:native-host] Socket closed\\n')\n socket = null\n if (!reconnecting) {\n reconnecting = true\n // Exponential backoff: 1s, 2s, 4s, ..., max 30s\n const delay = Math.min(\n RECONNECT.INITIAL_DELAY * Math.pow(RECONNECT.MULTIPLIER, retryCount),\n RECONNECT.MAX_DELAY,\n )\n retryCount++\n process.stderr.write(\n `[viyv-browser:native-host] Reconnecting in ${delay}ms (attempt ${retryCount})\\n`,\n )\n setTimeout(() => {\n reconnecting = false\n connectSocket()\n }, delay)\n }\n })\n }\n\n // Messages from Chrome (via stdin) -> MCP Server\n createMessageReader(\n process.stdin,\n (message) => {\n if (socket && !socket.destroyed) {\n // NM5: Compress large payloads (e.g., screenshots) before Unix socket transfer\n const json = JSON.stringify(message)\n if (json.length > LIMITS.CHUNK_SIZE) {\n const { compressed, wasCompressed } = compressPayload(json)\n if (wasCompressed) {\n socket.write(`${JSON.stringify({ type: 'compressed', data: compressed })}\\n`)\n } else {\n socket.write(`${json}\\n`)\n }\n } else {\n socket.write(`${json}\\n`)\n }\n } else {\n // Buffer messages while disconnected\n if (pendingMessages.length < MAX_BUFFER_SIZE) {\n pendingMessages.push(message)\n } else {\n process.stderr.write(\n '[viyv-browser:native-host] Message buffer full, dropping message\\n',\n )\n }\n }\n },\n onError,\n )\n\n connectSocket()\n\n // Clean shutdown handlers\n process.on('SIGINT', () => {\n socket?.destroy()\n process.exit(0)\n })\n\n process.on('SIGTERM', () => {\n socket?.destroy()\n process.exit(0)\n })\n\n process.stdin.on('end', () => {\n process.stderr.write('[viyv-browser:native-host] stdin closed, shutting down\\n')\n socket?.destroy()\n process.exit(0)\n })\n}\n","/**\n * Native Messaging transport: length-prefixed JSON over stdin/stdout.\n * Chrome Native Messaging uses 4-byte little-endian length prefix + UTF-8 JSON.\n */\n\nconst MAX_MESSAGE_SIZE = 1024 * 1024 // 1MB Chrome limit\n\nexport function encodeMessage(message: unknown): Buffer {\n const json = JSON.stringify(message)\n const body = Buffer.from(json, 'utf-8')\n\n if (body.length > MAX_MESSAGE_SIZE) {\n throw new Error(`Message too large: ${body.length} bytes (max ${MAX_MESSAGE_SIZE})`)\n }\n\n const header = Buffer.alloc(4)\n header.writeUInt32LE(body.length, 0)\n return Buffer.concat([header, body])\n}\n\nexport function createMessageReader(\n stream: NodeJS.ReadableStream,\n onMessage: (message: unknown) => void,\n onError?: (error: Error) => void,\n onClose?: () => void,\n) {\n let buffer = Buffer.alloc(0)\n let expectedLength: number | null = null\n\n stream.on('data', (chunk: Buffer) => {\n buffer = Buffer.concat([buffer, chunk])\n\n while (true) {\n // Read length header\n if (expectedLength === null) {\n if (buffer.length < 4) break\n expectedLength = buffer.readUInt32LE(0)\n buffer = buffer.subarray(4)\n\n if (expectedLength > MAX_MESSAGE_SIZE) {\n onError?.(new Error(`Message too large: ${expectedLength} bytes`))\n expectedLength = null\n buffer = Buffer.alloc(0)\n break\n }\n }\n\n // Read message body\n if (buffer.length < expectedLength) break\n\n const jsonBuffer = buffer.subarray(0, expectedLength)\n buffer = buffer.subarray(expectedLength)\n expectedLength = null\n\n try {\n const message = JSON.parse(jsonBuffer.toString('utf-8'))\n onMessage(message)\n } catch (error) {\n onError?.(new Error(`Invalid JSON: ${(error as Error).message}`))\n }\n }\n })\n\n // FIX #19: Handle stream close/error events\n stream.on('error', (error: Error) => {\n onError?.(new Error(`Stream error: ${error.message}`))\n })\n\n stream.on('end', () => {\n onClose?.()\n })\n\n stream.on('close', () => {\n onClose?.()\n })\n}\n\nexport function writeMessage(stream: NodeJS.WritableStream, message: unknown): void {\n const encoded = encodeMessage(message)\n stream.write(encoded)\n}\n","/**\n * Setup command: registers Native Messaging Host manifest.\n * `npx @viyv/browser-mcp setup`\n */\n\nimport { writeFileSync, mkdirSync, chmodSync, existsSync } from 'node:fs'\nimport { resolve, dirname } from 'node:path'\nimport { homedir, platform } from 'node:os'\nimport { execSync } from 'node:child_process'\nimport { NATIVE_HOST_NAME } from '@viyv-browser/shared'\n\ninterface SetupOptions {\n extensionId?: string\n}\n\nexport function runSetup(options: SetupOptions = {}): void {\n const os = platform()\n const binaryPath = getBinaryPath()\n\n console.log('Viyv Browser MCP - Native Messaging Host Setup')\n console.log('================================================')\n console.log(`Platform: ${os}`)\n console.log(`Binary: ${binaryPath}`)\n\n // Verify binary path exists\n if (!existsSync(binaryPath)) {\n console.error(`WARNING: Binary not found at ${binaryPath}`)\n console.error('The Native Messaging Host may not work until the binary is available.')\n }\n\n const allowedOrigins = options.extensionId\n ? [`chrome-extension://${options.extensionId}/`]\n : ['chrome-extension://*/'] // Allow all during development\n\n // Security warning for wildcard origins\n if (!options.extensionId) {\n process.stderr.write(\n 'WARNING: Using wildcard allowed_origins (chrome-extension://*/). ' +\n 'This allows any Chrome extension to connect. ' +\n 'For production, specify --extension-id to restrict access.\\n',\n )\n }\n\n // Chrome Native Messaging Host manifest doesn't support args.\n // Create a wrapper script that launches the binary with --native-host flag.\n const wrapperPath = createNativeHostWrapper(os, binaryPath)\n\n const manifest = {\n name: NATIVE_HOST_NAME,\n description: 'Viyv Browser MCP Native Messaging Host',\n path: wrapperPath,\n type: 'stdio',\n allowed_origins: allowedOrigins,\n }\n\n const manifestPath = getManifestPath(os)\n const manifestDir = dirname(manifestPath)\n\n console.log(`Wrapper: ${wrapperPath}`)\n console.log(`Manifest path: ${manifestPath}`)\n\n mkdirSync(manifestDir, { recursive: true })\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2))\n chmodSync(manifestPath, 0o644)\n\n console.log('\\nNative Messaging Host registered successfully!')\n console.log('\\nNext steps:')\n console.log('1. Start the MCP Server: node <path>/dist/index.js')\n console.log('2. Install the Viyv Browser Chrome Extension')\n console.log('3. Click the extension icon to connect')\n}\n\nfunction getBinaryPath(): string {\n // Find the actual binary path\n const whichCmd = process.platform === 'win32' ? 'where' : 'which'\n try {\n const found = execSync(`${whichCmd} viyv-browser-mcp`, { encoding: 'utf-8' }).trim()\n if (found) return found\n } catch {\n // Not globally installed, use npx path\n }\n\n // Fallback: resolve from current module\n const currentScript = process.argv[1]\n return resolve(currentScript)\n}\n\nfunction createNativeHostWrapper(os: string, binaryPath: string): string {\n const manifestDir = dirname(getManifestPath(os))\n mkdirSync(manifestDir, { recursive: true })\n\n // Chrome launches native hosts in a clean environment without user's PATH.\n // We must use the absolute path to node, not rely on #!/usr/bin/env node.\n const nodePath = getNodePath()\n\n if (os === 'win32') {\n // Windows: .bat wrapper\n const wrapperPath = resolve(manifestDir, `${NATIVE_HOST_NAME}.bat`)\n writeFileSync(wrapperPath, `@echo off\\r\\n\"${nodePath}\" \"${binaryPath}\" --native-host\\r\\n`)\n return wrapperPath\n }\n\n // macOS/Linux: shell wrapper\n const wrapperPath = resolve(manifestDir, `${NATIVE_HOST_NAME}.sh`)\n writeFileSync(\n wrapperPath,\n `#!/bin/bash\\nexec \"${nodePath}\" \"${binaryPath}\" --native-host\\n`,\n )\n chmodSync(wrapperPath, 0o755)\n return wrapperPath\n}\n\nfunction getNodePath(): string {\n try {\n return execSync('which node', { encoding: 'utf-8' }).trim()\n } catch {\n // Fallback: use the current process's node binary\n return process.execPath\n }\n}\n\nfunction getManifestPath(os: string): string {\n const home = homedir()\n\n switch (os) {\n case 'darwin':\n return resolve(\n home,\n 'Library/Application Support/Google/Chrome/NativeMessagingHosts',\n `${NATIVE_HOST_NAME}.json`,\n )\n case 'linux':\n return resolve(\n home,\n '.config/google-chrome/NativeMessagingHosts',\n `${NATIVE_HOST_NAME}.json`,\n )\n case 'win32':\n // On Windows, we'd also need to create a registry entry\n return resolve(\n home,\n 'AppData/Local/Google/Chrome/User Data/NativeMessagingHosts',\n `${NATIVE_HOST_NAME}.json`,\n )\n default:\n throw new Error(`Unsupported platform: ${os}`)\n }\n}\n"],"mappings":"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","names":["existsSync","randomUUID","sessions","randomUUID","resolve","existsSync","existsSync","wrapperPath","waitForSocket","existsSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/server.ts","../../shared/src/constants.ts","../src/agent-session.ts","../src/event-bridge.ts","../src/health.ts","../src/native-host/compression.ts","../src/tools/index.ts","../src/tools/advanced/gif-creator.ts","../src/tools/advanced/resize-window.ts","../src/tools/advanced/shortcuts-execute.ts","../src/tools/advanced/shortcuts-list.ts","../src/tools/advanced/switch-browser.ts","../src/tools/advanced/update-plan.ts","../src/tools/advanced/upload-image.ts","../src/tools/core/click.ts","../src/tools/core/drag.ts","../src/tools/core/find.ts","../src/tools/core/form-input.ts","../src/tools/core/get-page-text.ts","../src/tools/core/handle-dialog.ts","../src/tools/core/hover.ts","../src/tools/core/javascript-exec.ts","../src/tools/core/key.ts","../src/tools/core/navigate.ts","../src/tools/core/read-page.ts","../src/tools/core/screenshot.ts","../src/tools/core/scroll.ts","../src/tools/core/type.ts","../src/tools/core/wait-for.ts","../src/tools/debug/read-console-messages.ts","../src/tools/debug/read-network-requests.ts","../src/tools/tabs/select-tab.ts","../src/tools/tabs/tab-close.ts","../src/tools/tabs/tabs-context.ts","../src/tools/tabs/tabs-create.ts","../src/tools/viyv/agent-tab-assign.ts","../src/tools/viyv/agent-tab-list.ts","../src/tools/viyv/artifact-from-page.ts","../src/tools/viyv/browser-event-subscribe.ts","../src/tools/viyv/browser-event-unsubscribe.ts","../src/tools/viyv/browser-health.ts","../src/tools/viyv/page-data-extract.ts","../src/native-host/bridge.ts","../src/native-host/transport.ts","../src/setup.ts"],"sourcesContent":["/**\n * @viyv/browser-mcp CLI entry point.\n *\n * Two modes:\n * viyv-browser-mcp → MCP Server mode (stdio transport + Unix socket)\n * viyv-browser-mcp --native-host → Native Messaging Host mode (Chrome bridge)\n * viyv-browser-mcp setup → Register Native Messaging Host manifest\n */\n\nimport { existsSync, readdirSync } from 'node:fs'\nimport { startMcpServer } from './server.js'\nimport { startBridge } from './native-host/bridge.js'\nimport { runSetup } from './setup.js'\n\nconst args = process.argv.slice(2)\n\nif (args.includes('setup')) {\n // Setup mode: register Native Messaging Host\n const extensionIdIdx = args.indexOf('--extension-id')\n const extensionId = extensionIdIdx >= 0 ? args[extensionIdIdx + 1] : undefined\n runSetup({ extensionId })\n} else if (args.includes('--native-host')) {\n // Native Messaging Host mode: bridge Chrome ↔ MCP Server\n // Socket may not exist yet (MCP Server starts when AI client connects).\n // Wait and retry until the socket appears.\n const SOCKET_PATH = '/tmp/viyv-browser.sock'\n const POLL_INTERVAL = 2000\n const MAX_WAIT = 120_000\n\n function waitForSocket() {\n const start = Date.now()\n\n function poll() {\n const socketPath = findSocketPath()\n if (socketPath) {\n process.stderr.write(\n `[viyv-browser:native-host] Found socket at ${socketPath}\\n`,\n )\n startBridge({\n socketPath,\n onError: (error) => {\n process.stderr.write(`[viyv-browser:native-host] Error: ${error.message}\\n`)\n },\n })\n return\n }\n\n if (Date.now() - start > MAX_WAIT) {\n process.stderr.write(\n `[viyv-browser:native-host] MCP server socket not found after ${MAX_WAIT / 1000}s. Exiting.\\n`,\n )\n process.exit(1)\n }\n\n process.stderr.write(\n `[viyv-browser:native-host] Waiting for MCP server socket (${SOCKET_PATH})...\\n`,\n )\n setTimeout(poll, POLL_INTERVAL)\n }\n\n poll()\n }\n\n waitForSocket()\n} else {\n // MCP Server mode (default) — fixed path so bridge can always find it on reconnect\n const socketPath = '/tmp/viyv-browser.sock'\n const agentNameIdx = args.indexOf('--agent-name')\n const agentName = agentNameIdx >= 0 ? args[agentNameIdx + 1] : undefined\n\n const transportIdx = args.indexOf('--transport')\n const transportMode = transportIdx >= 0 ? args[transportIdx + 1] : 'stdio'\n if (transportMode !== 'stdio' && transportMode !== 'sse') {\n process.stderr.write(\n `[viyv-browser:mcp] Invalid transport: \"${transportMode}\". Must be \"stdio\" or \"sse\".\\n`,\n )\n process.exit(1)\n }\n const portIdx = args.indexOf('--port')\n const port = portIdx >= 0 ? Number(args[portIdx + 1]) : undefined\n\n startMcpServer(socketPath, agentName, { transport: transportMode, port })\n}\n\nfunction findSocketPath(): string | null {\n const envSocket = process.env.VIYV_BROWSER_SOCKET\n if (envSocket) return envSocket\n\n // Check fixed socket path first\n const fixedPath = '/tmp/viyv-browser.sock'\n if (existsSync(fixedPath)) return fixedPath\n\n // Fallback: scan for legacy PID-based sockets\n try {\n const tmpFiles = readdirSync('/tmp')\n const socketFile = tmpFiles.find((f) => f.startsWith('viyv-browser-') && f.endsWith('.sock'))\n if (socketFile) return `/tmp/${socketFile}`\n } catch {\n // Ignore\n }\n\n return null\n}\n","/**\n * MCP Server for viyv-browser.\n * Communicates with viyv Daemon via stdio (JSON-RPC) or SSE (HTTP),\n * and with Chrome Extension via Unix socket <-> Native Messaging bridge.\n */\n\nimport { randomUUID } from 'node:crypto'\nimport { existsSync, unlinkSync } from 'node:fs'\nimport http from 'node:http'\nimport { type Server as NetServer, type Socket, createServer } from 'node:net'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { type BrowserEventType, MCP_SERVER, PROTOCOL_VERSION, TIMEOUTS } from '@viyv-browser/shared'\nimport {\n closeSession,\n createSession,\n getDefaultAgentId,\n setDefaultAgentId,\n touchSession,\n} from './agent-session.js'\nimport {\n addEventListener,\n addSubscription,\n processEvent,\n removeEventListener,\n removeSubscription,\n removeSubscriptionsByAgent,\n} from './event-bridge.js'\nimport { isExtensionConnected, recordHeartbeat, setExtensionConnected } from './health.js'\nimport { decompressPayload } from './native-host/compression.js'\nimport { allTools } from './tools/index.js'\n\ninterface PendingRequest {\n resolve: (result: Record<string, unknown>) => void\n reject: (error: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\nconst pendingRequests = new Map<string, PendingRequest>()\nlet extensionSocket: Socket | null = null\n\nexport interface McpServerOptions {\n transport?: 'stdio' | 'sse'\n port?: number\n}\n\n/**\n * Creates a fully configured McpServer with all tools registered and event forwarding.\n * Each SSE session needs its own McpServer instance (McpServer.connect() can only be called once).\n */\nfunction createConfiguredMcpServer(): McpServer {\n const server = new McpServer({\n name: MCP_SERVER.NAME,\n version: MCP_SERVER.VERSION,\n })\n\n // Register all tools -- pass Zod shape directly (FIX #1: MCP SDK expects Zod, not JSON Schema)\n for (const tool of allTools) {\n const shape = tool.inputSchema._def.shape?.() ?? {}\n server.tool(tool.name, tool.description, shape, async (params) => {\n const result = await callExtensionTool(tool.name, params as Record<string, unknown>)\n\n // BUG-4 FIX: Sync event subscriptions with MCP server's event-bridge\n if (tool.name === 'browser_event_subscribe' && result.content[0]) {\n try {\n const parsed = JSON.parse(result.content[0].text)\n if (parsed.subscriptionId) {\n const p = params as Record<string, unknown>\n addSubscription({\n id: parsed.subscriptionId,\n agentId: getDefaultAgentId(),\n eventTypes: (p.eventTypes as BrowserEventType[]) ?? [],\n urlPattern: p.urlPattern as string | undefined,\n createdAt: Date.now(),\n })\n }\n } catch {\n /* ignore parse errors */\n }\n } else if (tool.name === 'browser_event_unsubscribe' && result.content[0]) {\n try {\n const parsed = JSON.parse(result.content[0].text)\n if (parsed.subscriptionId) {\n removeSubscription(parsed.subscriptionId)\n }\n } catch {\n /* ignore parse errors */\n }\n }\n\n return result\n })\n }\n\n // Forward browser events through MCP logging notification\n const listener = (event: Record<string, unknown>) => {\n server\n .sendLoggingMessage({\n level: 'info',\n data: event,\n })\n .catch(() => {\n // Ignore send errors for events (client may not be listening)\n })\n }\n addEventListener(listener)\n\n // Clean up listener when transport closes\n server.server.onclose = () => {\n removeEventListener(listener)\n }\n\n return server\n}\n\nexport async function startMcpServer(\n socketPath: string,\n agentName?: string,\n options?: McpServerOptions,\n): Promise<void> {\n if (agentName) {\n setDefaultAgentId(agentName)\n }\n\n // -- Unix Socket Server (for Native Host connections) -- shared by both transports\n const socketServer = createSocketServer(socketPath)\n\n if (options?.transport === 'sse') {\n // -- SSE mode: HTTP server, one McpServer per SSE session --\n const sessions = new Map<string, { transport: SSEServerTransport; server: McpServer }>()\n\n const httpServer = http.createServer()\n\n httpServer.on('request', (req, res) => {\n handleSseRequest(req, res, sessions).catch((error) => {\n process.stderr.write(`[viyv-browser:mcp] SSE request error: ${(error as Error).message}\\n`)\n if (!res.headersSent) {\n res.writeHead(500).end('Internal server error')\n }\n })\n })\n\n const listenPort = options.port ?? 0\n httpServer.listen(listenPort, '127.0.0.1', () => {\n const addr = httpServer.address()\n const port = typeof addr === 'object' ? addr?.port : listenPort\n process.stdout.write(`${JSON.stringify({ port })}\\n`)\n process.stderr.write(`[viyv-browser:mcp] SSE server listening on 127.0.0.1:${port}\\n`)\n })\n\n process.stderr.write(`[viyv-browser:mcp] MCP Server started (SSE), socket: ${socketPath}\\n`)\n\n // Graceful shutdown: close SSE sessions async, then sync cleanup\n let shuttingDown = false\n const shutdown = async () => {\n if (shuttingDown) return\n shuttingDown = true\n for (const { server: s } of sessions.values()) {\n await s.close().catch(() => {})\n }\n httpServer.close(() => {})\n socketServer.close(() => {})\n cleanupSocket(socketPath)\n process.exit(0)\n }\n process.on('SIGINT', () => {\n shutdown()\n })\n process.on('SIGTERM', () => {\n shutdown()\n })\n\n // Sync fallback for unexpected exit (e.g. uncaughtException)\n // shutdown() already handled close — only clean up socket file here\n process.on('exit', () => {\n cleanupSocket(socketPath)\n })\n } else {\n // -- stdio mode (default) --\n const server = createConfiguredMcpServer()\n const transport = new StdioServerTransport()\n await server.connect(transport)\n\n process.stderr.write(`[viyv-browser:mcp] MCP Server started (stdio), socket: ${socketPath}\\n`)\n\n process.on('SIGINT', () => process.exit(0))\n process.on('SIGTERM', () => process.exit(0))\n\n process.on('exit', () => {\n socketServer.close()\n cleanupSocket(socketPath)\n })\n }\n}\n\nasync function handleSseRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n sessions: Map<string, { transport: SSEServerTransport; server: McpServer }>,\n): Promise<void> {\n if (req.method === 'GET' && req.url === '/sse') {\n // New SSE session\n const transport = new SSEServerTransport('/message', res)\n const mcpServer = createConfiguredMcpServer()\n\n transport.onclose = () => {\n sessions.delete(transport.sessionId)\n }\n\n // Fallback: clean up session if HTTP connection closes without transport.onclose\n res.on('close', () => {\n if (sessions.has(transport.sessionId)) {\n sessions.delete(transport.sessionId)\n transport.close()\n }\n })\n\n await mcpServer.connect(transport)\n\n // Register session only after connect succeeds\n sessions.set(transport.sessionId, { transport, server: mcpServer })\n } else if (req.method === 'POST' && req.url?.startsWith('/message')) {\n // Route POST to the correct session\n const url = new URL(req.url, `http://${req.headers.host ?? 'localhost'}`)\n const sessionId = url.searchParams.get('sessionId')\n const session = sessionId ? sessions.get(sessionId) : null\n\n if (session) {\n await session.transport.handlePostMessage(req, res)\n } else {\n res.writeHead(404).end('Session not found')\n }\n } else {\n res.writeHead(404).end()\n }\n}\n\nfunction createSocketServer(socketPath: string): NetServer {\n cleanupSocket(socketPath)\n\n const server = createServer((socket) => {\n // FIX #6: Clean up old connection before accepting new one\n if (extensionSocket && !extensionSocket.destroyed) {\n process.stderr.write('[viyv-browser:mcp] Replacing existing extension connection\\n')\n extensionSocket.destroy()\n }\n\n process.stderr.write('[viyv-browser:mcp] Extension connected via Unix socket\\n')\n extensionSocket = socket\n setExtensionConnected(true)\n\n // NM3: Send session_init with protocol version on connection\n const agentId = getDefaultAgentId()\n createSession(agentId)\n const initMsg = {\n id: randomUUID(),\n type: 'session_init',\n agentId,\n protocolVersion: PROTOCOL_VERSION,\n timestamp: Date.now(),\n }\n socket.write(`${JSON.stringify(initMsg)}\\n`)\n\n // TCP stream fragmentation fix: line-based buffer\n let lineBuffer = ''\n\n socket.on('data', (data) => {\n lineBuffer += data.toString('utf-8')\n const lines = lineBuffer.split('\\n')\n lineBuffer = lines.pop() ?? '' // Keep incomplete last line\n for (const line of lines) {\n if (!line) continue\n try {\n let parsed = JSON.parse(line)\n // NM5: Handle compressed messages from Native Host\n if (parsed.type === 'compressed' && typeof parsed.data === 'string') {\n const decompressed = decompressPayload(parsed.data, true)\n parsed = JSON.parse(decompressed)\n }\n handleExtensionMessage(parsed)\n } catch (error) {\n process.stderr.write(`[viyv-browser:mcp] Parse error: ${(error as Error).message}\\n`)\n }\n }\n })\n\n socket.on('close', () => {\n process.stderr.write('[viyv-browser:mcp] Extension disconnected\\n')\n // Only clear if this is still the active socket\n if (extensionSocket === socket) {\n extensionSocket = null\n setExtensionConnected(false)\n }\n\n // Reject all pending requests on disconnect\n for (const [id, pending] of pendingRequests) {\n clearTimeout(pending.timer)\n pendingRequests.delete(id)\n pending.resolve({\n error: {\n code: 'EXTENSION_NOT_CONNECTED',\n message: 'Extension disconnected while request was pending',\n },\n })\n }\n })\n\n socket.on('error', (error) => {\n process.stderr.write(`[viyv-browser:mcp] Socket error: ${error.message}\\n`)\n })\n })\n\n server.listen(socketPath, () => {\n process.stderr.write(`[viyv-browser:mcp] Unix socket listening on ${socketPath}\\n`)\n })\n\n return server\n}\n\n// FIX #8: Validate message structure before processing\nfunction handleExtensionMessage(message: unknown) {\n if (!message || typeof message !== 'object') return\n const msg = message as Record<string, unknown>\n\n const type = typeof msg.type === 'string' ? msg.type : null\n const id = typeof msg.id === 'string' ? msg.id : null\n if (!type) return\n\n if (type === 'tool_result' && id) {\n const pending = pendingRequests.get(id)\n if (pending) {\n clearTimeout(pending.timer)\n pendingRequests.delete(id)\n\n if (msg.success) {\n pending.resolve((msg.result as Record<string, unknown>) ?? {})\n } else {\n const err = msg.error as Record<string, unknown> | undefined\n const code = typeof err?.code === 'string' ? err.code : 'UNKNOWN'\n const errMsg = typeof err?.message === 'string' ? err.message : 'Unknown error'\n pending.reject(new Error(`[${code}] ${errMsg}`))\n }\n }\n } else if (type === 'session_heartbeat') {\n recordHeartbeat()\n // NM6: Touch session on heartbeat\n const hbAgentId = typeof msg.agentId === 'string' ? msg.agentId : null\n if (hbAgentId) touchSession(hbAgentId)\n } else if (type === 'session_close') {\n // NH2: Clean up session resources on close\n const closeAgentId = typeof msg.agentId === 'string' ? msg.agentId : null\n if (closeAgentId) {\n closeSession(closeAgentId)\n // L2 FIX: Clean up stale event subscriptions for this agent\n removeSubscriptionsByAgent(closeAgentId)\n process.stderr.write(`[viyv-browser:mcp] Session closed and cleaned up: ${closeAgentId}\\n`)\n }\n } else if (type === 'session_recovery') {\n // NH2: Handle session recovery after SW restart\n const recoveryAgentId = typeof msg.agentId === 'string' ? msg.agentId : null\n if (recoveryAgentId) {\n createSession(recoveryAgentId)\n process.stderr.write(`[viyv-browser:mcp] Session recovered: ${recoveryAgentId}\\n`)\n }\n } else if (type === 'session_init') {\n // L3 FIX: Verify Extension's protocol version (bidirectional check)\n const remoteVersion = typeof msg.protocolVersion === 'string' ? msg.protocolVersion : null\n if (remoteVersion && remoteVersion !== PROTOCOL_VERSION) {\n process.stderr.write(\n `[viyv-browser:mcp] Protocol version mismatch: local=${PROTOCOL_VERSION}, remote=${remoteVersion}\\n`,\n )\n }\n } else if (type === 'browser_event') {\n process.stderr.write(`[viyv-browser:mcp] Browser event: ${String(msg.eventType)}\\n`)\n processEvent({\n eventType: msg.eventType as import('@viyv-browser/shared').BrowserEventType,\n agentId: String(msg.agentId ?? ''),\n tabId: Number(msg.tabId ?? 0),\n url: String(msg.url ?? ''),\n payload: (msg.payload as Record<string, unknown>) ?? {},\n sequenceNumber: Number(msg.sequenceNumber ?? 0),\n })\n }\n}\n\nasync function callExtensionTool(\n tool: string,\n input: Record<string, unknown>,\n): Promise<{ content: Array<{ type: string; text: string }> }> {\n // switch_browser is handled server-side: disconnect and wait for reconnection\n if (tool === 'switch_browser') {\n return handleSwitchBrowser()\n }\n\n if (!extensionSocket || extensionSocket.destroyed) {\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: {\n code: 'EXTENSION_NOT_CONNECTED',\n message:\n 'Chrome Extension is not connected. Please open Chrome and click the Viyv Browser extension icon.',\n },\n }),\n },\n ],\n }\n }\n\n const requestId = randomUUID()\n const agentId = getDefaultAgentId()\n\n // NM6: Touch session to record activity\n touchSession(agentId)\n\n // Capture socket reference before entering Promise to avoid null race\n const sock = extensionSocket\n\n // Per-tool timeout: wait_for gets the tool's timeout + 5s buffer\n let toolTimeout = TIMEOUTS.MCP_TOOL\n if (tool === 'wait_for' && typeof input.timeout === 'number') {\n toolTimeout = input.timeout + 5000\n }\n\n return new Promise((resolve) => {\n // M3 FIX: Define error listener before timer so removeErrorListener is callable from timeout\n const onError = () => {\n const pending = pendingRequests.get(requestId)\n if (pending) {\n clearTimeout(pending.timer)\n pendingRequests.delete(requestId)\n resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: {\n code: 'EXTENSION_NOT_CONNECTED',\n message: 'Socket write failed',\n },\n }),\n },\n ],\n })\n }\n }\n\n const removeErrorListener = () => {\n sock.removeListener('error', onError)\n }\n\n const timer = setTimeout(() => {\n pendingRequests.delete(requestId)\n removeErrorListener()\n resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: {\n code: 'TIMEOUT',\n message: `Tool '${tool}' timed out after ${toolTimeout}ms`,\n },\n }),\n },\n ],\n })\n }, toolTimeout)\n\n pendingRequests.set(requestId, {\n resolve: (result) => {\n removeErrorListener()\n resolve({\n content: [{ type: 'text', text: JSON.stringify(result) }],\n })\n },\n reject: (error) => {\n removeErrorListener()\n resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: { code: 'CDP_ERROR', message: error.message },\n }),\n },\n ],\n })\n },\n timer,\n })\n\n // FIX #7: Handle socket write errors\n const request = {\n id: requestId,\n type: 'tool_call',\n agentId,\n tool,\n input,\n timestamp: Date.now(),\n }\n\n const written = sock.write(`${JSON.stringify(request)}\\n`)\n if (!written) {\n // Backpressure -- wait for drain but don't block\n sock.once('drain', () => {\n // Buffer flushed, nothing to do\n })\n }\n\n sock.once('error', onError)\n })\n}\n\nasync function handleSwitchBrowser(): Promise<{\n content: Array<{ type: string; text: string }>\n}> {\n const SWITCH_TIMEOUT = 60_000\n\n // Close existing connection gracefully\n if (extensionSocket && !extensionSocket.destroyed) {\n process.stderr.write('[viyv-browser:mcp] switch_browser: closing current connection\\n')\n extensionSocket.destroy()\n extensionSocket = null\n setExtensionConnected(false)\n }\n\n // Wait for a new connection\n process.stderr.write('[viyv-browser:mcp] switch_browser: waiting for new browser connection...\\n')\n return new Promise((resolve) => {\n const checkInterval = setInterval(() => {\n if (extensionSocket && !extensionSocket.destroyed && isExtensionConnected()) {\n clearInterval(checkInterval)\n clearTimeout(timer)\n resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n switched: true,\n message: 'Successfully connected to new browser instance.',\n }),\n },\n ],\n })\n }\n }, 500)\n\n const timer = setTimeout(() => {\n clearInterval(checkInterval)\n resolve({\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n error: {\n code: 'TIMEOUT',\n message: `No new browser connected within ${SWITCH_TIMEOUT / 1000}s. Please open Chrome and click the Viyv Browser extension icon.`,\n },\n }),\n },\n ],\n })\n }, SWITCH_TIMEOUT)\n })\n}\n\nfunction cleanupSocket(socketPath: string) {\n if (existsSync(socketPath)) {\n try {\n unlinkSync(socketPath)\n } catch {\n // Ignore -- may be cleaned up by another process\n }\n }\n}\n","/** Protocol version for compatibility checks */\nexport const PROTOCOL_VERSION = '1.0.0'\n\n/** Native Messaging host name (must match manifest) */\nexport const NATIVE_HOST_NAME = 'com.viyv.browser'\n\n/** Extension ID (will be assigned by CWS) */\nexport const EXTENSION_ID = '' // Set after CWS registration\n\n// ── Timeouts (ms) ──\n\nexport const TIMEOUTS = {\n /** Overall MCP tool timeout */\n MCP_TOOL: 30_000,\n /** Native Messaging request timeout */\n NATIVE_MESSAGE: 15_000,\n /** CDP command timeout */\n CDP_COMMAND: 10_000,\n /** Screenshot capture timeout */\n SCREENSHOT: 5_000,\n /** Navigation timeout */\n NAVIGATION: 30_000,\n /** Chunk reassembly timeout */\n CHUNK_REASSEMBLY: 10_000,\n /** Default wait_for timeout */\n WAIT_FOR: 30_000,\n /** Heartbeat interval */\n HEARTBEAT: 30_000,\n /** CDP idle detach delay */\n CDP_IDLE_DETACH: 5_000,\n /** Tab lock TTL (deadlock prevention) */\n TAB_LOCK_TTL: 60_000,\n} as const\n\n// ── Limits ──\n\nexport const LIMITS = {\n /** Native Messaging max message size (Chrome limit) */\n NATIVE_MESSAGE_MAX_BYTES: 1024 * 1024,\n /** Chunk size for large payloads */\n CHUNK_SIZE: 768 * 1024,\n /** A11y tree max elements */\n A11Y_MAX_ELEMENTS: 5000,\n /** A11y tree default depth */\n A11Y_DEFAULT_DEPTH: 8,\n /** A11y tree default max chars */\n A11Y_DEFAULT_MAX_CHARS: 50_000,\n /** Event buffer max entries */\n EVENT_BUFFER_MAX: 1000,\n /** Event buffer max bytes */\n EVENT_BUFFER_MAX_BYTES: 10 * 1024 * 1024,\n /** Message buffer during disconnection */\n MESSAGE_BUFFER_MAX: 1000,\n /** Default screenshot JPEG quality */\n SCREENSHOT_JPEG_QUALITY: 80,\n /** Console buffer per tab */\n CONSOLE_BUFFER_MAX: 1000,\n /** Network buffer per tab */\n NETWORK_BUFFER_MAX: 1000,\n} as const\n\n// ── Reconnection ──\n\nexport const RECONNECT = {\n /** Initial delay (ms) */\n INITIAL_DELAY: 1000,\n /** Max delay (ms) */\n MAX_DELAY: 30_000,\n /** Backoff multiplier */\n MULTIPLIER: 2,\n} as const\n\n// ── Keep-alive ──\n\nexport const KEEP_ALIVE = {\n /** Alarm name for backup keep-alive */\n ALARM_NAME: 'viyv-browser-keepalive',\n /** Alarm period (minutes) - minimum for Chrome alarms */\n ALARM_PERIOD_MIN: 0.5,\n} as const\n\n// ── MCP Server ──\n\nexport const MCP_SERVER = {\n /** Server name for MCP protocol */\n NAME: 'viyv-browser',\n /** Server version */\n VERSION: '0.1.0',\n /** Unix socket path template */\n SOCKET_PATH_TEMPLATE: '/tmp/viyv-browser-{pid}.sock',\n} as const\n","/**\n * Multi-agent session management.\n * Tracks which agents are connected and their session tokens.\n */\n\nimport { randomUUID } from 'node:crypto'\n\ninterface AgentSessionInfo {\n agentId: string\n sessionToken: string\n agentName: string\n status: 'active' | 'idle' | 'disconnected'\n lastActivity: number\n createdAt: number\n}\n\nconst sessions = new Map<string, AgentSessionInfo>()\nlet configuredDefaultAgentId = 'default'\n\nexport function setDefaultAgentId(id: string): void {\n configuredDefaultAgentId = id\n}\n\nexport function createSession(agentId: string, agentName?: string): AgentSessionInfo {\n const existing = sessions.get(agentId)\n if (existing) {\n existing.lastActivity = Date.now()\n existing.status = 'active'\n return existing\n }\n\n const session: AgentSessionInfo = {\n agentId,\n sessionToken: randomUUID(),\n agentName: agentName ?? agentId,\n status: 'active',\n lastActivity: Date.now(),\n createdAt: Date.now(),\n }\n\n sessions.set(agentId, session)\n return session\n}\n\nexport function getSession(agentId: string): AgentSessionInfo | undefined {\n return sessions.get(agentId)\n}\n\nexport function validateSession(agentId: string, sessionToken: string): boolean {\n const session = sessions.get(agentId)\n return session?.sessionToken === sessionToken\n}\n\nexport function touchSession(agentId: string): void {\n const session = sessions.get(agentId)\n if (session) {\n session.lastActivity = Date.now()\n }\n}\n\nexport function closeSession(agentId: string): void {\n sessions.delete(agentId)\n}\n\nexport function listSessions(): AgentSessionInfo[] {\n return Array.from(sessions.values())\n}\n\nexport function getDefaultAgentId(): string {\n // Return the first active session, or create a default\n const active = Array.from(sessions.values()).find((s) => s.status === 'active')\n if (active) return active.agentId\n\n const defaultSession = createSession(configuredDefaultAgentId)\n return defaultSession.agentId\n}\n\nconst STALE_SESSION_TTL = 5 * 60 * 1000 // 5 minutes\nconst CLEANUP_INTERVAL = 60 * 1000 // Check every minute\n\nexport function cleanupStaleSessions(): number {\n const now = Date.now()\n let cleaned = 0\n for (const [agentId, session] of sessions) {\n if (now - session.lastActivity > STALE_SESSION_TTL) {\n sessions.delete(agentId)\n cleaned++\n }\n }\n if (cleaned > 0) {\n process.stderr.write(\n `[viyv-browser:mcp] Cleaned up ${cleaned} stale session(s)\\n`,\n )\n }\n return cleaned\n}\n\n// Periodic stale session cleanup\nconst cleanupTimer = setInterval(cleanupStaleSessions, CLEANUP_INTERVAL)\ncleanupTimer.unref() // Don't prevent process from exiting\n","/**\n * Event bridge: forwards browser events from Extension to stdout\n * for consumption by viyv Daemon EventTriggerManager.\n */\n\nimport type { BrowserEventType, EventSubscription } from '@viyv-browser/shared'\n\nconst subscriptions = new Map<string, EventSubscription>()\nconst eventListeners = new Set<(event: Record<string, unknown>) => void>()\n\nexport function addEventListener(cb: (event: Record<string, unknown>) => void) {\n eventListeners.add(cb)\n}\n\nexport function removeEventListener(cb: (event: Record<string, unknown>) => void) {\n eventListeners.delete(cb)\n}\n\nexport function addSubscription(sub: EventSubscription): void {\n subscriptions.set(sub.id, sub)\n}\n\nexport function removeSubscription(subId: string): boolean {\n return subscriptions.delete(subId)\n}\n\n// L2 FIX: Remove all subscriptions for an agent on session close\nexport function removeSubscriptionsByAgent(agentId: string): number {\n let removed = 0\n for (const [id, sub] of subscriptions) {\n if (sub.agentId === agentId) {\n subscriptions.delete(id)\n removed++\n }\n }\n return removed\n}\n\nexport function getSubscriptions(agentId?: string): EventSubscription[] {\n const subs = Array.from(subscriptions.values())\n if (agentId) return subs.filter((s) => s.agentId === agentId)\n return subs\n}\n\nexport function processEvent(event: {\n eventType: BrowserEventType\n agentId: string\n tabId: number\n url: string\n payload: Record<string, unknown>\n sequenceNumber: number\n}): void {\n // Check subscriptions\n for (const sub of subscriptions.values()) {\n if (sub.agentId !== event.agentId) continue\n if (!sub.eventTypes.includes(event.eventType)) continue\n if (sub.urlPattern && !event.url.includes(sub.urlPattern)) continue\n\n // Forward to all listeners\n const payload = {\n type: 'browser_event',\n subscriptionId: sub.id,\n ...event,\n timestamp: Date.now(),\n }\n for (const listener of eventListeners) {\n listener(payload)\n }\n }\n}\n","/**\n * Health check for MCP Server ↔ Extension connection.\n */\n\nlet extensionConnected = false\nlet lastHeartbeat: number | null = null\n\nexport function setExtensionConnected(connected: boolean) {\n extensionConnected = connected\n if (connected) lastHeartbeat = Date.now()\n}\n\nexport function recordHeartbeat() {\n lastHeartbeat = Date.now()\n}\n\nconst HEARTBEAT_STALENESS_MS = 60_000\n\nexport function isExtensionConnected(): boolean {\n if (!extensionConnected) return false\n // Also verify heartbeat is within staleness threshold\n if (lastHeartbeat !== null && Date.now() - lastHeartbeat > HEARTBEAT_STALENESS_MS) {\n return false\n }\n return true\n}\n\nexport function getHealthStatus() {\n return {\n extensionConnected,\n lastHeartbeat,\n uptime: process.uptime(),\n memoryUsage: process.memoryUsage().heapUsed,\n }\n}\n","/**\n * Compression utilities for large payloads.\n * Used when messages approach the 1MB Native Messaging limit.\n */\n\nimport { gzipSync, gunzipSync } from 'node:zlib'\nimport type { ChunkedMessage } from '@viyv-browser/shared'\n\nconst CHUNK_SIZE = 768 * 1024 // 768KB per chunk\n\n// Use shared ChunkedMessage as the canonical type\nexport type ChunkedPayload = ChunkedMessage\n\nexport function compressPayload(data: string): { compressed: string; wasCompressed: boolean } {\n const original = Buffer.from(data, 'utf-8')\n const gzipped = gzipSync(original)\n\n if (gzipped.length < original.length) {\n return { compressed: gzipped.toString('base64'), wasCompressed: true }\n }\n return { compressed: data, wasCompressed: false }\n}\n\nexport function decompressPayload(data: string, isCompressed: boolean): string {\n if (!isCompressed) return data\n const buf = Buffer.from(data, 'base64')\n return gunzipSync(buf).toString('utf-8')\n}\n\nexport function chunkPayload(\n requestId: string,\n agentId: string,\n data: string,\n compressed: boolean,\n): ChunkedPayload[] {\n const totalSize = data.length\n const totalChunks = Math.ceil(totalSize / CHUNK_SIZE)\n const chunks: ChunkedPayload[] = []\n\n for (let i = 0; i < totalChunks; i++) {\n chunks.push({\n type: 'chunk',\n requestId,\n agentId,\n chunkIndex: i,\n totalChunks,\n totalSize,\n compressed,\n data: data.slice(i * CHUNK_SIZE, (i + 1) * CHUNK_SIZE),\n })\n }\n\n return chunks\n}\n\n// FIX #20: Guard against empty chunks array\nexport function reassembleChunks(chunks: ChunkedPayload[]): string {\n if (chunks.length === 0) {\n throw new Error('Cannot reassemble: no chunks provided')\n }\n\n const sorted = [...chunks].sort((a, b) => a.chunkIndex - b.chunkIndex)\n\n if (sorted.length !== sorted[0].totalChunks) {\n throw new Error(\n `Incomplete chunks: got ${sorted.length}, expected ${sorted[0].totalChunks}`,\n )\n }\n\n const data = sorted.map((c) => c.data).join('')\n return decompressPayload(data, sorted[0].compressed)\n}\n","/**\n * Tool registry: defines all MCP tools and their schemas.\n */\n\nimport { z } from 'zod'\n\nimport { GIF_CREATOR_DESCRIPTION } from './advanced/gif-creator.js'\nimport { RESIZE_WINDOW_DESCRIPTION } from './advanced/resize-window.js'\nimport { SHORTCUTS_EXECUTE_DESCRIPTION } from './advanced/shortcuts-execute.js'\nimport { SHORTCUTS_LIST_DESCRIPTION } from './advanced/shortcuts-list.js'\nimport { SWITCH_BROWSER_DESCRIPTION } from './advanced/switch-browser.js'\nimport { UPDATE_PLAN_DESCRIPTION } from './advanced/update-plan.js'\nimport { UPLOAD_IMAGE_DESCRIPTION } from './advanced/upload-image.js'\nimport { CLICK_DESCRIPTION } from './core/click.js'\nimport { DRAG_DESCRIPTION } from './core/drag.js'\nimport { FIND_DESCRIPTION } from './core/find.js'\nimport { FORM_INPUT_DESCRIPTION } from './core/form-input.js'\nimport { GET_PAGE_TEXT_DESCRIPTION } from './core/get-page-text.js'\nimport { HANDLE_DIALOG_DESCRIPTION } from './core/handle-dialog.js'\nimport { HOVER_DESCRIPTION } from './core/hover.js'\nimport { JAVASCRIPT_EXEC_DESCRIPTION } from './core/javascript-exec.js'\nimport { KEY_DESCRIPTION } from './core/key.js'\nimport { NAVIGATE_DESCRIPTION } from './core/navigate.js'\nimport { READ_PAGE_DESCRIPTION } from './core/read-page.js'\nimport { SCREENSHOT_DESCRIPTION } from './core/screenshot.js'\nimport { SCROLL_DESCRIPTION } from './core/scroll.js'\nimport { TYPE_DESCRIPTION } from './core/type.js'\nimport { WAIT_FOR_DESCRIPTION } from './core/wait-for.js'\nimport { READ_CONSOLE_MESSAGES_DESCRIPTION } from './debug/read-console-messages.js'\nimport { READ_NETWORK_REQUESTS_DESCRIPTION } from './debug/read-network-requests.js'\nimport { SELECT_TAB_DESCRIPTION } from './tabs/select-tab.js'\nimport { TAB_CLOSE_DESCRIPTION } from './tabs/tab-close.js'\nimport { TABS_CONTEXT_DESCRIPTION } from './tabs/tabs-context.js'\nimport { TABS_CREATE_DESCRIPTION } from './tabs/tabs-create.js'\nimport { AGENT_TAB_ASSIGN_DESCRIPTION } from './viyv/agent-tab-assign.js'\nimport { AGENT_TAB_LIST_DESCRIPTION } from './viyv/agent-tab-list.js'\nimport { ARTIFACT_FROM_PAGE_DESCRIPTION } from './viyv/artifact-from-page.js'\nimport { BROWSER_EVENT_SUBSCRIBE_DESCRIPTION } from './viyv/browser-event-subscribe.js'\nimport { BROWSER_EVENT_UNSUBSCRIBE_DESCRIPTION } from './viyv/browser-event-unsubscribe.js'\nimport { BROWSER_HEALTH_DESCRIPTION } from './viyv/browser-health.js'\nimport { PAGE_DATA_EXTRACT_DESCRIPTION } from './viyv/page-data-extract.js'\n\nexport interface ToolDefinition {\n name: string\n description: string\n inputSchema: z.ZodType\n}\n\n// ── Core Browser Tools ──\n\nexport const navigateTool: ToolDefinition = {\n name: 'navigate',\n description: NAVIGATE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID to navigate'),\n url: z.string().describe('URL to navigate to, or \"back\"/\"forward\" for history'),\n }),\n}\n\nexport const screenshotTool: ToolDefinition = {\n name: 'screenshot',\n description: SCREENSHOT_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID to capture'),\n format: z.enum(['jpeg', 'png']).optional().describe('Image format (default: jpeg)'),\n quality: z.number().min(1).max(100).optional().describe('JPEG quality (default: 80)'),\n region: z\n .tuple([z.number(), z.number(), z.number(), z.number()])\n .optional()\n .describe('Capture region [x0, y0, x1, y1]'),\n }),\n}\n\nexport const clickTool: ToolDefinition = {\n name: 'click',\n description: CLICK_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n coordinate: z\n .tuple([z.number(), z.number()])\n .optional()\n .describe('Click position [x, y]'),\n ref: z.string().optional().describe('Element reference ID'),\n action: z\n .enum(['left_click', 'right_click', 'double_click', 'triple_click'])\n .optional()\n .describe('Click type (default: left_click)'),\n modifiers: z.string().optional().describe('Modifier keys (e.g., \"ctrl+shift\")'),\n }),\n}\n\nexport const typeTool: ToolDefinition = {\n name: 'type',\n description: TYPE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n text: z.string().describe('Text to type'),\n }),\n}\n\nexport const keyTool: ToolDefinition = {\n name: 'key',\n description: KEY_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n keys: z.string().describe('Space-separated keys (e.g., \"Enter\", \"ctrl+a\")'),\n repeat: z.number().min(1).max(100).optional().describe('Repeat count'),\n }),\n}\n\nexport const scrollTool: ToolDefinition = {\n name: 'scroll',\n description: SCROLL_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n coordinate: z\n .tuple([z.number(), z.number()])\n .optional()\n .describe('Scroll position [x, y] (required for directional scroll)'),\n direction: z\n .enum(['up', 'down', 'left', 'right'])\n .optional()\n .describe('Scroll direction (required for directional scroll)'),\n amount: z.number().min(1).max(10).optional().describe('Scroll amount (default: 3)'),\n ref: z.string().optional().describe('Element reference ID to scroll into view'),\n }),\n}\n\nexport const hoverTool: ToolDefinition = {\n name: 'hover',\n description: HOVER_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n coordinate: z.tuple([z.number(), z.number()]).optional().describe('Hover position [x, y]'),\n ref: z.string().optional().describe('Element reference ID'),\n }),\n}\n\nexport const dragTool: ToolDefinition = {\n name: 'drag',\n description: DRAG_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n startCoordinate: z.tuple([z.number(), z.number()]).describe('Start position [x, y]'),\n endCoordinate: z.tuple([z.number(), z.number()]).describe('End position [x, y]'),\n }),\n}\n\nexport const readPageTool: ToolDefinition = {\n name: 'read_page',\n description: READ_PAGE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n filter: z\n .enum(['interactive', 'all'])\n .optional()\n .describe('Filter: \"interactive\" for buttons/links/inputs, \"all\" for everything'),\n depth: z.number().min(1).max(20).optional().describe('Max tree depth (default: 8)'),\n refId: z.string().optional().describe('Focus on a specific element by ref'),\n maxChars: z.number().optional().describe('Max output characters (default: 50000)'),\n }),\n}\n\nexport const findTool: ToolDefinition = {\n name: 'find',\n description: FIND_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n query: z.string().describe('Natural language description of what to find'),\n }),\n}\n\nexport const formInputTool: ToolDefinition = {\n name: 'form_input',\n description: FORM_INPUT_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n ref: z.string().describe('Element reference ID'),\n value: z.union([z.string(), z.boolean(), z.number()]).describe('Value to set'),\n }),\n}\n\nexport const javascriptExecTool: ToolDefinition = {\n name: 'javascript_exec',\n description: JAVASCRIPT_EXEC_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n code: z.string().describe('JavaScript code to execute'),\n }),\n}\n\nexport const waitForTool: ToolDefinition = {\n name: 'wait_for',\n description: WAIT_FOR_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n selector: z.string().optional().describe('CSS selector to wait for'),\n navigation: z.boolean().optional().describe('Wait for navigation to complete'),\n timeout: z.number().optional().describe('Timeout in ms (default: 30000)'),\n }),\n}\n\nexport const getPageTextTool: ToolDefinition = {\n name: 'get_page_text',\n description: GET_PAGE_TEXT_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n }),\n}\n\nexport const handleDialogTool: ToolDefinition = {\n name: 'handle_dialog',\n description: HANDLE_DIALOG_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n action: z.enum(['accept', 'dismiss']).describe('Dialog action'),\n text: z.string().optional().describe('Text for prompt dialog'),\n }),\n}\n\n// ── Tab Management Tools ──\n\nexport const tabsContextTool: ToolDefinition = {\n name: 'tabs_context',\n description: TABS_CONTEXT_DESCRIPTION,\n inputSchema: z.object({\n createIfEmpty: z\n .boolean()\n .optional()\n .describe('Create a new tab group if none exists'),\n }),\n}\n\nexport const tabsCreateTool: ToolDefinition = {\n name: 'tabs_create',\n description: TABS_CREATE_DESCRIPTION,\n inputSchema: z.object({\n url: z.string().optional().describe('URL to open in the new tab'),\n }),\n}\n\nexport const tabCloseTool: ToolDefinition = {\n name: 'tab_close',\n description: TAB_CLOSE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID to close'),\n }),\n}\n\nexport const selectTabTool: ToolDefinition = {\n name: 'select_tab',\n description: SELECT_TAB_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID to focus'),\n }),\n}\n\n// ── Debug Tools ──\n\nexport const readConsoleMessagesTool: ToolDefinition = {\n name: 'read_console_messages',\n description: READ_CONSOLE_MESSAGES_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n pattern: z.string().optional().describe('Regex pattern to filter messages'),\n onlyErrors: z.boolean().optional().describe('Only return errors'),\n limit: z.number().optional().describe('Max messages to return (default: 100)'),\n clear: z.boolean().optional().describe('Clear messages after reading'),\n }),\n}\n\nexport const readNetworkRequestsTool: ToolDefinition = {\n name: 'read_network_requests',\n description: READ_NETWORK_REQUESTS_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n urlPattern: z.string().optional().describe('URL pattern to filter requests'),\n limit: z.number().optional().describe('Max requests to return (default: 100)'),\n clear: z.boolean().optional().describe('Clear requests after reading'),\n }),\n}\n\n// ── Advanced Tools ──\n\nexport const gifCreatorTool: ToolDefinition = {\n name: 'gif_creator',\n description: GIF_CREATOR_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n action: z\n .enum(['start_recording', 'stop_recording', 'export', 'clear'])\n .describe('GIF action'),\n filename: z.string().optional().describe('Filename for export'),\n options: z\n .object({\n showClickIndicators: z.boolean().optional(),\n showDragPaths: z.boolean().optional(),\n showActionLabels: z.boolean().optional(),\n showProgressBar: z.boolean().optional(),\n showWatermark: z.boolean().optional(),\n quality: z.number().min(1).max(30).optional(),\n })\n .optional()\n .describe('GIF rendering options'),\n download: z.boolean().optional().describe('Download the GIF'),\n }),\n}\n\nexport const uploadImageTool: ToolDefinition = {\n name: 'upload_image',\n description: UPLOAD_IMAGE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n imageId: z.string().describe('Image ID from a previous screenshot'),\n ref: z.string().optional().describe('Element reference for file input'),\n coordinate: z\n .tuple([z.number(), z.number()])\n .optional()\n .describe('Coordinates for drag & drop'),\n }),\n}\n\nexport const updatePlanTool: ToolDefinition = {\n name: 'update_plan',\n description: UPDATE_PLAN_DESCRIPTION,\n inputSchema: z.object({\n domains: z.array(z.string()).describe('Domains to visit'),\n approach: z.array(z.string()).describe('Steps in the plan'),\n }),\n}\n\nexport const resizeWindowTool: ToolDefinition = {\n name: 'resize_window',\n description: RESIZE_WINDOW_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n width: z.number().describe('Window width in pixels'),\n height: z.number().describe('Window height in pixels'),\n }),\n}\n\nexport const shortcutsListTool: ToolDefinition = {\n name: 'shortcuts_list',\n description: SHORTCUTS_LIST_DESCRIPTION,\n inputSchema: z.object({\n tabId: z\n .number()\n .optional()\n .describe('Tab ID (used to identify the tab group context)'),\n }),\n}\n\nexport const shortcutsExecuteTool: ToolDefinition = {\n name: 'shortcuts_execute',\n description: SHORTCUTS_EXECUTE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID to execute the shortcut on'),\n command: z.string().optional().describe('Command name of the shortcut'),\n shortcutId: z.string().optional().describe('ID of the shortcut'),\n }),\n}\n\nexport const switchBrowserTool: ToolDefinition = {\n name: 'switch_browser',\n description: SWITCH_BROWSER_DESCRIPTION,\n inputSchema: z.object({}),\n}\n\n// ── viyv Integration Tools ──\n\nexport const agentTabAssignTool: ToolDefinition = {\n name: 'agent_tab_assign',\n description: AGENT_TAB_ASSIGN_DESCRIPTION,\n inputSchema: z.object({\n agentId: z.string().describe('Agent ID'),\n agentName: z.string().describe('Display name'),\n color: z.string().optional().describe('Tab group color'),\n }),\n}\n\nexport const agentTabListTool: ToolDefinition = {\n name: 'agent_tab_list',\n description: AGENT_TAB_LIST_DESCRIPTION,\n inputSchema: z.object({}),\n}\n\nexport const browserEventSubscribeTool: ToolDefinition = {\n name: 'browser_event_subscribe',\n description: BROWSER_EVENT_SUBSCRIBE_DESCRIPTION,\n inputSchema: z.object({\n eventTypes: z.array(z.string()).describe('Event types to subscribe to'),\n urlPattern: z.string().optional().describe('URL pattern filter'),\n conditions: z.record(z.unknown()).optional().describe('Additional conditions'),\n }),\n}\n\nexport const browserEventUnsubscribeTool: ToolDefinition = {\n name: 'browser_event_unsubscribe',\n description: BROWSER_EVENT_UNSUBSCRIBE_DESCRIPTION,\n inputSchema: z.object({\n subscriptionId: z.string().describe('Subscription ID'),\n }),\n}\n\nexport const artifactFromPageTool: ToolDefinition = {\n name: 'artifact_from_page',\n description: ARTIFACT_FROM_PAGE_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n type: z.string().describe('Artifact type (text, html, screenshot)'),\n title: z.string().optional().describe('Artifact title'),\n }),\n}\n\nexport const pageDataExtractTool: ToolDefinition = {\n name: 'page_data_extract',\n description: PAGE_DATA_EXTRACT_DESCRIPTION,\n inputSchema: z.object({\n tabId: z.number().describe('Tab ID'),\n schema: z.record(z.unknown()).describe('Data extraction schema'),\n selector: z.string().optional().describe('CSS selector to scope extraction'),\n }),\n}\n\nexport const browserHealthTool: ToolDefinition = {\n name: 'browser_health',\n description: BROWSER_HEALTH_DESCRIPTION,\n inputSchema: z.object({}),\n}\n\n// ── All Tools ──\n\nexport const allTools: ToolDefinition[] = [\n // Core (15)\n navigateTool,\n screenshotTool,\n clickTool,\n typeTool,\n keyTool,\n scrollTool,\n hoverTool,\n dragTool,\n readPageTool,\n findTool,\n formInputTool,\n javascriptExecTool,\n waitForTool,\n getPageTextTool,\n handleDialogTool,\n // Tabs (4)\n tabsContextTool,\n tabsCreateTool,\n tabCloseTool,\n selectTabTool,\n // Debug (2)\n readConsoleMessagesTool,\n readNetworkRequestsTool,\n // Advanced (7)\n gifCreatorTool,\n uploadImageTool,\n updatePlanTool,\n resizeWindowTool,\n shortcutsListTool,\n shortcutsExecuteTool,\n switchBrowserTool,\n // viyv Integration (7)\n agentTabAssignTool,\n agentTabListTool,\n browserEventSubscribeTool,\n browserEventUnsubscribeTool,\n artifactFromPageTool,\n pageDataExtractTool,\n browserHealthTool,\n]\n","export const GIF_CREATOR_DESCRIPTION = `Record a GIF of browser activity.\nCaptures a sequence of screenshots over a specified duration\nand assembles them into an animated GIF. Useful for documenting\nvisual interactions or creating shareable recordings of workflows.`\n","export const RESIZE_WINDOW_DESCRIPTION = `Resize the browser window to specified dimensions.\nSets the width and height of the browser viewport, useful for\ntesting responsive layouts or ensuring consistent screenshot\ndimensions across different operations.`\n","export const SHORTCUTS_EXECUTE_DESCRIPTION = `Execute a shortcut or workflow by command name or ID.\n\nRuns the specified shortcut in the side panel using the current tab.\nLook up by command name or shortcutId. Use shortcuts_list first\nto see available shortcuts.`\n","export const SHORTCUTS_LIST_DESCRIPTION = `List all available shortcuts and workflows.\n\nReturns registered shortcuts with their commands, descriptions,\nand whether they are workflows. Shortcuts can be executed using\nthe shortcuts_execute tool.`\n","export const SWITCH_BROWSER_DESCRIPTION = `Switch to a different Chrome browser instance.\n\nDisconnects the current Extension connection and waits for a new\nChrome browser to connect (up to 60s). The user should click\n\"Connect\" in the desired browser's extension.`\n","export const UPDATE_PLAN_DESCRIPTION = `Present a step-by-step plan to the user for review.\nDisplays the proposed sequence of actions the agent intends to take,\nallowing the user to approve, modify, or reject the plan before\nexecution begins.`\n","export const UPLOAD_IMAGE_DESCRIPTION = `Upload an image to a file input element on the page.\nAccepts a local file path or base64-encoded image data and\nprogrammatically sets it on the target file input. Supports\ncommon image formats including PNG, JPEG, GIF, and WebP.`\n","export const CLICK_DESCRIPTION = `Click at coordinates or on a referenced element.\n\nProvide either coordinate [x, y] or ref (element reference from read_page/find).\nActions: left_click (default), right_click, double_click, triple_click.\nSupports modifier keys: ctrl, shift, alt, cmd (e.g., \"ctrl+shift\").`\n","export const DRAG_DESCRIPTION = `Drag from one coordinate to another.\n\nPerforms mousedown at start, mousemove to end, then mouseup.`\n","export const FIND_DESCRIPTION = `Find elements on the page using a natural language query.\nSearches the DOM for elements matching the given description,\nreturning references that can be used for subsequent interactions\nsuch as clicking, typing, or extracting content.`\n","export const FORM_INPUT_DESCRIPTION = `Set a value in a form element identified by its ref.\nSupports text inputs, textareas, selects, checkboxes, and radio buttons.\nThe ref must be obtained from a prior find or snapshot operation\nto ensure the correct element is targeted.`\n","export const GET_PAGE_TEXT_DESCRIPTION = `Extract readable text content from the current page.\nStrips away HTML tags, scripts, and styles to return a clean\ntext representation of the visible page content, suitable for\nanalysis, summarization, or further processing.`\n","export const HANDLE_DIALOG_DESCRIPTION = `Handle JavaScript dialogs such as alert, confirm, and prompt.\nAllows accepting or dismissing the dialog, and optionally providing\ninput text for prompt dialogs. Must be called while a dialog\nis actively displayed on the page.`\n","export const HOVER_DESCRIPTION = `Move mouse to coordinates or element without clicking.\n\nUseful for revealing tooltips, dropdown menus, or triggering hover states.`\n","export const JAVASCRIPT_EXEC_DESCRIPTION = `Execute arbitrary JavaScript code in the page context.\nThe script runs in the main world of the active page and can access\nthe DOM, window object, and any page-level APIs. Returns the\nserialized result of the last evaluated expression.`\n","export const KEY_DESCRIPTION = `Press keyboard key(s).\n\nSpace-separated key names. Supports keyboard shortcuts.\nExamples: \"Enter\", \"Tab\", \"Backspace\", \"ctrl+a\", \"cmd+c\".\nUse repeat parameter for repeated presses (e.g., arrow keys).`\n","export const NAVIGATE_DESCRIPTION = `Navigate to a URL, or go forward/back in browser history.\n\nUse \"back\" to go back in history, \"forward\" to go forward.\nProvide a full URL (with protocol) to navigate to a new page.\nWaits for page load to complete before returning.`\n","export const READ_PAGE_DESCRIPTION = `Get accessibility tree representation of page elements.\n\nSupports:\n- filter: \"interactive\" for buttons/links/inputs only, \"all\" for everything\n- depth: max tree depth (1-20, default 8)\n- refId: focus on a specific element subtree\n- maxChars: limit output size (default 50000)\n\nReturns elements with ref IDs that can be used with click, form_input, etc.`\n","export const SCREENSHOT_DESCRIPTION = `Take a screenshot of a tab.\n\nReturns base64-encoded image data.\nDefault format is JPEG with quality 80 (optimized for Native Messaging 1MB limit).\nUse PNG for lossless screenshots when needed.\nOptionally capture a specific region [x0, y0, x1, y1].`\n","export const SCROLL_DESCRIPTION = `Scroll in a direction at given coordinates, or scroll an element into view by ref.\n\nTwo modes:\n1. Directional scroll: provide coordinate + direction (+ optional amount 1-10, default 3).\n2. Scroll to element: provide ref (element reference ID from read_page/find). Scrolls the element into view using smooth scrolling.`\n","export const TYPE_DESCRIPTION = `Type text into the currently focused element.\n\nEach character is typed individually with keyDown/keyUp events.\nFor special keys (Enter, Tab, etc.), use the 'key' tool instead.`\n","export const WAIT_FOR_DESCRIPTION = `Wait for a specified condition before proceeding.\nSupports waiting for a CSS selector to appear in the DOM,\nfor a navigation event to complete, or for a fixed timeout duration.\nUseful for synchronizing with asynchronous page updates.`\n","export const READ_CONSOLE_MESSAGES_DESCRIPTION = `Read console messages captured from the page.\nReturns log, warning, error, and info messages that have been\nemitted by page scripts. Supports filtering by log level\nand limiting the number of returned entries.`\n","export const READ_NETWORK_REQUESTS_DESCRIPTION = `Read network requests captured from the page.\nReturns details of HTTP requests and responses including URL, method,\nstatus code, headers, and timing information. Supports filtering\nby URL pattern or resource type.`\n","export const SELECT_TAB_DESCRIPTION = `Switch focus to a specific tab by its identifier.\nMakes the target tab the active tab in the agent's group,\nbringing it to the foreground for subsequent operations\nsuch as navigation, clicking, or content extraction.`\n","export const TAB_CLOSE_DESCRIPTION = `Close a tab by its identifier.\nRemoves the specified tab from the browser and the agent's tab group.\nIf the closed tab was active, focus shifts to the nearest remaining\ntab in the group.`\n","export const TABS_CONTEXT_DESCRIPTION = `Get information about the current agent tab group.\nReturns the list of tabs belonging to the agent's assigned group,\nincluding each tab's ID, URL, title, and active status.\nUseful for understanding the current browsing context.`\n","export const TABS_CREATE_DESCRIPTION = `Create a new tab within the agent's tab group.\nOpens a new tab with an optional URL and automatically assigns it\nto the current agent's group. The new tab becomes the active tab\nunless otherwise specified.`\n","export const AGENT_TAB_ASSIGN_DESCRIPTION = `Assign a tab group to a specific agent.\nBinds an existing Chrome tab group to the calling agent, granting\nexclusive control over all tabs within the group. Prevents other\nagents from interfering with the assigned tabs.`\n","export const AGENT_TAB_LIST_DESCRIPTION = `List all agent-to-tab-group mappings.\nReturns a summary of which agents are assigned to which tab groups,\nincluding the group ID, agent identifier, and the number of tabs\nin each group.`\n","export const ARTIFACT_FROM_PAGE_DESCRIPTION = `Save the current page as a persistent artifact.\nCaptures the page content as HTML, PDF, or screenshot and stores it\nas a named artifact for later reference. Artifacts can be retrieved\nby other tools or returned to the user as output.`\n","export const BROWSER_EVENT_SUBSCRIBE_DESCRIPTION = `Subscribe to browser events for real-time monitoring.\nRegisters a listener for specified event types such as navigation,\ntab updates, DOM changes, or network activity. Events are queued\nand delivered on subsequent polling or callback.`\n","export const BROWSER_EVENT_UNSUBSCRIBE_DESCRIPTION = `Unsubscribe from previously registered browser events.\nRemoves the event listener for the specified subscription ID,\nstopping further event delivery. Cleans up associated resources\nand flushes any remaining queued events.`\n","export const BROWSER_HEALTH_DESCRIPTION = `Check the health status of the browser connection.\nVerifies that the browser process is running, the CDP connection\nis active, and the agent's tab group is accessible. Returns\ndiagnostic information useful for troubleshooting connectivity issues.`\n","export const PAGE_DATA_EXTRACT_DESCRIPTION = `Extract structured data from the current page.\nParses the page content according to a provided schema or natural\nlanguage description, returning well-formed JSON. Supports extracting\ntables, lists, key-value pairs, and other structured patterns.`\n","/**\n * Bridge between Native Messaging Host and MCP Server via Unix socket.\n *\n * When running as --native-host:\n * Chrome <-> stdin/stdout (Native Messaging) <-> this bridge <-> Unix socket <-> MCP Server\n */\n\nimport { createConnection, type Socket } from 'node:net'\nimport { createMessageReader, writeMessage } from './transport.js'\nimport { compressPayload, decompressPayload } from './compression.js'\nimport { RECONNECT, LIMITS } from '@viyv-browser/shared'\n\nconst MAX_BUFFER_SIZE = 1000\n\nexport interface BridgeOptions {\n socketPath: string\n onError?: (error: Error) => void\n}\n\nexport function startBridge(options: BridgeOptions): void {\n const { socketPath, onError } = options\n let socket: Socket | null = null\n let reconnecting = false\n let retryCount = 0\n\n // FIX #2: Actual message buffer for messages received while socket is disconnected\n const pendingMessages: unknown[] = []\n\n function flushBuffer() {\n if (!socket || socket.destroyed) return\n while (pendingMessages.length > 0) {\n const msg = pendingMessages[0] // FIX NL3: Peek first, don't shift until write succeeds\n try {\n const written = socket.write(`${JSON.stringify(msg)}\\n`)\n pendingMessages.shift() // Safe to remove after successful write call\n if (!written) {\n // Backpressure: wait for drain before continuing flush\n socket.once('drain', () => flushBuffer())\n return\n }\n } catch (error) {\n // Message stays in buffer for retry on reconnection\n onError?.(error as Error)\n return\n }\n }\n }\n\n function connectSocket() {\n socket = createConnection(socketPath)\n\n socket.on('connect', () => {\n process.stderr.write(\n `[viyv-browser:native-host] Connected to MCP server at ${socketPath}\\n`,\n )\n retryCount = 0 // Reset backoff on successful connection\n flushBuffer()\n })\n\n // Messages from MCP Server -> Chrome (via stdout)\n // TCP stream fragmentation fix: line-based buffer\n let lineBuffer = ''\n\n socket.on('data', (data) => {\n lineBuffer += data.toString('utf-8')\n const lines = lineBuffer.split('\\n')\n lineBuffer = lines.pop() ?? '' // Keep incomplete last line\n for (const line of lines) {\n if (!line) continue\n try {\n let message = JSON.parse(line)\n // NM5: Decompress incoming compressed messages from MCP Server\n if (message.type === 'compressed' && typeof message.data === 'string') {\n const decompressed = decompressPayload(message.data, true)\n message = JSON.parse(decompressed)\n }\n writeMessage(process.stdout, message)\n } catch (error) {\n onError?.(error as Error)\n }\n }\n })\n\n socket.on('error', (error) => {\n process.stderr.write(\n `[viyv-browser:native-host] Socket error: ${error.message}\\n`,\n )\n onError?.(error)\n })\n\n socket.on('close', () => {\n process.stderr.write('[viyv-browser:native-host] Socket closed\\n')\n socket = null\n if (!reconnecting) {\n reconnecting = true\n // Exponential backoff: 1s, 2s, 4s, ..., max 30s\n const delay = Math.min(\n RECONNECT.INITIAL_DELAY * Math.pow(RECONNECT.MULTIPLIER, retryCount),\n RECONNECT.MAX_DELAY,\n )\n retryCount++\n process.stderr.write(\n `[viyv-browser:native-host] Reconnecting in ${delay}ms (attempt ${retryCount})\\n`,\n )\n setTimeout(() => {\n reconnecting = false\n connectSocket()\n }, delay)\n }\n })\n }\n\n // Messages from Chrome (via stdin) -> MCP Server\n createMessageReader(\n process.stdin,\n (message) => {\n if (socket && !socket.destroyed) {\n // NM5: Compress large payloads (e.g., screenshots) before Unix socket transfer\n const json = JSON.stringify(message)\n if (json.length > LIMITS.CHUNK_SIZE) {\n const { compressed, wasCompressed } = compressPayload(json)\n if (wasCompressed) {\n socket.write(`${JSON.stringify({ type: 'compressed', data: compressed })}\\n`)\n } else {\n socket.write(`${json}\\n`)\n }\n } else {\n socket.write(`${json}\\n`)\n }\n } else {\n // Buffer messages while disconnected\n if (pendingMessages.length < MAX_BUFFER_SIZE) {\n pendingMessages.push(message)\n } else {\n process.stderr.write(\n '[viyv-browser:native-host] Message buffer full, dropping message\\n',\n )\n }\n }\n },\n onError,\n )\n\n connectSocket()\n\n // Clean shutdown handlers\n process.on('SIGINT', () => {\n socket?.destroy()\n process.exit(0)\n })\n\n process.on('SIGTERM', () => {\n socket?.destroy()\n process.exit(0)\n })\n\n process.stdin.on('end', () => {\n process.stderr.write('[viyv-browser:native-host] stdin closed, shutting down\\n')\n socket?.destroy()\n process.exit(0)\n })\n}\n","/**\n * Native Messaging transport: length-prefixed JSON over stdin/stdout.\n * Chrome Native Messaging uses 4-byte little-endian length prefix + UTF-8 JSON.\n */\n\nconst MAX_MESSAGE_SIZE = 1024 * 1024 // 1MB Chrome limit\n\nexport function encodeMessage(message: unknown): Buffer {\n const json = JSON.stringify(message)\n const body = Buffer.from(json, 'utf-8')\n\n if (body.length > MAX_MESSAGE_SIZE) {\n throw new Error(`Message too large: ${body.length} bytes (max ${MAX_MESSAGE_SIZE})`)\n }\n\n const header = Buffer.alloc(4)\n header.writeUInt32LE(body.length, 0)\n return Buffer.concat([header, body])\n}\n\nexport function createMessageReader(\n stream: NodeJS.ReadableStream,\n onMessage: (message: unknown) => void,\n onError?: (error: Error) => void,\n onClose?: () => void,\n) {\n let buffer = Buffer.alloc(0)\n let expectedLength: number | null = null\n\n stream.on('data', (chunk: Buffer) => {\n buffer = Buffer.concat([buffer, chunk])\n\n while (true) {\n // Read length header\n if (expectedLength === null) {\n if (buffer.length < 4) break\n expectedLength = buffer.readUInt32LE(0)\n buffer = buffer.subarray(4)\n\n if (expectedLength > MAX_MESSAGE_SIZE) {\n onError?.(new Error(`Message too large: ${expectedLength} bytes`))\n expectedLength = null\n buffer = Buffer.alloc(0)\n break\n }\n }\n\n // Read message body\n if (buffer.length < expectedLength) break\n\n const jsonBuffer = buffer.subarray(0, expectedLength)\n buffer = buffer.subarray(expectedLength)\n expectedLength = null\n\n try {\n const message = JSON.parse(jsonBuffer.toString('utf-8'))\n onMessage(message)\n } catch (error) {\n onError?.(new Error(`Invalid JSON: ${(error as Error).message}`))\n }\n }\n })\n\n // FIX #19: Handle stream close/error events\n stream.on('error', (error: Error) => {\n onError?.(new Error(`Stream error: ${error.message}`))\n })\n\n stream.on('end', () => {\n onClose?.()\n })\n\n stream.on('close', () => {\n onClose?.()\n })\n}\n\nexport function writeMessage(stream: NodeJS.WritableStream, message: unknown): void {\n const encoded = encodeMessage(message)\n stream.write(encoded)\n}\n","/**\n * Setup command: registers Native Messaging Host manifest.\n * `npx @viyv/browser-mcp setup`\n */\n\nimport { writeFileSync, mkdirSync, chmodSync, existsSync } from 'node:fs'\nimport { resolve, dirname } from 'node:path'\nimport { homedir, platform } from 'node:os'\nimport { execSync } from 'node:child_process'\nimport { NATIVE_HOST_NAME } from '@viyv-browser/shared'\n\ninterface SetupOptions {\n extensionId?: string\n}\n\nexport function runSetup(options: SetupOptions = {}): void {\n const os = platform()\n const binaryPath = getBinaryPath()\n\n console.log('Viyv Browser MCP - Native Messaging Host Setup')\n console.log('================================================')\n console.log(`Platform: ${os}`)\n console.log(`Binary: ${binaryPath}`)\n\n // Verify binary path exists\n if (!existsSync(binaryPath)) {\n console.error(`WARNING: Binary not found at ${binaryPath}`)\n console.error('The Native Messaging Host may not work until the binary is available.')\n }\n\n const allowedOrigins = options.extensionId\n ? [`chrome-extension://${options.extensionId}/`]\n : ['chrome-extension://*/'] // Allow all during development\n\n // Security warning for wildcard origins\n if (!options.extensionId) {\n process.stderr.write(\n 'WARNING: Using wildcard allowed_origins (chrome-extension://*/). ' +\n 'This allows any Chrome extension to connect. ' +\n 'For production, specify --extension-id to restrict access.\\n',\n )\n }\n\n // Chrome Native Messaging Host manifest doesn't support args.\n // Create a wrapper script that launches the binary with --native-host flag.\n const wrapperPath = createNativeHostWrapper(os, binaryPath)\n\n const manifest = {\n name: NATIVE_HOST_NAME,\n description: 'Viyv Browser MCP Native Messaging Host',\n path: wrapperPath,\n type: 'stdio',\n allowed_origins: allowedOrigins,\n }\n\n const manifestPath = getManifestPath(os)\n const manifestDir = dirname(manifestPath)\n\n console.log(`Wrapper: ${wrapperPath}`)\n console.log(`Manifest path: ${manifestPath}`)\n\n mkdirSync(manifestDir, { recursive: true })\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2))\n chmodSync(manifestPath, 0o644)\n\n console.log('\\nNative Messaging Host registered successfully!')\n console.log('\\nNext steps:')\n console.log('1. Start the MCP Server: node <path>/dist/index.js')\n console.log('2. Install the Viyv Browser Chrome Extension')\n console.log('3. Click the extension icon to connect')\n}\n\nfunction getBinaryPath(): string {\n // Find the actual binary path\n const whichCmd = process.platform === 'win32' ? 'where' : 'which'\n try {\n const found = execSync(`${whichCmd} viyv-browser-mcp`, { encoding: 'utf-8' }).trim()\n if (found) return found\n } catch {\n // Not globally installed, use npx path\n }\n\n // Fallback: resolve from current module\n const currentScript = process.argv[1]\n return resolve(currentScript)\n}\n\nfunction createNativeHostWrapper(os: string, binaryPath: string): string {\n const manifestDir = dirname(getManifestPath(os))\n mkdirSync(manifestDir, { recursive: true })\n\n // Chrome launches native hosts in a clean environment without user's PATH.\n // We must use the absolute path to node, not rely on #!/usr/bin/env node.\n const nodePath = getNodePath()\n\n if (os === 'win32') {\n // Windows: .bat wrapper\n const wrapperPath = resolve(manifestDir, `${NATIVE_HOST_NAME}.bat`)\n writeFileSync(wrapperPath, `@echo off\\r\\n\"${nodePath}\" \"${binaryPath}\" --native-host\\r\\n`)\n return wrapperPath\n }\n\n // macOS/Linux: shell wrapper\n const wrapperPath = resolve(manifestDir, `${NATIVE_HOST_NAME}.sh`)\n writeFileSync(\n wrapperPath,\n `#!/bin/bash\\nexec \"${nodePath}\" \"${binaryPath}\" --native-host\\n`,\n )\n chmodSync(wrapperPath, 0o755)\n return wrapperPath\n}\n\nfunction getNodePath(): string {\n try {\n return execSync('which node', { encoding: 'utf-8' }).trim()\n } catch {\n // Fallback: use the current process's node binary\n return process.execPath\n }\n}\n\nfunction getManifestPath(os: string): string {\n const home = homedir()\n\n switch (os) {\n case 'darwin':\n return resolve(\n home,\n 'Library/Application Support/Google/Chrome/NativeMessagingHosts',\n `${NATIVE_HOST_NAME}.json`,\n )\n case 'linux':\n return resolve(\n home,\n '.config/google-chrome/NativeMessagingHosts',\n `${NATIVE_HOST_NAME}.json`,\n )\n case 'win32':\n // On Windows, we'd also need to create a registry entry\n return resolve(\n home,\n 'AppData/Local/Google/Chrome/User Data/NativeMessagingHosts',\n `${NATIVE_HOST_NAME}.json`,\n )\n default:\n throw new Error(`Unsupported platform: ${os}`)\n }\n}\n"],"mappings":"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","names":["existsSync","randomUUID","sessions","randomUUID","resolve","existsSync","existsSync","wrapperPath","waitForSocket","existsSync"]}
|