@elizaos/plugin-browser 2.0.0-beta.1 → 2.0.3-beta.3

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.
Files changed (196) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +106 -64
  3. package/dist/actions/browser-autofill-login.d.ts.map +1 -1
  4. package/dist/actions/browser-autofill-login.js.map +1 -1
  5. package/dist/actions/browser.d.ts +5 -6
  6. package/dist/actions/browser.d.ts.map +1 -1
  7. package/dist/actions/browser.js +312 -60
  8. package/dist/actions/browser.js.map +1 -1
  9. package/dist/actions/manage-browser-bridge.d.ts.map +1 -1
  10. package/dist/actions/manage-browser-bridge.js +10 -14
  11. package/dist/actions/manage-browser-bridge.js.map +1 -1
  12. package/dist/actions/wait-for-url-predicate.d.ts +34 -0
  13. package/dist/actions/wait-for-url-predicate.d.ts.map +1 -0
  14. package/dist/actions/wait-for-url-predicate.js +33 -0
  15. package/dist/actions/wait-for-url-predicate.js.map +1 -0
  16. package/dist/actions/wait-for-url.d.ts +64 -0
  17. package/dist/actions/wait-for-url.d.ts.map +1 -0
  18. package/dist/actions/wait-for-url.js +89 -0
  19. package/dist/actions/wait-for-url.js.map +1 -0
  20. package/dist/bridge-policy.d.ts +10 -0
  21. package/dist/bridge-policy.d.ts.map +1 -0
  22. package/dist/bridge-policy.js +37 -0
  23. package/dist/bridge-policy.js.map +1 -0
  24. package/dist/bridge-readiness.d.ts +16 -0
  25. package/dist/bridge-readiness.d.ts.map +1 -0
  26. package/dist/bridge-readiness.js +82 -0
  27. package/dist/bridge-readiness.js.map +1 -0
  28. package/dist/bridge-records.d.ts +9 -0
  29. package/dist/bridge-records.d.ts.map +1 -0
  30. package/dist/bridge-records.js +37 -0
  31. package/dist/bridge-records.js.map +1 -0
  32. package/dist/browser-capture-hooks.d.ts +9 -0
  33. package/dist/browser-capture-hooks.d.ts.map +1 -0
  34. package/dist/browser-capture-hooks.js +15 -0
  35. package/dist/browser-capture-hooks.js.map +1 -0
  36. package/dist/browser-service.d.ts +22 -4
  37. package/dist/browser-service.d.ts.map +1 -1
  38. package/dist/browser-service.js +63 -15
  39. package/dist/browser-service.js.map +1 -1
  40. package/dist/browser-workspace-hooks.d.ts +14 -0
  41. package/dist/browser-workspace-hooks.d.ts.map +1 -0
  42. package/dist/browser-workspace-hooks.js +15 -0
  43. package/dist/browser-workspace-hooks.js.map +1 -0
  44. package/dist/companion-auth.d.ts +34 -0
  45. package/dist/companion-auth.d.ts.map +1 -0
  46. package/dist/companion-auth.js +98 -0
  47. package/dist/companion-auth.js.map +1 -0
  48. package/dist/index.d.ts +12 -3
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +66 -12
  51. package/dist/index.js.map +1 -1
  52. package/dist/message-adapter.d.ts +9 -0
  53. package/dist/message-adapter.d.ts.map +1 -0
  54. package/dist/message-adapter.js +104 -0
  55. package/dist/message-adapter.js.map +1 -0
  56. package/dist/packaging.d.ts.map +1 -1
  57. package/dist/packaging.js +2 -0
  58. package/dist/packaging.js.map +1 -1
  59. package/dist/parity/browser-matrix.d.ts +45 -0
  60. package/dist/parity/browser-matrix.d.ts.map +1 -0
  61. package/dist/parity/browser-matrix.js +361 -0
  62. package/dist/parity/browser-matrix.js.map +1 -0
  63. package/dist/parity/index.d.ts +5 -0
  64. package/dist/parity/index.d.ts.map +1 -0
  65. package/dist/parity/index.js +13 -0
  66. package/dist/parity/index.js.map +1 -0
  67. package/dist/password-manager-bridge.d.ts +50 -0
  68. package/dist/password-manager-bridge.d.ts.map +1 -0
  69. package/dist/password-manager-bridge.js +437 -0
  70. package/dist/password-manager-bridge.js.map +1 -0
  71. package/dist/plugin.d.ts.map +1 -1
  72. package/dist/plugin.js +8 -4
  73. package/dist/plugin.js.map +1 -1
  74. package/dist/providers/workspace.d.ts +1 -1
  75. package/dist/providers/workspace.js.map +1 -1
  76. package/dist/routes/bridge.d.ts.map +1 -1
  77. package/dist/routes/bridge.js +63 -14
  78. package/dist/routes/bridge.js.map +1 -1
  79. package/dist/routes/workspace-setup.d.ts.map +1 -1
  80. package/dist/routes/workspace-setup.js +1 -1
  81. package/dist/routes/workspace-setup.js.map +1 -1
  82. package/dist/routes/workspace.d.ts +1 -2
  83. package/dist/routes/workspace.d.ts.map +1 -1
  84. package/dist/routes/workspace.js +104 -4
  85. package/dist/routes/workspace.js.map +1 -1
  86. package/dist/schema.d.ts +2 -2
  87. package/dist/schema.js.map +1 -1
  88. package/dist/service.d.ts +1 -1
  89. package/dist/service.d.ts.map +1 -1
  90. package/dist/service.js.map +1 -1
  91. package/dist/targets/bridge-target.d.ts +1 -1
  92. package/dist/targets/bridge-target.d.ts.map +1 -1
  93. package/dist/targets/bridge-target.js.map +1 -1
  94. package/dist/targets/stagehand-target.d.ts +3 -0
  95. package/dist/targets/stagehand-target.d.ts.map +1 -0
  96. package/dist/targets/stagehand-target.js +187 -0
  97. package/dist/targets/stagehand-target.js.map +1 -0
  98. package/dist/workspace/browser-capture.d.ts +1 -1
  99. package/dist/workspace/browser-capture.d.ts.map +1 -1
  100. package/dist/workspace/browser-capture.js +33 -1
  101. package/dist/workspace/browser-capture.js.map +1 -1
  102. package/dist/workspace/browser-workspace-desktop.d.ts +1 -1
  103. package/dist/workspace/browser-workspace-desktop.d.ts.map +1 -1
  104. package/dist/workspace/browser-workspace-desktop.js +66 -30
  105. package/dist/workspace/browser-workspace-desktop.js.map +1 -1
  106. package/dist/workspace/browser-workspace-errors.d.ts +62 -0
  107. package/dist/workspace/browser-workspace-errors.d.ts.map +1 -0
  108. package/dist/workspace/browser-workspace-errors.js +69 -0
  109. package/dist/workspace/browser-workspace-errors.js.map +1 -0
  110. package/dist/workspace/browser-workspace-forms.d.ts.map +1 -1
  111. package/dist/workspace/browser-workspace-forms.js +1 -1
  112. package/dist/workspace/browser-workspace-forms.js.map +1 -1
  113. package/dist/workspace/browser-workspace-helpers.d.ts +7 -0
  114. package/dist/workspace/browser-workspace-helpers.d.ts.map +1 -1
  115. package/dist/workspace/browser-workspace-helpers.js +64 -6
  116. package/dist/workspace/browser-workspace-helpers.js.map +1 -1
  117. package/dist/workspace/browser-workspace-network.d.ts +1 -1
  118. package/dist/workspace/browser-workspace-network.d.ts.map +1 -1
  119. package/dist/workspace/browser-workspace-types.d.ts +15 -0
  120. package/dist/workspace/browser-workspace-types.d.ts.map +1 -1
  121. package/dist/workspace/browser-workspace-types.js.map +1 -1
  122. package/dist/workspace/browser-workspace-web.d.ts.map +1 -1
  123. package/dist/workspace/browser-workspace-web.js +34 -93
  124. package/dist/workspace/browser-workspace-web.js.map +1 -1
  125. package/dist/workspace/browser-workspace.d.ts +1 -1
  126. package/dist/workspace/browser-workspace.d.ts.map +1 -1
  127. package/dist/workspace/browser-workspace.js +9 -4
  128. package/dist/workspace/browser-workspace.js.map +1 -1
  129. package/dist/workspace/index.d.ts +1 -0
  130. package/dist/workspace/index.d.ts.map +1 -1
  131. package/dist/workspace/index.js +1 -0
  132. package/dist/workspace/index.js.map +1 -1
  133. package/package.json +29 -7
  134. package/registry-entry.json +75 -0
  135. package/dist/actions/browser-autofill-login.d.js +0 -1
  136. package/dist/actions/browser-autofill-login.d.js.map +0 -1
  137. package/dist/actions/browser.d.js +0 -1
  138. package/dist/actions/browser.d.js.map +0 -1
  139. package/dist/actions/manage-browser-bridge.d.js +0 -1
  140. package/dist/actions/manage-browser-bridge.d.js.map +0 -1
  141. package/dist/ambient-jsdom.d.js +0 -1
  142. package/dist/ambient-jsdom.d.js.map +0 -1
  143. package/dist/browser-service.d.js +0 -1
  144. package/dist/browser-service.d.js.map +0 -1
  145. package/dist/contracts.d.js +0 -1
  146. package/dist/contracts.d.js.map +0 -1
  147. package/dist/index.d.js +0 -21
  148. package/dist/index.d.js.map +0 -1
  149. package/dist/lifeops-session-contracts.d.js +0 -1
  150. package/dist/lifeops-session-contracts.d.js.map +0 -1
  151. package/dist/packaging.d.js +0 -1
  152. package/dist/packaging.d.js.map +0 -1
  153. package/dist/plugin.d.js +0 -1
  154. package/dist/plugin.d.js.map +0 -1
  155. package/dist/providers/workspace.d.js +0 -1
  156. package/dist/providers/workspace.d.js.map +0 -1
  157. package/dist/routes/bridge.d.js +0 -1
  158. package/dist/routes/bridge.d.js.map +0 -1
  159. package/dist/routes/workspace-account-gate.d.js +0 -1
  160. package/dist/routes/workspace-account-gate.d.js.map +0 -1
  161. package/dist/routes/workspace-setup.d.js +0 -1
  162. package/dist/routes/workspace-setup.d.js.map +0 -1
  163. package/dist/routes/workspace.d.js +0 -1
  164. package/dist/routes/workspace.d.js.map +0 -1
  165. package/dist/schema.d.js +0 -1
  166. package/dist/schema.d.js.map +0 -1
  167. package/dist/service.d.js +0 -1
  168. package/dist/service.d.js.map +0 -1
  169. package/dist/targets/bridge-target.d.js +0 -1
  170. package/dist/targets/bridge-target.d.js.map +0 -1
  171. package/dist/workspace/browser-capture.d.js +0 -1
  172. package/dist/workspace/browser-capture.d.js.map +0 -1
  173. package/dist/workspace/browser-workspace-desktop.d.js +0 -1
  174. package/dist/workspace/browser-workspace-desktop.d.js.map +0 -1
  175. package/dist/workspace/browser-workspace-elements.d.js +0 -1
  176. package/dist/workspace/browser-workspace-elements.d.js.map +0 -1
  177. package/dist/workspace/browser-workspace-forms.d.js +0 -1
  178. package/dist/workspace/browser-workspace-forms.d.js.map +0 -1
  179. package/dist/workspace/browser-workspace-helpers.d.js +0 -1
  180. package/dist/workspace/browser-workspace-helpers.d.js.map +0 -1
  181. package/dist/workspace/browser-workspace-jsdom.d.js +0 -1
  182. package/dist/workspace/browser-workspace-jsdom.d.js.map +0 -1
  183. package/dist/workspace/browser-workspace-network.d.js +0 -1
  184. package/dist/workspace/browser-workspace-network.d.js.map +0 -1
  185. package/dist/workspace/browser-workspace-snapshots.d.js +0 -1
  186. package/dist/workspace/browser-workspace-snapshots.d.js.map +0 -1
  187. package/dist/workspace/browser-workspace-state.d.js +0 -1
  188. package/dist/workspace/browser-workspace-state.d.js.map +0 -1
  189. package/dist/workspace/browser-workspace-types.d.js +0 -1
  190. package/dist/workspace/browser-workspace-types.d.js.map +0 -1
  191. package/dist/workspace/browser-workspace-web.d.js +0 -1
  192. package/dist/workspace/browser-workspace-web.d.js.map +0 -1
  193. package/dist/workspace/browser-workspace.d.js +0 -11
  194. package/dist/workspace/browser-workspace.d.js.map +0 -1
  195. package/dist/workspace/index.d.js +0 -3
  196. 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 Content,\n HandlerCallback,\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 type BrowserWorkspaceCommandResult,\n executeBrowserWorkspaceCommand,\n getBrowserWorkspaceMode,\n} from \"../workspace/browser-workspace.js\";\nimport {\n WAIT_FOR_URL_DEFAULT_POLL_INTERVAL_MS,\n WAIT_FOR_URL_DEFAULT_TIMEOUT_MS,\n waitForUrl,\n} from \"./wait-for-url.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 =\n | BrowserWorkspaceSubaction\n | \"autofill-login\"\n | \"wait-for-url\";\ntype BrowserActionValue =\n | BrowserWorkspaceAction\n | \"autofill_login\"\n | \"autofill-login\"\n | \"wait_for_url\"\n | \"wait-for-url\";\ntype NormalizedBrowserAction =\n | BrowserWorkspaceSubaction\n | \"autofill-login\"\n | \"wait-for-url\"\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 /** For action=wait_for_url: substring or regex to match the tab URL. */\n pattern?: string;\n /** For action=wait_for_url: poll cadence in ms (default ~2000). */\n pollIntervalMs?: number;\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 /** Emit one compact progress callback after the browser step dispatches. */\n streamProgress?: boolean;\n /** Optional rationale to show in the compact progress callback. */\n rationale?: string;\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\" | \"wait-for-url\" {\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 if (\n normalizedAction === \"wait-for-url\" ||\n params?.subaction === \"wait-for-url\"\n ) {\n return \"wait-for-url\";\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 case \"wait_for_url\":\n case \"wait-for-url\":\n return \"wait-for-url\";\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 case \"wait-for-url\":\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\nfunction browserProgressRationale(\n command: BrowserWorkspaceCommand,\n params: BrowserActionParameters | undefined,\n messageText: string,\n): string {\n const explicit = params?.rationale?.trim();\n if (explicit) return explicit;\n\n switch (command.subaction) {\n case \"open\":\n case \"navigate\":\n return command.url ? `open ${command.url}` : \"open requested page\";\n case \"click\":\n case \"realistic-click\":\n return command.selector\n ? `click ${command.selector}`\n : \"click requested target\";\n case \"type\":\n case \"realistic-fill\":\n case \"realistic-type\":\n return command.selector\n ? `fill ${command.selector}`\n : \"type requested text\";\n case \"press\":\n case \"realistic-press\":\n return command.key ? `press ${command.key}` : \"press requested key\";\n case \"tab\":\n return command.tabAction\n ? `${command.tabAction} browser tab`\n : \"manage browser tabs\";\n case \"wait\":\n return command.selector\n ? `wait for ${command.selector}`\n : \"wait for browser state\";\n case \"state\":\n return messageText.trim() || \"read browser state\";\n default:\n return `run browser ${command.subaction}`;\n }\n}\n\nfunction buildBrowserStepProgressContent(\n command: BrowserWorkspaceCommand,\n params: BrowserActionParameters | undefined,\n messageText: string,\n success: boolean,\n error?: string,\n): Content {\n const rationale = error\n ? `failed: ${error}`\n : browserProgressRationale(command, params, messageText);\n return {\n text: `Step 1: ${command.subaction} — ${rationale}`,\n source: \"action_progress\",\n merge: \"replace\",\n metadata: {\n transient: true,\n compactProgress: true,\n progress: {\n source: \"browser\",\n actionName: \"BROWSER\",\n step: 1,\n kind: command.subaction,\n rationale,\n success,\n error,\n },\n },\n };\n}\n\nasync function emitBrowserStepProgress(\n callback: HandlerCallback | undefined,\n command: BrowserWorkspaceCommand,\n params: BrowserActionParameters | undefined,\n messageText: string,\n success: boolean,\n error?: string,\n): Promise<void> {\n if (params?.streamProgress !== true || !callback) return;\n try {\n await callback(\n buildBrowserStepProgressContent(\n command,\n params,\n messageText,\n success,\n error,\n ),\n \"BROWSER\",\n );\n } catch (callbackError) {\n logger.warn(\n {\n src: \"plugin:browser\",\n action: command.subaction,\n error:\n callbackError instanceof Error\n ? callbackError.message\n : String(callbackError),\n },\n \"Failed to emit browser progress callback\",\n );\n }\n}\n\nfunction currentUrlFromResult(\n result: BrowserWorkspaceCommandResult,\n): string | null {\n if (result.tab?.url) {\n return result.tab.url;\n }\n if (typeof result.value === \"string\" && result.value.trim()) {\n return result.value.trim();\n }\n if (Array.isArray(result.tabs)) {\n const visible = result.tabs.find((tab) => tab.visible) ?? result.tabs[0];\n if (visible?.url) {\n return visible.url;\n }\n }\n return null;\n}\n\n/**\n * Reads the current tab URL via the active browser target. Prefers a targeted\n * `get url` (cheap), falling back to `state` for backends that don't implement\n * the get-url mode. Returns null when the URL is not yet readable.\n */\nasync function readCurrentBrowserUrl(\n browserService: BrowserService | null,\n target: BrowserTarget | undefined,\n tabId: string | undefined,\n): Promise<string | null> {\n const run = async (\n command: BrowserWorkspaceCommand,\n ): Promise<BrowserWorkspaceCommandResult> =>\n browserService\n ? browserService.execute(command, target)\n : executeBrowserWorkspaceCommand(command);\n\n try {\n const got = await run({\n subaction: \"get\",\n getMode: \"url\",\n id: tabId,\n });\n const url = currentUrlFromResult(got);\n if (url) {\n return url;\n }\n } catch (error) {\n logger.debug(\n `[BROWSER] wait_for_url get-url poll failed, falling back to state: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n\n try {\n const state = await run({ subaction: \"state\", id: tabId });\n return currentUrlFromResult(state);\n } catch (error) {\n logger.debug(\n `[BROWSER] wait_for_url state poll could not read URL: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n return null;\n }\n}\n\n/**\n * Handles `action: \"wait_for_url\"`. Optionally opens/navigates to a starting\n * URL, tells the user it is watching, then polls the tab URL against `pattern`,\n * streaming a status update each poll. Resolves with a typed success/timeout\n * result and never throws on timeout.\n */\nasync function executeBrowserWaitForUrl(\n runtime: Parameters<NonNullable<Action[\"handler\"]>>[0],\n params: BrowserActionParameters | undefined,\n messageText: string,\n callback: HandlerCallback | undefined,\n): Promise<ReturnType<NonNullable<Action[\"handler\"]>>> {\n const pattern = (params?.pattern ?? \"\").trim();\n if (!pattern) {\n const text =\n \"wait_for_url needs a `pattern` (substring or regex) to watch for.\";\n logger.warn(`[BROWSER] ${text}`);\n return {\n text,\n success: false,\n values: { success: false, error: \"BROWSER_WAIT_FOR_URL_NO_PATTERN\" },\n data: { actionName: \"BROWSER\", subaction: \"wait_for_url\" },\n };\n }\n\n const browserService =\n runtime.getService<BrowserService>(BROWSER_SERVICE_TYPE) ?? null;\n const target = params?.target;\n const startUrl =\n params?.url?.trim() || extractFirstUrl(messageText) || undefined;\n const timeoutMs = params?.timeoutMs ?? WAIT_FOR_URL_DEFAULT_TIMEOUT_MS;\n const pollIntervalMs =\n params?.pollIntervalMs ?? WAIT_FOR_URL_DEFAULT_POLL_INTERVAL_MS;\n\n let tabId = params?.id?.trim() || undefined;\n\n // Optionally launch the starting URL so the user can act on it.\n if (startUrl) {\n const openCommand: BrowserWorkspaceCommand = {\n subaction: tabId ? \"navigate\" : \"open\",\n url: startUrl,\n id: tabId,\n };\n try {\n const opened = browserService\n ? await browserService.execute(openCommand, target)\n : await executeBrowserWorkspaceCommand(openCommand);\n tabId = opened.tab?.id ?? tabId;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n logger.warn(\n `[BROWSER] wait_for_url could not open ${startUrl}: ${reason}`,\n );\n return {\n text: `Couldn't open ${startUrl} to watch for \"${pattern}\": ${reason}`,\n success: false,\n values: { success: false, error: \"BROWSER_WAIT_FOR_URL_OPEN_FAILED\" },\n data: { actionName: \"BROWSER\", subaction: \"wait_for_url\" },\n };\n }\n }\n\n await callback?.({\n text: startUrl\n ? `I opened ${startUrl} — watching for \"${pattern}\" and I'll resume when it's reached.`\n : `Watching the current tab for \"${pattern}\" — I'll resume when it's reached.`,\n });\n\n logger.info(\n `[BROWSER] wait_for_url pattern=\"${pattern}\" timeoutMs=${timeoutMs} pollIntervalMs=${pollIntervalMs} target=${target ?? \"auto\"}`,\n );\n\n const outcome = await waitForUrl(\n { pattern, timeoutMs, pollIntervalMs },\n {\n getCurrentUrl: () => readCurrentBrowserUrl(browserService, target, tabId),\n emitStatus: async (text) => {\n await callback?.({ text });\n },\n },\n );\n\n return {\n text: outcome.message,\n success: outcome.matched,\n userFacingText: outcome.message,\n values: {\n success: outcome.matched,\n subaction: \"wait_for_url\",\n status: outcome.status,\n matched: outcome.matched,\n polls: outcome.polls,\n },\n data: {\n actionName: \"BROWSER\",\n subaction: \"wait_for_url\",\n outcome,\n },\n };\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. action=wait_for_url + pattern opens an optional url then watches the tab and resumes when its URL matches (OAuth callback, deploy/CI done), streaming progress.\",\n descriptionCompressed:\n \"Browser open|navigate|click|type|screenshot|state|autofill_login|wait_for_url; bridge status elsewhere\",\n validate: async () => true,\n handler: async (\n runtime,\n message,\n _state,\n options,\n callback?: HandlerCallback,\n ) => {\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 if (subaction === \"wait-for-url\") {\n return executeBrowserWaitForUrl(runtime, params, messageText, callback);\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 await emitBrowserStepProgress(\n callback,\n command,\n params,\n messageText,\n true,\n );\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 errorText =\n error instanceof Error ? error.message : \"Browser action failed\";\n logger.warn(`[BROWSER] Failed: ${errorText}`);\n await emitBrowserStepProgress(\n callback,\n command,\n params,\n messageText,\n false,\n errorText,\n );\n return {\n text: `Browser action failed: ${errorText}`,\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: \"streamProgress\",\n description:\n \"When true, emit a compact Step 1 progress callback after the browser command dispatches.\",\n required: false,\n schema: { type: \"boolean\" as const, default: false },\n },\n {\n name: \"rationale\",\n description: \"Optional rationale shown in streamProgress callback text.\",\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 \"wait_for_url\",\n ],\n },\n },\n {\n name: \"pattern\",\n description:\n \"For action=wait_for_url: substring or /regex/ to match the tab URL (e.g. callback?code=, or /\\\\/done$/).\",\n required: false,\n schema: { type: \"string\" as const },\n },\n {\n name: \"pollIntervalMs\",\n description: \"For action=wait_for_url: poll cadence in ms. Default 2000.\",\n required: false,\n schema: { type: \"number\" as const },\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 [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Open the GitHub OAuth page and let me know when it redirects back to our callback.\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"I opened https://github.com/login/oauth/authorize — watching for \\\"callback?code=\\\" and I'll resume when it's reached.\",\n actions: [\"BROWSER\"],\n },\n },\n ],\n ] as ActionExample[][],\n};\n"],"mappings":"AAQA,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EAGE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA2HP,SAAS,eAAe,SAAqC;AAC3D,QAAM,UAAU,SAAS;AACzB,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,EACT;AACA,SAAO,OAAO,SAAS,SAAS,WAAW,QAAQ,OAAO;AAC5D;AAEA,SAAS,gBAAgB,OAA8B;AACrD,QAAM,QAAQ,MAAM,MAAM,yBAAyB;AACnD,SAAO,QAAQ,CAAC,KAAK;AACvB;AAEA,SAAS,sBACP,QACA,aAC0E;AAC1E,QAAM,mBAAmB,uBAAuB,QAAQ,MAAM;AAC9D,MACE,qBAAqB,oBACrB,QAAQ,cAAc,kBACtB;AACA,WAAO;AAAA,EACT;AAEA,MACE,qBAAqB,kBACrB,QAAQ,cAAc,gBACtB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkB,6BAA6B,gBAAgB;AACrE,MAAI,iBAAiB;AACnB,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,WAAW;AACrB,WAAO,OAAO;AAAA,EAChB;AAEA,MAAI,QAAQ,WAAW;AACrB,WAAO;AAAA,EACT;AAMA,QAAM,YAAY,QAAQ,cAAc;AAExC,MAAI,QAAQ,YAAY,QAAQ,MAAM;AACpC,WAAO,YAAY,mBAAmB;AAAA,EACxC;AAEA,MAAI,QAAQ,UAAU;AACpB,WAAO,YAAY,oBAAoB;AAAA,EACzC;AAEA,MAAI,QAAQ,KAAK,KAAK,KAAK,gBAAgB,WAAW,GAAG;AACvD,WAAO,QAAQ,KAAK,aAAa;AAAA,EACnC;AAEA,SAAO;AACT;AAEA,SAAS,uBACP,QACqC;AACrC,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,6BACP,QACkD;AAClD,QAAM,mBAAmB,uBAAuB,MAAM;AACtD,UAAQ,kBAAkB;AAAA,IACxB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO,qBAAqB,gBAAgB,IACxC,mBACA;AAAA,EACR;AACF;AAEA,SAAS,qBACP,QACgD;AAChD,SACE,WAAW,UACX,WAAW,WACX,WAAW,WACX,WAAW,aACX,WAAW,SACX,WAAW,UACX,WAAW,cACX,WAAW,UACX,WAAW,WACX,WAAW,YACX,WAAW,gBACX,WAAW,UACX,WAAW,cACX,WAAW,WACX,WAAW,SACX,WAAW,UACX,WAAW,UACX,WAAW,qBACX,WAAW,oBACX,WAAW,oBACX,WAAW,qBACX,WAAW,iBACX,WAAW;AAEf;AAEA,SAAS,yBACP,QACkD;AAClD,UAAQ,uBAAuB,MAAM,GAAG;AAAA,IACtC,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,2BACP,SACA,QACQ;AACR,MAAI,OAAO,MAAM;AACf,UAAM,SAAS,OAAO,KACnB,IAAI,CAAC,QAAQ,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,GAAG,EAC1C,KAAK,IAAI;AACZ,WAAO,SACH,iBAAiB,OAAO,IAAI;AAAA,EAAO,MAAM,KACzC,qCAAqC,OAAO,IAAI;AAAA,EACtD;AAEA,MAAI,OAAO,QAAQ;AACjB,WAAO,mBAAmB,OAAO,IAAI;AAAA,EACvC;AAEA,MAAI,OAAO,KAAK;AACd,WAAO,GAAG,QAAQ,SAAS,iBAAiB,OAAO,IAAI;AAAA,EAAW,OAAO,IAAI,KAAK;AAAA,EAAK,OAAO,IAAI,GAAG;AAAA,EACvG;AAEA,MAAI,OAAO,UAAU,QAAW;AAC9B,QACE,QAAQ,cAAc,iBACtB,OAAO,UAAU,QACjB,OAAO,OAAO,UAAU,YACxB,OAAO,OAAO,SACd,OAAO,OAAO,OACd;AACA,YAAM,SAAS,OAAO;AACtB,aAAO,oBAAoB,KAAK,MAAM,OAAO,CAAC,CAAC,KAAK,KAAK,MAAM,OAAO,CAAC,CAAC,QAAQ,OAAO,IAAI;AAAA,IAC7F;AACA,UAAM,aACJ,OAAO,OAAO,UAAU,WACpB,OAAO,QACP,KAAK,UAAU,OAAO,OAAO,MAAM,CAAC;AAC1C,WAAO,WAAW,QAAQ,SAAS,YAAY,OAAO,IAAI;AAAA,EAAO,UAAU;AAAA,EAC7E;AAEA,MAAI,OAAO,UAAU,MAAM;AACzB,WAAO,WAAW,QAAQ,SAAS,0BAA0B,OAAO,IAAI;AAAA,EAC1E;AAEA,SAAO,WAAW,QAAQ,SAAS,iBAAiB,OAAO,IAAI;AACjE;AAEA,SAAS,yBACP,SACA,QACA,aACQ;AACR,QAAM,WAAW,QAAQ,WAAW,KAAK;AACzC,MAAI,SAAU,QAAO;AAErB,UAAQ,QAAQ,WAAW;AAAA,IACzB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,QAAQ,MAAM,QAAQ,QAAQ,GAAG,KAAK;AAAA,IAC/C,KAAK;AAAA,IACL,KAAK;AACH,aAAO,QAAQ,WACX,SAAS,QAAQ,QAAQ,KACzB;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO,QAAQ,WACX,QAAQ,QAAQ,QAAQ,KACxB;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AACH,aAAO,QAAQ,MAAM,SAAS,QAAQ,GAAG,KAAK;AAAA,IAChD,KAAK;AACH,aAAO,QAAQ,YACX,GAAG,QAAQ,SAAS,iBACpB;AAAA,IACN,KAAK;AACH,aAAO,QAAQ,WACX,YAAY,QAAQ,QAAQ,KAC5B;AAAA,IACN,KAAK;AACH,aAAO,YAAY,KAAK,KAAK;AAAA,IAC/B;AACE,aAAO,eAAe,QAAQ,SAAS;AAAA,EAC3C;AACF;AAEA,SAAS,gCACP,SACA,QACA,aACA,SACA,OACS;AACT,QAAM,YAAY,QACd,WAAW,KAAK,KAChB,yBAAyB,SAAS,QAAQ,WAAW;AACzD,SAAO;AAAA,IACL,MAAM,WAAW,QAAQ,SAAS,WAAM,SAAS;AAAA,IACjD,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,UAAU;AAAA,MACR,WAAW;AAAA,MACX,iBAAiB;AAAA,MACjB,UAAU;AAAA,QACR,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,MAAM;AAAA,QACN,MAAM,QAAQ;AAAA,QACd;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,wBACb,UACA,SACA,QACA,aACA,SACA,OACe;AACf,MAAI,QAAQ,mBAAmB,QAAQ,CAAC,SAAU;AAClD,MAAI;AACF,UAAM;AAAA,MACJ;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF,SAAS,eAAe;AACtB,WAAO;AAAA,MACL;AAAA,QACE,KAAK;AAAA,QACL,QAAQ,QAAQ;AAAA,QAChB,OACE,yBAAyB,QACrB,cAAc,UACd,OAAO,aAAa;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,qBACP,QACe;AACf,MAAI,OAAO,KAAK,KAAK;AACnB,WAAO,OAAO,IAAI;AAAA,EACpB;AACA,MAAI,OAAO,OAAO,UAAU,YAAY,OAAO,MAAM,KAAK,GAAG;AAC3D,WAAO,OAAO,MAAM,KAAK;AAAA,EAC3B;AACA,MAAI,MAAM,QAAQ,OAAO,IAAI,GAAG;AAC9B,UAAM,UAAU,OAAO,KAAK,KAAK,CAAC,QAAQ,IAAI,OAAO,KAAK,OAAO,KAAK,CAAC;AACvE,QAAI,SAAS,KAAK;AAChB,aAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAOA,eAAe,sBACb,gBACA,QACA,OACwB;AACxB,QAAM,MAAM,OACV,YAEA,iBACI,eAAe,QAAQ,SAAS,MAAM,IACtC,+BAA+B,OAAO;AAE5C,MAAI;AACF,UAAM,MAAM,MAAM,IAAI;AAAA,MACpB,WAAW;AAAA,MACX,SAAS;AAAA,MACT,IAAI;AAAA,IACN,CAAC;AACD,UAAM,MAAM,qBAAqB,GAAG;AACpC,QAAI,KAAK;AACP,aAAO;AAAA,IACT;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,sEACE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,UAAM,QAAQ,MAAM,IAAI,EAAE,WAAW,SAAS,IAAI,MAAM,CAAC;AACzD,WAAO,qBAAqB,KAAK;AAAA,EACnC,SAAS,OAAO;AACd,WAAO;AAAA,MACL,yDACE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAQA,eAAe,yBACb,SACA,QACA,aACA,UACqD;AACrD,QAAM,WAAW,QAAQ,WAAW,IAAI,KAAK;AAC7C,MAAI,CAAC,SAAS;AACZ,UAAM,OACJ;AACF,WAAO,KAAK,aAAa,IAAI,EAAE;AAC/B,WAAO;AAAA,MACL;AAAA,MACA,SAAS;AAAA,MACT,QAAQ,EAAE,SAAS,OAAO,OAAO,kCAAkC;AAAA,MACnE,MAAM,EAAE,YAAY,WAAW,WAAW,eAAe;AAAA,IAC3D;AAAA,EACF;AAEA,QAAM,iBACJ,QAAQ,WAA2B,oBAAoB,KAAK;AAC9D,QAAM,SAAS,QAAQ;AACvB,QAAM,WACJ,QAAQ,KAAK,KAAK,KAAK,gBAAgB,WAAW,KAAK;AACzD,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,iBACJ,QAAQ,kBAAkB;AAE5B,MAAI,QAAQ,QAAQ,IAAI,KAAK,KAAK;AAGlC,MAAI,UAAU;AACZ,UAAM,cAAuC;AAAA,MAC3C,WAAW,QAAQ,aAAa;AAAA,MAChC,KAAK;AAAA,MACL,IAAI;AAAA,IACN;AACA,QAAI;AACF,YAAM,SAAS,iBACX,MAAM,eAAe,QAAQ,aAAa,MAAM,IAChD,MAAM,+BAA+B,WAAW;AACpD,cAAQ,OAAO,KAAK,MAAM;AAAA,IAC5B,SAAS,OAAO;AACd,YAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACpE,aAAO;AAAA,QACL,yCAAyC,QAAQ,KAAK,MAAM;AAAA,MAC9D;AACA,aAAO;AAAA,QACL,MAAM,iBAAiB,QAAQ,kBAAkB,OAAO,MAAM,MAAM;AAAA,QACpE,SAAS;AAAA,QACT,QAAQ,EAAE,SAAS,OAAO,OAAO,mCAAmC;AAAA,QACpE,MAAM,EAAE,YAAY,WAAW,WAAW,eAAe;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW;AAAA,IACf,MAAM,WACF,YAAY,QAAQ,yBAAoB,OAAO,yCAC/C,iCAAiC,OAAO;AAAA,EAC9C,CAAC;AAED,SAAO;AAAA,IACL,mCAAmC,OAAO,eAAe,SAAS,mBAAmB,cAAc,WAAW,UAAU,MAAM;AAAA,EAChI;AAEA,QAAM,UAAU,MAAM;AAAA,IACpB,EAAE,SAAS,WAAW,eAAe;AAAA,IACrC;AAAA,MACE,eAAe,MAAM,sBAAsB,gBAAgB,QAAQ,KAAK;AAAA,MACxE,YAAY,OAAO,SAAS;AAC1B,cAAM,WAAW,EAAE,KAAK,CAAC;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ;AAAA,IACjB,gBAAgB,QAAQ;AAAA,IACxB,QAAQ;AAAA,MACN,SAAS,QAAQ;AAAA,MACjB,WAAW;AAAA,MACX,QAAQ,QAAQ;AAAA,MAChB,SAAS,QAAQ;AAAA,MACjB,OAAO,QAAQ;AAAA,IACjB;AAAA,IACA,MAAM;AAAA,MACJ,YAAY;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACF;AAEO,MAAM,gBAAwB;AAAA,EACnC,MAAM;AAAA,EACN,UAAU,CAAC,WAAW,OAAO,cAAc,SAAS;AAAA,EACpD,UAAU,EAAE,SAAS,QAAQ;AAAA,EAC7B,SAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,aACE;AAAA,EACF,uBACE;AAAA,EACF,UAAU,YAAY;AAAA,EACtB,SAAS,OACP,SACA,SACA,QACA,SACA,aACG;AACH,UAAM,SAAU,SAAwC;AAGxD,UAAM,cAAc,eAAe,OAAO;AAC1C,UAAM,YAAY,sBAAsB,QAAQ,WAAW;AAE3D,QAAI,cAAc,kBAAkB;AAClC,YAAM,EAAE,4BAA4B,IAAI,MAAM,OAC5C,6BACF;AACA,aAAO,4BAA4B,SAAS,SAAS,OAAO;AAAA,IAC9D;AAEA,QAAI,cAAc,gBAAgB;AAChC,aAAO,yBAAyB,SAAS,QAAQ,aAAa,QAAQ;AAAA,IACxE;AAEA,UAAM,MACJ,QAAQ,KAAK,KAAK,KAAK,gBAAgB,WAAW,KAAK;AAEzD,UAAM,UAAmC;AAAA,MACvC,IAAI,QAAQ,IAAI,KAAK;AAAA,MACrB,KAAK,QAAQ,KAAK,KAAK;AAAA,MACvB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA,MAChB,UAAU,QAAQ,UAAU,KAAK;AAAA,MACjC;AAAA,MACA,WAAW,QAAQ,aAAa,yBAAyB,QAAQ,MAAM;AAAA,MACvE,MAAM,QAAQ;AAAA,MACd,OAAO,QAAQ;AAAA,MACf,WAAW,QAAQ;AAAA,MACnB;AAAA,MACA,kBAAkB,QAAQ;AAAA,MAC1B,gBAAgB,QAAQ;AAAA,MACxB,SAAS,QAAQ;AAAA,MACjB,GAAG,QAAQ;AAAA,MACX,GAAG,QAAQ;AAAA,IACb;AAEA,UAAM,iBACJ,QAAQ,WAA2B,oBAAoB;AAEzD,QAAI;AACF,aAAO;AAAA,QACL,aAAa,QAAQ,SAAS,eAAe,QAAQ,UAAU,MAAM,oBAAoB,wBAAwB,QAAQ,GAAG,CAAC;AAAA,MAC/H;AACA,YAAM,SAAS,iBACX,MAAM,eAAe,QAAQ,SAAS,QAAQ,MAAM,IACpD,MAAM,+BAA+B,OAAO;AAChD,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,aAAO;AAAA,QACL,MAAM,2BAA2B,SAAS,MAAM;AAAA,QAChD,SAAS;AAAA,QACT,QAAQ;AAAA,UACN,SAAS;AAAA,UACT,MAAM,OAAO;AAAA,UACb,WAAW,OAAO;AAAA,QACpB;AAAA,QACA,MAAM;AAAA,UACJ,YAAY;AAAA,UACZ;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,YAAM,YACJ,iBAAiB,QAAQ,MAAM,UAAU;AAC3C,aAAO,KAAK,qBAAqB,SAAS,EAAE;AAC5C,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO;AAAA,QACL,MAAM,0BAA0B,SAAS;AAAA,QACzC,SAAS;AAAA,QACT,QAAQ,EAAE,SAAS,OAAO,OAAO,iBAAiB;AAAA,QAClD,MAAM;AAAA,UACJ,YAAY;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,WAAoB,SAAS,MAAM;AAAA,IACrD;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,UAAU;AAAA,MACV,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM,CAAC,SAAS,QAAQ,OAAO,QAAQ;AAAA,MACzC;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,UAAmB;AAAA,IACrC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,UAAmB;AAAA,IACrC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,UAAmB;AAAA,IACrC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ,EAAE,MAAM,SAAkB;AAAA,IACpC;AAAA,EACF;AAAA,EACA,UAAU;AAAA,IACR;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,UACN,SAAS,CAAC,SAAS;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -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;AAodhF,eAAO,MAAM,yBAAyB,EAAE,MAgKvC,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 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.",
