@elizaos/plugin-browser 2.0.0-alpha.9 → 2.0.11-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +98 -83
  3. package/auto-enable.ts +24 -0
  4. package/dist/actions/browser-autofill-login.d.ts +43 -0
  5. package/dist/actions/browser-autofill-login.d.ts.map +1 -0
  6. package/dist/actions/browser-autofill-login.js +278 -0
  7. package/dist/actions/browser-autofill-login.js.map +1 -0
  8. package/dist/actions/browser.d.ts +11 -0
  9. package/dist/actions/browser.d.ts.map +1 -0
  10. package/dist/actions/browser.js +412 -0
  11. package/dist/actions/browser.js.map +1 -0
  12. package/dist/actions/manage-browser-bridge.d.ts +34 -0
  13. package/dist/actions/manage-browser-bridge.d.ts.map +1 -0
  14. package/dist/actions/manage-browser-bridge.js +572 -0
  15. package/dist/actions/manage-browser-bridge.js.map +1 -0
  16. package/dist/bridge-policy.d.ts +10 -0
  17. package/dist/bridge-policy.d.ts.map +1 -0
  18. package/dist/bridge-policy.js +37 -0
  19. package/dist/bridge-policy.js.map +1 -0
  20. package/dist/bridge-readiness.d.ts +16 -0
  21. package/dist/bridge-readiness.d.ts.map +1 -0
  22. package/dist/bridge-readiness.js +82 -0
  23. package/dist/bridge-readiness.js.map +1 -0
  24. package/dist/bridge-records.d.ts +9 -0
  25. package/dist/bridge-records.d.ts.map +1 -0
  26. package/dist/bridge-records.js +37 -0
  27. package/dist/bridge-records.js.map +1 -0
  28. package/dist/browser-capture-hooks.d.ts +9 -0
  29. package/dist/browser-capture-hooks.d.ts.map +1 -0
  30. package/dist/browser-capture-hooks.js +15 -0
  31. package/dist/browser-capture-hooks.js.map +1 -0
  32. package/dist/browser-service.d.ts +103 -0
  33. package/dist/browser-service.d.ts.map +1 -0
  34. package/dist/browser-service.js +186 -0
  35. package/dist/browser-service.js.map +1 -0
  36. package/dist/browser-workspace-hooks.d.ts +14 -0
  37. package/dist/browser-workspace-hooks.d.ts.map +1 -0
  38. package/dist/browser-workspace-hooks.js +15 -0
  39. package/dist/browser-workspace-hooks.js.map +1 -0
  40. package/dist/companion-auth.d.ts +34 -0
  41. package/dist/companion-auth.d.ts.map +1 -0
  42. package/dist/companion-auth.js +98 -0
  43. package/dist/companion-auth.js.map +1 -0
  44. package/dist/contracts.d.ts +284 -0
  45. package/dist/contracts.d.ts.map +1 -0
  46. package/dist/contracts.js +56 -0
  47. package/dist/contracts.js.map +1 -0
  48. package/dist/index.d.ts +30 -16
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +76 -90
  51. package/dist/index.js.map +1 -1
  52. package/dist/lifeops-session-contracts.d.ts +46 -0
  53. package/dist/lifeops-session-contracts.d.ts.map +1 -0
  54. package/dist/lifeops-session-contracts.js +1 -0
  55. package/dist/lifeops-session-contracts.js.map +1 -0
  56. package/dist/message-adapter.d.ts +9 -0
  57. package/dist/message-adapter.d.ts.map +1 -0
  58. package/dist/message-adapter.js +104 -0
  59. package/dist/message-adapter.js.map +1 -0
  60. package/dist/packaging.d.ts +27 -0
  61. package/dist/packaging.d.ts.map +1 -0
  62. package/dist/packaging.js +571 -0
  63. package/dist/packaging.js.map +1 -0
  64. package/dist/password-manager-bridge.d.ts +50 -0
  65. package/dist/password-manager-bridge.d.ts.map +1 -0
  66. package/dist/password-manager-bridge.js +437 -0
  67. package/dist/password-manager-bridge.js.map +1 -0
  68. package/dist/plugin.d.ts +10 -0
  69. package/dist/plugin.d.ts.map +1 -0
  70. package/dist/plugin.js +168 -0
  71. package/dist/plugin.js.map +1 -0
  72. package/dist/providers/workspace.d.ts +13 -0
  73. package/dist/providers/workspace.d.ts.map +1 -0
  74. package/dist/providers/workspace.js +64 -0
  75. package/dist/providers/workspace.js.map +1 -0
  76. package/dist/routes/bridge.d.ts +37 -0
  77. package/dist/routes/bridge.d.ts.map +1 -0
  78. package/dist/routes/bridge.js +844 -0
  79. package/dist/routes/bridge.js.map +1 -0
  80. package/dist/routes/workspace-account-gate.d.ts +29 -0
  81. package/dist/routes/workspace-account-gate.d.ts.map +1 -0
  82. package/dist/routes/workspace-account-gate.js +147 -0
  83. package/dist/routes/workspace-account-gate.js.map +1 -0
  84. package/dist/routes/workspace-setup.d.ts +10 -0
  85. package/dist/routes/workspace-setup.d.ts.map +1 -0
  86. package/dist/routes/workspace-setup.js +65 -0
  87. package/dist/routes/workspace-setup.js.map +1 -0
  88. package/dist/routes/workspace.d.ts +20 -0
  89. package/dist/routes/workspace.d.ts.map +1 -0
  90. package/dist/routes/workspace.js +276 -0
  91. package/dist/routes/workspace.js.map +1 -0
  92. package/dist/schema.d.ts +2326 -0
  93. package/dist/schema.d.ts.map +1 -0
  94. package/dist/schema.js +133 -0
  95. package/dist/schema.js.map +1 -0
  96. package/dist/service.d.ts +30 -0
  97. package/dist/service.d.ts.map +1 -0
  98. package/dist/service.js +5 -0
  99. package/dist/service.js.map +1 -0
  100. package/dist/targets/bridge-target.d.ts +31 -0
  101. package/dist/targets/bridge-target.d.ts.map +1 -0
  102. package/dist/targets/bridge-target.js +98 -0
  103. package/dist/targets/bridge-target.js.map +1 -0
  104. package/dist/targets/stagehand-target.d.ts +3 -0
  105. package/dist/targets/stagehand-target.d.ts.map +1 -0
  106. package/dist/targets/stagehand-target.js +187 -0
  107. package/dist/targets/stagehand-target.js.map +1 -0
  108. package/dist/workspace/browser-capture.d.ts +41 -0
  109. package/dist/workspace/browser-capture.d.ts.map +1 -0
  110. package/dist/workspace/browser-capture.js +159 -0
  111. package/dist/workspace/browser-capture.js.map +1 -0
  112. package/dist/workspace/browser-workspace-desktop.d.ts +19 -0
  113. package/dist/workspace/browser-workspace-desktop.d.ts.map +1 -0
  114. package/dist/workspace/browser-workspace-desktop.js +1578 -0
  115. package/dist/workspace/browser-workspace-desktop.js.map +1 -0
  116. package/dist/workspace/browser-workspace-elements.d.ts +42 -0
  117. package/dist/workspace/browser-workspace-elements.d.ts.map +1 -0
  118. package/dist/workspace/browser-workspace-elements.js +547 -0
  119. package/dist/workspace/browser-workspace-elements.js.map +1 -0
  120. package/dist/workspace/browser-workspace-forms.d.ts +19 -0
  121. package/dist/workspace/browser-workspace-forms.d.ts.map +1 -0
  122. package/dist/workspace/browser-workspace-forms.js +277 -0
  123. package/dist/workspace/browser-workspace-forms.js.map +1 -0
  124. package/dist/workspace/browser-workspace-helpers.d.ts +32 -0
  125. package/dist/workspace/browser-workspace-helpers.d.ts.map +1 -0
  126. package/dist/workspace/browser-workspace-helpers.js +232 -0
  127. package/dist/workspace/browser-workspace-helpers.js.map +1 -0
  128. package/dist/workspace/browser-workspace-jsdom.d.ts +16 -0
  129. package/dist/workspace/browser-workspace-jsdom.d.ts.map +1 -0
  130. package/dist/workspace/browser-workspace-jsdom.js +233 -0
  131. package/dist/workspace/browser-workspace-jsdom.js.map +1 -0
  132. package/dist/workspace/browser-workspace-network.d.ts +7 -0
  133. package/dist/workspace/browser-workspace-network.d.ts.map +1 -0
  134. package/dist/workspace/browser-workspace-network.js +145 -0
  135. package/dist/workspace/browser-workspace-network.js.map +1 -0
  136. package/dist/workspace/browser-workspace-snapshots.d.ts +14 -0
  137. package/dist/workspace/browser-workspace-snapshots.d.ts.map +1 -0
  138. package/dist/workspace/browser-workspace-snapshots.js +144 -0
  139. package/dist/workspace/browser-workspace-snapshots.js.map +1 -0
  140. package/dist/workspace/browser-workspace-state.d.ts +24 -0
  141. package/dist/workspace/browser-workspace-state.d.ts.map +1 -0
  142. package/dist/workspace/browser-workspace-state.js +155 -0
  143. package/dist/workspace/browser-workspace-state.js.map +1 -0
  144. package/dist/workspace/browser-workspace-types.d.ts +345 -0
  145. package/dist/workspace/browser-workspace-types.d.ts.map +1 -0
  146. package/dist/workspace/browser-workspace-types.js +11 -0
  147. package/dist/workspace/browser-workspace-types.js.map +1 -0
  148. package/dist/workspace/browser-workspace-web.d.ts +8 -0
  149. package/dist/workspace/browser-workspace-web.d.ts.map +1 -0
  150. package/dist/workspace/browser-workspace-web.js +1342 -0
  151. package/dist/workspace/browser-workspace-web.js.map +1 -0
  152. package/dist/workspace/browser-workspace.d.ts +39 -0
  153. package/dist/workspace/browser-workspace.d.ts.map +1 -0
  154. package/dist/workspace/browser-workspace.js +958 -0
  155. package/dist/workspace/browser-workspace.js.map +1 -0
  156. package/dist/workspace/index.d.ts +26 -0
  157. package/dist/workspace/index.d.ts.map +1 -0
  158. package/dist/workspace/index.js +3 -0
  159. package/dist/workspace/index.js.map +1 -0
  160. package/dist/workspace.d.ts +2 -0
  161. package/dist/workspace.d.ts.map +1 -0
  162. package/dist/workspace.js +2 -0
  163. package/dist/workspace.js.map +1 -0
  164. package/package.json +71 -110
  165. package/dist/actions/click.d.ts +0 -3
  166. package/dist/actions/click.d.ts.map +0 -1
  167. package/dist/actions/click.js +0 -158
  168. package/dist/actions/click.js.map +0 -1
  169. package/dist/actions/extract.d.ts +0 -3
  170. package/dist/actions/extract.d.ts.map +0 -1
  171. package/dist/actions/extract.js +0 -168
  172. package/dist/actions/extract.js.map +0 -1
  173. package/dist/actions/index.d.ts +0 -7
  174. package/dist/actions/index.d.ts.map +0 -1
  175. package/dist/actions/index.js +0 -7
  176. package/dist/actions/index.js.map +0 -1
  177. package/dist/actions/navigate.d.ts +0 -3
  178. package/dist/actions/navigate.d.ts.map +0 -1
  179. package/dist/actions/navigate.js +0 -187
  180. package/dist/actions/navigate.js.map +0 -1
  181. package/dist/actions/screenshot.d.ts +0 -3
  182. package/dist/actions/screenshot.d.ts.map +0 -1
  183. package/dist/actions/screenshot.js +0 -167
  184. package/dist/actions/screenshot.js.map +0 -1
  185. package/dist/actions/select.d.ts +0 -3
  186. package/dist/actions/select.d.ts.map +0 -1
  187. package/dist/actions/select.js +0 -167
  188. package/dist/actions/select.js.map +0 -1
  189. package/dist/actions/type.d.ts +0 -3
  190. package/dist/actions/type.d.ts.map +0 -1
  191. package/dist/actions/type.js +0 -167
  192. package/dist/actions/type.js.map +0 -1
  193. package/dist/cli/index.d.ts +0 -8
  194. package/dist/cli/index.d.ts.map +0 -1
  195. package/dist/cli/index.js +0 -13
  196. package/dist/cli/index.js.map +0 -1
  197. package/dist/cli/register.d.ts +0 -20
  198. package/dist/cli/register.d.ts.map +0 -1
  199. package/dist/cli/register.js +0 -403
  200. package/dist/cli/register.js.map +0 -1
  201. package/dist/providerRelevance.d.ts +0 -4
  202. package/dist/providerRelevance.d.ts.map +0 -1
  203. package/dist/providerRelevance.js +0 -33
  204. package/dist/providerRelevance.js.map +0 -1
  205. package/dist/providers/browser-state.d.ts +0 -3
  206. package/dist/providers/browser-state.d.ts.map +0 -1
  207. package/dist/providers/browser-state.js +0 -72
  208. package/dist/providers/browser-state.js.map +0 -1
  209. package/dist/providers/index.d.ts +0 -2
  210. package/dist/providers/index.d.ts.map +0 -1
  211. package/dist/providers/index.js +0 -2
  212. package/dist/providers/index.js.map +0 -1
  213. package/dist/services/browser-service.d.ts +0 -32
  214. package/dist/services/browser-service.d.ts.map +0 -1
  215. package/dist/services/browser-service.js +0 -213
  216. package/dist/services/browser-service.js.map +0 -1
  217. package/dist/services/index.d.ts +0 -4
  218. package/dist/services/index.d.ts.map +0 -1
  219. package/dist/services/index.js +0 -4
  220. package/dist/services/index.js.map +0 -1
  221. package/dist/services/process-manager.d.ts +0 -24
  222. package/dist/services/process-manager.d.ts.map +0 -1
  223. package/dist/services/process-manager.js +0 -270
  224. package/dist/services/process-manager.js.map +0 -1
  225. package/dist/services/websocket-client.d.ts +0 -35
  226. package/dist/services/websocket-client.d.ts.map +0 -1
  227. package/dist/services/websocket-client.js +0 -221
  228. package/dist/services/websocket-client.js.map +0 -1
  229. package/dist/types.d.ts +0 -101
  230. package/dist/types.d.ts.map +0 -1
  231. package/dist/types.js +0 -2
  232. package/dist/types.js.map +0 -1
  233. package/dist/utils/captcha.d.ts +0 -33
  234. package/dist/utils/captcha.d.ts.map +0 -1
  235. package/dist/utils/captcha.js +0 -219
  236. package/dist/utils/captcha.js.map +0 -1
  237. package/dist/utils/errors.d.ts +0 -37
  238. package/dist/utils/errors.d.ts.map +0 -1
  239. package/dist/utils/errors.js +0 -81
  240. package/dist/utils/errors.js.map +0 -1
  241. package/dist/utils/index.d.ts +0 -5
  242. package/dist/utils/index.d.ts.map +0 -1
  243. package/dist/utils/index.js +0 -5
  244. package/dist/utils/index.js.map +0 -1
  245. package/dist/utils/retry.d.ts +0 -26
  246. package/dist/utils/retry.d.ts.map +0 -1
  247. package/dist/utils/retry.js +0 -55
  248. package/dist/utils/retry.js.map +0 -1
  249. package/dist/utils/security.d.ts +0 -27
  250. package/dist/utils/security.d.ts.map +0 -1
  251. package/dist/utils/security.js +0 -139
  252. package/dist/utils/security.js.map +0 -1
  253. package/dist/utils/url.d.ts +0 -12
  254. package/dist/utils/url.d.ts.map +0 -1
  255. package/dist/utils/url.js +0 -39
  256. package/dist/utils/url.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/routes/bridge.ts"],"sourcesContent":["/**\n * Agent Browser Bridge HTTP routes.\n *\n * Mounted under `/api/browser-bridge/*` by the plugin-collector. Pair +\n * settings + companion-sync + tabs + current-page + packaging endpoints\n * are fully generic. Session endpoints (confirm/progress/complete) still\n * operate on the LifeOps-owned `life_browser_sessions` table and therefore\n * call into the LifeOps route service because that app owns workflow-scoped\n * browser sessions.\n *\n * Companion/auto-pair/sync authentication uses the\n * `X-Browser-Bridge-Companion-Id` header paired with a bearer pairing\n * token. The old `X-LifeOps-Browser-Companion-Id` and legacy\n * `x-eliza-browser-companion-id` aliases were deliberately removed.\n */\n\nimport fs from \"node:fs\";\nimport type http from \"node:http\";\nimport type { ReadJsonBodyOptions } from \"@elizaos/core\";\nimport { type AgentRuntime, logger, type UUID } from \"@elizaos/core\";\nimport {\n BROWSER_BRIDGE_PACKAGE_PATH_TARGETS,\n type BrowserBridgeCompanionAuthErrorCode,\n type CreateBrowserBridgeCompanionAutoPairRequest,\n type CreateBrowserBridgeCompanionPairingRequest,\n type SyncBrowserBridgeStateRequest,\n type UpdateBrowserBridgeSessionProgressRequest,\n type UpdateBrowserBridgeSettingsRequest,\n} from \"../contracts.js\";\nimport type {\n CompleteLifeOpsBrowserSessionRequest,\n ConfirmLifeOpsBrowserSessionRequest,\n CreateLifeOpsBrowserSessionRequest,\n} from \"../lifeops-session-contracts.js\";\nimport {\n buildBrowserBridgeCompanionPackage,\n getBrowserBridgeCompanionDownloadFile,\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\nexport interface BrowserBridgeRouteContext {\n req: http.IncomingMessage;\n res: http.ServerResponse;\n method: string;\n pathname: string;\n url: URL;\n state: {\n runtime: AgentRuntime | null;\n adminEntityId: UUID | null;\n };\n json: (res: http.ServerResponse, data: unknown, status?: number) => void;\n error: (res: http.ServerResponse, message: string, status?: number) => void;\n readJsonBody: <T extends object>(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n options?: ReadJsonBodyOptions,\n ) => Promise<T | null>;\n decodePathComponent: (\n raw: string,\n res: http.ServerResponse,\n label: string,\n ) => string | null;\n}\n\nfunction getService(\n ctx: BrowserBridgeRouteContext,\n): BrowserBridgeRouteService | null {\n if (!ctx.state.runtime) {\n ctx.error(ctx.res, \"Agent runtime is not available\", 503);\n return null;\n }\n const service = ctx.state.runtime.getService<BrowserBridgeRouteService>(\n BROWSER_BRIDGE_ROUTE_SERVICE_TYPE,\n );\n if (!service) {\n ctx.error(ctx.res, \"Browser Bridge service is not available\", 503);\n return null;\n }\n return service;\n}\n\nfunction getBrowserCompanionAuth(\n ctx: BrowserBridgeRouteContext,\n): { companionId: string; pairingToken: string } | null {\n const companionHeader = ctx.req.headers[\"x-browser-bridge-companion-id\"];\n const companionId =\n typeof companionHeader === \"string\" ? companionHeader.trim() : \"\";\n if (!companionId) {\n routeJsonError(\n ctx,\n \"Missing X-Browser-Bridge-Companion-Id header\",\n 401,\n \"browser_bridge_companion_auth_missing_id\",\n );\n return null;\n }\n const authHeader =\n typeof ctx.req.headers.authorization === \"string\"\n ? ctx.req.headers.authorization.trim()\n : \"\";\n const match = /^Bearer\\s+(.+)$/i.exec(authHeader);\n const pairingToken = match?.[1]?.trim() ?? \"\";\n if (!pairingToken) {\n routeJsonError(\n ctx,\n \"Missing browser companion bearer token\",\n 401,\n \"browser_bridge_companion_auth_missing_token\",\n );\n return null;\n }\n return {\n companionId,\n pairingToken,\n };\n}\n\nfunction browserAutoPairOriginAllowed(ctx: BrowserBridgeRouteContext): boolean {\n const originHeader =\n typeof ctx.req.headers.origin === \"string\"\n ? ctx.req.headers.origin.trim()\n : \"\";\n if (!originHeader) {\n return requestIsLoopback(ctx);\n }\n if (originHeader === ctx.url.origin) {\n return true;\n }\n return (\n originHeader.startsWith(\"chrome-extension://\") ||\n originHeader.startsWith(\"safari-web-extension://\")\n );\n}\n\nfunction requestIsLoopback(ctx: BrowserBridgeRouteContext): boolean {\n const remoteAddress = ctx.req.socket.remoteAddress?.trim().toLowerCase();\n return (\n remoteAddress === \"127.0.0.1\" ||\n remoteAddress === \"::1\" ||\n remoteAddress === \"0:0:0:0:0:0:0:1\" ||\n remoteAddress === \"::ffff:127.0.0.1\" ||\n remoteAddress === \"::ffff:0:127.0.0.1\"\n );\n}\n\nconst BROWSER_BRIDGE_RATE_LIMITS = {\n default: { maxRequests: 60, windowMs: 60_000 },\n} satisfies Record<string, RateLimitConfig>;\n\ninterface RateLimitConfig {\n maxRequests: number;\n windowMs: number;\n}\n\ninterface RateLimitEntry {\n timestamps: number[];\n}\n\nconst rateLimitBuckets = new Map<string, RateLimitEntry>();\nconst RATE_LIMIT_CLEANUP_INTERVAL_MS = 5 * 60 * 1_000;\nlet lastRateLimitCleanup = Date.now();\n\nfunction cleanupRateLimitBuckets(windowMs: number): void {\n const now = Date.now();\n if (now - lastRateLimitCleanup < RATE_LIMIT_CLEANUP_INTERVAL_MS) return;\n lastRateLimitCleanup = now;\n const cutoff = now - windowMs;\n for (const [key, entry] of rateLimitBuckets) {\n entry.timestamps = entry.timestamps.filter(\n (timestamp) => timestamp > cutoff,\n );\n if (entry.timestamps.length === 0) rateLimitBuckets.delete(key);\n }\n}\n\nfunction checkBrowserBridgeRateLimit(\n key: string,\n config: RateLimitConfig,\n): { allowed: boolean; retryAfterMs: number } {\n const now = Date.now();\n cleanupRateLimitBuckets(config.windowMs);\n let entry = rateLimitBuckets.get(key);\n if (!entry) {\n entry = { timestamps: [] };\n rateLimitBuckets.set(key, entry);\n }\n\n const cutoff = now - config.windowMs;\n entry.timestamps = entry.timestamps.filter((timestamp) => timestamp > cutoff);\n\n if (entry.timestamps.length >= config.maxRequests) {\n const oldestInWindow = entry.timestamps[0];\n const retryAfterMs =\n oldestInWindow === undefined ? 0 : oldestInWindow + config.windowMs - now;\n return { allowed: false, retryAfterMs: Math.max(retryAfterMs, 0) };\n }\n\n entry.timestamps.push(now);\n return { allowed: true, retryAfterMs: 0 };\n}\n\nfunction rateLimitRequest(\n ctx: BrowserBridgeRouteContext,\n operation: string,\n): boolean {\n const agentId = String(ctx.state.runtime?.agentId ?? \"unknown\");\n const companionHeader = ctx.req.headers[\"x-browser-bridge-companion-id\"];\n const companionId =\n typeof companionHeader === \"string\" ? companionHeader.trim() : \"anonymous\";\n const remoteAddress = ctx.req.socket.remoteAddress?.trim() ?? \"unknown\";\n const limitKey = `${agentId}:${operation}:${remoteAddress}:${companionId}`;\n const config = BROWSER_BRIDGE_RATE_LIMITS.default;\n const { allowed, retryAfterMs } = checkBrowserBridgeRateLimit(\n limitKey,\n config,\n );\n if (!allowed) {\n ctx.res.writeHead(429, {\n \"Content-Type\": \"application/json\",\n \"Retry-After\": String(Math.ceil(retryAfterMs / 1_000)),\n });\n ctx.res.end(JSON.stringify({ error: \"Rate limit exceeded\", retryAfterMs }));\n return true;\n }\n return false;\n}\n\nfunction routeOperation(ctx: BrowserBridgeRouteContext): string {\n return `${ctx.method.toUpperCase()} ${ctx.pathname}`;\n}\n\ninterface BrowserBridgeTelemetrySpan {\n success: (args?: { statusCode?: number }) => void;\n failure: (args?: {\n statusCode?: number;\n error?: unknown;\n errorKind?: string;\n }) => void;\n}\n\nfunction sanitizeTelemetryToken(value: string | undefined): string | undefined {\n if (!value) return undefined;\n const token = value.toLowerCase().replace(/[^a-z0-9_-]/g, \"_\");\n const normalized = token.replace(/_+/g, \"_\").replace(/^_+|_+$/g, \"\");\n return normalized ? normalized.slice(0, 64) : undefined;\n}\n\nfunction inferTelemetryErrorKind(error: unknown): string | undefined {\n if (error instanceof Error) {\n const message = error.message.toLowerCase();\n if (\n error.name === \"AbortError\" ||\n error.name === \"TimeoutError\" ||\n message.includes(\"timeout\") ||\n message.includes(\"timed out\")\n ) {\n return \"timeout\";\n }\n return sanitizeTelemetryToken(error.name);\n }\n return typeof error === \"string\" ? sanitizeTelemetryToken(error) : undefined;\n}\n\nfunction createBrowserBridgeTelemetrySpan(meta: {\n boundary: \"browser-bridge\";\n operation: string;\n timeoutMs?: number;\n}): BrowserBridgeTelemetrySpan {\n const startedAt = Date.now();\n let settled = false;\n\n const finalize = (\n outcome: \"success\" | \"failure\",\n args?: { statusCode?: number; error?: unknown; errorKind?: string },\n ): void => {\n if (settled) return;\n settled = true;\n const event: Record<string, unknown> = {\n schema: \"integration_boundary_v1\",\n boundary: meta.boundary,\n operation: meta.operation,\n outcome,\n durationMs: Math.max(0, Date.now() - startedAt),\n };\n if (typeof meta.timeoutMs === \"number\") event.timeoutMs = meta.timeoutMs;\n if (typeof args?.statusCode === \"number\")\n event.statusCode = args.statusCode;\n if (outcome === \"failure\") {\n event.errorKind =\n sanitizeTelemetryToken(args?.errorKind) ??\n inferTelemetryErrorKind(args?.error);\n }\n const line = `[integration] ${JSON.stringify(event)}`;\n if (outcome === \"success\") {\n logger.info(line);\n } else {\n logger.warn(line);\n }\n };\n\n return {\n success: (args) => finalize(\"success\", args),\n failure: (args) => finalize(\"failure\", args),\n };\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction routeJsonError(\n ctx: BrowserBridgeRouteContext,\n message: string,\n status: number,\n code?: BrowserBridgeCompanionAuthErrorCode | string | null,\n): void {\n ctx.json(\n ctx.res,\n {\n error: message,\n ...(code ? { code } : {}),\n },\n status,\n );\n}\n\nfunction isBrowserBridgeRouteBodyObject(\n value: unknown,\n): value is Record<string, unknown> {\n return Boolean(value && typeof value === \"object\" && !Array.isArray(value));\n}\n\nfunction rejectMalformedBrowserBridgePayload(\n ctx: BrowserBridgeRouteContext,\n): true {\n ctx.error(ctx.res, \"request body must be a JSON object\", 400);\n return true;\n}\n\nfunction isStatusError(\n error: unknown,\n): error is Error & { readonly status: number } {\n return (\n error instanceof Error &&\n \"status\" in error &&\n typeof error.status === \"number\"\n );\n}\n\nfunction statusErrorCode(error: unknown): string | null {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n typeof (error as { code?: unknown }).code === \"string\"\n ) {\n return (error as { code: string }).code;\n }\n return null;\n}\n\nfunction decodeMatchedPathComponent(\n ctx: BrowserBridgeRouteContext,\n match: RegExpMatchArray | null,\n index: number,\n res: http.ServerResponse,\n label: string,\n): string | null {\n const raw = match?.[index];\n return raw ? ctx.decodePathComponent(raw, res, label) : null;\n}\n\nasync function runRoute(\n ctx: BrowserBridgeRouteContext,\n fn: (service: BrowserBridgeRouteService) => Promise<void>,\n): Promise<boolean> {\n const operation = routeOperation(ctx);\n const span = createBrowserBridgeTelemetrySpan({\n boundary: \"browser-bridge\",\n operation,\n });\n const service = getService(ctx);\n if (!service) {\n logger.info(\n {\n boundary: \"browser-bridge\",\n operation,\n statusCode: 503,\n },\n \"[browser-bridge] Route rejected because agent runtime is unavailable\",\n );\n span.failure({\n statusCode: 503,\n errorKind: \"runtime_unavailable\",\n });\n return true;\n }\n try {\n await fn(service);\n span.success({\n statusCode: ctx.res.statusCode >= 400 ? ctx.res.statusCode : 200,\n });\n return true;\n } catch (error) {\n if (isStatusError(error)) {\n const logFn =\n error.status === 401\n ? logger.debug.bind(logger)\n : logger.warn.bind(logger);\n logFn(\n {\n boundary: \"browser-bridge\",\n operation,\n statusCode: error.status,\n },\n `[browser-bridge] Route failed: ${error.message}`,\n );\n span.failure({\n statusCode: error.status,\n error,\n errorKind:\n error.status === 401\n ? \"browser_bridge_auth_invalid\"\n : \"browser_bridge_service_error\",\n });\n routeJsonError(ctx, error.message, error.status, statusErrorCode(error));\n return true;\n }\n logger.error(\n {\n boundary: \"browser-bridge\",\n operation,\n },\n `[browser-bridge] Route crashed: ${errorMessage(error)}`,\n );\n span.failure({\n error,\n errorKind: \"unhandled_error\",\n });\n throw error;\n }\n}\n\nasync function runStatelessRoute(\n ctx: BrowserBridgeRouteContext,\n fn: () => Promise<void>,\n): Promise<boolean> {\n const operation = routeOperation(ctx);\n const span = createBrowserBridgeTelemetrySpan({\n boundary: \"browser-bridge\",\n operation,\n });\n try {\n await fn();\n span.success({\n statusCode: ctx.res.statusCode >= 400 ? ctx.res.statusCode : 200,\n });\n return true;\n } catch (error) {\n if (isStatusError(error)) {\n logger.warn(\n {\n boundary: \"browser-bridge\",\n operation,\n statusCode: error.status,\n },\n `[browser-bridge] Route failed: ${error.message}`,\n );\n span.failure({\n statusCode: error.status,\n error,\n errorKind: \"browser_bridge_service_error\",\n });\n ctx.error(ctx.res, error.message, error.status);\n return true;\n }\n logger.error(\n {\n boundary: \"browser-bridge\",\n operation,\n },\n `[browser-bridge] Route crashed: ${errorMessage(error)}`,\n );\n span.failure({\n error,\n errorKind: \"unhandled_error\",\n });\n throw error;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Dispatcher\n// ---------------------------------------------------------------------------\n\nexport async function handleBrowserBridgeRoutes(\n ctx: BrowserBridgeRouteContext,\n): Promise<boolean> {\n const { req, res, method, pathname, json, readJsonBody } = ctx;\n\n if (method === \"GET\" && pathname === \"/api/browser-bridge/sessions\") {\n return runRoute(ctx, async (service) => {\n json(res, {\n sessions: await service.listBrowserSessions(ctx.state.adminEntityId),\n });\n });\n }\n\n if (method === \"GET\" && pathname === \"/api/browser-bridge/settings\") {\n return runRoute(ctx, async (service) => {\n json(res, {\n settings: await service.getBrowserSettings(ctx.state.adminEntityId),\n });\n });\n }\n\n if (method === \"POST\" && pathname === \"/api/browser-bridge/settings\") {\n const body = await readJsonBody<UpdateBrowserBridgeSettingsRequest>(\n req,\n res,\n );\n if (!body) return true;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n return rejectMalformedBrowserBridgePayload(ctx);\n }\n return runRoute(ctx, async (service) => {\n json(res, {\n settings: await service.updateBrowserSettings(\n body,\n ctx.state.adminEntityId,\n ),\n });\n });\n }\n\n if (method === \"POST\" && pathname === \"/api/browser-bridge/companions/pair\") {\n const body = await readJsonBody<CreateBrowserBridgeCompanionPairingRequest>(\n req,\n res,\n );\n if (!body) return true;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n return rejectMalformedBrowserBridgePayload(ctx);\n }\n return runRoute(ctx, async (service) => {\n json(\n res,\n await service.createBrowserCompanionPairing(\n body,\n ctx.state.adminEntityId,\n ),\n 201,\n );\n });\n }\n\n if (\n method === \"POST\" &&\n pathname === \"/api/browser-bridge/companions/auto-pair\"\n ) {\n if (rateLimitRequest(ctx, \"companions:auto-pair\")) {\n return true;\n }\n if (!browserAutoPairOriginAllowed(ctx)) {\n ctx.error(\n res,\n \"browser auto-pair must come from the agent app or a browser extension\",\n 403,\n );\n return true;\n }\n const body =\n await readJsonBody<CreateBrowserBridgeCompanionAutoPairRequest>(req, res);\n if (!body) return true;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n return rejectMalformedBrowserBridgePayload(ctx);\n }\n return runRoute(ctx, async (service) => {\n json(\n res,\n await service.autoPairBrowserCompanion(\n body,\n ctx.url.origin,\n ctx.state.adminEntityId,\n ),\n 201,\n );\n });\n }\n\n if (method === \"GET\" && pathname === \"/api/browser-bridge/companions\") {\n return runRoute(ctx, async (service) => {\n json(res, {\n companions: await service.listBrowserCompanions(\n ctx.state.adminEntityId,\n ),\n });\n });\n }\n\n if (\n method === \"POST\" &&\n pathname === \"/api/browser-bridge/companions/revoke\"\n ) {\n if (rateLimitRequest(ctx, \"companions:revoke\")) {\n return true;\n }\n return runRoute(ctx, async (service) => {\n const auth = getBrowserCompanionAuth(ctx);\n if (!auth) {\n return;\n }\n json(\n res,\n await service.revokeBrowserCompanionFromCompanion(\n auth.companionId,\n auth.pairingToken,\n ctx.state.adminEntityId,\n ),\n );\n });\n }\n\n const browserCompanionRevokeMatch = pathname.match(\n /^\\/api\\/browser-bridge\\/companions\\/([^/]+)\\/revoke$/,\n );\n if (method === \"POST\" && browserCompanionRevokeMatch) {\n const companionId = decodeMatchedPathComponent(\n ctx,\n browserCompanionRevokeMatch,\n 1,\n res,\n \"browser companion id\",\n );\n if (!companionId) return true;\n return runRoute(ctx, async (service) => {\n json(\n res,\n await service.revokeBrowserCompanion(\n companionId,\n ctx.state.adminEntityId,\n ),\n );\n });\n }\n\n if (method === \"GET\" && pathname === \"/api/browser-bridge/packages\") {\n return runStatelessRoute(ctx, async () => {\n json(res, { status: getBrowserBridgeCompanionPackageStatus() });\n });\n }\n\n if (\n method === \"POST\" &&\n pathname === \"/api/browser-bridge/packages/open-path\"\n ) {\n if (!requestIsLoopback(ctx)) {\n ctx.error(\n res,\n \"Local extension install helpers can only run on the same machine as the agent\",\n 403,\n );\n return true;\n }\n const body = await readJsonBody<{\n target?: string;\n revealOnly?: boolean;\n }>(req, res);\n if (!body) return true;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n return rejectMalformedBrowserBridgePayload(ctx);\n }\n if (\n typeof body.target !== \"string\" ||\n !BROWSER_BRIDGE_PACKAGE_PATH_TARGETS.includes(\n body.target as (typeof BROWSER_BRIDGE_PACKAGE_PATH_TARGETS)[number],\n )\n ) {\n ctx.error(\n res,\n `target must be one of: ${BROWSER_BRIDGE_PACKAGE_PATH_TARGETS.join(\", \")}`,\n 400,\n );\n return true;\n }\n const validatedTarget =\n body.target as (typeof BROWSER_BRIDGE_PACKAGE_PATH_TARGETS)[number];\n return runStatelessRoute(ctx, async () => {\n json(\n res,\n await openBrowserBridgeCompanionPackagePath(validatedTarget, {\n revealOnly: body.revealOnly === true,\n }),\n );\n });\n }\n\n if (method === \"POST\" && pathname === \"/api/browser-bridge/companions/sync\") {\n if (rateLimitRequest(ctx, \"companions:sync\")) {\n return true;\n }\n return runRoute(ctx, async (service) => {\n const auth = getBrowserCompanionAuth(ctx);\n if (!auth) {\n return;\n }\n const body = await readJsonBody<SyncBrowserBridgeStateRequest>(req, res);\n if (!body) return;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n rejectMalformedBrowserBridgePayload(ctx);\n return;\n }\n json(\n res,\n await service.syncBrowserCompanion(\n auth.companionId,\n auth.pairingToken,\n body,\n ctx.state.adminEntityId,\n ),\n );\n });\n }\n\n if (method === \"GET\" && pathname === \"/api/browser-bridge/tabs\") {\n return runRoute(ctx, async (service) => {\n json(res, {\n tabs: await service.listBrowserTabs(ctx.state.adminEntityId),\n });\n });\n }\n\n const browserPackageBuildMatch = pathname.match(\n /^\\/api\\/browser-bridge\\/packages\\/([^/]+)\\/build$/,\n );\n if (method === \"POST\" && browserPackageBuildMatch) {\n const browser = decodeMatchedPathComponent(\n ctx,\n browserPackageBuildMatch,\n 1,\n res,\n \"browser package target\",\n );\n if (!browser) return true;\n if (browser !== \"chrome\" && browser !== \"safari\") {\n ctx.error(res, \"browser must be chrome or safari\", 400);\n return true;\n }\n return runStatelessRoute(ctx, async () => {\n json(res, {\n status: await buildBrowserBridgeCompanionPackage(browser),\n });\n });\n }\n\n const browserPackageOpenManagerMatch = pathname.match(\n /^\\/api\\/browser-bridge\\/packages\\/([^/]+)\\/open-manager$/,\n );\n if (method === \"POST\" && browserPackageOpenManagerMatch) {\n if (!requestIsLoopback(ctx)) {\n ctx.error(\n res,\n \"Local extension install helpers can only run on the same machine as the agent\",\n 403,\n );\n return true;\n }\n const browser = decodeMatchedPathComponent(\n ctx,\n browserPackageOpenManagerMatch,\n 1,\n res,\n \"browser package target\",\n );\n if (!browser) return true;\n if (browser !== \"chrome\" && browser !== \"safari\") {\n ctx.error(res, \"browser must be chrome or safari\", 400);\n return true;\n }\n return runStatelessRoute(ctx, async () => {\n json(res, await openBrowserBridgeCompanionManager(browser));\n });\n }\n\n const browserPackageDownloadMatch = pathname.match(\n /^\\/api\\/browser-bridge\\/packages\\/([^/]+)\\/download$/,\n );\n if (method === \"GET\" && browserPackageDownloadMatch) {\n const browser = decodeMatchedPathComponent(\n ctx,\n browserPackageDownloadMatch,\n 1,\n res,\n \"browser package target\",\n );\n if (!browser) return true;\n if (browser !== \"chrome\" && browser !== \"safari\") {\n ctx.error(res, \"browser must be chrome or safari\", 400);\n return true;\n }\n return runStatelessRoute(ctx, async () => {\n const artifact = getBrowserBridgeCompanionDownloadFile(browser);\n res.statusCode = 200;\n res.setHeader(\"Content-Type\", artifact.contentType);\n res.setHeader(\n \"Content-Disposition\",\n `attachment; filename=\"${artifact.filename}\"`,\n );\n await new Promise<void>((resolve, reject) => {\n const stream = fs.createReadStream(artifact.path);\n stream.on(\"error\", reject);\n res.on(\"error\", reject);\n stream.on(\"end\", resolve);\n stream.pipe(res);\n });\n });\n }\n\n if (method === \"GET\" && pathname === \"/api/browser-bridge/current-page\") {\n return runRoute(ctx, async (service) => {\n json(res, {\n page: await service.getCurrentBrowserPage(ctx.state.adminEntityId),\n });\n });\n }\n\n if (method === \"POST\" && pathname === \"/api/browser-bridge/sync\") {\n const body = await readJsonBody<SyncBrowserBridgeStateRequest>(req, res);\n if (!body) return true;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n return rejectMalformedBrowserBridgePayload(ctx);\n }\n return runRoute(ctx, async (service) => {\n json(res, await service.syncBrowserState(body, ctx.state.adminEntityId));\n });\n }\n\n if (method === \"POST\" && pathname === \"/api/browser-bridge/sessions\") {\n const body = await readJsonBody<CreateLifeOpsBrowserSessionRequest>(\n req,\n res,\n );\n if (!body) return true;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n return rejectMalformedBrowserBridgePayload(ctx);\n }\n return runRoute(ctx, async (service) => {\n json(\n res,\n {\n session: await service.createBrowserSession(\n body,\n ctx.state.adminEntityId,\n ),\n },\n 201,\n );\n });\n }\n\n const browserSessionMatch = pathname.match(\n /^\\/api\\/browser-bridge\\/sessions\\/([^/]+)$/,\n );\n if (browserSessionMatch) {\n const sessionId = decodeMatchedPathComponent(\n ctx,\n browserSessionMatch,\n 1,\n res,\n \"browser session id\",\n );\n if (!sessionId) return true;\n if (method === \"GET\") {\n return runRoute(ctx, async (service) => {\n json(res, {\n session: await service.getBrowserSession(\n sessionId,\n ctx.state.adminEntityId,\n ),\n });\n });\n }\n }\n\n const browserConfirmMatch = pathname.match(\n /^\\/api\\/browser-bridge\\/sessions\\/([^/]+)\\/confirm$/,\n );\n if (method === \"POST\" && browserConfirmMatch) {\n const sessionId = decodeMatchedPathComponent(\n ctx,\n browserConfirmMatch,\n 1,\n res,\n \"browser session id\",\n );\n if (!sessionId) return true;\n const body = await readJsonBody<ConfirmLifeOpsBrowserSessionRequest>(\n req,\n res,\n );\n if (!body) return true;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n return rejectMalformedBrowserBridgePayload(ctx);\n }\n return runRoute(ctx, async (service) => {\n json(res, {\n session: await service.confirmBrowserSession(\n sessionId,\n body,\n ctx.state.adminEntityId,\n ),\n });\n });\n }\n\n const browserProgressMatch = pathname.match(\n /^\\/api\\/browser-bridge\\/sessions\\/([^/]+)\\/progress$/,\n );\n if (method === \"POST\" && browserProgressMatch) {\n const sessionId = decodeMatchedPathComponent(\n ctx,\n browserProgressMatch,\n 1,\n res,\n \"browser session id\",\n );\n if (!sessionId) return true;\n const body = await readJsonBody<UpdateBrowserBridgeSessionProgressRequest>(\n req,\n res,\n );\n if (!body) return true;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n return rejectMalformedBrowserBridgePayload(ctx);\n }\n return runRoute(ctx, async (service) => {\n json(res, {\n session: await service.updateBrowserSessionProgress(\n sessionId,\n body,\n ctx.state.adminEntityId,\n ),\n });\n });\n }\n\n const browserCompleteMatch = pathname.match(\n /^\\/api\\/browser-bridge\\/sessions\\/([^/]+)\\/complete$/,\n );\n if (method === \"POST\" && browserCompleteMatch) {\n const sessionId = decodeMatchedPathComponent(\n ctx,\n browserCompleteMatch,\n 1,\n res,\n \"browser session id\",\n );\n if (!sessionId) return true;\n const body = await readJsonBody<CompleteLifeOpsBrowserSessionRequest>(\n req,\n res,\n );\n if (!body) return true;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n return rejectMalformedBrowserBridgePayload(ctx);\n }\n return runRoute(ctx, async (service) => {\n json(res, {\n session: await service.completeBrowserSession(\n sessionId,\n body,\n ctx.state.adminEntityId,\n ),\n });\n });\n }\n\n const browserCompanionProgressMatch = pathname.match(\n /^\\/api\\/browser-bridge\\/companions\\/sessions\\/([^/]+)\\/progress$/,\n );\n if (method === \"POST\" && browserCompanionProgressMatch) {\n if (rateLimitRequest(ctx, \"companions:session-progress\")) {\n return true;\n }\n const sessionId = decodeMatchedPathComponent(\n ctx,\n browserCompanionProgressMatch,\n 1,\n res,\n \"browser session id\",\n );\n if (!sessionId) return true;\n return runRoute(ctx, async (service) => {\n const auth = getBrowserCompanionAuth(ctx);\n if (!auth) {\n return;\n }\n const body = await readJsonBody<UpdateBrowserBridgeSessionProgressRequest>(\n req,\n res,\n );\n if (!body) return;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n rejectMalformedBrowserBridgePayload(ctx);\n return;\n }\n json(res, {\n session: await service.updateBrowserSessionProgressFromCompanion(\n auth.companionId,\n auth.pairingToken,\n sessionId,\n body,\n ctx.state.adminEntityId,\n ),\n });\n });\n }\n\n const browserCompanionCompleteMatch = pathname.match(\n /^\\/api\\/browser-bridge\\/companions\\/sessions\\/([^/]+)\\/complete$/,\n );\n if (method === \"POST\" && browserCompanionCompleteMatch) {\n if (rateLimitRequest(ctx, \"companions:session-complete\")) {\n return true;\n }\n const sessionId = decodeMatchedPathComponent(\n ctx,\n browserCompanionCompleteMatch,\n 1,\n res,\n \"browser session id\",\n );\n if (!sessionId) return true;\n return runRoute(ctx, async (service) => {\n const auth = getBrowserCompanionAuth(ctx);\n if (!auth) {\n return;\n }\n const body = await readJsonBody<CompleteLifeOpsBrowserSessionRequest>(\n req,\n res,\n );\n if (!body) return;\n if (!isBrowserBridgeRouteBodyObject(body)) {\n rejectMalformedBrowserBridgePayload(ctx);\n return;\n }\n json(res, {\n session: await service.completeBrowserSessionFromCompanion(\n auth.companionId,\n auth.pairingToken,\n sessionId,\n body,\n ctx.state.adminEntityId,\n ),\n });\n });\n }\n\n return false;\n}\n\nexport { rateLimitRequest };\n"],"mappings":"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","names":[]}
