@elizaos/plugin-browser 2.0.0-beta.1 → 2.0.11-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +106 -64
- package/dist/actions/browser-autofill-login.d.ts.map +1 -1
- package/dist/actions/browser-autofill-login.js.map +1 -1
- package/dist/actions/browser.d.ts +5 -6
- package/dist/actions/browser.d.ts.map +1 -1
- package/dist/actions/browser.js +54 -59
- package/dist/actions/browser.js.map +1 -1
- package/dist/actions/manage-browser-bridge.d.ts.map +1 -1
- package/dist/actions/manage-browser-bridge.js +10 -14
- package/dist/actions/manage-browser-bridge.js.map +1 -1
- package/dist/bridge-policy.d.ts +10 -0
- package/dist/bridge-policy.d.ts.map +1 -0
- package/dist/bridge-policy.js +37 -0
- package/dist/bridge-policy.js.map +1 -0
- package/dist/bridge-readiness.d.ts +16 -0
- package/dist/bridge-readiness.d.ts.map +1 -0
- package/dist/bridge-readiness.js +82 -0
- package/dist/bridge-readiness.js.map +1 -0
- package/dist/bridge-records.d.ts +9 -0
- package/dist/bridge-records.d.ts.map +1 -0
- package/dist/bridge-records.js +37 -0
- package/dist/bridge-records.js.map +1 -0
- package/dist/browser-capture-hooks.d.ts +9 -0
- package/dist/browser-capture-hooks.d.ts.map +1 -0
- package/dist/browser-capture-hooks.js +15 -0
- package/dist/browser-capture-hooks.js.map +1 -0
- package/dist/browser-service.d.ts +22 -4
- package/dist/browser-service.d.ts.map +1 -1
- package/dist/browser-service.js +63 -15
- package/dist/browser-service.js.map +1 -1
- package/dist/browser-workspace-hooks.d.ts +14 -0
- package/dist/browser-workspace-hooks.d.ts.map +1 -0
- package/dist/browser-workspace-hooks.js +15 -0
- package/dist/browser-workspace-hooks.js.map +1 -0
- package/dist/companion-auth.d.ts +34 -0
- package/dist/companion-auth.d.ts.map +1 -0
- package/dist/companion-auth.js +98 -0
- package/dist/companion-auth.js.map +1 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -11
- package/dist/index.js.map +1 -1
- package/dist/message-adapter.d.ts +9 -0
- package/dist/message-adapter.d.ts.map +1 -0
- package/dist/message-adapter.js +104 -0
- package/dist/message-adapter.js.map +1 -0
- package/dist/packaging.d.ts.map +1 -1
- package/dist/packaging.js +2 -0
- package/dist/packaging.js.map +1 -1
- package/dist/password-manager-bridge.d.ts +50 -0
- package/dist/password-manager-bridge.d.ts.map +1 -0
- package/dist/password-manager-bridge.js +437 -0
- package/dist/password-manager-bridge.js.map +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +8 -4
- package/dist/plugin.js.map +1 -1
- package/dist/providers/workspace.d.ts +1 -1
- package/dist/providers/workspace.js.map +1 -1
- package/dist/routes/bridge.d.ts.map +1 -1
- package/dist/routes/bridge.js +63 -14
- package/dist/routes/bridge.js.map +1 -1
- package/dist/routes/workspace-setup.d.ts.map +1 -1
- package/dist/routes/workspace-setup.js +1 -1
- package/dist/routes/workspace-setup.js.map +1 -1
- package/dist/routes/workspace.d.ts +1 -2
- package/dist/routes/workspace.d.ts.map +1 -1
- package/dist/routes/workspace.js +63 -3
- package/dist/routes/workspace.js.map +1 -1
- package/dist/schema.d.ts +2 -2
- package/dist/schema.js.map +1 -1
- package/dist/service.d.ts +1 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js.map +1 -1
- package/dist/targets/bridge-target.d.ts +1 -1
- package/dist/targets/bridge-target.d.ts.map +1 -1
- package/dist/targets/bridge-target.js.map +1 -1
- package/dist/targets/stagehand-target.d.ts +3 -0
- package/dist/targets/stagehand-target.d.ts.map +1 -0
- package/dist/targets/stagehand-target.js +187 -0
- package/dist/targets/stagehand-target.js.map +1 -0
- package/dist/workspace/browser-capture.d.ts +1 -1
- package/dist/workspace/browser-capture.js.map +1 -1
- package/dist/workspace/browser-workspace-desktop.d.ts +1 -1
- package/dist/workspace/browser-workspace-desktop.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-desktop.js +47 -25
- package/dist/workspace/browser-workspace-desktop.js.map +1 -1
- package/dist/workspace/browser-workspace-forms.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-forms.js +1 -1
- package/dist/workspace/browser-workspace-forms.js.map +1 -1
- package/dist/workspace/browser-workspace-helpers.d.ts +7 -0
- package/dist/workspace/browser-workspace-helpers.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-helpers.js +37 -0
- package/dist/workspace/browser-workspace-helpers.js.map +1 -1
- package/dist/workspace/browser-workspace-network.d.ts +1 -1
- package/dist/workspace/browser-workspace-network.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-types.d.ts +15 -0
- package/dist/workspace/browser-workspace-types.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-types.js.map +1 -1
- package/dist/workspace/browser-workspace-web.d.ts.map +1 -1
- package/dist/workspace/browser-workspace-web.js +15 -88
- package/dist/workspace/browser-workspace-web.js.map +1 -1
- package/dist/workspace/browser-workspace.d.ts +1 -1
- package/dist/workspace/browser-workspace.d.ts.map +1 -1
- package/dist/workspace/browser-workspace.js +9 -4
- package/dist/workspace/browser-workspace.js.map +1 -1
- package/package.json +28 -7
- package/dist/actions/browser-autofill-login.d.js +0 -1
- package/dist/actions/browser-autofill-login.d.js.map +0 -1
- package/dist/actions/browser.d.js +0 -1
- package/dist/actions/browser.d.js.map +0 -1
- package/dist/actions/manage-browser-bridge.d.js +0 -1
- package/dist/actions/manage-browser-bridge.d.js.map +0 -1
- package/dist/ambient-jsdom.d.js +0 -1
- package/dist/ambient-jsdom.d.js.map +0 -1
- package/dist/browser-service.d.js +0 -1
- package/dist/browser-service.d.js.map +0 -1
- package/dist/contracts.d.js +0 -1
- package/dist/contracts.d.js.map +0 -1
- package/dist/index.d.js +0 -21
- package/dist/index.d.js.map +0 -1
- package/dist/lifeops-session-contracts.d.js +0 -1
- package/dist/lifeops-session-contracts.d.js.map +0 -1
- package/dist/packaging.d.js +0 -1
- package/dist/packaging.d.js.map +0 -1
- package/dist/plugin.d.js +0 -1
- package/dist/plugin.d.js.map +0 -1
- package/dist/providers/workspace.d.js +0 -1
- package/dist/providers/workspace.d.js.map +0 -1
- package/dist/routes/bridge.d.js +0 -1
- package/dist/routes/bridge.d.js.map +0 -1
- package/dist/routes/workspace-account-gate.d.js +0 -1
- package/dist/routes/workspace-account-gate.d.js.map +0 -1
- package/dist/routes/workspace-setup.d.js +0 -1
- package/dist/routes/workspace-setup.d.js.map +0 -1
- package/dist/routes/workspace.d.js +0 -1
- package/dist/routes/workspace.d.js.map +0 -1
- package/dist/schema.d.js +0 -1
- package/dist/schema.d.js.map +0 -1
- package/dist/service.d.js +0 -1
- package/dist/service.d.js.map +0 -1
- package/dist/targets/bridge-target.d.js +0 -1
- package/dist/targets/bridge-target.d.js.map +0 -1
- package/dist/workspace/browser-capture.d.js +0 -1
- package/dist/workspace/browser-capture.d.js.map +0 -1
- package/dist/workspace/browser-workspace-desktop.d.js +0 -1
- package/dist/workspace/browser-workspace-desktop.d.js.map +0 -1
- package/dist/workspace/browser-workspace-elements.d.js +0 -1
- package/dist/workspace/browser-workspace-elements.d.js.map +0 -1
- package/dist/workspace/browser-workspace-forms.d.js +0 -1
- package/dist/workspace/browser-workspace-forms.d.js.map +0 -1
- package/dist/workspace/browser-workspace-helpers.d.js +0 -1
- package/dist/workspace/browser-workspace-helpers.d.js.map +0 -1
- package/dist/workspace/browser-workspace-jsdom.d.js +0 -1
- package/dist/workspace/browser-workspace-jsdom.d.js.map +0 -1
- package/dist/workspace/browser-workspace-network.d.js +0 -1
- package/dist/workspace/browser-workspace-network.d.js.map +0 -1
- package/dist/workspace/browser-workspace-snapshots.d.js +0 -1
- package/dist/workspace/browser-workspace-snapshots.d.js.map +0 -1
- package/dist/workspace/browser-workspace-state.d.js +0 -1
- package/dist/workspace/browser-workspace-state.d.js.map +0 -1
- package/dist/workspace/browser-workspace-types.d.js +0 -1
- package/dist/workspace/browser-workspace-types.d.js.map +0 -1
- package/dist/workspace/browser-workspace-web.d.js +0 -1
- package/dist/workspace/browser-workspace-web.d.js.map +0 -1
- package/dist/workspace/browser-workspace.d.js +0 -11
- package/dist/workspace/browser-workspace.d.js.map +0 -1
- package/dist/workspace/index.d.js +0 -3
- package/dist/workspace/index.d.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/actions/browser.ts"],"sourcesContent":["import type {\n Action,\n ActionExample,\n HandlerOptions,\n Memory,\n} from \"@elizaos/core\";\nimport { logger } from \"@elizaos/core\";\nimport {\n BROWSER_SERVICE_TYPE,\n type BrowserService,\n} from \"../browser-service.js\";\nimport { executeBrowserAutofillLogin } from \"./browser-autofill-login.js\";\nimport {\n type BrowserWorkspaceCommand,\n executeBrowserWorkspaceCommand,\n getBrowserWorkspaceMode,\n} from \"../workspace/browser-workspace.js\";\n\n/**\n * Targets are the registered browser backends. The agent uses what is\n * available; specifying a target overrides the default. `workspace` is the\n * current default (electrobun-embedded BrowserView with JSDOM fallback).\n * `bridge` (Chrome/Safari companion) and `computeruse` (puppeteer Chromium)\n * are reserved for the BrowserService target-registry refactor — see\n * follow-up work.\n */\nexport type BrowserTarget = \"workspace\" | \"bridge\" | \"computeruse\";\n\ntype BrowserWorkspaceSubaction =\n | \"back\"\n | \"click\"\n | \"close\"\n | \"forward\"\n | \"get\"\n | \"hide\"\n | \"navigate\"\n | \"open\"\n | \"press\"\n | \"reload\"\n | \"screenshot\"\n | \"show\"\n | \"snapshot\"\n | \"state\"\n | \"tab\"\n | \"type\"\n | \"wait\"\n | \"realistic-click\"\n | \"realistic-fill\"\n | \"realistic-type\"\n | \"realistic-press\"\n | \"cursor-move\"\n | \"cursor-hide\";\n\ntype BrowserActionSubaction = BrowserWorkspaceSubaction | \"autofill-login\";\n\ntype BrowserActionParameters = {\n /**\n * Optional target override. Default: the BrowserService active target\n * (currently always `workspace`). Forces a specific backend when set.\n */\n target?: BrowserTarget;\n id?: string;\n key?: string;\n pixels?: number;\n script?: string;\n selector?: string;\n /**\n * Canonical browser action. Legacy `subaction` remains accepted.\n */\n action?:\n | BrowserWorkspaceSubaction\n | \"autofill-login\"\n | \"info\"\n | \"context\"\n | \"get_context\"\n | \"list_tabs\"\n | \"open_tab\"\n | \"close_tab\"\n | \"switch_tab\";\n subaction?: BrowserActionSubaction;\n /** Registrable hostname for `action: \"autofill-login\"`. */\n domain?: string;\n /** Saved login username for autofill-login (optional). */\n username?: string;\n /** When true with autofill-login, submit after filling. */\n submit?: boolean;\n tabAction?: \"close\" | \"list\" | \"new\" | \"switch\";\n text?: string;\n timeoutMs?: number;\n url?: string;\n /** Cursor animation duration (ms) for realistic-* + cursor-* subactions. */\n cursorDurationMs?: number;\n /** Per-character delay for realistic-type / realistic-fill (ms). */\n perCharDelayMs?: number;\n /** Replace existing input value when filling (vs append). */\n replace?: boolean;\n /** Cursor target X (CSS pixels) for cursor-move. */\n x?: number;\n /** Cursor target Y (CSS pixels) for cursor-move. */\n y?: number;\n /** Hint that the agent is operating in a watch-mode (page-browser) scope. */\n watchMode?: boolean;\n};\n\nfunction getMessageText(message: Memory | undefined): string {\n const content = message?.content;\n if (typeof content === \"string\") {\n return content;\n }\n return typeof content?.text === \"string\" ? content.text : \"\";\n}\n\nfunction extractFirstUrl(value: string): string | null {\n const match = value.match(/https?:\\/\\/[^\\s<>\"'`]+/i);\n return match?.[0] ?? null;\n}\n\nfunction inferBrowserSubaction(\n params: BrowserActionParameters | undefined,\n messageText: string,\n): BrowserWorkspaceCommand[\"subaction\"] | \"autofill-login\" {\n if (params?.action === \"autofill-login\" || params?.subaction === \"autofill-login\") {\n return \"autofill-login\";\n }\n\n const legacySubaction = normalizeLegacyBrowserAction(params?.action);\n if (legacySubaction) {\n return legacySubaction;\n }\n if (params?.subaction) {\n return params.subaction;\n }\n\n if (params?.tabAction) {\n return \"tab\";\n }\n\n // In watch mode the user is observing the agent drive the browser; prefer\n // the realistic-* subactions so the cursor moves and pointer events fire\n // faithfully. Default-mode (no watcher) keeps the leaner click()/value=\n // path for speed.\n const watchMode = params?.watchMode === true;\n\n if (params?.selector && params?.text) {\n return watchMode ? \"realistic-fill\" : \"type\";\n }\n\n if (params?.selector) {\n return watchMode ? \"realistic-click\" : \"click\";\n }\n\n if (params?.url?.trim() || extractFirstUrl(messageText)) {\n return params?.id ? \"navigate\" : \"open\";\n }\n\n return \"state\";\n}\n\nfunction normalizeLegacyBrowserAction(\n action: BrowserActionParameters[\"action\"] | undefined,\n): BrowserWorkspaceCommand[\"subaction\"] | undefined {\n switch (action) {\n case \"info\":\n case \"context\":\n case \"get_context\":\n return \"state\";\n case \"list_tabs\":\n case \"open_tab\":\n case \"close_tab\":\n case \"switch_tab\":\n return \"tab\";\n case \"autofill-login\":\n return undefined;\n case undefined:\n return undefined;\n default:\n return action;\n }\n}\n\nfunction normalizeLegacyTabAction(\n action: BrowserActionParameters[\"action\"] | undefined,\n): BrowserActionParameters[\"tabAction\"] | undefined {\n switch (action) {\n case \"list_tabs\":\n return \"list\";\n case \"open_tab\":\n return \"new\";\n case \"close_tab\":\n return \"close\";\n case \"switch_tab\":\n return \"switch\";\n default:\n return undefined;\n }\n}\n\nfunction formatBrowserSessionResult(\n command: BrowserWorkspaceCommand,\n result: Awaited<ReturnType<typeof executeBrowserWorkspaceCommand>>,\n): string {\n if (result.tabs) {\n const labels = result.tabs\n .map((tab) => `- ${tab.title} (${tab.url})`)\n .join(\"\\n\");\n return labels\n ? `Browser tabs (${result.mode}):\\n${labels}`\n : `No browser session tabs are open (${result.mode}).`;\n }\n\n if (result.closed) {\n return `Browser closed (${result.mode}).`;\n }\n\n if (result.tab) {\n return `${command.subaction} completed in ${result.mode} mode.\\n${result.tab.title}\\n${result.tab.url}`;\n }\n\n if (result.value !== undefined) {\n if (\n command.subaction === \"cursor-move\" &&\n result.value !== null &&\n typeof result.value === \"object\" &&\n \"x\" in result.value &&\n \"y\" in result.value\n ) {\n const cursor = result.value as { x: number; y: number };\n return `Cursor moved to (${Math.round(cursor.x)}, ${Math.round(cursor.y)}) in ${result.mode} mode.`;\n }\n const serialized =\n typeof result.value === \"string\"\n ? result.value\n : JSON.stringify(result.value, null, 2);\n return `Browser ${command.subaction} result (${result.mode}):\\n${serialized}`;\n }\n\n if (result.snapshot?.data) {\n return `Browser ${command.subaction} captured a preview in ${result.mode} mode.`;\n }\n\n return `Browser ${command.subaction} completed in ${result.mode} mode.`;\n}\n\nexport const browserAction: Action = {\n name: \"BROWSER\",\n contexts: [\"browser\", \"web\", \"automation\", \"secrets\"],\n roleGate: { minRole: \"OWNER\" },\n similes: [\n \"BROWSE_SITE\",\n \"BROWSER_SESSION\",\n \"CONTROL_BROWSER\",\n \"CONTROL_BROWSER_SESSION\",\n \"MANAGE_ELIZA_BROWSER_WORKSPACE\",\n \"MANAGE_LIFEOPS_BROWSER\",\n \"NAVIGATE_SITE\",\n \"OPEN_SITE\",\n \"USE_BROWSER\",\n \"BROWSER_ACTION\",\n \"BROWSER_AUTOFILL_LOGIN\",\n \"AGENT_AUTOFILL\",\n \"AUTOFILL_BROWSER_LOGIN\",\n \"AUTOFILL_LOGIN\",\n \"FILL_BROWSER_CREDENTIALS\",\n \"LOG_INTO_SITE\",\n \"SIGN_IN_TO_SITE\",\n ],\n description:\n \"Single BROWSER action — control whichever browser target is registered. Targets are pluggable: `workspace` (electrobun-embedded BrowserView, the default; falls back to a JSDOM web mode when the desktop bridge isn't configured), `bridge` (the user's real Chrome/Safari via the Agent Browser Bridge companion extension), and `computeruse` (a local puppeteer-driven Chromium via plugin-computeruse). The agent uses what is available — the BrowserService picks the active target when none is specified. Use `subaction: \\\"autofill-login\\\"` with `domain` (and optional `username`, `submit`) to vault-gated autofill into an open workspace tab.\",\n descriptionCompressed:\n \"Browser tab/page control: open/navigate/click/type/screenshot/state; subaction autofill-login + domain autofill vault-gated credential into workspace tab pre-authorized in Settings Vault Logins. Bridge settings/status use MANAGE_BROWSER_BRIDGE.\",\n validate: async () => true,\n handler: async (runtime, message, _state, options) => {\n const params = (options as HandlerOptions | undefined)?.parameters as\n | BrowserActionParameters\n | undefined;\n const messageText = getMessageText(message);\n const subaction = inferBrowserSubaction(params, messageText);\n\n if (subaction === \"autofill-login\") {\n return executeBrowserAutofillLogin(runtime, message, options);\n }\n\n const url =\n params?.url?.trim() || extractFirstUrl(messageText) || undefined;\n\n const command: BrowserWorkspaceCommand = {\n id: params?.id?.trim(),\n key: params?.key?.trim(),\n pixels: params?.pixels,\n script: params?.script,\n selector: params?.selector?.trim(),\n subaction,\n tabAction: params?.tabAction ?? normalizeLegacyTabAction(params?.action),\n text: params?.text,\n timeoutMs: params?.timeoutMs,\n url,\n cursorDurationMs: params?.cursorDurationMs,\n perCharDelayMs: params?.perCharDelayMs,\n replace: params?.replace,\n x: params?.x,\n y: params?.y,\n };\n\n const browserService = runtime.getService<BrowserService>(\n BROWSER_SERVICE_TYPE,\n );\n\n try {\n logger.info(\n `[BROWSER] ${command.subaction} via target=${params?.target ?? \"auto\"} (workspace mode=${getBrowserWorkspaceMode(process.env)})`,\n );\n const result = browserService\n ? await browserService.execute(command, params?.target)\n : await executeBrowserWorkspaceCommand(command);\n\n return {\n text: formatBrowserSessionResult(command, result),\n success: true,\n values: {\n success: true,\n mode: result.mode,\n subaction: result.subaction,\n },\n data: {\n actionName: \"BROWSER\",\n command,\n result,\n },\n };\n } catch (error) {\n const messageText =\n error instanceof Error ? error.message : \"Browser action failed\";\n logger.warn(`[BROWSER] Failed: ${messageText}`);\n return {\n text: `Browser action failed: ${messageText}`,\n success: false,\n values: { success: false, error: \"BROWSER_FAILED\" },\n data: {\n actionName: \"BROWSER\",\n command,\n },\n };\n }\n },\n parameters: [\n {\n name: \"action\",\n description:\n \"Browser action to perform. Legacy subaction is also accepted.\",\n required: false,\n schema: {\n type: \"string\" as const,\n enum: [\n \"back\",\n \"click\",\n \"close\",\n \"context\",\n \"forward\",\n \"get\",\n \"get_context\",\n \"hide\",\n \"info\",\n \"list_tabs\",\n \"navigate\",\n \"open\",\n \"open_tab\",\n \"press\",\n \"reload\",\n \"screenshot\",\n \"show\",\n \"snapshot\",\n \"state\",\n \"tab\",\n \"type\",\n \"wait\",\n \"close_tab\",\n \"switch_tab\",\n \"realistic-click\",\n \"realistic-fill\",\n \"realistic-type\",\n \"realistic-press\",\n \"cursor-move\",\n \"cursor-hide\",\n \"autofill-login\",\n ],\n },\n },\n {\n name: \"subaction\",\n description: \"Legacy alias for action.\",\n required: false,\n schema: {\n type: \"string\" as const,\n enum: [\n \"back\",\n \"click\",\n \"close\",\n \"forward\",\n \"get\",\n \"hide\",\n \"navigate\",\n \"open\",\n \"press\",\n \"reload\",\n \"screenshot\",\n \"show\",\n \"snapshot\",\n \"state\",\n \"tab\",\n \"type\",\n \"wait\",\n \"realistic-click\",\n \"realistic-fill\",\n \"realistic-type\",\n \"realistic-press\",\n \"cursor-move\",\n \"cursor-hide\",\n \"autofill-login\",\n ],\n },\n },\n {\n name: \"tabAction\",\n description: \"Tab operation when subaction is tab\",\n required: false,\n schema: {\n type: \"string\" as const,\n enum: [\"close\", \"list\", \"new\", \"switch\"],\n },\n },\n {\n name: \"domain\",\n description:\n \"Required when subaction is autofill-login: registrable hostname (e.g. `github.com`).\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"username\",\n description:\n \"When using autofill-login: specific saved login; omit for most recently modified.\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"submit\",\n description:\n \"When using autofill-login: submit the form after filling (default false).\",\n required: false,\n schema: { type: \"boolean\" as const },\n },\n {\n name: \"id\",\n description: \"Session or tab id to target\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"url\",\n description: \"URL for open or navigate\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"selector\",\n description: \"Selector for click, type, or wait\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"text\",\n description: \"Text for type\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"key\",\n description: \"Keyboard key for press\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"pixels\",\n description: \"Scroll distance in pixels\",\n required: false,\n schema: { type: \"number\" as const },\n },\n {\n name: \"timeoutMs\",\n description: \"Command timeout in milliseconds\",\n required: false,\n schema: { type: \"number\" as const },\n },\n {\n name: \"script\",\n description: \"Script for eval\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"watchMode\",\n description:\n \"Hint that the user is watching; prefers realistic-* subactions for click/fill so the cursor moves visibly and pointer events fire faithfully.\",\n required: false,\n schema: { type: \"boolean\" as const },\n },\n {\n name: \"cursorDurationMs\",\n description: \"Cursor animation duration (ms) for realistic-* subactions\",\n required: false,\n schema: { type: \"number\" as const },\n },\n {\n name: \"perCharDelayMs\",\n description: \"Per-character delay for realistic-type/realistic-fill (ms)\",\n required: false,\n schema: { type: \"number\" as const },\n },\n {\n name: \"replace\",\n description:\n \"Replace existing input value when filling (vs append) — applies to realistic-fill\",\n required: false,\n schema: { type: \"boolean\" as const },\n },\n {\n name: \"x\",\n description: \"Cursor target X (CSS pixels) for cursor-move\",\n required: false,\n schema: { type: \"number\" as const },\n },\n {\n name: \"y\",\n description: \"Cursor target Y (CSS pixels) for cursor-move\",\n required: false,\n schema: { type: \"number\" as const },\n },\n ],\n examples: [\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Open elizaos.ai in a new browser tab.\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"open completed in desktop mode.\\nelizaOS\\nhttps://elizaos.ai\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Click the sign-in button on that page.\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"click completed in desktop mode.\",\n },\n },\n ],\n ] as ActionExample[][],\n};\n"],"mappings":"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","names":["messageText"]}
|
|
1
|
+
{"version":3,"sources":["../../src/actions/browser.ts"],"sourcesContent":["import type {\n Action,\n ActionExample,\n HandlerOptions,\n Memory,\n} from \"@elizaos/core\";\nimport { logger } from \"@elizaos/core\";\nimport {\n BROWSER_SERVICE_TYPE,\n type BrowserService,\n} from \"../browser-service.js\";\nimport {\n type BrowserWorkspaceCommand,\n executeBrowserWorkspaceCommand,\n getBrowserWorkspaceMode,\n} from \"../workspace/browser-workspace.js\";\n\n/**\n * Targets are the registered browser backends. The agent uses what is\n * available; specifying a target overrides automatic routing. `workspace`\n * is the app-owned browser surface, `bridge` is the paired Chrome/Safari\n * companion, `stagehand` is the Playwright/Stagehand fallback, and other\n * plugins may register additional target ids.\n */\nexport type BrowserTarget = string;\n\ntype BrowserWorkspaceSubaction =\n | \"back\"\n | \"click\"\n | \"close\"\n | \"forward\"\n | \"get\"\n | \"hide\"\n | \"navigate\"\n | \"open\"\n | \"press\"\n | \"reload\"\n | \"screenshot\"\n | \"show\"\n | \"snapshot\"\n | \"state\"\n | \"tab\"\n | \"type\"\n | \"wait\"\n | \"realistic-click\"\n | \"realistic-fill\"\n | \"realistic-type\"\n | \"realistic-press\"\n | \"cursor-move\"\n | \"cursor-hide\";\n\ntype BrowserWorkspaceAction =\n | BrowserWorkspaceSubaction\n | \"realistic_click\"\n | \"realistic_fill\"\n | \"realistic_type\"\n | \"realistic_press\"\n | \"cursor_move\"\n | \"cursor_hide\";\n\ntype BrowserActionSubaction = BrowserWorkspaceSubaction | \"autofill-login\";\ntype BrowserActionValue =\n | BrowserWorkspaceAction\n | \"autofill_login\"\n | \"autofill-login\";\ntype NormalizedBrowserAction =\n | BrowserWorkspaceSubaction\n | \"autofill-login\"\n | \"info\"\n | \"context\"\n | \"get_context\"\n | \"list_tabs\"\n | \"open_tab\"\n | \"close_tab\"\n | \"switch_tab\";\n\ntype BrowserActionParameters = {\n /**\n * Optional target override. Default: the BrowserService active target\n * selected from registered targets. Forces a specific backend when set.\n */\n target?: BrowserTarget;\n id?: string;\n key?: string;\n pixels?: number;\n script?: string;\n selector?: string;\n /**\n * Canonical browser action. Legacy `subaction` remains accepted.\n */\n action?:\n | BrowserActionValue\n | \"info\"\n | \"context\"\n | \"get_context\"\n | \"list_tabs\"\n | \"open_tab\"\n | \"close_tab\"\n | \"switch_tab\";\n subaction?: BrowserActionSubaction;\n /** Registrable hostname for `action: \"autofill_login\"`. */\n domain?: string;\n /** Saved login username for autofill-login (optional). */\n username?: string;\n /** When true with autofill-login, submit after filling. */\n submit?: boolean;\n tabAction?: \"close\" | \"list\" | \"new\" | \"switch\";\n text?: string;\n timeoutMs?: number;\n url?: string;\n /** Cursor animation duration (ms) for realistic-* + cursor-* subactions. */\n cursorDurationMs?: number;\n /** Per-character delay for realistic-type / realistic-fill (ms). */\n perCharDelayMs?: number;\n /** Replace existing input value when filling (vs append). */\n replace?: boolean;\n /** Cursor target X (CSS pixels) for cursor-move. */\n x?: number;\n /** Cursor target Y (CSS pixels) for cursor-move. */\n y?: number;\n /** Hint that the agent is operating in a watch-mode (page-browser) scope. */\n watchMode?: boolean;\n};\n\nfunction getMessageText(message: Memory | undefined): string {\n const content = message?.content;\n if (typeof content === \"string\") {\n return content;\n }\n return typeof content?.text === \"string\" ? content.text : \"\";\n}\n\nfunction extractFirstUrl(value: string): string | null {\n const match = value.match(/https?:\\/\\/[^\\s<>\"'`]+/i);\n return match?.[0] ?? null;\n}\n\nfunction inferBrowserSubaction(\n params: BrowserActionParameters | undefined,\n messageText: string,\n): BrowserWorkspaceCommand[\"subaction\"] | \"autofill-login\" {\n const normalizedAction = normalizeBrowserAction(params?.action);\n if (\n normalizedAction === \"autofill-login\" ||\n params?.subaction === \"autofill-login\"\n ) {\n return \"autofill-login\";\n }\n\n const legacySubaction = normalizeLegacyBrowserAction(normalizedAction);\n if (legacySubaction) {\n return legacySubaction;\n }\n if (params?.subaction) {\n return params.subaction;\n }\n\n if (params?.tabAction) {\n return \"tab\";\n }\n\n // In watch mode the user is observing the agent drive the browser; prefer\n // the realistic-* subactions so the cursor moves and pointer events fire\n // faithfully. Default-mode (no watcher) keeps the leaner click()/value=\n // path for speed.\n const watchMode = params?.watchMode === true;\n\n if (params?.selector && params?.text) {\n return watchMode ? \"realistic-fill\" : \"type\";\n }\n\n if (params?.selector) {\n return watchMode ? \"realistic-click\" : \"click\";\n }\n\n if (params?.url?.trim() || extractFirstUrl(messageText)) {\n return params?.id ? \"navigate\" : \"open\";\n }\n\n return \"state\";\n}\n\nfunction normalizeBrowserAction(\n action: BrowserActionParameters[\"action\"] | undefined,\n): NormalizedBrowserAction | undefined {\n switch (action) {\n case \"realistic_click\":\n return \"realistic-click\";\n case \"realistic_fill\":\n return \"realistic-fill\";\n case \"realistic_type\":\n return \"realistic-type\";\n case \"realistic_press\":\n return \"realistic-press\";\n case \"cursor_move\":\n return \"cursor-move\";\n case \"cursor_hide\":\n return \"cursor-hide\";\n case \"autofill_login\":\n return \"autofill-login\";\n default:\n return action as NormalizedBrowserAction | undefined;\n }\n}\n\nfunction normalizeLegacyBrowserAction(\n action: BrowserActionParameters[\"action\"] | undefined,\n): BrowserWorkspaceCommand[\"subaction\"] | undefined {\n const normalizedAction = normalizeBrowserAction(action);\n switch (normalizedAction) {\n case \"info\":\n case \"context\":\n case \"get_context\":\n return \"state\";\n case \"list_tabs\":\n case \"open_tab\":\n case \"close_tab\":\n case \"switch_tab\":\n return \"tab\";\n case \"autofill-login\":\n return undefined;\n case undefined:\n return undefined;\n default:\n return isWorkspaceSubaction(normalizedAction)\n ? normalizedAction\n : undefined;\n }\n}\n\nfunction isWorkspaceSubaction(\n action: unknown,\n): action is BrowserWorkspaceCommand[\"subaction\"] {\n return (\n action === \"back\" ||\n action === \"click\" ||\n action === \"close\" ||\n action === \"forward\" ||\n action === \"get\" ||\n action === \"hide\" ||\n action === \"navigate\" ||\n action === \"open\" ||\n action === \"press\" ||\n action === \"reload\" ||\n action === \"screenshot\" ||\n action === \"show\" ||\n action === \"snapshot\" ||\n action === \"state\" ||\n action === \"tab\" ||\n action === \"type\" ||\n action === \"wait\" ||\n action === \"realistic-click\" ||\n action === \"realistic-fill\" ||\n action === \"realistic-type\" ||\n action === \"realistic-press\" ||\n action === \"cursor-move\" ||\n action === \"cursor-hide\"\n );\n}\n\nfunction normalizeLegacyTabAction(\n action: BrowserActionParameters[\"action\"] | undefined,\n): BrowserActionParameters[\"tabAction\"] | undefined {\n switch (normalizeBrowserAction(action)) {\n case \"list_tabs\":\n return \"list\";\n case \"open_tab\":\n return \"new\";\n case \"close_tab\":\n return \"close\";\n case \"switch_tab\":\n return \"switch\";\n default:\n return undefined;\n }\n}\n\nfunction formatBrowserSessionResult(\n command: BrowserWorkspaceCommand,\n result: Awaited<ReturnType<typeof executeBrowserWorkspaceCommand>>,\n): string {\n if (result.tabs) {\n const labels = result.tabs\n .map((tab) => `- ${tab.title} (${tab.url})`)\n .join(\"\\n\");\n return labels\n ? `Browser tabs (${result.mode}):\\n${labels}`\n : `No browser session tabs are open (${result.mode}).`;\n }\n\n if (result.closed) {\n return `Browser closed (${result.mode}).`;\n }\n\n if (result.tab) {\n return `${command.subaction} completed in ${result.mode} mode.\\n${result.tab.title}\\n${result.tab.url}`;\n }\n\n if (result.value !== undefined) {\n if (\n command.subaction === \"cursor-move\" &&\n result.value !== null &&\n typeof result.value === \"object\" &&\n \"x\" in result.value &&\n \"y\" in result.value\n ) {\n const cursor = result.value as { x: number; y: number };\n return `Cursor moved to (${Math.round(cursor.x)}, ${Math.round(cursor.y)}) in ${result.mode} mode.`;\n }\n const serialized =\n typeof result.value === \"string\"\n ? result.value\n : JSON.stringify(result.value, null, 2);\n return `Browser ${command.subaction} result (${result.mode}):\\n${serialized}`;\n }\n\n if (result.snapshot?.data) {\n return `Browser ${command.subaction} captured a preview in ${result.mode} mode.`;\n }\n\n return `Browser ${command.subaction} completed in ${result.mode} mode.`;\n}\n\nexport const browserAction: Action = {\n name: \"BROWSER\",\n contexts: [\"browser\", \"web\", \"automation\", \"secrets\"],\n roleGate: { minRole: \"OWNER\" },\n similes: [\n \"BROWSE_SITE\",\n \"BROWSER_SESSION\",\n \"CONTROL_BROWSER\",\n \"CONTROL_BROWSER_SESSION\",\n \"MANAGE_ELIZA_BROWSER_WORKSPACE\",\n \"NAVIGATE_SITE\",\n \"OPEN_SITE\",\n \"USE_BROWSER\",\n \"BROWSER_ACTION\",\n \"BROWSER_AUTOFILL_LOGIN\",\n \"AGENT_AUTOFILL\",\n \"AUTOFILL_BROWSER_LOGIN\",\n \"AUTOFILL_LOGIN\",\n \"FILL_BROWSER_CREDENTIALS\",\n \"LOG_INTO_SITE\",\n \"SIGN_IN_TO_SITE\",\n ],\n description:\n \"BROWSER action. Control registered browser target: app workspace, bridge Chrome/Safari companion, computeruse Chromium, or Stagehand fallback. BrowserService picks target if omitted. action=autofill_login + domain vault-gated autofills open workspace tab.\",\n descriptionCompressed:\n \"Browser open|navigate|click|type|screenshot|state|autofill_login; bridge status elsewhere\",\n validate: async () => true,\n handler: async (runtime, message, _state, options) => {\n const params = (options as HandlerOptions | undefined)?.parameters as\n | BrowserActionParameters\n | undefined;\n const messageText = getMessageText(message);\n const subaction = inferBrowserSubaction(params, messageText);\n\n if (subaction === \"autofill-login\") {\n const { executeBrowserAutofillLogin } = await import(\n \"./browser-autofill-login.js\"\n );\n return executeBrowserAutofillLogin(runtime, message, options);\n }\n\n const url =\n params?.url?.trim() || extractFirstUrl(messageText) || undefined;\n\n const command: BrowserWorkspaceCommand = {\n id: params?.id?.trim(),\n key: params?.key?.trim(),\n pixels: params?.pixels,\n script: params?.script,\n selector: params?.selector?.trim(),\n subaction,\n tabAction: params?.tabAction ?? normalizeLegacyTabAction(params?.action),\n text: params?.text,\n value: params?.text,\n timeoutMs: params?.timeoutMs,\n url,\n cursorDurationMs: params?.cursorDurationMs,\n perCharDelayMs: params?.perCharDelayMs,\n replace: params?.replace,\n x: params?.x,\n y: params?.y,\n };\n\n const browserService =\n runtime.getService<BrowserService>(BROWSER_SERVICE_TYPE);\n\n try {\n logger.info(\n `[BROWSER] ${command.subaction} via target=${params?.target ?? \"auto\"} (workspace mode=${getBrowserWorkspaceMode(process.env)})`,\n );\n const result = browserService\n ? await browserService.execute(command, params?.target)\n : await executeBrowserWorkspaceCommand(command);\n\n return {\n text: formatBrowserSessionResult(command, result),\n success: true,\n values: {\n success: true,\n mode: result.mode,\n subaction: result.subaction,\n },\n data: {\n actionName: \"BROWSER\",\n command,\n result,\n },\n };\n } catch (error) {\n const messageText =\n error instanceof Error ? error.message : \"Browser action failed\";\n logger.warn(`[BROWSER] Failed: ${messageText}`);\n return {\n text: `Browser action failed: ${messageText}`,\n success: false,\n values: { success: false, error: \"BROWSER_FAILED\" },\n data: {\n actionName: \"BROWSER\",\n command,\n },\n };\n }\n },\n parameters: [\n {\n name: \"target\",\n description:\n \"Optional browser target id. Common values: workspace, bridge, computeruse, stagehand.\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"action\",\n description:\n \"Browser action. Snake_case canonical; legacy kebab-case and subaction accepted.\",\n required: false,\n schema: {\n type: \"string\" as const,\n enum: [\n \"back\",\n \"click\",\n \"close\",\n \"context\",\n \"forward\",\n \"get\",\n \"get_context\",\n \"hide\",\n \"info\",\n \"list_tabs\",\n \"navigate\",\n \"open\",\n \"open_tab\",\n \"press\",\n \"reload\",\n \"screenshot\",\n \"show\",\n \"snapshot\",\n \"state\",\n \"tab\",\n \"type\",\n \"wait\",\n \"close_tab\",\n \"switch_tab\",\n \"realistic_click\",\n \"realistic_fill\",\n \"realistic_type\",\n \"realistic_press\",\n \"cursor_move\",\n \"cursor_hide\",\n \"autofill_login\",\n ],\n },\n },\n {\n name: \"tabAction\",\n description: \"Tab operation when subaction is tab\",\n required: false,\n schema: {\n type: \"string\" as const,\n enum: [\"close\", \"list\", \"new\", \"switch\"],\n },\n },\n {\n name: \"domain\",\n description:\n \"Required for action=autofill_login: registrable hostname, e.g. github.com.\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"username\",\n description: \"For autofill-login: saved login username; omit for latest.\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"submit\",\n description: \"For autofill-login: submit after filling. Default false.\",\n required: false,\n schema: { type: \"boolean\" as const },\n },\n {\n name: \"id\",\n description: \"Session or tab id to target\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"url\",\n description: \"URL for open or navigate\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"selector\",\n description: \"Selector for click, type, or wait\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"text\",\n description: \"Text for type\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"key\",\n description: \"Keyboard key for press\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"pixels\",\n description: \"Scroll distance in pixels\",\n required: false,\n schema: { type: \"number\" as const },\n },\n {\n name: \"timeoutMs\",\n description: \"Command timeout in milliseconds\",\n required: false,\n schema: { type: \"number\" as const },\n },\n {\n name: \"script\",\n description: \"Script for eval\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"watchMode\",\n description:\n \"User watching hint; prefer realistic-* click/fill, visible cursor, pointer events.\",\n required: false,\n schema: { type: \"boolean\" as const },\n },\n {\n name: \"cursorDurationMs\",\n description: \"Cursor animation duration (ms) for realistic-* subactions\",\n required: false,\n schema: { type: \"number\" as const },\n },\n {\n name: \"perCharDelayMs\",\n description: \"Per-character delay for realistic-type/realistic-fill (ms)\",\n required: false,\n schema: { type: \"number\" as const },\n },\n {\n name: \"replace\",\n description: \"For realistic-fill: replace existing input, not append.\",\n required: false,\n schema: { type: \"boolean\" as const },\n },\n {\n name: \"x\",\n description: \"Cursor target X (CSS pixels) for cursor-move\",\n required: false,\n schema: { type: \"number\" as const },\n },\n {\n name: \"y\",\n description: \"Cursor target Y (CSS pixels) for cursor-move\",\n required: false,\n schema: { type: \"number\" as const },\n },\n ],\n examples: [\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Open elizaos.ai in a new browser tab.\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"open completed in desktop mode.\\nelizaOS\\nhttps://elizaos.ai\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Click the sign-in button on that page.\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"click completed in desktop mode.\",\n },\n },\n ],\n ] as ActionExample[][],\n};\n"],"mappings":"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","names":["messageText"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manage-browser-bridge.d.ts","sourceRoot":"","sources":["../../src/actions/manage-browser-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EACV,MAAM,EAKP,MAAM,eAAe,CAAC;AAqBvB,eAAO,MAAM,yBAAyB,kEAK5B,CAAC;AACX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"manage-browser-bridge.d.ts","sourceRoot":"","sources":["../../src/actions/manage-browser-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EACV,MAAM,EAKP,MAAM,eAAe,CAAC;AAqBvB,eAAO,MAAM,yBAAyB,kEAK5B,CAAC;AACX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAudhF,eAAO,MAAM,yBAAyB,EAAE,MA2JvC,CAAC"}
|
|
@@ -461,8 +461,8 @@ const manageBrowserBridgeAction = {
|
|
|
461
461
|
"BROWSER_BRIDGE_OPEN_MANAGER",
|
|
462
462
|
"BROWSER_BRIDGE_REFRESH"
|
|
463
463
|
],
|
|
464
|
-
description: "Owner-only
|
|
465
|
-
descriptionCompressed: "
|
|
464
|
+
description: "Owner-only Agent Browser Bridge management for Chrome/Safari. Actions: refresh status/settings/connection, install build+reveal setup, reveal_folder open build folder, open_manager chrome://extensions only on explicit ask. Infer action if omitted.",
|
|
465
|
+
descriptionCompressed: "Browser Bridge: refresh|install|reveal_folder|open_manager chrome://extensions",
|
|
466
466
|
validate: async (_runtime, message, state) => {
|
|
467
467
|
return hasSelectedContext(state) || hasBrowserBridgeIntent(message, state);
|
|
468
468
|
},
|
|
@@ -483,7 +483,9 @@ const manageBrowserBridgeAction = {
|
|
|
483
483
|
return await runRefresh(runtime);
|
|
484
484
|
default: {
|
|
485
485
|
const exhaustive = subaction;
|
|
486
|
-
throw new Error(
|
|
486
|
+
throw new Error(
|
|
487
|
+
`Unsupported MANAGE_BROWSER_BRIDGE subaction: ${exhaustive}`
|
|
488
|
+
);
|
|
487
489
|
}
|
|
488
490
|
}
|
|
489
491
|
} catch (err) {
|
|
@@ -507,16 +509,7 @@ const manageBrowserBridgeAction = {
|
|
|
507
509
|
parameters: [
|
|
508
510
|
{
|
|
509
511
|
name: "action",
|
|
510
|
-
description: "Bridge
|
|
511
|
-
required: false,
|
|
512
|
-
schema: {
|
|
513
|
-
type: "string",
|
|
514
|
-
enum: [...BROWSER_BRIDGE_SUBACTIONS]
|
|
515
|
-
}
|
|
516
|
-
},
|
|
517
|
-
{
|
|
518
|
-
name: "subaction",
|
|
519
|
-
description: "Legacy alias for action.",
|
|
512
|
+
description: "Bridge action. refresh=status/settings; open_manager only explicit chrome://extensions; install setup; reveal_folder build folder. Infer if omitted.",
|
|
520
513
|
required: false,
|
|
521
514
|
schema: {
|
|
522
515
|
type: "string",
|
|
@@ -542,7 +535,10 @@ const manageBrowserBridgeAction = {
|
|
|
542
535
|
[
|
|
543
536
|
{
|
|
544
537
|
name: "{{name1}}",
|
|
545
|
-
content: {
|
|
538
|
+
content: {
|
|
539
|
+
text: "Install the agent browser bridge extension.",
|
|
540
|
+
source: "chat"
|
|
541
|
+
}
|
|
546
542
|
},
|
|
547
543
|
{
|
|
548
544
|
name: "{{agentName}}",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/actions/manage-browser-bridge.ts"],"sourcesContent":["/**\n * MANAGE_BROWSER_BRIDGE — single action that covers the bridge-extension\n * management surface (Install, Reveal Folder, Open Manager, Refresh) that the\n * `BrowserWorkspaceView` UI exposes.\n *\n * This replaces the four previously-separate actions\n * (`BROWSER_BRIDGE_INSTALL`, `BROWSER_BRIDGE_REVEAL_FOLDER`,\n * `BROWSER_BRIDGE_OPEN_MANAGER`, `BROWSER_BRIDGE_REFRESH`) — folded into one\n * because each one took zero parameters and only differed in which packaging\n * helper it called. One action with an `action` parameter is the right agent\n * surface; the LLM picks the child action.\n *\n * Calls directly into the local packaging helpers (the same code path the\n * route layer uses) rather than going back through HTTP, so the action runs\n * inside the runtime process without an HTTP round trip.\n *\n * Authorization: OWNER only. The bridge is local-machine plumbing —\n * installing a browser extension, opening Chrome's extensions page,\n * inspecting paired companions — that should never be triggered by a\n * non-owner user.\n *\n * Validation: keyword-based on the message (and recent messages) using a\n * deliberately liberal multilingual set covering \"browser\", \"bridge\",\n * \"chrome / safari / firefox / brave / edge / arc / opera / vivaldi\",\n * \"extension\", \"companion\", \"install\", \"manager\", \"reveal\", \"refresh\",\n * \"connection\", \"pair\", and Spanish / French / German / Italian / Japanese /\n * Chinese / Korean / Portuguese / Russian / Arabic / Hindi / Turkish /\n * Vietnamese / Thai / Polish / Dutch / Indonesian / Hebrew variants.\n */\n\nimport type {\n Action,\n ActionResult,\n IAgentRuntime,\n Memory,\n State,\n} from \"@elizaos/core\";\nimport { logger } from \"@elizaos/core\";\nimport type {\n BrowserBridgeCompanionPackageStatus,\n BrowserBridgeCompanionStatus,\n} from \"../contracts.js\";\nimport {\n buildBrowserBridgeCompanionPackage,\n getBrowserBridgeCompanionPackageStatus,\n openBrowserBridgeCompanionManager,\n openBrowserBridgeCompanionPackagePath,\n} from \"../packaging.js\";\nimport {\n BROWSER_BRIDGE_ROUTE_SERVICE_TYPE,\n type BrowserBridgeRouteService,\n} from \"../service.js\";\n\nconst ACTION_NAME = \"MANAGE_BROWSER_BRIDGE\";\nconst MAX_BROWSER_BRIDGE_TEXT_LENGTH = 3000;\nconst BROWSER_BRIDGE_TIMEOUT_MS = 30_000;\n\nexport const BROWSER_BRIDGE_SUBACTIONS = [\n \"install\",\n \"reveal_folder\",\n \"open_manager\",\n \"refresh\",\n] as const;\nexport type BrowserBridgeSubaction = (typeof BROWSER_BRIDGE_SUBACTIONS)[number];\n\nconst BROWSER_BRIDGE_KEYWORDS = [\n // English — concept\n \"browser\",\n \"browsers\",\n \"browser bridge\",\n \"agent browser bridge\",\n \"bridge\",\n \"extension\",\n \"extensions\",\n \"companion\",\n \"companions\",\n \"connection\",\n \"pair\",\n \"paired\",\n \"pairing\",\n // English — browser brands\n \"chrome\",\n \"safari\",\n \"firefox\",\n \"brave\",\n \"edge\",\n \"arc\",\n \"opera\",\n \"vivaldi\",\n // English — actions\n \"install\",\n \"installer\",\n \"installed\",\n \"uninstall\",\n \"reveal\",\n \"show folder\",\n \"open folder\",\n \"open manager\",\n \"manager\",\n \"refresh\",\n \"reload\",\n \"reconnect\",\n \"connect\",\n \"disconnect\",\n \"status\",\n \"settings\",\n \"setting\",\n \"configuration\",\n \"config\",\n \"folder\",\n \"load unpacked\",\n \"chrome://extensions\",\n // Spanish\n \"navegador\",\n \"navegadores\",\n \"extensión\",\n \"extensiones\",\n \"instalar\",\n \"instalador\",\n \"desinstalar\",\n \"carpeta\",\n \"actualizar\",\n \"conectar\",\n \"conexión\",\n \"puente\",\n // French\n \"navigateur\",\n \"navigateurs\",\n \"installer\",\n \"désinstaller\",\n \"dossier\",\n \"actualiser\",\n \"rafraîchir\",\n \"connexion\",\n \"pont\",\n // German\n \"browser\",\n \"erweiterung\",\n \"erweiterungen\",\n \"installieren\",\n \"deinstallieren\",\n \"ordner\",\n \"aktualisieren\",\n \"verbindung\",\n \"brücke\",\n // Italian\n \"navigatore\",\n \"estensione\",\n \"estensioni\",\n \"installare\",\n \"disinstallare\",\n \"cartella\",\n \"aggiornare\",\n \"collegamento\",\n \"ponte\",\n // Portuguese\n \"navegador\",\n \"extensão\",\n \"extensões\",\n \"instalar\",\n \"pasta\",\n \"atualizar\",\n \"conexão\",\n \"ponte\",\n // Russian\n \"браузер\",\n \"расширение\",\n \"установить\",\n \"обновить\",\n \"папка\",\n \"соединение\",\n \"мост\",\n // Japanese\n \"ブラウザ\",\n \"拡張機能\",\n \"インストール\",\n \"フォルダ\",\n \"更新\",\n \"接続\",\n \"ブリッジ\",\n // Chinese (simplified + traditional)\n \"浏览器\",\n \"瀏覽器\",\n \"扩展\",\n \"擴充\",\n \"安装\",\n \"安裝\",\n \"文件夹\",\n \"資料夾\",\n \"刷新\",\n \"重新整理\",\n \"连接\",\n \"連線\",\n \"桥\",\n \"橋\",\n // Korean\n \"브라우저\",\n \"확장\",\n \"설치\",\n \"폴더\",\n \"새로고침\",\n \"연결\",\n \"브리지\",\n // Arabic\n \"متصفح\",\n \"إضافة\",\n \"تثبيت\",\n \"مجلد\",\n \"تحديث\",\n \"اتصال\",\n \"جسر\",\n // Hindi\n \"ब्राउज़र\",\n \"एक्सटेंशन\",\n \"इंस्टॉल\",\n \"फ़ोल्डर\",\n \"रिफ्रेश\",\n \"कनेक्शन\",\n // Turkish\n \"tarayıcı\",\n \"uzantı\",\n \"yükle\",\n \"klasör\",\n \"yenile\",\n \"bağlantı\",\n \"köprü\",\n // Vietnamese\n \"trình duyệt\",\n \"tiện ích\",\n \"cài đặt\",\n \"thư mục\",\n \"làm mới\",\n \"kết nối\",\n \"cầu nối\",\n // Thai\n \"เบราว์เซอร์\",\n \"ส่วนขยาย\",\n \"ติดตั้ง\",\n \"โฟลเดอร์\",\n \"รีเฟรช\",\n \"เชื่อมต่อ\",\n // Polish\n \"przeglądarka\",\n \"rozszerzenie\",\n \"zainstaluj\",\n \"folder\",\n \"odśwież\",\n \"połączenie\",\n \"most\",\n // Dutch\n \"browser\",\n \"extensie\",\n \"installeer\",\n \"map\",\n \"vernieuw\",\n \"verbinding\",\n \"brug\",\n // Indonesian / Malay\n \"peramban\",\n \"penjelajah\",\n \"ekstensi\",\n \"pasang\",\n \"folder\",\n \"muat ulang\",\n \"koneksi\",\n \"jembatan\",\n // Hebrew\n \"דפדפן\",\n \"הרחבה\",\n \"התקנה\",\n \"תיקייה\",\n \"רענון\",\n \"חיבור\",\n] as const;\n\nfunction describeError(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction withBrowserBridgeTimeout<T>(\n promise: Promise<T>,\n label: string,\n): Promise<T> {\n return Promise.race([\n promise,\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`${label} timed out`)),\n BROWSER_BRIDGE_TIMEOUT_MS,\n ),\n ),\n ]);\n}\n\nconst SELECTED_CONTEXT_KEYS = [\n \"browser\",\n \"files\",\n \"connectors\",\n \"settings\",\n \"automation\",\n \"admin\",\n] as const;\n\nfunction hasSelectedContext(state: State | undefined): boolean {\n const selected = new Set<string>();\n const collect = (value: unknown) => {\n if (!Array.isArray(value)) return;\n for (const item of value) {\n if (typeof item === \"string\") selected.add(item);\n }\n };\n collect(\n (state?.values as Record<string, unknown> | undefined)?.selectedContexts,\n );\n collect(\n (state?.data as Record<string, unknown> | undefined)?.selectedContexts,\n );\n const contextObject = (state?.data as Record<string, unknown> | undefined)\n ?.contextObject as\n | {\n trajectoryPrefix?: { selectedContexts?: unknown };\n metadata?: { selectedContexts?: unknown };\n }\n | undefined;\n collect(contextObject?.trajectoryPrefix?.selectedContexts);\n collect(contextObject?.metadata?.selectedContexts);\n return SELECTED_CONTEXT_KEYS.some((context) => selected.has(context));\n}\n\nfunction hasBrowserBridgeIntent(\n message: Memory,\n state: State | undefined,\n): boolean {\n const text = [\n typeof message.content?.text === \"string\" ? message.content.text : \"\",\n typeof state?.values?.recentMessages === \"string\"\n ? state.values.recentMessages\n : \"\",\n ]\n .join(\"\\n\")\n .toLowerCase();\n return BROWSER_BRIDGE_KEYWORDS.some((keyword) =>\n text.includes(keyword.toLowerCase()),\n );\n}\n\ntype ManageBrowserBridgeParameters = {\n action?: BrowserBridgeSubaction;\n subaction?: BrowserBridgeSubaction;\n};\n\nfunction normalizeSubaction(\n raw: string | undefined,\n): BrowserBridgeSubaction | null {\n if (!raw) return null;\n const trimmed = raw.trim().toLowerCase().replace(/[\\s-]+/g, \"_\");\n return (BROWSER_BRIDGE_SUBACTIONS as readonly string[]).includes(trimmed)\n ? (trimmed as BrowserBridgeSubaction)\n : null;\n}\n\nfunction inferSubactionFromMessage(text: string): BrowserBridgeSubaction {\n const normalized = text.toLowerCase();\n if (\n /\\b(reveal|show|open).{0,12}(folder|build folder|directory)\\b/.test(\n normalized,\n ) &&\n !/\\bextension manager\\b/.test(normalized)\n ) {\n return \"reveal_folder\";\n }\n if (\n /\\bopen.{0,8}(extensions?|extension manager|chrome:\\/\\/extensions)\\b/.test(\n normalized,\n )\n ) {\n return \"open_manager\";\n }\n if (\n /\\b(refresh|reload|reconnect|status|settings?|config(?:uration)?|update|sync|update status|connection state)\\b/.test(\n normalized,\n )\n ) {\n return \"refresh\";\n }\n return \"install\";\n}\n\nasync function runInstall(): Promise<ActionResult> {\n let status: BrowserBridgeCompanionPackageStatus =\n getBrowserBridgeCompanionPackageStatus();\n if (!status.chromeBuildPath) {\n status = await withBrowserBridgeTimeout(\n buildBrowserBridgeCompanionPackage(\"chrome\"),\n \"browser bridge package build\",\n );\n }\n const reveal = await withBrowserBridgeTimeout(\n openBrowserBridgeCompanionPackagePath(\"chrome_build\", { revealOnly: true }),\n \"browser bridge reveal\",\n );\n let openedManager = true;\n try {\n await withBrowserBridgeTimeout(\n openBrowserBridgeCompanionManager(\"chrome\"),\n \"browser bridge manager open\",\n );\n } catch (err) {\n openedManager = false;\n logger.warn(\n `[${ACTION_NAME}] could not open chrome://extensions: ${describeError(err)}`,\n );\n }\n const text = (\n openedManager\n ? `Chrome is ready. Click Load unpacked and choose ${reveal.path}.`\n : `The Agent Browser Bridge folder is ready at ${reveal.path}. Open chrome://extensions, click Load unpacked, and choose that folder.`\n ).slice(0, MAX_BROWSER_BRIDGE_TEXT_LENGTH);\n return {\n text,\n success: true,\n values: { success: true, subaction: \"install\", openedManager },\n data: {\n actionName: ACTION_NAME,\n subaction: \"install\",\n path: reveal.path,\n openedManager,\n status,\n },\n };\n}\n\nasync function runRevealFolder(): Promise<ActionResult> {\n const reveal = await withBrowserBridgeTimeout(\n openBrowserBridgeCompanionPackagePath(\"chrome_build\", { revealOnly: true }),\n \"browser bridge reveal\",\n );\n const text =\n `Revealed the Agent Browser Bridge folder at ${reveal.path}.`.slice(\n 0,\n MAX_BROWSER_BRIDGE_TEXT_LENGTH,\n );\n return {\n text,\n success: true,\n values: { success: true, subaction: \"reveal_folder\" },\n data: {\n actionName: ACTION_NAME,\n subaction: \"reveal_folder\",\n path: reveal.path,\n },\n };\n}\n\nasync function runOpenManager(): Promise<ActionResult> {\n await withBrowserBridgeTimeout(\n openBrowserBridgeCompanionManager(\"chrome\"),\n \"browser bridge manager open\",\n );\n const text =\n \"Opened Chrome extensions. Click Load unpacked and choose the Agent Browser Bridge folder.\".slice(\n 0,\n MAX_BROWSER_BRIDGE_TEXT_LENGTH,\n );\n return {\n text,\n success: true,\n values: { success: true, subaction: \"open_manager\" },\n data: { actionName: ACTION_NAME, subaction: \"open_manager\" },\n };\n}\n\nasync function runRefresh(runtime: IAgentRuntime): Promise<ActionResult> {\n const status = getBrowserBridgeCompanionPackageStatus();\n let settings:\n | Awaited<ReturnType<BrowserBridgeRouteService[\"getBrowserSettings\"]>>\n | null = null;\n let companions: BrowserBridgeCompanionStatus[] = [];\n const service = runtime.getService<BrowserBridgeRouteService>(\n BROWSER_BRIDGE_ROUTE_SERVICE_TYPE,\n );\n if (!service) {\n return {\n text: \"Agent Browser Bridge package status is available, but companion status cannot be read because the Browser Bridge service is not registered.\",\n success: false,\n values: {\n success: false,\n subaction: \"refresh\",\n error: \"BROWSER_BRIDGE_SERVICE_UNAVAILABLE\",\n },\n data: {\n actionName: ACTION_NAME,\n subaction: \"refresh\",\n status,\n settings,\n companions,\n },\n };\n }\n settings = await service.getBrowserSettings();\n companions = (await service.listBrowserCompanions()).slice(0, 25);\n const connected = companions.length > 0;\n const text = [\n \"Refreshed Agent Browser Bridge settings.\",\n `Tracking: ${settings.trackingMode}.`,\n `Browser control: ${settings.allowBrowserControl ? \"on\" : \"off\"}.`,\n connected\n ? `Companions: ${companions.length} paired.`\n : \"Companions: none paired.\",\n ].join(\" \");\n return {\n text,\n success: true,\n values: {\n success: true,\n subaction: \"refresh\",\n connected,\n trackingMode: settings.trackingMode,\n allowBrowserControl: settings.allowBrowserControl,\n companionCount: companions.length,\n },\n data: {\n actionName: ACTION_NAME,\n subaction: \"refresh\",\n status,\n settings,\n companions,\n },\n };\n}\n\nexport const manageBrowserBridgeAction: Action = {\n name: ACTION_NAME,\n contexts: [\"browser\", \"files\", \"connectors\", \"settings\"],\n contextGate: { anyOf: [\"browser\", \"files\", \"connectors\", \"settings\"] },\n roleGate: { minRole: \"OWNER\" },\n similes: [\n // Install / setup synonyms\n \"INSTALL_BROWSER_BRIDGE\",\n \"SETUP_BROWSER_BRIDGE\",\n \"PAIR_BROWSER\",\n \"CONNECT_BROWSER\",\n \"ADD_BROWSER_EXTENSION\",\n // Reveal folder synonyms\n \"REVEAL_BROWSER_BRIDGE_FOLDER\",\n \"OPEN_BROWSER_BRIDGE_FOLDER\",\n \"SHOW_BROWSER_EXTENSION_FOLDER\",\n // Open manager synonyms\n \"OPEN_CHROME_EXTENSIONS\",\n \"OPEN_BROWSER_BRIDGE_MANAGER\",\n \"OPEN_EXTENSION_MANAGER\",\n // Refresh synonyms\n \"REFRESH_BROWSER_BRIDGE\",\n \"REFRESH_BROWSER_BRIDGE_CONNECTION\",\n \"RELOAD_BROWSER_BRIDGE_STATUS\",\n \"RECONNECT_BROWSER\",\n // Generic\n \"MANAGE_CHROME_EXTENSION\",\n \"MANAGE_SAFARI_EXTENSION\",\n \"BROWSER_BRIDGE_INSTALL\",\n \"BROWSER_BRIDGE_REVEAL_FOLDER\",\n \"BROWSER_BRIDGE_OPEN_MANAGER\",\n \"BROWSER_BRIDGE_REFRESH\",\n ],\n description:\n \"Owner-only management of the Agent Browser Bridge companion extension that connects Eliza to the user's Chrome and Safari browsers. Actions: refresh (show settings/status/connection state), install (build and reveal the extension for setup), reveal_folder (open the built extension folder), open_manager (open chrome://extensions only when the owner explicitly asks). The action parameter is inferred from message text when omitted; show/settings/status maps to refresh and 'open chrome extensions' maps to open_manager. Prefer the browser-bridge provider for passive companion status and use this action's refresh child action only for an explicit live refresh.\",\n descriptionCompressed:\n \"Manage LifeOps Browser Bridge: refresh shows settings/status; install setup; reveal_folder build folder; open_manager chrome://extensions.\",\n validate: async (\n _runtime: IAgentRuntime,\n message: Memory,\n state?: State,\n ): Promise<boolean> => {\n return hasSelectedContext(state) || hasBrowserBridgeIntent(message, state);\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state,\n options,\n ): Promise<ActionResult> => {\n const params = (options as { parameters?: ManageBrowserBridgeParameters })\n ?.parameters;\n const subaction =\n normalizeSubaction(params?.action) ??\n normalizeSubaction(params?.subaction) ??\n inferSubactionFromMessage(\n typeof message.content?.text === \"string\" ? message.content.text : \"\",\n );\n try {\n switch (subaction) {\n case \"install\":\n return await runInstall();\n case \"reveal_folder\":\n return await runRevealFolder();\n case \"open_manager\":\n return await runOpenManager();\n case \"refresh\":\n return await runRefresh(runtime);\n default: {\n const exhaustive: never = subaction;\n throw new Error(`Unsupported MANAGE_BROWSER_BRIDGE subaction: ${exhaustive}`);\n }\n }\n } catch (err) {\n const text =\n `Failed MANAGE_BROWSER_BRIDGE ${subaction}: ${describeError(err)}`.slice(\n 0,\n MAX_BROWSER_BRIDGE_TEXT_LENGTH,\n );\n logger.warn(`[${ACTION_NAME}] ${text}`);\n return {\n text,\n success: false,\n values: {\n success: false,\n subaction,\n error: `MANAGE_BROWSER_BRIDGE_${subaction.toUpperCase()}_FAILED`,\n },\n data: { actionName: ACTION_NAME, subaction },\n };\n }\n },\n parameters: [\n {\n name: \"action\",\n description:\n \"Bridge management action. Use refresh for show/settings/status/connection-state requests. Use open_manager only for explicit chrome://extensions or extension-manager requests. install builds/reveals/opens setup; reveal_folder opens the build folder. Inferred from message text if omitted.\",\n required: false,\n schema: {\n type: \"string\" as const,\n enum: [...BROWSER_BRIDGE_SUBACTIONS],\n },\n },\n {\n name: \"subaction\",\n description: \"Legacy alias for action.\",\n required: false,\n schema: {\n type: \"string\" as const,\n enum: [...BROWSER_BRIDGE_SUBACTIONS],\n },\n },\n ],\n examples: [\n [\n {\n name: \"{{name1}}\",\n content: { text: \"Show the browser bridge status.\", source: \"chat\" },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Refreshing the browser bridge status.\",\n actions: [\"MANAGE_BROWSER_BRIDGE\"],\n thought:\n \"Show/status request maps to MANAGE_BROWSER_BRIDGE action=refresh.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: { text: \"Install the agent browser bridge extension.\", source: \"chat\" },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Building and revealing the bridge extension.\",\n actions: [\"MANAGE_BROWSER_BRIDGE\"],\n thought:\n \"Setup intent maps to MANAGE_BROWSER_BRIDGE action=install.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: { text: \"Open chrome://extensions for me.\", source: \"chat\" },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Opening the extension manager.\",\n actions: [\"MANAGE_BROWSER_BRIDGE\"],\n thought:\n \"Explicit chrome://extensions request maps to MANAGE_BROWSER_BRIDGE action=open_manager.\",\n },\n },\n ],\n ],\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/actions/manage-browser-bridge.ts"],"sourcesContent":["/**\n * MANAGE_BROWSER_BRIDGE — single action that covers the bridge-extension\n * management surface (Install, Reveal Folder, Open Manager, Refresh) that the\n * `BrowserWorkspaceView` UI exposes.\n *\n * This replaces the four previously-separate actions\n * (`BROWSER_BRIDGE_INSTALL`, `BROWSER_BRIDGE_REVEAL_FOLDER`,\n * `BROWSER_BRIDGE_OPEN_MANAGER`, `BROWSER_BRIDGE_REFRESH`) — folded into one\n * because each one took zero parameters and only differed in which packaging\n * helper it called. One action with an `action` parameter is the right agent\n * surface; the LLM picks the child action.\n *\n * Calls directly into the local packaging helpers (the same code path the\n * route layer uses) rather than going back through HTTP, so the action runs\n * inside the runtime process without an HTTP round trip.\n *\n * Authorization: OWNER only. The bridge is local-machine plumbing —\n * installing a browser extension, opening Chrome's extensions page,\n * inspecting paired companions — that should never be triggered by a\n * non-owner user.\n *\n * Validation: keyword-based on the message (and recent messages) using a\n * deliberately liberal multilingual set covering \"browser\", \"bridge\",\n * \"chrome / safari / firefox / brave / edge / arc / opera / vivaldi\",\n * \"extension\", \"companion\", \"install\", \"manager\", \"reveal\", \"refresh\",\n * \"connection\", \"pair\", and Spanish / French / German / Italian / Japanese /\n * Chinese / Korean / Portuguese / Russian / Arabic / Hindi / Turkish /\n * Vietnamese / Thai / Polish / Dutch / Indonesian / Hebrew variants.\n */\n\nimport type {\n Action,\n ActionResult,\n IAgentRuntime,\n Memory,\n State,\n} from \"@elizaos/core\";\nimport { logger } from \"@elizaos/core\";\nimport type {\n BrowserBridgeCompanionPackageStatus,\n BrowserBridgeCompanionStatus,\n} from \"../contracts.js\";\nimport {\n buildBrowserBridgeCompanionPackage,\n getBrowserBridgeCompanionPackageStatus,\n openBrowserBridgeCompanionManager,\n openBrowserBridgeCompanionPackagePath,\n} from \"../packaging.js\";\nimport {\n BROWSER_BRIDGE_ROUTE_SERVICE_TYPE,\n type BrowserBridgeRouteService,\n} from \"../service.js\";\n\nconst ACTION_NAME = \"MANAGE_BROWSER_BRIDGE\";\nconst MAX_BROWSER_BRIDGE_TEXT_LENGTH = 3000;\nconst BROWSER_BRIDGE_TIMEOUT_MS = 30_000;\n\nexport const BROWSER_BRIDGE_SUBACTIONS = [\n \"install\",\n \"reveal_folder\",\n \"open_manager\",\n \"refresh\",\n] as const;\nexport type BrowserBridgeSubaction = (typeof BROWSER_BRIDGE_SUBACTIONS)[number];\n\nconst BROWSER_BRIDGE_KEYWORDS = [\n // English — concept\n \"browser\",\n \"browsers\",\n \"browser bridge\",\n \"agent browser bridge\",\n \"bridge\",\n \"extension\",\n \"extensions\",\n \"companion\",\n \"companions\",\n \"connection\",\n \"pair\",\n \"paired\",\n \"pairing\",\n // English — browser brands\n \"chrome\",\n \"safari\",\n \"firefox\",\n \"brave\",\n \"edge\",\n \"arc\",\n \"opera\",\n \"vivaldi\",\n // English — actions\n \"install\",\n \"installer\",\n \"installed\",\n \"uninstall\",\n \"reveal\",\n \"show folder\",\n \"open folder\",\n \"open manager\",\n \"manager\",\n \"refresh\",\n \"reload\",\n \"reconnect\",\n \"connect\",\n \"disconnect\",\n \"status\",\n \"settings\",\n \"setting\",\n \"configuration\",\n \"config\",\n \"folder\",\n \"load unpacked\",\n \"chrome://extensions\",\n // Spanish\n \"navegador\",\n \"navegadores\",\n \"extensión\",\n \"extensiones\",\n \"instalar\",\n \"instalador\",\n \"desinstalar\",\n \"carpeta\",\n \"actualizar\",\n \"conectar\",\n \"conexión\",\n \"puente\",\n // French\n \"navigateur\",\n \"navigateurs\",\n \"installer\",\n \"désinstaller\",\n \"dossier\",\n \"actualiser\",\n \"rafraîchir\",\n \"connexion\",\n \"pont\",\n // German\n \"browser\",\n \"erweiterung\",\n \"erweiterungen\",\n \"installieren\",\n \"deinstallieren\",\n \"ordner\",\n \"aktualisieren\",\n \"verbindung\",\n \"brücke\",\n // Italian\n \"navigatore\",\n \"estensione\",\n \"estensioni\",\n \"installare\",\n \"disinstallare\",\n \"cartella\",\n \"aggiornare\",\n \"collegamento\",\n \"ponte\",\n // Portuguese\n \"navegador\",\n \"extensão\",\n \"extensões\",\n \"instalar\",\n \"pasta\",\n \"atualizar\",\n \"conexão\",\n \"ponte\",\n // Russian\n \"браузер\",\n \"расширение\",\n \"установить\",\n \"обновить\",\n \"папка\",\n \"соединение\",\n \"мост\",\n // Japanese\n \"ブラウザ\",\n \"拡張機能\",\n \"インストール\",\n \"フォルダ\",\n \"更新\",\n \"接続\",\n \"ブリッジ\",\n // Chinese (simplified + traditional)\n \"浏览器\",\n \"瀏覽器\",\n \"扩展\",\n \"擴充\",\n \"安装\",\n \"安裝\",\n \"文件夹\",\n \"資料夾\",\n \"刷新\",\n \"重新整理\",\n \"连接\",\n \"連線\",\n \"桥\",\n \"橋\",\n // Korean\n \"브라우저\",\n \"확장\",\n \"설치\",\n \"폴더\",\n \"새로고침\",\n \"연결\",\n \"브리지\",\n // Arabic\n \"متصفح\",\n \"إضافة\",\n \"تثبيت\",\n \"مجلد\",\n \"تحديث\",\n \"اتصال\",\n \"جسر\",\n // Hindi\n \"ब्राउज़र\",\n \"एक्सटेंशन\",\n \"इंस्टॉल\",\n \"फ़ोल्डर\",\n \"रिफ्रेश\",\n \"कनेक्शन\",\n // Turkish\n \"tarayıcı\",\n \"uzantı\",\n \"yükle\",\n \"klasör\",\n \"yenile\",\n \"bağlantı\",\n \"köprü\",\n // Vietnamese\n \"trình duyệt\",\n \"tiện ích\",\n \"cài đặt\",\n \"thư mục\",\n \"làm mới\",\n \"kết nối\",\n \"cầu nối\",\n // Thai\n \"เบราว์เซอร์\",\n \"ส่วนขยาย\",\n \"ติดตั้ง\",\n \"โฟลเดอร์\",\n \"รีเฟรช\",\n \"เชื่อมต่อ\",\n // Polish\n \"przeglądarka\",\n \"rozszerzenie\",\n \"zainstaluj\",\n \"folder\",\n \"odśwież\",\n \"połączenie\",\n \"most\",\n // Dutch\n \"browser\",\n \"extensie\",\n \"installeer\",\n \"map\",\n \"vernieuw\",\n \"verbinding\",\n \"brug\",\n // Indonesian / Malay\n \"peramban\",\n \"penjelajah\",\n \"ekstensi\",\n \"pasang\",\n \"folder\",\n \"muat ulang\",\n \"koneksi\",\n \"jembatan\",\n // Hebrew\n \"דפדפן\",\n \"הרחבה\",\n \"התקנה\",\n \"תיקייה\",\n \"רענון\",\n \"חיבור\",\n] as const;\n\nfunction describeError(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction withBrowserBridgeTimeout<T>(\n promise: Promise<T>,\n label: string,\n): Promise<T> {\n return Promise.race([\n promise,\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`${label} timed out`)),\n BROWSER_BRIDGE_TIMEOUT_MS,\n ),\n ),\n ]);\n}\n\nconst SELECTED_CONTEXT_KEYS = [\n \"browser\",\n \"files\",\n \"connectors\",\n \"settings\",\n \"automation\",\n \"admin\",\n] as const;\n\nfunction hasSelectedContext(state: State | undefined): boolean {\n const selected = new Set<string>();\n const collect = (value: unknown) => {\n if (!Array.isArray(value)) return;\n for (const item of value) {\n if (typeof item === \"string\") selected.add(item);\n }\n };\n collect(\n (state?.values as Record<string, unknown> | undefined)?.selectedContexts,\n );\n collect(\n (state?.data as Record<string, unknown> | undefined)?.selectedContexts,\n );\n const contextObject = (state?.data as Record<string, unknown> | undefined)\n ?.contextObject as\n | {\n trajectoryPrefix?: { selectedContexts?: unknown };\n metadata?: { selectedContexts?: unknown };\n }\n | undefined;\n collect(contextObject?.trajectoryPrefix?.selectedContexts);\n collect(contextObject?.metadata?.selectedContexts);\n return SELECTED_CONTEXT_KEYS.some((context) => selected.has(context));\n}\n\nfunction hasBrowserBridgeIntent(\n message: Memory,\n state: State | undefined,\n): boolean {\n const text = [\n typeof message.content?.text === \"string\" ? message.content.text : \"\",\n typeof state?.values?.recentMessages === \"string\"\n ? state.values.recentMessages\n : \"\",\n ]\n .join(\"\\n\")\n .toLowerCase();\n return BROWSER_BRIDGE_KEYWORDS.some((keyword) =>\n text.includes(keyword.toLowerCase()),\n );\n}\n\ntype ManageBrowserBridgeParameters = {\n action?: BrowserBridgeSubaction;\n subaction?: BrowserBridgeSubaction;\n};\n\nfunction normalizeSubaction(\n raw: string | undefined,\n): BrowserBridgeSubaction | null {\n if (!raw) return null;\n const trimmed = raw\n .trim()\n .toLowerCase()\n .replace(/[\\s-]+/g, \"_\");\n return (BROWSER_BRIDGE_SUBACTIONS as readonly string[]).includes(trimmed)\n ? (trimmed as BrowserBridgeSubaction)\n : null;\n}\n\nfunction inferSubactionFromMessage(text: string): BrowserBridgeSubaction {\n const normalized = text.toLowerCase();\n if (\n /\\b(reveal|show|open).{0,12}(folder|build folder|directory)\\b/.test(\n normalized,\n ) &&\n !/\\bextension manager\\b/.test(normalized)\n ) {\n return \"reveal_folder\";\n }\n if (\n /\\bopen.{0,8}(extensions?|extension manager|chrome:\\/\\/extensions)\\b/.test(\n normalized,\n )\n ) {\n return \"open_manager\";\n }\n if (\n /\\b(refresh|reload|reconnect|status|settings?|config(?:uration)?|update|sync|update status|connection state)\\b/.test(\n normalized,\n )\n ) {\n return \"refresh\";\n }\n return \"install\";\n}\n\nasync function runInstall(): Promise<ActionResult> {\n let status: BrowserBridgeCompanionPackageStatus =\n getBrowserBridgeCompanionPackageStatus();\n if (!status.chromeBuildPath) {\n status = await withBrowserBridgeTimeout(\n buildBrowserBridgeCompanionPackage(\"chrome\"),\n \"browser bridge package build\",\n );\n }\n const reveal = await withBrowserBridgeTimeout(\n openBrowserBridgeCompanionPackagePath(\"chrome_build\", { revealOnly: true }),\n \"browser bridge reveal\",\n );\n let openedManager = true;\n try {\n await withBrowserBridgeTimeout(\n openBrowserBridgeCompanionManager(\"chrome\"),\n \"browser bridge manager open\",\n );\n } catch (err) {\n openedManager = false;\n logger.warn(\n `[${ACTION_NAME}] could not open chrome://extensions: ${describeError(err)}`,\n );\n }\n const text = (\n openedManager\n ? `Chrome is ready. Click Load unpacked and choose ${reveal.path}.`\n : `The Agent Browser Bridge folder is ready at ${reveal.path}. Open chrome://extensions, click Load unpacked, and choose that folder.`\n ).slice(0, MAX_BROWSER_BRIDGE_TEXT_LENGTH);\n return {\n text,\n success: true,\n values: { success: true, subaction: \"install\", openedManager },\n data: {\n actionName: ACTION_NAME,\n subaction: \"install\",\n path: reveal.path,\n openedManager,\n status,\n },\n };\n}\n\nasync function runRevealFolder(): Promise<ActionResult> {\n const reveal = await withBrowserBridgeTimeout(\n openBrowserBridgeCompanionPackagePath(\"chrome_build\", { revealOnly: true }),\n \"browser bridge reveal\",\n );\n const text =\n `Revealed the Agent Browser Bridge folder at ${reveal.path}.`.slice(\n 0,\n MAX_BROWSER_BRIDGE_TEXT_LENGTH,\n );\n return {\n text,\n success: true,\n values: { success: true, subaction: \"reveal_folder\" },\n data: {\n actionName: ACTION_NAME,\n subaction: \"reveal_folder\",\n path: reveal.path,\n },\n };\n}\n\nasync function runOpenManager(): Promise<ActionResult> {\n await withBrowserBridgeTimeout(\n openBrowserBridgeCompanionManager(\"chrome\"),\n \"browser bridge manager open\",\n );\n const text =\n \"Opened Chrome extensions. Click Load unpacked and choose the Agent Browser Bridge folder.\".slice(\n 0,\n MAX_BROWSER_BRIDGE_TEXT_LENGTH,\n );\n return {\n text,\n success: true,\n values: { success: true, subaction: \"open_manager\" },\n data: { actionName: ACTION_NAME, subaction: \"open_manager\" },\n };\n}\n\nasync function runRefresh(runtime: IAgentRuntime): Promise<ActionResult> {\n const status = getBrowserBridgeCompanionPackageStatus();\n let settings: Awaited<\n ReturnType<BrowserBridgeRouteService[\"getBrowserSettings\"]>\n > | null = null;\n let companions: BrowserBridgeCompanionStatus[] = [];\n const service = runtime.getService<BrowserBridgeRouteService>(\n BROWSER_BRIDGE_ROUTE_SERVICE_TYPE,\n );\n if (!service) {\n return {\n text: \"Agent Browser Bridge package status is available, but companion status cannot be read because the Browser Bridge service is not registered.\",\n success: false,\n values: {\n success: false,\n subaction: \"refresh\",\n error: \"BROWSER_BRIDGE_SERVICE_UNAVAILABLE\",\n },\n data: {\n actionName: ACTION_NAME,\n subaction: \"refresh\",\n status,\n settings,\n companions,\n },\n };\n }\n settings = await service.getBrowserSettings();\n companions = (await service.listBrowserCompanions()).slice(0, 25);\n const connected = companions.length > 0;\n const text = [\n \"Refreshed Agent Browser Bridge settings.\",\n `Tracking: ${settings.trackingMode}.`,\n `Browser control: ${settings.allowBrowserControl ? \"on\" : \"off\"}.`,\n connected\n ? `Companions: ${companions.length} paired.`\n : \"Companions: none paired.\",\n ].join(\" \");\n return {\n text,\n success: true,\n values: {\n success: true,\n subaction: \"refresh\",\n connected,\n trackingMode: settings.trackingMode,\n allowBrowserControl: settings.allowBrowserControl,\n companionCount: companions.length,\n },\n data: {\n actionName: ACTION_NAME,\n subaction: \"refresh\",\n status,\n settings,\n companions,\n },\n };\n}\n\nexport const manageBrowserBridgeAction: Action = {\n name: ACTION_NAME,\n contexts: [\"browser\", \"files\", \"connectors\", \"settings\"],\n contextGate: { anyOf: [\"browser\", \"files\", \"connectors\", \"settings\"] },\n roleGate: { minRole: \"OWNER\" },\n similes: [\n // Install / setup synonyms\n \"INSTALL_BROWSER_BRIDGE\",\n \"SETUP_BROWSER_BRIDGE\",\n \"PAIR_BROWSER\",\n \"CONNECT_BROWSER\",\n \"ADD_BROWSER_EXTENSION\",\n // Reveal folder synonyms\n \"REVEAL_BROWSER_BRIDGE_FOLDER\",\n \"OPEN_BROWSER_BRIDGE_FOLDER\",\n \"SHOW_BROWSER_EXTENSION_FOLDER\",\n // Open manager synonyms\n \"OPEN_CHROME_EXTENSIONS\",\n \"OPEN_BROWSER_BRIDGE_MANAGER\",\n \"OPEN_EXTENSION_MANAGER\",\n // Refresh synonyms\n \"REFRESH_BROWSER_BRIDGE\",\n \"REFRESH_BROWSER_BRIDGE_CONNECTION\",\n \"RELOAD_BROWSER_BRIDGE_STATUS\",\n \"RECONNECT_BROWSER\",\n // Generic\n \"MANAGE_CHROME_EXTENSION\",\n \"MANAGE_SAFARI_EXTENSION\",\n \"BROWSER_BRIDGE_INSTALL\",\n \"BROWSER_BRIDGE_REVEAL_FOLDER\",\n \"BROWSER_BRIDGE_OPEN_MANAGER\",\n \"BROWSER_BRIDGE_REFRESH\",\n ],\n description:\n \"Owner-only Agent Browser Bridge management for Chrome/Safari. Actions: refresh status/settings/connection, install build+reveal setup, reveal_folder open build folder, open_manager chrome://extensions only on explicit ask. Infer action if omitted.\",\n descriptionCompressed:\n \"Browser Bridge: refresh|install|reveal_folder|open_manager chrome://extensions\",\n validate: async (\n _runtime: IAgentRuntime,\n message: Memory,\n state?: State,\n ): Promise<boolean> => {\n return hasSelectedContext(state) || hasBrowserBridgeIntent(message, state);\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state,\n options,\n ): Promise<ActionResult> => {\n const params = (options as { parameters?: ManageBrowserBridgeParameters })\n ?.parameters;\n const subaction =\n normalizeSubaction(params?.action) ??\n normalizeSubaction(params?.subaction) ??\n inferSubactionFromMessage(\n typeof message.content?.text === \"string\" ? message.content.text : \"\",\n );\n try {\n switch (subaction) {\n case \"install\":\n return await runInstall();\n case \"reveal_folder\":\n return await runRevealFolder();\n case \"open_manager\":\n return await runOpenManager();\n case \"refresh\":\n return await runRefresh(runtime);\n default: {\n const exhaustive: never = subaction;\n throw new Error(\n `Unsupported MANAGE_BROWSER_BRIDGE subaction: ${exhaustive}`,\n );\n }\n }\n } catch (err) {\n const text =\n `Failed MANAGE_BROWSER_BRIDGE ${subaction}: ${describeError(err)}`.slice(\n 0,\n MAX_BROWSER_BRIDGE_TEXT_LENGTH,\n );\n logger.warn(`[${ACTION_NAME}] ${text}`);\n return {\n text,\n success: false,\n values: {\n success: false,\n subaction,\n error: `MANAGE_BROWSER_BRIDGE_${subaction.toUpperCase()}_FAILED`,\n },\n data: { actionName: ACTION_NAME, subaction },\n };\n }\n },\n parameters: [\n {\n name: \"action\",\n description:\n \"Bridge action. refresh=status/settings; open_manager only explicit chrome://extensions; install setup; reveal_folder build folder. Infer if omitted.\",\n required: false,\n schema: {\n type: \"string\" as const,\n enum: [...BROWSER_BRIDGE_SUBACTIONS],\n },\n },\n ],\n examples: [\n [\n {\n name: \"{{name1}}\",\n content: { text: \"Show the browser bridge status.\", source: \"chat\" },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Refreshing the browser bridge status.\",\n actions: [\"MANAGE_BROWSER_BRIDGE\"],\n thought:\n \"Show/status request maps to MANAGE_BROWSER_BRIDGE action=refresh.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Install the agent browser bridge extension.\",\n source: \"chat\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Building and revealing the bridge extension.\",\n actions: [\"MANAGE_BROWSER_BRIDGE\"],\n thought: \"Setup intent maps to MANAGE_BROWSER_BRIDGE action=install.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: { text: \"Open chrome://extensions for me.\", source: \"chat\" },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Opening the extension manager.\",\n actions: [\"MANAGE_BROWSER_BRIDGE\"],\n thought:\n \"Explicit chrome://extensions request maps to MANAGE_BROWSER_BRIDGE action=open_manager.\",\n },\n },\n ],\n ],\n};\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const MAX_BROWSER_FOCUS_WINDOW_MS: number;
|
|
2
|
+
export declare const DEFAULT_BROWSER_COMPANION_PAIRING_TOKEN_TTL_MS: number;
|
|
3
|
+
type BrowserBridgeCompanionPairingTokenEnv = {
|
|
4
|
+
readonly [key: string]: string | undefined;
|
|
5
|
+
};
|
|
6
|
+
export declare function resolveBrowserBridgeCompanionPairingTokenTtlMs(env?: BrowserBridgeCompanionPairingTokenEnv): number;
|
|
7
|
+
export declare function resolveBrowserBridgeCompanionPairingTokenExpiresAt(nowMs?: number, env?: Parameters<typeof resolveBrowserBridgeCompanionPairingTokenTtlMs>[0]): string;
|
|
8
|
+
export declare function browserBridgeDomainFromUrl(url: string): string | null;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=bridge-policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-policy.d.ts","sourceRoot":"","sources":["../src/bridge-policy.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,QAAgB,CAAC;AACzD,eAAO,MAAM,8CAA8C,QACjC,CAAC;AAE3B,KAAK,qCAAqC,GAAG;IAC3C,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC5C,CAAC;AAEF,wBAAgB,8CAA8C,CAC5D,GAAG,GAAE,qCAAmD,GACvD,MAAM,CAWR;AAED,wBAAgB,kDAAkD,CAChE,KAAK,SAAa,EAClB,GAAG,CAAC,EAAE,UAAU,CAAC,OAAO,8CAA8C,CAAC,CAAC,CAAC,CAAC,GACzE,MAAM,CAIR;AAED,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAWrE"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const MAX_BROWSER_FOCUS_WINDOW_MS = 2 * 60 * 1e3;
|
|
2
|
+
const DEFAULT_BROWSER_COMPANION_PAIRING_TOKEN_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
3
|
+
function resolveBrowserBridgeCompanionPairingTokenTtlMs(env = process.env) {
|
|
4
|
+
const raw = env.BROWSER_BRIDGE_COMPANION_TOKEN_TTL_MS ?? env.ELIZA_BROWSER_BRIDGE_COMPANION_TOKEN_TTL_MS;
|
|
5
|
+
if (typeof raw === "string" && raw.trim().length > 0) {
|
|
6
|
+
const parsed = Number(raw);
|
|
7
|
+
if (Number.isFinite(parsed) && parsed > 0) {
|
|
8
|
+
return Math.trunc(parsed);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return DEFAULT_BROWSER_COMPANION_PAIRING_TOKEN_TTL_MS;
|
|
12
|
+
}
|
|
13
|
+
function resolveBrowserBridgeCompanionPairingTokenExpiresAt(nowMs = Date.now(), env) {
|
|
14
|
+
return new Date(
|
|
15
|
+
nowMs + resolveBrowserBridgeCompanionPairingTokenTtlMs(env)
|
|
16
|
+
).toISOString();
|
|
17
|
+
}
|
|
18
|
+
function browserBridgeDomainFromUrl(url) {
|
|
19
|
+
try {
|
|
20
|
+
const parsed = new URL(url);
|
|
21
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const hostname = parsed.hostname.trim().toLowerCase().replace(/\.+$/, "");
|
|
25
|
+
return hostname.length > 0 ? hostname : null;
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
DEFAULT_BROWSER_COMPANION_PAIRING_TOKEN_TTL_MS,
|
|
32
|
+
MAX_BROWSER_FOCUS_WINDOW_MS,
|
|
33
|
+
browserBridgeDomainFromUrl,
|
|
34
|
+
resolveBrowserBridgeCompanionPairingTokenExpiresAt,
|
|
35
|
+
resolveBrowserBridgeCompanionPairingTokenTtlMs
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=bridge-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bridge-policy.ts"],"sourcesContent":["export const MAX_BROWSER_FOCUS_WINDOW_MS = 2 * 60 * 1000;\nexport const DEFAULT_BROWSER_COMPANION_PAIRING_TOKEN_TTL_MS =\n 30 * 24 * 60 * 60 * 1000;\n\ntype BrowserBridgeCompanionPairingTokenEnv = {\n readonly [key: string]: string | undefined;\n};\n\nexport function resolveBrowserBridgeCompanionPairingTokenTtlMs(\n env: BrowserBridgeCompanionPairingTokenEnv = process.env,\n): number {\n const raw =\n env.BROWSER_BRIDGE_COMPANION_TOKEN_TTL_MS ??\n env.ELIZA_BROWSER_BRIDGE_COMPANION_TOKEN_TTL_MS;\n if (typeof raw === \"string\" && raw.trim().length > 0) {\n const parsed = Number(raw);\n if (Number.isFinite(parsed) && parsed > 0) {\n return Math.trunc(parsed);\n }\n }\n return DEFAULT_BROWSER_COMPANION_PAIRING_TOKEN_TTL_MS;\n}\n\nexport function resolveBrowserBridgeCompanionPairingTokenExpiresAt(\n nowMs = Date.now(),\n env?: Parameters<typeof resolveBrowserBridgeCompanionPairingTokenTtlMs>[0],\n): string {\n return new Date(\n nowMs + resolveBrowserBridgeCompanionPairingTokenTtlMs(env),\n ).toISOString();\n}\n\nexport function browserBridgeDomainFromUrl(url: string): string | null {\n try {\n const parsed = new URL(url);\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n return null;\n }\n const hostname = parsed.hostname.trim().toLowerCase().replace(/\\.+$/, \"\");\n return hostname.length > 0 ? hostname : null;\n } catch {\n return null;\n }\n}\n"],"mappings":"AAAO,MAAM,8BAA8B,IAAI,KAAK;AAC7C,MAAM,iDACX,KAAK,KAAK,KAAK,KAAK;AAMf,SAAS,+CACd,MAA6C,QAAQ,KAC7C;AACR,QAAM,MACJ,IAAI,yCACJ,IAAI;AACN,MAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,EAAE,SAAS,GAAG;AACpD,UAAM,SAAS,OAAO,GAAG;AACzB,QAAI,OAAO,SAAS,MAAM,KAAK,SAAS,GAAG;AACzC,aAAO,KAAK,MAAM,MAAM;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,mDACd,QAAQ,KAAK,IAAI,GACjB,KACQ;AACR,SAAO,IAAI;AAAA,IACT,QAAQ,+CAA+C,GAAG;AAAA,EAC5D,EAAE,YAAY;AAChB;AAEO,SAAS,2BAA2B,KAA4B;AACrE,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAI,OAAO,aAAa,WAAW,OAAO,aAAa,UAAU;AAC/D,aAAO;AAAA,IACT;AACA,UAAM,WAAW,OAAO,SAAS,KAAK,EAAE,YAAY,EAAE,QAAQ,QAAQ,EAAE;AACxE,WAAO,SAAS,SAAS,IAAI,WAAW;AAAA,EAC1C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BrowserBridgeCompanionStatus, BrowserBridgePermissionState, BrowserBridgeSettings } from "./contracts.js";
|
|
2
|
+
export declare const BROWSER_BRIDGE_RECENT_CONTACT_WINDOW_MS: number;
|
|
3
|
+
export type BrowserBridgeReadinessState = "ready" | "disabled" | "tracking_off" | "paused" | "control_disabled" | "no_companion" | "stale" | "permission_blocked";
|
|
4
|
+
export interface BrowserBridgeReadiness {
|
|
5
|
+
state: BrowserBridgeReadinessState;
|
|
6
|
+
ready: boolean;
|
|
7
|
+
connectedCompanions: BrowserBridgeCompanionStatus[];
|
|
8
|
+
recentConnectedCompanions: BrowserBridgeCompanionStatus[];
|
|
9
|
+
primaryCompanion: BrowserBridgeCompanionStatus | null;
|
|
10
|
+
}
|
|
11
|
+
export declare function isBrowserBridgePaused(settings: Pick<BrowserBridgeSettings, "pauseUntil">, nowMs?: number): boolean;
|
|
12
|
+
export declare function browserBridgeCompanionIsRecent(companion: Pick<BrowserBridgeCompanionStatus, "lastSeenAt">, nowMs?: number, recentWindowMs?: number): boolean;
|
|
13
|
+
export declare function browserBridgeSiteAccessReady(settings: Pick<BrowserBridgeSettings, "siteAccessMode" | "grantedOrigins">, permissions: BrowserBridgePermissionState): boolean;
|
|
14
|
+
export declare function browserBridgePermissionsReady(settings: Pick<BrowserBridgeSettings, "siteAccessMode" | "grantedOrigins">, permissions: BrowserBridgePermissionState): boolean;
|
|
15
|
+
export declare function resolveBrowserBridgeReadiness(settings: BrowserBridgeSettings, companions: readonly BrowserBridgeCompanionStatus[], nowMs?: number): BrowserBridgeReadiness;
|
|
16
|
+
//# sourceMappingURL=bridge-readiness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-readiness.d.ts","sourceRoot":"","sources":["../src/bridge-readiness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,4BAA4B,EAC5B,4BAA4B,EAC5B,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAExB,eAAO,MAAM,uCAAuC,QAAa,CAAC;AAElE,MAAM,MAAM,2BAA2B,GACnC,OAAO,GACP,UAAU,GACV,cAAc,GACd,QAAQ,GACR,kBAAkB,GAClB,cAAc,GACd,OAAO,GACP,oBAAoB,CAAC;AAEzB,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,2BAA2B,CAAC;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,mBAAmB,EAAE,4BAA4B,EAAE,CAAC;IACpD,yBAAyB,EAAE,4BAA4B,EAAE,CAAC;IAC1D,gBAAgB,EAAE,4BAA4B,GAAG,IAAI,CAAC;CACvD;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,IAAI,CAAC,qBAAqB,EAAE,YAAY,CAAC,EACnD,KAAK,SAAa,GACjB,OAAO,CAMT;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,IAAI,CAAC,4BAA4B,EAAE,YAAY,CAAC,EAC3D,KAAK,SAAa,EAClB,cAAc,SAA0C,GACvD,OAAO,CAMT;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,IAAI,CAAC,qBAAqB,EAAE,gBAAgB,GAAG,gBAAgB,CAAC,EAC1E,WAAW,EAAE,4BAA4B,GACxC,OAAO,CAeT;AAED,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,IAAI,CAAC,qBAAqB,EAAE,gBAAgB,GAAG,gBAAgB,CAAC,EAC1E,WAAW,EAAE,4BAA4B,GACxC,OAAO,CAOT;AAED,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,qBAAqB,EAC/B,UAAU,EAAE,SAAS,4BAA4B,EAAE,EACnD,KAAK,SAAa,GACjB,sBAAsB,CAqDxB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const BROWSER_BRIDGE_RECENT_CONTACT_WINDOW_MS = 5 * 6e4;
|
|
2
|
+
function isBrowserBridgePaused(settings, nowMs = Date.now()) {
|
|
3
|
+
if (!settings.pauseUntil) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
const pauseUntilMs = Date.parse(settings.pauseUntil);
|
|
7
|
+
return Number.isFinite(pauseUntilMs) && pauseUntilMs > nowMs;
|
|
8
|
+
}
|
|
9
|
+
function browserBridgeCompanionIsRecent(companion, nowMs = Date.now(), recentWindowMs = BROWSER_BRIDGE_RECENT_CONTACT_WINDOW_MS) {
|
|
10
|
+
if (!companion.lastSeenAt) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
const lastSeenMs = Date.parse(companion.lastSeenAt);
|
|
14
|
+
return Number.isFinite(lastSeenMs) && nowMs - lastSeenMs < recentWindowMs;
|
|
15
|
+
}
|
|
16
|
+
function browserBridgeSiteAccessReady(settings, permissions) {
|
|
17
|
+
switch (settings.siteAccessMode) {
|
|
18
|
+
case "all_sites":
|
|
19
|
+
return permissions.allOrigins;
|
|
20
|
+
case "granted_sites":
|
|
21
|
+
return permissions.allOrigins || settings.grantedOrigins.length > 0 && permissions.grantedOrigins.length > 0;
|
|
22
|
+
case "current_site_only":
|
|
23
|
+
return permissions.activeTab;
|
|
24
|
+
default:
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function browserBridgePermissionsReady(settings, permissions) {
|
|
29
|
+
return permissions.tabs && permissions.scripting && permissions.activeTab && browserBridgeSiteAccessReady(settings, permissions);
|
|
30
|
+
}
|
|
31
|
+
function resolveBrowserBridgeReadiness(settings, companions, nowMs = Date.now()) {
|
|
32
|
+
const connectedCompanions = companions.filter(
|
|
33
|
+
(companion) => companion.connectionState === "connected"
|
|
34
|
+
);
|
|
35
|
+
const recentConnectedCompanions = connectedCompanions.filter(
|
|
36
|
+
(companion) => browserBridgeCompanionIsRecent(companion, nowMs)
|
|
37
|
+
);
|
|
38
|
+
const primaryCompanion = recentConnectedCompanions[0] ?? connectedCompanions[0] ?? companions[0] ?? null;
|
|
39
|
+
const base = {
|
|
40
|
+
connectedCompanions,
|
|
41
|
+
recentConnectedCompanions,
|
|
42
|
+
primaryCompanion
|
|
43
|
+
};
|
|
44
|
+
if (!settings.enabled) {
|
|
45
|
+
return { ...base, ready: false, state: "disabled" };
|
|
46
|
+
}
|
|
47
|
+
if (settings.trackingMode === "off") {
|
|
48
|
+
return { ...base, ready: false, state: "tracking_off" };
|
|
49
|
+
}
|
|
50
|
+
if (isBrowserBridgePaused(settings, nowMs)) {
|
|
51
|
+
return { ...base, ready: false, state: "paused" };
|
|
52
|
+
}
|
|
53
|
+
if (!settings.allowBrowserControl) {
|
|
54
|
+
return { ...base, ready: false, state: "control_disabled" };
|
|
55
|
+
}
|
|
56
|
+
if (companions.length === 0) {
|
|
57
|
+
return { ...base, ready: false, state: "no_companion" };
|
|
58
|
+
}
|
|
59
|
+
if (connectedCompanions.length === 0 && companions.some(
|
|
60
|
+
(companion) => companion.connectionState === "permission_blocked"
|
|
61
|
+
)) {
|
|
62
|
+
return { ...base, ready: false, state: "permission_blocked" };
|
|
63
|
+
}
|
|
64
|
+
if (recentConnectedCompanions.length === 0) {
|
|
65
|
+
return { ...base, ready: false, state: "stale" };
|
|
66
|
+
}
|
|
67
|
+
if (recentConnectedCompanions.some(
|
|
68
|
+
(companion) => browserBridgePermissionsReady(settings, companion.permissions)
|
|
69
|
+
)) {
|
|
70
|
+
return { ...base, ready: true, state: "ready" };
|
|
71
|
+
}
|
|
72
|
+
return { ...base, ready: false, state: "permission_blocked" };
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
BROWSER_BRIDGE_RECENT_CONTACT_WINDOW_MS,
|
|
76
|
+
browserBridgeCompanionIsRecent,
|
|
77
|
+
browserBridgePermissionsReady,
|
|
78
|
+
browserBridgeSiteAccessReady,
|
|
79
|
+
isBrowserBridgePaused,
|
|
80
|
+
resolveBrowserBridgeReadiness
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=bridge-readiness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bridge-readiness.ts"],"sourcesContent":["import type {\n BrowserBridgeCompanionStatus,\n BrowserBridgePermissionState,\n BrowserBridgeSettings,\n} from \"./contracts.js\";\n\nexport const BROWSER_BRIDGE_RECENT_CONTACT_WINDOW_MS = 5 * 60_000;\n\nexport type BrowserBridgeReadinessState =\n | \"ready\"\n | \"disabled\"\n | \"tracking_off\"\n | \"paused\"\n | \"control_disabled\"\n | \"no_companion\"\n | \"stale\"\n | \"permission_blocked\";\n\nexport interface BrowserBridgeReadiness {\n state: BrowserBridgeReadinessState;\n ready: boolean;\n connectedCompanions: BrowserBridgeCompanionStatus[];\n recentConnectedCompanions: BrowserBridgeCompanionStatus[];\n primaryCompanion: BrowserBridgeCompanionStatus | null;\n}\n\nexport function isBrowserBridgePaused(\n settings: Pick<BrowserBridgeSettings, \"pauseUntil\">,\n nowMs = Date.now(),\n): boolean {\n if (!settings.pauseUntil) {\n return false;\n }\n const pauseUntilMs = Date.parse(settings.pauseUntil);\n return Number.isFinite(pauseUntilMs) && pauseUntilMs > nowMs;\n}\n\nexport function browserBridgeCompanionIsRecent(\n companion: Pick<BrowserBridgeCompanionStatus, \"lastSeenAt\">,\n nowMs = Date.now(),\n recentWindowMs = BROWSER_BRIDGE_RECENT_CONTACT_WINDOW_MS,\n): boolean {\n if (!companion.lastSeenAt) {\n return false;\n }\n const lastSeenMs = Date.parse(companion.lastSeenAt);\n return Number.isFinite(lastSeenMs) && nowMs - lastSeenMs < recentWindowMs;\n}\n\nexport function browserBridgeSiteAccessReady(\n settings: Pick<BrowserBridgeSettings, \"siteAccessMode\" | \"grantedOrigins\">,\n permissions: BrowserBridgePermissionState,\n): boolean {\n switch (settings.siteAccessMode) {\n case \"all_sites\":\n return permissions.allOrigins;\n case \"granted_sites\":\n return (\n permissions.allOrigins ||\n (settings.grantedOrigins.length > 0 &&\n permissions.grantedOrigins.length > 0)\n );\n case \"current_site_only\":\n return permissions.activeTab;\n default:\n return false;\n }\n}\n\nexport function browserBridgePermissionsReady(\n settings: Pick<BrowserBridgeSettings, \"siteAccessMode\" | \"grantedOrigins\">,\n permissions: BrowserBridgePermissionState,\n): boolean {\n return (\n permissions.tabs &&\n permissions.scripting &&\n permissions.activeTab &&\n browserBridgeSiteAccessReady(settings, permissions)\n );\n}\n\nexport function resolveBrowserBridgeReadiness(\n settings: BrowserBridgeSettings,\n companions: readonly BrowserBridgeCompanionStatus[],\n nowMs = Date.now(),\n): BrowserBridgeReadiness {\n const connectedCompanions = companions.filter(\n (companion) => companion.connectionState === \"connected\",\n );\n const recentConnectedCompanions = connectedCompanions.filter((companion) =>\n browserBridgeCompanionIsRecent(companion, nowMs),\n );\n const primaryCompanion =\n recentConnectedCompanions[0] ??\n connectedCompanions[0] ??\n companions[0] ??\n null;\n\n const base = {\n connectedCompanions,\n recentConnectedCompanions,\n primaryCompanion,\n };\n\n if (!settings.enabled) {\n return { ...base, ready: false, state: \"disabled\" };\n }\n if (settings.trackingMode === \"off\") {\n return { ...base, ready: false, state: \"tracking_off\" };\n }\n if (isBrowserBridgePaused(settings, nowMs)) {\n return { ...base, ready: false, state: \"paused\" };\n }\n if (!settings.allowBrowserControl) {\n return { ...base, ready: false, state: \"control_disabled\" };\n }\n if (companions.length === 0) {\n return { ...base, ready: false, state: \"no_companion\" };\n }\n if (\n connectedCompanions.length === 0 &&\n companions.some(\n (companion) => companion.connectionState === \"permission_blocked\",\n )\n ) {\n return { ...base, ready: false, state: \"permission_blocked\" };\n }\n if (recentConnectedCompanions.length === 0) {\n return { ...base, ready: false, state: \"stale\" };\n }\n if (\n recentConnectedCompanions.some((companion) =>\n browserBridgePermissionsReady(settings, companion.permissions),\n )\n ) {\n return { ...base, ready: true, state: \"ready\" };\n }\n return { ...base, ready: false, state: \"permission_blocked\" };\n}\n"],"mappings":"AAMO,MAAM,0CAA0C,IAAI;AAoBpD,SAAS,sBACd,UACA,QAAQ,KAAK,IAAI,GACR;AACT,MAAI,CAAC,SAAS,YAAY;AACxB,WAAO;AAAA,EACT;AACA,QAAM,eAAe,KAAK,MAAM,SAAS,UAAU;AACnD,SAAO,OAAO,SAAS,YAAY,KAAK,eAAe;AACzD;AAEO,SAAS,+BACd,WACA,QAAQ,KAAK,IAAI,GACjB,iBAAiB,yCACR;AACT,MAAI,CAAC,UAAU,YAAY;AACzB,WAAO;AAAA,EACT;AACA,QAAM,aAAa,KAAK,MAAM,UAAU,UAAU;AAClD,SAAO,OAAO,SAAS,UAAU,KAAK,QAAQ,aAAa;AAC7D;AAEO,SAAS,6BACd,UACA,aACS;AACT,UAAQ,SAAS,gBAAgB;AAAA,IAC/B,KAAK;AACH,aAAO,YAAY;AAAA,IACrB,KAAK;AACH,aACE,YAAY,cACX,SAAS,eAAe,SAAS,KAChC,YAAY,eAAe,SAAS;AAAA,IAE1C,KAAK;AACH,aAAO,YAAY;AAAA,IACrB;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,8BACd,UACA,aACS;AACT,SACE,YAAY,QACZ,YAAY,aACZ,YAAY,aACZ,6BAA6B,UAAU,WAAW;AAEtD;AAEO,SAAS,8BACd,UACA,YACA,QAAQ,KAAK,IAAI,GACO;AACxB,QAAM,sBAAsB,WAAW;AAAA,IACrC,CAAC,cAAc,UAAU,oBAAoB;AAAA,EAC/C;AACA,QAAM,4BAA4B,oBAAoB;AAAA,IAAO,CAAC,cAC5D,+BAA+B,WAAW,KAAK;AAAA,EACjD;AACA,QAAM,mBACJ,0BAA0B,CAAC,KAC3B,oBAAoB,CAAC,KACrB,WAAW,CAAC,KACZ;AAEF,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,SAAS;AACrB,WAAO,EAAE,GAAG,MAAM,OAAO,OAAO,OAAO,WAAW;AAAA,EACpD;AACA,MAAI,SAAS,iBAAiB,OAAO;AACnC,WAAO,EAAE,GAAG,MAAM,OAAO,OAAO,OAAO,eAAe;AAAA,EACxD;AACA,MAAI,sBAAsB,UAAU,KAAK,GAAG;AAC1C,WAAO,EAAE,GAAG,MAAM,OAAO,OAAO,OAAO,SAAS;AAAA,EAClD;AACA,MAAI,CAAC,SAAS,qBAAqB;AACjC,WAAO,EAAE,GAAG,MAAM,OAAO,OAAO,OAAO,mBAAmB;AAAA,EAC5D;AACA,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO,EAAE,GAAG,MAAM,OAAO,OAAO,OAAO,eAAe;AAAA,EACxD;AACA,MACE,oBAAoB,WAAW,KAC/B,WAAW;AAAA,IACT,CAAC,cAAc,UAAU,oBAAoB;AAAA,EAC/C,GACA;AACA,WAAO,EAAE,GAAG,MAAM,OAAO,OAAO,OAAO,qBAAqB;AAAA,EAC9D;AACA,MAAI,0BAA0B,WAAW,GAAG;AAC1C,WAAO,EAAE,GAAG,MAAM,OAAO,OAAO,OAAO,QAAQ;AAAA,EACjD;AACA,MACE,0BAA0B;AAAA,IAAK,CAAC,cAC9B,8BAA8B,UAAU,UAAU,WAAW;AAAA,EAC/D,GACA;AACA,WAAO,EAAE,GAAG,MAAM,OAAO,MAAM,OAAO,QAAQ;AAAA,EAChD;AACA,SAAO,EAAE,GAAG,MAAM,OAAO,OAAO,OAAO,qBAAqB;AAC9D;","names":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BrowserBridgeCompanionStatus, BrowserBridgePageContext, BrowserBridgeTabSummary } from "./contracts.js";
|
|
2
|
+
export declare function createBrowserBridgeCompanionStatus(params: Omit<BrowserBridgeCompanionStatus, "id" | "createdAt" | "updatedAt" | "pairedAt" | "pairingTokenExpiresAt" | "pairingTokenRevokedAt"> & {
|
|
3
|
+
pairedAt?: string | null;
|
|
4
|
+
pairingTokenExpiresAt?: string | null;
|
|
5
|
+
pairingTokenRevokedAt?: string | null;
|
|
6
|
+
}): BrowserBridgeCompanionStatus;
|
|
7
|
+
export declare function createBrowserBridgeTabSummary(params: Omit<BrowserBridgeTabSummary, "id" | "createdAt" | "updatedAt">): BrowserBridgeTabSummary;
|
|
8
|
+
export declare function createBrowserBridgePageContext(params: Omit<BrowserBridgePageContext, "id">): BrowserBridgePageContext;
|
|
9
|
+
//# sourceMappingURL=bridge-records.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-records.d.ts","sourceRoot":"","sources":["../src/bridge-records.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,4BAA4B,EAC5B,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,gBAAgB,CAAC;AAMxB,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,IAAI,CACV,4BAA4B,EAC1B,IAAI,GACJ,WAAW,GACX,WAAW,GACX,UAAU,GACV,uBAAuB,GACvB,uBAAuB,CAC1B,GAAG;IACF,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC,GACA,4BAA4B,CAW9B;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,IAAI,CAAC,uBAAuB,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC,GACtE,uBAAuB,CAQzB;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,IAAI,CAAC,wBAAwB,EAAE,IAAI,CAAC,GAC3C,wBAAwB,CAK1B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
function isoNow() {
|
|
3
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
4
|
+
}
|
|
5
|
+
function createBrowserBridgeCompanionStatus(params) {
|
|
6
|
+
const timestamp = isoNow();
|
|
7
|
+
return {
|
|
8
|
+
...params,
|
|
9
|
+
id: crypto.randomUUID(),
|
|
10
|
+
pairedAt: params.pairedAt ?? timestamp,
|
|
11
|
+
pairingTokenExpiresAt: params.pairingTokenExpiresAt ?? null,
|
|
12
|
+
pairingTokenRevokedAt: params.pairingTokenRevokedAt ?? null,
|
|
13
|
+
createdAt: timestamp,
|
|
14
|
+
updatedAt: timestamp
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function createBrowserBridgeTabSummary(params) {
|
|
18
|
+
const timestamp = isoNow();
|
|
19
|
+
return {
|
|
20
|
+
...params,
|
|
21
|
+
id: crypto.randomUUID(),
|
|
22
|
+
createdAt: timestamp,
|
|
23
|
+
updatedAt: timestamp
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function createBrowserBridgePageContext(params) {
|
|
27
|
+
return {
|
|
28
|
+
...params,
|
|
29
|
+
id: crypto.randomUUID()
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export {
|
|
33
|
+
createBrowserBridgeCompanionStatus,
|
|
34
|
+
createBrowserBridgePageContext,
|
|
35
|
+
createBrowserBridgeTabSummary
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=bridge-records.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/bridge-records.ts"],"sourcesContent":["import crypto from \"node:crypto\";\nimport type {\n BrowserBridgeCompanionStatus,\n BrowserBridgePageContext,\n BrowserBridgeTabSummary,\n} from \"./contracts.js\";\n\nfunction isoNow(): string {\n return new Date().toISOString();\n}\n\nexport function createBrowserBridgeCompanionStatus(\n params: Omit<\n BrowserBridgeCompanionStatus,\n | \"id\"\n | \"createdAt\"\n | \"updatedAt\"\n | \"pairedAt\"\n | \"pairingTokenExpiresAt\"\n | \"pairingTokenRevokedAt\"\n > & {\n pairedAt?: string | null;\n pairingTokenExpiresAt?: string | null;\n pairingTokenRevokedAt?: string | null;\n },\n): BrowserBridgeCompanionStatus {\n const timestamp = isoNow();\n return {\n ...params,\n id: crypto.randomUUID(),\n pairedAt: params.pairedAt ?? timestamp,\n pairingTokenExpiresAt: params.pairingTokenExpiresAt ?? null,\n pairingTokenRevokedAt: params.pairingTokenRevokedAt ?? null,\n createdAt: timestamp,\n updatedAt: timestamp,\n };\n}\n\nexport function createBrowserBridgeTabSummary(\n params: Omit<BrowserBridgeTabSummary, \"id\" | \"createdAt\" | \"updatedAt\">,\n): BrowserBridgeTabSummary {\n const timestamp = isoNow();\n return {\n ...params,\n id: crypto.randomUUID(),\n createdAt: timestamp,\n updatedAt: timestamp,\n };\n}\n\nexport function createBrowserBridgePageContext(\n params: Omit<BrowserBridgePageContext, \"id\">,\n): BrowserBridgePageContext {\n return {\n ...params,\n id: crypto.randomUUID(),\n };\n}\n"],"mappings":"AAAA,OAAO,YAAY;AAOnB,SAAS,SAAiB;AACxB,UAAO,oBAAI,KAAK,GAAE,YAAY;AAChC;AAEO,SAAS,mCACd,QAa8B;AAC9B,QAAM,YAAY,OAAO;AACzB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,IAAI,OAAO,WAAW;AAAA,IACtB,UAAU,OAAO,YAAY;AAAA,IAC7B,uBAAuB,OAAO,yBAAyB;AAAA,IACvD,uBAAuB,OAAO,yBAAyB;AAAA,IACvD,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AACF;AAEO,SAAS,8BACd,QACyB;AACzB,QAAM,YAAY,OAAO;AACzB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,IAAI,OAAO,WAAW;AAAA,IACtB,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AACF;AAEO,SAAS,+BACd,QAC0B;AAC1B,SAAO;AAAA,IACL,GAAG;AAAA,IACH,IAAI,OAAO,WAAW;AAAA,EACxB;AACF;","names":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BrowserCaptureConfig } from "./workspace/browser-capture.js";
|
|
2
|
+
export interface BrowserCaptureHooks {
|
|
3
|
+
frameFile: string;
|
|
4
|
+
startBrowserCapture(config: BrowserCaptureConfig): Promise<void>;
|
|
5
|
+
stopBrowserCapture(): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
export declare function registerBrowserCaptureHooks(hooks: BrowserCaptureHooks): void;
|
|
8
|
+
export declare function getBrowserCaptureHooks(): BrowserCaptureHooks | null;
|
|
9
|
+
//# sourceMappingURL=browser-capture-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-capture-hooks.d.ts","sourceRoot":"","sources":["../src/browser-capture-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAE3E,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC;AAYD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAE5E;AAED,wBAAgB,sBAAsB,IAAI,mBAAmB,GAAG,IAAI,CAEnE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const BROWSER_CAPTURE_HOOKS = /* @__PURE__ */ Symbol.for("elizaos.browser-capture.hooks");
|
|
2
|
+
function hooksGlobal() {
|
|
3
|
+
return globalThis;
|
|
4
|
+
}
|
|
5
|
+
function registerBrowserCaptureHooks(hooks) {
|
|
6
|
+
hooksGlobal()[BROWSER_CAPTURE_HOOKS] = hooks;
|
|
7
|
+
}
|
|
8
|
+
function getBrowserCaptureHooks() {
|
|
9
|
+
return hooksGlobal()[BROWSER_CAPTURE_HOOKS] ?? null;
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
getBrowserCaptureHooks,
|
|
13
|
+
registerBrowserCaptureHooks
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=browser-capture-hooks.js.map
|