465
- descriptionCompressed: "Manage LifeOps Browser Bridge: refresh shows settings/status; install setup; reveal_folder build folder; open_manager chrome://extensions.",
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(`Unsupported MANAGE_BROWSER_BRIDGE subaction: ${exhaustive}`);
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 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.",
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: { text: "Install the agent browser bridge extension.", source: "chat" }
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":"AAqCA,SAAS,cAAc;AAKvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,OAEK;AAEP,MAAM,cAAc;AACpB,MAAM,iCAAiC;AACvC,MAAM,4BAA4B;AAE3B,MAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,MAAM,0BAA0B;AAAA;AAAA,EAE9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,cAAc,KAAsB;AAC3C,SAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACxD;AAEA,SAAS,yBACP,SACA,OACY;AACZ,SAAO,QAAQ,KAAK;AAAA,IAClB;AAAA,IACA,IAAI;AAAA,MAAe,CAAC,GAAG,WACrB;AAAA,QACE,MAAM,OAAO,IAAI,MAAM,GAAG,KAAK,YAAY,CAAC;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,MAAM,wBAAwB;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,mBAAmB,OAAmC;AAC7D,QAAM,WAAW,oBAAI,IAAY;AACjC,QAAM,UAAU,CAAC,UAAmB;AAClC,QAAI,CAAC,MAAM,QAAQ,KAAK,EAAG;AAC3B,eAAW,QAAQ,OAAO;AACxB,UAAI,OAAO,SAAS,SAAU,UAAS,IAAI,IAAI;AAAA,IACjD;AAAA,EACF;AACA;AAAA,IACG,OAAO,QAAgD;AAAA,EAC1D;AACA;AAAA,IACG,OAAO,MAA8C;AAAA,EACxD;AACA,QAAM,gBAAiB,OAAO,MAC1B;AAMJ,UAAQ,eAAe,kBAAkB,gBAAgB;AACzD,UAAQ,eAAe,UAAU,gBAAgB;AACjD,SAAO,sBAAsB,KAAK,CAAC,YAAY,SAAS,IAAI,OAAO,CAAC;AACtE;AAEA,SAAS,uBACP,SACA,OACS;AACT,QAAM,OAAO;AAAA,IACX,OAAO,QAAQ,SAAS,SAAS,WAAW,QAAQ,QAAQ,OAAO;AAAA,IACnE,OAAO,OAAO,QAAQ,mBAAmB,WACrC,MAAM,OAAO,iBACb;AAAA,EACN,EACG,KAAK,IAAI,EACT,YAAY;AACf,SAAO,wBAAwB;AAAA,IAAK,CAAC,YACnC,KAAK,SAAS,QAAQ,YAAY,CAAC;AAAA,EACrC;AACF;AAOA,SAAS,mBACP,KAC+B;AAC/B,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,UAAU,IAAI,KAAK,EAAE,YAAY,EAAE,QAAQ,WAAW,GAAG;AAC/D,SAAQ,0BAAgD,SAAS,OAAO,IACnE,UACD;AACN;AAEA,SAAS,0BAA0B,MAAsC;AACvE,QAAM,aAAa,KAAK,YAAY;AACpC,MACE,+DAA+D;AAAA,IAC7D;AAAA,EACF,KACA,CAAC,wBAAwB,KAAK,UAAU,GACxC;AACA,WAAO;AAAA,EACT;AACA,MACE,sEAAsE;AAAA,IACpE;AAAA,EACF,GACA;AACA,WAAO;AAAA,EACT;AACA,MACE,gHAAgH;AAAA,IAC9G;AAAA,EACF,GACA;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,eAAe,aAAoC;AACjD,MAAI,SACF,uCAAuC;AACzC,MAAI,CAAC,OAAO,iBAAiB;AAC3B,aAAS,MAAM;AAAA,MACb,mCAAmC,QAAQ;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACA,QAAM,SAAS,MAAM;AAAA,IACnB,sCAAsC,gBAAgB,EAAE,YAAY,KAAK,CAAC;AAAA,IAC1E;AAAA,EACF;AACA,MAAI,gBAAgB;AACpB,MAAI;AACF,UAAM;AAAA,MACJ,kCAAkC,QAAQ;AAAA,MAC1C;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,oBAAgB;AAChB,WAAO;AAAA,MACL,IAAI,WAAW,yCAAyC,cAAc,GAAG,CAAC;AAAA,IAC5E;AAAA,EACF;AACA,QAAM,QACJ,gBACI,mDAAmD,OAAO,IAAI,MAC9D,+CAA+C,OAAO,IAAI,4EAC9D,MAAM,GAAG,8BAA8B;AACzC,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,IACT,QAAQ,EAAE,SAAS,MAAM,WAAW,WAAW,cAAc;AAAA,IAC7D,MAAM;AAAA,MACJ,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,MAAM,OAAO;AAAA,MACb;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,kBAAyC;AACtD,QAAM,SAAS,MAAM;AAAA,IACnB,sCAAsC,gBAAgB,EAAE,YAAY,KAAK,CAAC;AAAA,IAC1E;AAAA,EACF;AACA,QAAM,OACJ,+CAA+C,OAAO,IAAI,IAAI;AAAA,IAC5D;AAAA,IACA;AAAA,EACF;AACF,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,IACT,QAAQ,EAAE,SAAS,MAAM,WAAW,gBAAgB;AAAA,IACpD,MAAM;AAAA,MACJ,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,MAAM,OAAO;AAAA,IACf;AAAA,EACF;AACF;AAEA,eAAe,iBAAwC;AACrD,QAAM;AAAA,IACJ,kCAAkC,QAAQ;AAAA,IAC1C;AAAA,EACF;AACA,QAAM,OACJ,4FAA4F;AAAA,IAC1F;AAAA,IACA;AAAA,EACF;AACF,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,IACT,QAAQ,EAAE,SAAS,MAAM,WAAW,eAAe;AAAA,IACnD,MAAM,EAAE,YAAY,aAAa,WAAW,eAAe;AAAA,EAC7D;AACF;AAEA,eAAe,WAAW,SAA+C;AACvE,QAAM,SAAS,uCAAuC;AACtD,MAAI,WAEO;AACX,MAAI,aAA6C,CAAC;AAClD,QAAM,UAAU,QAAQ;AAAA,IACtB;AAAA,EACF;AACA,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,QACN,SAAS;AAAA,QACT,WAAW;AAAA,QACX,OAAO;AAAA,MACT;AAAA,MACA,MAAM;AAAA,QACJ,YAAY;AAAA,QACZ,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,aAAW,MAAM,QAAQ,mBAAmB;AAC5C,gBAAc,MAAM,QAAQ,sBAAsB,GAAG,MAAM,GAAG,EAAE;AAChE,QAAM,YAAY,WAAW,SAAS;AACtC,QAAM,OAAO;AAAA,IACX;AAAA,IACA,aAAa,SAAS,YAAY;AAAA,IAClC,oBAAoB,SAAS,sBAAsB,OAAO,KAAK;AAAA,IAC/D,YACI,eAAe,WAAW,MAAM,aAChC;AAAA,EACN,EAAE,KAAK,GAAG;AACV,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,IACT,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,WAAW;AAAA,MACX;AAAA,MACA,cAAc,SAAS;AAAA,MACvB,qBAAqB,SAAS;AAAA,MAC9B,gBAAgB,WAAW;AAAA,IAC7B;AAAA,IACA,MAAM;AAAA,MACJ,YAAY;AAAA,MACZ,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEO,MAAM,4BAAoC;AAAA,EAC/C,MAAM;AAAA,EACN,UAAU,CAAC,WAAW,SAAS,cAAc,UAAU;AAAA,EACvD,aAAa,EAAE,OAAO,CAAC,WAAW,SAAS,cAAc,UAAU,EAAE;AAAA,EACrE,UAAU,EAAE,SAAS,QAAQ;AAAA,EAC7B,SAAS;AAAA;AAAA,IAEP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,aACE;AAAA,EACF,uBACE;AAAA,EACF,UAAU,OACR,UACA,SACA,UACqB;AACrB,WAAO,mBAAmB,KAAK,KAAK,uBAAuB,SAAS,KAAK;AAAA,EAC3E;AAAA,EACA,SAAS,OACP,SACA,SACA,QACA,YAC0B;AAC1B,UAAM,SAAU,SACZ;AACJ,UAAM,YACJ,mBAAmB,QAAQ,MAAM,KACjC,mBAAmB,QAAQ,SAAS,KACpC;AAAA,MACE,OAAO,QAAQ,SAAS,SAAS,WAAW,QAAQ,QAAQ,OAAO;AAAA,IACrE;AACF,QAAI;AACF,cAAQ,WAAW;AAAA,QACjB,KAAK;AACH,iBAAO,MAAM,WAAW;AAAA,QAC1B,KAAK;AACH,iBAAO,MAAM,gBAAgB;AAAA,QAC/B,KAAK;AACH,iBAAO,MAAM,eAAe;AAAA,QAC9B,KAAK;AACH,iBAAO,MAAM,WAAW,OAAO;AAAA,QACjC,SAAS;AACP,gBAAM,aAAoB;AAC1B,gBAAM,IAAI,MAAM,gDAAgD,UAAU,EAAE;AAAA,QAC9E;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,OACJ,gCAAgC,SAAS,KAAK,cAAc,GAAG,CAAC,GAAG;AAAA,QACjE;AAAA,QACA;AAAA,MACF;AACF,aAAO,KAAK,IAAI,WAAW,KAAK,IAAI,EAAE;AACtC,aAAO;AAAA,QACL;AAAA,QACA,SAAS;AAAA,QACT,QAAQ;AAAA,UACN,SAAS;AAAA,UACT;AAAA,UACA,OAAO,yBAAyB,UAAU,YAAY,CAAC;AAAA,QACzD;AAAA,QACA,MAAM,EAAE,YAAY,aAAa,UAAU;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAAA,EACA,YAAY;AAAA,IACV;AAAA,MACE,MAAM;AAAA,MACN,aACE;AAAA,MACF,UAAU;AAAA,MACV,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM,CAAC,GAAG,yBAAyB;AAAA,MACrC;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM,CAAC,GAAG,yBAAyB;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EACA,UAAU;AAAA,IACR;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,SAAS,EAAE,MAAM,mCAAmC,QAAQ,OAAO;AAAA,MACrE;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,UACN,SAAS,CAAC,uBAAuB;AAAA,UACjC,SACE;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,SAAS,EAAE,MAAM,+CAA+C,QAAQ,OAAO;AAAA,MACjF;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,UACN,SAAS,CAAC,uBAAuB;AAAA,UACjC,SACE;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE;AAAA,QACE,MAAM;AAAA,QACN,SAAS,EAAE,MAAM,oCAAoC,QAAQ,OAAO;AAAA,MACtE;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM;AAAA,UACN,SAAS,CAAC,uBAAuB;AAAA,UACjC,SACE;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","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,34 @@
1
+ /**
2
+ * Pure URL-matching predicate for the BROWSER `wait_for_url` subaction.
3
+ *
4
+ * A `pattern` is treated as a regular expression only when it is written as a
5
+ * `/.../` literal (with optional flags); any other pattern is a
6
+ * case-insensitive substring match. This keeps ordinary URL fragments like
7
+ * `callback?code=` (which contain regex metacharacters) predictable. An invalid
8
+ * regex literal always falls back to a substring match so the agent never
9
+ * crashes on user input.
10
+ *
11
+ * Kept free of any browser/runtime imports so it stays trivially unit-testable.
12
+ */
13
+ /** How a given pattern was interpreted when building the predicate. */
14
+ export type WaitForUrlPatternKind = "regex" | "substring";
15
+ export interface WaitForUrlPredicate {
16
+ /** The original, untrimmed pattern the caller supplied. */
17
+ readonly pattern: string;
18
+ /** How the pattern was interpreted ("regex" or "substring"). */
19
+ readonly kind: WaitForUrlPatternKind;
20
+ /** Returns true when `url` satisfies the pattern. */
21
+ test(url: string): boolean;
22
+ }
23
+ /**
24
+ * Build a {@link WaitForUrlPredicate} from a caller-supplied pattern.
25
+ *
26
+ * - `"/foo\\d+/i"` → regex `/foo\d+/i`.
27
+ * - `"/\\/done$/"` → regex.
28
+ * - `"callback?code="` → substring (case-insensitive), even though it contains
29
+ * regex metacharacters.
30
+ * - An invalid `/.../ ` literal → falls back to a case-insensitive substring
31
+ * match on the original pattern text.
32
+ */
33
+ export declare function buildWaitForUrlPredicate(pattern: string): WaitForUrlPredicate;
34
+ //# sourceMappingURL=wait-for-url-predicate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait-for-url-predicate.d.ts","sourceRoot":"","sources":["../../src/actions/wait-for-url-predicate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,uEAAuE;AACvE,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,WAAW,CAAC;AAE1D,MAAM,WAAW,mBAAmB;IAClC,2DAA2D;IAC3D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,qDAAqD;IACrD,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAYD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAwB7E"}
@@ -0,0 +1,33 @@
1
+ const REGEX_LITERAL = /^\/(.+)\/([a-z]*)$/i;
2
+ function compileRegex(source, flags) {
3
+ try {
4
+ return new RegExp(source, flags);
5
+ } catch {
6
+ return null;
7
+ }
8
+ }
9
+ function buildWaitForUrlPredicate(pattern) {
10
+ const trimmed = pattern.trim();
11
+ const literalMatch = trimmed.match(REGEX_LITERAL);
12
+ if (literalMatch) {
13
+ const [, source, flags] = literalMatch;
14
+ const compiled = compileRegex(source, flags || "");
15
+ if (compiled) {
16
+ return {
17
+ pattern,
18
+ kind: "regex",
19
+ test: (url) => compiled.test(url)
20
+ };
21
+ }
22
+ }
23
+ const needle = trimmed.toLowerCase();
24
+ return {
25
+ pattern,
26
+ kind: "substring",
27
+ test: (url) => needle.length === 0 ? false : url.toLowerCase().includes(needle)
28
+ };
29
+ }
30
+ export {
31
+ buildWaitForUrlPredicate
32
+ };
33
+ //# sourceMappingURL=wait-for-url-predicate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/actions/wait-for-url-predicate.ts"],"sourcesContent":["/**\n * Pure URL-matching predicate for the BROWSER `wait_for_url` subaction.\n *\n * A `pattern` is treated as a regular expression only when it is written as a\n * `/.../` literal (with optional flags); any other pattern is a\n * case-insensitive substring match. This keeps ordinary URL fragments like\n * `callback?code=` (which contain regex metacharacters) predictable. An invalid\n * regex literal always falls back to a substring match so the agent never\n * crashes on user input.\n *\n * Kept free of any browser/runtime imports so it stays trivially unit-testable.\n */\n\n/** How a given pattern was interpreted when building the predicate. */\nexport type WaitForUrlPatternKind = \"regex\" | \"substring\";\n\nexport interface WaitForUrlPredicate {\n /** The original, untrimmed pattern the caller supplied. */\n readonly pattern: string;\n /** How the pattern was interpreted (\"regex\" or \"substring\"). */\n readonly kind: WaitForUrlPatternKind;\n /** Returns true when `url` satisfies the pattern. */\n test(url: string): boolean;\n}\n\nconst REGEX_LITERAL = /^\\/(.+)\\/([a-z]*)$/i;\n\nfunction compileRegex(source: string, flags: string): RegExp | null {\n try {\n return new RegExp(source, flags);\n } catch {\n return null;\n }\n}\n\n/**\n * Build a {@link WaitForUrlPredicate} from a caller-supplied pattern.\n *\n * - `\"/foo\\\\d+/i\"` → regex `/foo\\d+/i`.\n * - `\"/\\\\/done$/\"` → regex.\n * - `\"callback?code=\"` → substring (case-insensitive), even though it contains\n * regex metacharacters.\n * - An invalid `/.../ ` literal → falls back to a case-insensitive substring\n * match on the original pattern text.\n */\nexport function buildWaitForUrlPredicate(pattern: string): WaitForUrlPredicate {\n const trimmed = pattern.trim();\n\n const literalMatch = trimmed.match(REGEX_LITERAL);\n if (literalMatch) {\n const [, source, flags] = literalMatch;\n const compiled = compileRegex(source, flags || \"\");\n if (compiled) {\n return {\n pattern,\n kind: \"regex\",\n test: (url: string) => compiled.test(url),\n };\n }\n // Invalid regex literal: fall through to substring on the raw pattern.\n }\n\n const needle = trimmed.toLowerCase();\n return {\n pattern,\n kind: \"substring\",\n test: (url: string) =>\n needle.length === 0 ? false : url.toLowerCase().includes(needle),\n };\n}\n"],"mappings":"AAyBA,MAAM,gBAAgB;AAEtB,SAAS,aAAa,QAAgB,OAA8B;AAClE,MAAI;AACF,WAAO,IAAI,OAAO,QAAQ,KAAK;AAAA,EACjC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAYO,SAAS,yBAAyB,SAAsC;AAC7E,QAAM,UAAU,QAAQ,KAAK;AAE7B,QAAM,eAAe,QAAQ,MAAM,aAAa;AAChD,MAAI,cAAc;AAChB,UAAM,CAAC,EAAE,QAAQ,KAAK,IAAI;AAC1B,UAAM,WAAW,aAAa,QAAQ,SAAS,EAAE;AACjD,QAAI,UAAU;AACZ,aAAO;AAAA,QACL;AAAA,QACA,MAAM;AAAA,QACN,MAAM,CAAC,QAAgB,SAAS,KAAK,GAAG;AAAA,MAC1C;AAAA,IACF;AAAA,EAEF;AAEA,QAAM,SAAS,QAAQ,YAAY;AACnC,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,MAAM,CAAC,QACL,OAAO,WAAW,IAAI,QAAQ,IAAI,YAAY,EAAE,SAAS,MAAM;AAAA,EACnE;AACF;","names":[]}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * BROWSER `wait_for_url` subaction core.
3
+ *
4
+ * Opens (or reuses) a tab, then polls the current tab URL until it matches a
5
+ * caller-supplied pattern (substring or regex — see
6
+ * {@link buildWaitForUrlPredicate}) or a deadline passes. Each poll iteration
7
+ * emits a streaming status update through the action's `HandlerCallback` so a
8
+ * Telegram/chat user sees progress; the loop never throws on timeout — it
9
+ * returns a typed {@link WaitForUrlOutcome}.
10
+ *
11
+ * The poll loop takes its URL source, clock, and sleep as injected
12
+ * dependencies so it is fully deterministic under test (fake URL source + fake
13
+ * timer) with no real browser.
14
+ */
15
+ /** Default deadline: 5 minutes. */
16
+ export declare const WAIT_FOR_URL_DEFAULT_TIMEOUT_MS = 300000;
17
+ /** Default poll cadence: ~2 seconds. */
18
+ export declare const WAIT_FOR_URL_DEFAULT_POLL_INTERVAL_MS = 2000;
19
+ export type WaitForUrlStatus = "matched" | "timeout";
20
+ export interface WaitForUrlOutcome {
21
+ status: WaitForUrlStatus;
22
+ /** True iff the URL matched before the deadline. */
23
+ matched: boolean;
24
+ /** The pattern the caller supplied. */
25
+ pattern: string;
26
+ /** The last URL observed from the tab (null if never readable). */
27
+ lastUrl: string | null;
28
+ /** Number of poll iterations performed. */
29
+ polls: number;
30
+ /** Wall-clock elapsed time, in ms, measured from the injected clock. */
31
+ elapsedMs: number;
32
+ /** Human-readable summary suitable for a chat reply. */
33
+ message: string;
34
+ }
35
+ export interface WaitForUrlOptions {
36
+ /** Substring or regex to match against the current tab URL. */
37
+ pattern: string;
38
+ /** Deadline in ms. Defaults to {@link WAIT_FOR_URL_DEFAULT_TIMEOUT_MS}. */
39
+ timeoutMs?: number;
40
+ /**
41
+ * Poll cadence in ms. Defaults to
42
+ * {@link WAIT_FOR_URL_DEFAULT_POLL_INTERVAL_MS}.
43
+ */
44
+ pollIntervalMs?: number;
45
+ }
46
+ export interface WaitForUrlDeps {
47
+ /**
48
+ * Reads the current tab URL. Returns null when the URL is not yet readable
49
+ * (e.g. tab still loading); the loop keeps polling until the deadline.
50
+ */
51
+ getCurrentUrl: () => Promise<string | null> | string | null;
52
+ /** Emits a status update to the user. Optional (may be a no-op). */
53
+ emitStatus?: (text: string) => Promise<void> | void;
54
+ /** Monotonic clock in ms. Defaults to `Date.now`. */
55
+ now?: () => number;
56
+ /** Async sleep. Defaults to a real `setTimeout` promise. */
57
+ sleep?: (ms: number) => Promise<void>;
58
+ }
59
+ /**
60
+ * Poll the current tab URL until it matches `pattern` or the deadline passes.
61
+ * Never throws on timeout — returns a typed {@link WaitForUrlOutcome}.
62
+ */
63
+ export declare function waitForUrl(options: WaitForUrlOptions, deps: WaitForUrlDeps): Promise<WaitForUrlOutcome>;
64
+ //# sourceMappingURL=wait-for-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wait-for-url.d.ts","sourceRoot":"","sources":["../../src/actions/wait-for-url.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,mCAAmC;AACnC,eAAO,MAAM,+BAA+B,SAAU,CAAC;AACvD,wCAAwC;AACxC,eAAO,MAAM,qCAAqC,OAAQ,CAAC;AAM3D,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAC;AAErD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,gBAAgB,CAAC;IACzB,oDAAoD;IACpD,OAAO,EAAE,OAAO,CAAC;IACjB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,aAAa,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5D,oEAAoE;IACpE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACpD,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AA4BD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,iBAAiB,EAC1B,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAgE5B"}
@@ -0,0 +1,89 @@
1
+ import { buildWaitForUrlPredicate } from "./wait-for-url-predicate.js";
2
+ const WAIT_FOR_URL_DEFAULT_TIMEOUT_MS = 3e5;
3
+ const WAIT_FOR_URL_DEFAULT_POLL_INTERVAL_MS = 2e3;
4
+ const WAIT_FOR_URL_MIN_POLL_INTERVAL_MS = 50;
5
+ const WAIT_FOR_URL_MIN_TIMEOUT_MS = 1;
6
+ function realSleep(ms) {
7
+ return new Promise((resolve) => {
8
+ setTimeout(resolve, ms);
9
+ });
10
+ }
11
+ function clampPollInterval(value) {
12
+ const candidate = value ?? WAIT_FOR_URL_DEFAULT_POLL_INTERVAL_MS;
13
+ if (!Number.isFinite(candidate) || candidate <= 0) {
14
+ return WAIT_FOR_URL_DEFAULT_POLL_INTERVAL_MS;
15
+ }
16
+ return Math.max(WAIT_FOR_URL_MIN_POLL_INTERVAL_MS, Math.floor(candidate));
17
+ }
18
+ function clampTimeout(value) {
19
+ const candidate = value ?? WAIT_FOR_URL_DEFAULT_TIMEOUT_MS;
20
+ if (!Number.isFinite(candidate) || candidate <= 0) {
21
+ return WAIT_FOR_URL_DEFAULT_TIMEOUT_MS;
22
+ }
23
+ return Math.max(WAIT_FOR_URL_MIN_TIMEOUT_MS, Math.floor(candidate));
24
+ }
25
+ function describeCurrentUrl(url) {
26
+ return url ? `current: ${url}` : "current: unknown";
27
+ }
28
+ async function waitForUrl(options, deps) {
29
+ const predicate = buildWaitForUrlPredicate(options.pattern);
30
+ const timeoutMs = clampTimeout(options.timeoutMs);
31
+ const pollIntervalMs = clampPollInterval(options.pollIntervalMs);
32
+ const now = deps.now ?? Date.now;
33
+ const sleep = deps.sleep ?? realSleep;
34
+ const startedAt = now();
35
+ const deadline = startedAt + timeoutMs;
36
+ let polls = 0;
37
+ let lastUrl = null;
38
+ while (true) {
39
+ polls += 1;
40
+ let currentUrl = null;
41
+ try {
42
+ currentUrl = await deps.getCurrentUrl() ?? null;
43
+ } catch {
44
+ currentUrl = null;
45
+ }
46
+ if (currentUrl !== null) {
47
+ lastUrl = currentUrl;
48
+ }
49
+ if (currentUrl !== null && predicate.test(currentUrl)) {
50
+ const elapsedMs2 = now() - startedAt;
51
+ const message = `Done \u2014 tab reached ${currentUrl} (matched ${predicate.kind} "${predicate.pattern}" after ${polls} check${polls === 1 ? "" : "s"}).`;
52
+ await deps.emitStatus?.(`\u2705 ${message}`);
53
+ return {
54
+ status: "matched",
55
+ matched: true,
56
+ pattern: predicate.pattern,
57
+ lastUrl,
58
+ polls,
59
+ elapsedMs: elapsedMs2,
60
+ message
61
+ };
62
+ }
63
+ const elapsedMs = now() - startedAt;
64
+ const remainingMs = deadline - now();
65
+ if (remainingMs <= 0) {
66
+ const message = `Timed out after ${Math.round(elapsedMs / 1e3)}s waiting for "${predicate.pattern}" (${describeCurrentUrl(lastUrl)}).`;
67
+ await deps.emitStatus?.(`\u231B ${message}`);
68
+ return {
69
+ status: "timeout",
70
+ matched: false,
71
+ pattern: predicate.pattern,
72
+ lastUrl,
73
+ polls,
74
+ elapsedMs,
75
+ message
76
+ };
77
+ }
78
+ await deps.emitStatus?.(
79
+ `\u23F3 still waiting for "${predicate.pattern}"\u2026 (${describeCurrentUrl(currentUrl)})`
80
+ );
81
+ await sleep(Math.min(pollIntervalMs, remainingMs));
82
+ }
83
+ }
84
+ export {
85
+ WAIT_FOR_URL_DEFAULT_POLL_INTERVAL_MS,
86
+ WAIT_FOR_URL_DEFAULT_TIMEOUT_MS,
87
+ waitForUrl
88
+ };
89
+ //# sourceMappingURL=wait-for-url.js.map