@@ -0,0 +1,29 @@
1
+ import { type ConnectorAccount, type IAgentRuntime, type PrivacyLevel } from "@elizaos/core";
2
+ import type { BrowserWorkspaceCommand } from "../workspace/browser-workspace-types.js";
3
+ export declare class BrowserWorkspaceConnectorAccountGateError extends Error {
4
+ readonly status: number;
5
+ readonly code: string;
6
+ constructor(message: string, status: number, code: string);
7
+ }
8
+ export interface BrowserWorkspaceConnectorAccountGateRequest {
9
+ runtime?: IAgentRuntime | null;
10
+ connectorProvider?: string | null;
11
+ connectorAccountId?: string | null;
12
+ partition?: string | null;
13
+ operation?: string;
14
+ }
15
+ export interface BrowserWorkspaceConnectorAccountGateResult {
16
+ account: ConnectorAccount;
17
+ accountId: string;
18
+ expectedPartition: string;
19
+ partition: string | null;
20
+ privacy: PrivacyLevel;
21
+ provider: string;
22
+ }
23
+ export declare function assertBrowserWorkspaceConnectorAccountGate(request: BrowserWorkspaceConnectorAccountGateRequest): Promise<BrowserWorkspaceConnectorAccountGateResult | null>;
24
+ export declare function assertBrowserWorkspaceCommandConnectorAccountGate(args: {
25
+ runtime?: IAgentRuntime | null;
26
+ command: BrowserWorkspaceCommand;
27
+ operation?: string;
28
+ }): Promise<void>;
29
+ //# sourceMappingURL=workspace-account-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-account-gate.d.ts","sourceRoot":"","sources":["../../src/routes/workspace-account-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EAMrB,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAKvB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAmBvF,qBAAa,yCAA0C,SAAQ,KAAK;IAClE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAM1D;AAED,MAAM,WAAW,2CAA2C;IAC1D,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,0CAA0C;IACzD,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,YAAY,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAwBD,wBAAsB,0CAA0C,CAC9D,OAAO,EAAE,2CAA2C,GACnD,OAAO,CAAC,0CAA0C,GAAG,IAAI,CAAC,CAqF5D;AAED,wBAAsB,iDAAiD,CAAC,IAAI,EAAE;IAC5E,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,uBAAuB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBhB"}
@@ -0,0 +1,147 @@
1
+ import {
2
+ getAccountPrivacy,
3
+ getConnectorAccountManager
4
+ } from "@elizaos/core";
5
+ import {
6
+ isConnectorBrowserWorkspacePartition,
7
+ resolveConnectorBrowserWorkspacePartition
8
+ } from "../workspace/browser-workspace-helpers.js";
9
+ const BROWSER_WORKSPACE_CONNECTOR_ROLES = [
10
+ "OWNER",
11
+ "AGENT",
12
+ "TEAM"
13
+ ];
14
+ const BROWSER_WORKSPACE_CONNECTOR_STATUSES = [
15
+ "connected"
16
+ ];
17
+ const BROWSER_WORKSPACE_CONNECTOR_ACCESS_GATES = [
18
+ "open",
19
+ "owner_binding"
20
+ ];
21
+ const BROWSER_WORKSPACE_CONNECTOR_PRIVACY_LEVELS = [
22
+ "owner_only",
23
+ "team_visible"
24
+ ];
25
+ class BrowserWorkspaceConnectorAccountGateError extends Error {
26
+ status;
27
+ code;
28
+ constructor(message, status, code) {
29
+ super(message);
30
+ this.name = "BrowserWorkspaceConnectorAccountGateError";
31
+ this.status = status;
32
+ this.code = code;
33
+ }
34
+ }
35
+ function cleanString(value) {
36
+ return typeof value === "string" ? value.trim() : "";
37
+ }
38
+ function gateError(message, status, code) {
39
+ return new BrowserWorkspaceConnectorAccountGateError(message, status, code);
40
+ }
41
+ function connectorReferenceRequested(request) {
42
+ return Boolean(
43
+ cleanString(request.connectorProvider) || cleanString(request.connectorAccountId) || isConnectorBrowserWorkspacePartition(request.partition)
44
+ );
45
+ }
46
+ async function assertBrowserWorkspaceConnectorAccountGate(request) {
47
+ if (!connectorReferenceRequested(request)) {
48
+ return null;
49
+ }
50
+ const provider = cleanString(request.connectorProvider).toLowerCase();
51
+ const accountId = cleanString(request.connectorAccountId);
52
+ const partition = cleanString(request.partition);
53
+ const operation = request.operation ?? "browser workspace";
54
+ if (!provider || !accountId) {
55
+ throw gateError(
56
+ `Connector ${operation} requires connectorProvider and connectorAccountId.`,
57
+ 400,
58
+ "browser_workspace_connector_account_required"
59
+ );
60
+ }
61
+ const runtime = request.runtime ?? null;
62
+ if (!runtime) {
63
+ throw gateError(
64
+ `Connector ${operation} requires an active agent runtime for account validation.`,
65
+ 503,
66
+ "browser_workspace_connector_runtime_unavailable"
67
+ );
68
+ }
69
+ const manager = getConnectorAccountManager(runtime);
70
+ const account = await manager.getAccount(provider, accountId);
71
+ if (!account) {
72
+ throw gateError(
73
+ `Connector account not found: ${provider}/${accountId}.`,
74
+ 404,
75
+ "browser_workspace_connector_account_not_found"
76
+ );
77
+ }
78
+ const policy = await manager.evaluatePolicy(
79
+ {
80
+ provider,
81
+ roles: BROWSER_WORKSPACE_CONNECTOR_ROLES,
82
+ statuses: BROWSER_WORKSPACE_CONNECTOR_STATUSES,
83
+ accessGates: BROWSER_WORKSPACE_CONNECTOR_ACCESS_GATES,
84
+ required: true
85
+ },
86
+ { accountId }
87
+ );
88
+ if (!policy.allowed) {
89
+ throw gateError(
90
+ policy.reason ?? `Connector account ${provider}/${accountId} is not allowed for ${operation}.`,
91
+ 403,
92
+ "browser_workspace_connector_account_denied"
93
+ );
94
+ }
95
+ const privacy = getAccountPrivacy(account);
96
+ if (!BROWSER_WORKSPACE_CONNECTOR_PRIVACY_LEVELS.includes(privacy)) {
97
+ throw gateError(
98
+ `Connector account ${provider}/${accountId} privacy ${privacy} is not allowed for ${operation}.`,
99
+ 403,
100
+ "browser_workspace_connector_account_privacy_denied"
101
+ );
102
+ }
103
+ const expectedPartition = resolveConnectorBrowserWorkspacePartition(
104
+ provider,
105
+ accountId
106
+ );
107
+ if (partition && partition !== expectedPartition) {
108
+ throw gateError(
109
+ `Connector ${operation} partition does not match connector account ${provider}/${accountId}.`,
110
+ 403,
111
+ "browser_workspace_connector_partition_mismatch"
112
+ );
113
+ }
114
+ return {
115
+ account,
116
+ accountId,
117
+ expectedPartition,
118
+ partition: partition || null,
119
+ privacy,
120
+ provider
121
+ };
122
+ }
123
+ async function assertBrowserWorkspaceCommandConnectorAccountGate(args) {
124
+ await assertBrowserWorkspaceConnectorAccountGate({
125
+ runtime: args.runtime,
126
+ connectorProvider: args.command.connectorProvider,
127
+ connectorAccountId: args.command.connectorAccountId,
128
+ partition: args.command.partition,
129
+ operation: args.operation ?? `command ${args.command.subaction}`
130
+ });
131
+ if (args.command.subaction !== "batch" || !Array.isArray(args.command.steps)) {
132
+ return;
133
+ }
134
+ for (const step of args.command.steps) {
135
+ await assertBrowserWorkspaceCommandConnectorAccountGate({
136
+ runtime: args.runtime,
137
+ command: step,
138
+ operation: `batch command ${step.subaction}`
139
+ });
140
+ }
141
+ }
142
+ export {
143
+ BrowserWorkspaceConnectorAccountGateError,
144
+ assertBrowserWorkspaceCommandConnectorAccountGate,
145
+ assertBrowserWorkspaceConnectorAccountGate
146
+ };
147
+ //# sourceMappingURL=workspace-account-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/routes/workspace-account-gate.ts"],"sourcesContent":["import {\n type ConnectorAccount,\n type ConnectorAccountAccessGate,\n type ConnectorAccountRole,\n type ConnectorAccountStatus,\n getAccountPrivacy,\n getConnectorAccountManager,\n type IAgentRuntime,\n type PrivacyLevel,\n} from \"@elizaos/core\";\nimport {\n isConnectorBrowserWorkspacePartition,\n resolveConnectorBrowserWorkspacePartition,\n} from \"../workspace/browser-workspace-helpers.js\";\nimport type { BrowserWorkspaceCommand } from \"../workspace/browser-workspace-types.js\";\n\nconst BROWSER_WORKSPACE_CONNECTOR_ROLES: ConnectorAccountRole[] = [\n \"OWNER\",\n \"AGENT\",\n \"TEAM\",\n];\nconst BROWSER_WORKSPACE_CONNECTOR_STATUSES: ConnectorAccountStatus[] = [\n \"connected\",\n];\nconst BROWSER_WORKSPACE_CONNECTOR_ACCESS_GATES: ConnectorAccountAccessGate[] = [\n \"open\",\n \"owner_binding\",\n];\nconst BROWSER_WORKSPACE_CONNECTOR_PRIVACY_LEVELS: PrivacyLevel[] = [\n \"owner_only\",\n \"team_visible\",\n];\n\nexport class BrowserWorkspaceConnectorAccountGateError extends Error {\n readonly status: number;\n readonly code: string;\n\n constructor(message: string, status: number, code: string) {\n super(message);\n this.name = \"BrowserWorkspaceConnectorAccountGateError\";\n this.status = status;\n this.code = code;\n }\n}\n\nexport interface BrowserWorkspaceConnectorAccountGateRequest {\n runtime?: IAgentRuntime | null;\n connectorProvider?: string | null;\n connectorAccountId?: string | null;\n partition?: string | null;\n operation?: string;\n}\n\nexport interface BrowserWorkspaceConnectorAccountGateResult {\n account: ConnectorAccount;\n accountId: string;\n expectedPartition: string;\n partition: string | null;\n privacy: PrivacyLevel;\n provider: string;\n}\n\nfunction cleanString(value: string | null | undefined): string {\n return typeof value === \"string\" ? value.trim() : \"\";\n}\n\nfunction gateError(\n message: string,\n status: number,\n code: string,\n): BrowserWorkspaceConnectorAccountGateError {\n return new BrowserWorkspaceConnectorAccountGateError(message, status, code);\n}\n\nfunction connectorReferenceRequested(\n request: BrowserWorkspaceConnectorAccountGateRequest,\n): boolean {\n return Boolean(\n cleanString(request.connectorProvider) ||\n cleanString(request.connectorAccountId) ||\n isConnectorBrowserWorkspacePartition(request.partition),\n );\n}\n\nexport async function assertBrowserWorkspaceConnectorAccountGate(\n request: BrowserWorkspaceConnectorAccountGateRequest,\n): Promise<BrowserWorkspaceConnectorAccountGateResult | null> {\n if (!connectorReferenceRequested(request)) {\n return null;\n }\n\n const provider = cleanString(request.connectorProvider).toLowerCase();\n const accountId = cleanString(request.connectorAccountId);\n const partition = cleanString(request.partition);\n const operation = request.operation ?? \"browser workspace\";\n\n if (!provider || !accountId) {\n throw gateError(\n `Connector ${operation} requires connectorProvider and connectorAccountId.`,\n 400,\n \"browser_workspace_connector_account_required\",\n );\n }\n\n const runtime = request.runtime ?? null;\n if (!runtime) {\n throw gateError(\n `Connector ${operation} requires an active agent runtime for account validation.`,\n 503,\n \"browser_workspace_connector_runtime_unavailable\",\n );\n }\n\n const manager = getConnectorAccountManager(runtime);\n const account = await manager.getAccount(provider, accountId);\n if (!account) {\n throw gateError(\n `Connector account not found: ${provider}/${accountId}.`,\n 404,\n \"browser_workspace_connector_account_not_found\",\n );\n }\n\n const policy = await manager.evaluatePolicy(\n {\n provider,\n roles: BROWSER_WORKSPACE_CONNECTOR_ROLES,\n statuses: BROWSER_WORKSPACE_CONNECTOR_STATUSES,\n accessGates: BROWSER_WORKSPACE_CONNECTOR_ACCESS_GATES,\n required: true,\n },\n { accountId },\n );\n if (!policy.allowed) {\n throw gateError(\n policy.reason ??\n `Connector account ${provider}/${accountId} is not allowed for ${operation}.`,\n 403,\n \"browser_workspace_connector_account_denied\",\n );\n }\n\n const privacy = getAccountPrivacy(account);\n if (!BROWSER_WORKSPACE_CONNECTOR_PRIVACY_LEVELS.includes(privacy)) {\n throw gateError(\n `Connector account ${provider}/${accountId} privacy ${privacy} is not allowed for ${operation}.`,\n 403,\n \"browser_workspace_connector_account_privacy_denied\",\n );\n }\n\n const expectedPartition = resolveConnectorBrowserWorkspacePartition(\n provider,\n accountId,\n );\n if (partition && partition !== expectedPartition) {\n throw gateError(\n `Connector ${operation} partition does not match connector account ${provider}/${accountId}.`,\n 403,\n \"browser_workspace_connector_partition_mismatch\",\n );\n }\n\n return {\n account,\n accountId,\n expectedPartition,\n partition: partition || null,\n privacy,\n provider,\n };\n}\n\nexport async function assertBrowserWorkspaceCommandConnectorAccountGate(args: {\n runtime?: IAgentRuntime | null;\n command: BrowserWorkspaceCommand;\n operation?: string;\n}): Promise<void> {\n await assertBrowserWorkspaceConnectorAccountGate({\n runtime: args.runtime,\n connectorProvider: args.command.connectorProvider,\n connectorAccountId: args.command.connectorAccountId,\n partition: args.command.partition,\n operation: args.operation ?? `command ${args.command.subaction}`,\n });\n\n if (\n args.command.subaction !== \"batch\" ||\n !Array.isArray(args.command.steps)\n ) {\n return;\n }\n\n for (const step of args.command.steps) {\n await assertBrowserWorkspaceCommandConnectorAccountGate({\n runtime: args.runtime,\n command: step,\n operation: `batch command ${step.subaction}`,\n });\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Browser workspace HTTP routes — Plugin route registration.
3
+ *
4
+ * Mounts the legacy `/api/browser-workspace/*` paths through `Plugin.routes`
5
+ * with `rawPath: true` so they keep their absolute paths under the runtime
6
+ * route registry (no `/<pluginName>/` prefix).
7
+ */
8
+ import type { Route } from "@elizaos/core";
9
+ export declare const browserWorkspaceRoutes: Route[];
10
+ //# sourceMappingURL=workspace-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-setup.d.ts","sourceRoot":"","sources":["../../src/routes/workspace-setup.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAqC,KAAK,EAAE,MAAM,eAAe,CAAC;AAsE9E,eAAO,MAAM,sBAAsB,EAAE,KAAK,EASvC,CAAC"}
@@ -0,0 +1,65 @@
1
+ import { TLSSocket } from "node:tls";
2
+ import {
3
+ readJsonBody as httpReadJsonBody,
4
+ sendJson as httpSendJson,
5
+ sendJsonError as httpSendJsonError
6
+ } from "@elizaos/core";
7
+ import {
8
+ BROWSER_WORKSPACE_ROUTE_PATHS,
9
+ handleBrowserWorkspaceRoutes
10
+ } from "./workspace.js";
11
+ function json(res, data, status = 200) {
12
+ httpSendJson(res, data, status);
13
+ }
14
+ function error(res, message, status = 400) {
15
+ httpSendJsonError(res, message, status);
16
+ }
17
+ function firstHeaderValue(value) {
18
+ if (Array.isArray(value)) {
19
+ return firstHeaderValue(value[0]);
20
+ }
21
+ if (typeof value !== "string") {
22
+ return null;
23
+ }
24
+ const normalized = value.split(",")[0]?.trim();
25
+ return normalized ? normalized : null;
26
+ }
27
+ function requestBaseUrl(req) {
28
+ const headers = req.headers ?? {};
29
+ const protocol = firstHeaderValue(headers["x-forwarded-proto"]) ?? (req.socket instanceof TLSSocket && req.socket.encrypted ? "https" : "http");
30
+ const host = firstHeaderValue(headers["x-forwarded-host"]) ?? firstHeaderValue(headers.host) ?? "localhost";
31
+ return `${protocol}://${host}`;
32
+ }
33
+ function browserWorkspaceRouteHandler() {
34
+ return async (req, res, runtime) => {
35
+ const httpReq = req;
36
+ const httpRes = res;
37
+ const method = (httpReq.method ?? "GET").toUpperCase();
38
+ const url = new URL(httpReq.url ?? "/", requestBaseUrl(httpReq));
39
+ await handleBrowserWorkspaceRoutes({
40
+ req: httpReq,
41
+ res: httpRes,
42
+ method,
43
+ pathname: url.pathname,
44
+ url,
45
+ state: {
46
+ runtime: runtime ?? null
47
+ },
48
+ readJsonBody: httpReadJsonBody,
49
+ json,
50
+ error
51
+ });
52
+ };
53
+ }
54
+ const browserWorkspaceRoutes = BROWSER_WORKSPACE_ROUTE_PATHS.map(
55
+ (r) => ({
56
+ type: r.type,
57
+ path: r.path,
58
+ rawPath: true,
59
+ handler: browserWorkspaceRouteHandler()
60
+ })
61
+ );
62
+ export {
63
+ browserWorkspaceRoutes
64
+ };
65
+ //# sourceMappingURL=workspace-setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/routes/workspace-setup.ts"],"sourcesContent":["/**\n * Browser workspace HTTP routes — Plugin route registration.\n *\n * Mounts the legacy `/api/browser-workspace/*` paths through `Plugin.routes`\n * with `rawPath: true` so they keep their absolute paths under the runtime\n * route registry (no `/<pluginName>/` prefix).\n */\n\nimport type http from \"node:http\";\nimport { TLSSocket } from \"node:tls\";\nimport type { IAgentRuntime, LegacyRouteHandler, Route } from \"@elizaos/core\";\nimport {\n readJsonBody as httpReadJsonBody,\n sendJson as httpSendJson,\n sendJsonError as httpSendJsonError,\n} from \"@elizaos/core\";\nimport {\n BROWSER_WORKSPACE_ROUTE_PATHS,\n handleBrowserWorkspaceRoutes,\n} from \"./workspace.js\";\n\nfunction json(res: http.ServerResponse, data: unknown, status = 200): void {\n httpSendJson(res, data, status);\n}\n\nfunction error(res: http.ServerResponse, message: string, status = 400): void {\n httpSendJsonError(res, message, status);\n}\n\nfunction firstHeaderValue(value: string | string[] | undefined): string | null {\n if (Array.isArray(value)) {\n return firstHeaderValue(value[0]);\n }\n if (typeof value !== \"string\") {\n return null;\n }\n const normalized = value.split(\",\")[0]?.trim();\n return normalized ? normalized : null;\n}\n\nfunction requestBaseUrl(req: http.IncomingMessage): string {\n const headers = req.headers ?? {};\n const protocol =\n firstHeaderValue(headers[\"x-forwarded-proto\"]) ??\n (req.socket instanceof TLSSocket && req.socket.encrypted\n ? \"https\"\n : \"http\");\n const host =\n firstHeaderValue(headers[\"x-forwarded-host\"]) ??\n firstHeaderValue(headers.host) ??\n \"localhost\";\n return `${protocol}://${host}`;\n}\n\nfunction browserWorkspaceRouteHandler(): LegacyRouteHandler {\n return async (\n req: unknown,\n res: unknown,\n runtime: unknown,\n ): Promise<void> => {\n const httpReq = req as http.IncomingMessage;\n const httpRes = res as http.ServerResponse;\n const method = (httpReq.method ?? \"GET\").toUpperCase();\n const url = new URL(httpReq.url ?? \"/\", requestBaseUrl(httpReq));\n await handleBrowserWorkspaceRoutes({\n req: httpReq,\n res: httpRes,\n method,\n pathname: url.pathname,\n url,\n state: {\n runtime: (runtime as IAgentRuntime) ?? null,\n },\n readJsonBody: httpReadJsonBody,\n json,\n error,\n });\n };\n}\n\nexport const browserWorkspaceRoutes: Route[] =\n BROWSER_WORKSPACE_ROUTE_PATHS.map(\n (r) =>\n ({\n type: r.type as Route[\"type\"],\n path: r.path,\n rawPath: true as const,\n handler: browserWorkspaceRouteHandler(),\n }) as Route,\n );\n"],"mappings":"AASA,SAAS,iBAAiB;AAE1B;AAAA,EACE,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,iBAAiB;AAAA,OACZ;AACP;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,SAAS,KAAK,KAA0B,MAAe,SAAS,KAAW;AACzE,eAAa,KAAK,MAAM,MAAM;AAChC;AAEA,SAAS,MAAM,KAA0B,SAAiB,SAAS,KAAW;AAC5E,oBAAkB,KAAK,SAAS,MAAM;AACxC;AAEA,SAAS,iBAAiB,OAAqD;AAC7E,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,iBAAiB,MAAM,CAAC,CAAC;AAAA,EAClC;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,aAAa,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK;AAC7C,SAAO,aAAa,aAAa;AACnC;AAEA,SAAS,eAAe,KAAmC;AACzD,QAAM,UAAU,IAAI,WAAW,CAAC;AAChC,QAAM,WACJ,iBAAiB,QAAQ,mBAAmB,CAAC,MAC5C,IAAI,kBAAkB,aAAa,IAAI,OAAO,YAC3C,UACA;AACN,QAAM,OACJ,iBAAiB,QAAQ,kBAAkB,CAAC,KAC5C,iBAAiB,QAAQ,IAAI,KAC7B;AACF,SAAO,GAAG,QAAQ,MAAM,IAAI;AAC9B;AAEA,SAAS,+BAAmD;AAC1D,SAAO,OACL,KACA,KACA,YACkB;AAClB,UAAM,UAAU;AAChB,UAAM,UAAU;AAChB,UAAM,UAAU,QAAQ,UAAU,OAAO,YAAY;AACrD,UAAM,MAAM,IAAI,IAAI,QAAQ,OAAO,KAAK,eAAe,OAAO,CAAC;AAC/D,UAAM,6BAA6B;AAAA,MACjC,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,UAAU,IAAI;AAAA,MACd;AAAA,MACA,OAAO;AAAA,QACL,SAAU,WAA6B;AAAA,MACzC;AAAA,MACA,cAAc;AAAA,MACd;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEO,MAAM,yBACX,8BAA8B;AAAA,EAC5B,CAAC,OACE;AAAA,IACC,MAAM,EAAE;AAAA,IACR,MAAM,EAAE;AAAA,IACR,SAAS;AAAA,IACT,SAAS,6BAA6B;AAAA,EACxC;AACJ;","names":[]}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Browser workspace HTTP routes.
3
+ *
4
+ * The runtime mounts these via `Plugin.routes` with `rawPath: true` so the
5
+ * legacy `/api/browser-workspace/*` paths are preserved. Implementation
6
+ * lives in `@elizaos/plugin-browser/workspace`; this is the HTTP edge.
7
+ */
8
+ import type { IAgentRuntime, RouteRequestContext } from "@elizaos/core";
9
+ export interface BrowserWorkspaceRouteContext extends RouteRequestContext {
10
+ url?: URL;
11
+ state?: {
12
+ runtime?: IAgentRuntime | null;
13
+ };
14
+ }
15
+ export declare function handleBrowserWorkspaceRoutes(ctx: BrowserWorkspaceRouteContext): Promise<boolean>;
16
+ export declare const BROWSER_WORKSPACE_ROUTE_PATHS: Array<{
17
+ type: string;
18
+ path: string;
19
+ }>;
20
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/routes/workspace.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAyDxE,MAAM,WAAW,4BAA6B,SAAQ,mBAAmB;IACvE,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,KAAK,CAAC,EAAE;QACN,OAAO,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;KAChC,CAAC;CACH;AA0FD,wBAAsB,4BAA4B,CAChD,GAAG,EAAE,4BAA4B,GAChC,OAAO,CAAC,OAAO,CAAC,CAqMlB;AAED,eAAO,MAAM,6BAA6B,EAAE,KAAK,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAYA,CAAC"}