@vibesdotdev/control 0.0.0-stage → 1.0.0-rc.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 (523) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +90 -2
  3. package/dist/browser/browser.cloud.plugin.d.ts +21 -0
  4. package/dist/browser/browser.cloud.plugin.d.ts.map +1 -0
  5. package/dist/browser/browser.cloud.plugin.js +37 -0
  6. package/dist/browser/browser.cloud.plugin.js.map +1 -0
  7. package/dist/browser/browser.consumer.plugin.d.ts +4 -0
  8. package/dist/browser/browser.consumer.plugin.d.ts.map +1 -0
  9. package/dist/browser/browser.consumer.plugin.js +77 -0
  10. package/dist/browser/browser.consumer.plugin.js.map +1 -0
  11. package/dist/browser/browser.plugin.d.ts +3 -0
  12. package/dist/browser/browser.plugin.d.ts.map +1 -0
  13. package/dist/browser/browser.plugin.js +3 -0
  14. package/dist/browser/browser.plugin.js.map +1 -0
  15. package/dist/browser/bun/webview.backend.d.ts +23 -0
  16. package/dist/browser/bun/webview.backend.d.ts.map +1 -0
  17. package/dist/browser/bun/webview.backend.js +262 -0
  18. package/dist/browser/bun/webview.backend.js.map +1 -0
  19. package/dist/browser/bun/webview.descriptor.d.ts +21 -0
  20. package/dist/browser/bun/webview.descriptor.d.ts.map +1 -0
  21. package/dist/browser/bun/webview.descriptor.js +21 -0
  22. package/dist/browser/bun/webview.descriptor.js.map +1 -0
  23. package/dist/browser/bun/webview.plugin.d.ts +3 -0
  24. package/dist/browser/bun/webview.plugin.d.ts.map +1 -0
  25. package/dist/browser/bun/webview.plugin.js +24 -0
  26. package/dist/browser/bun/webview.plugin.js.map +1 -0
  27. package/dist/browser/client/browser-client.d.ts +92 -0
  28. package/dist/browser/client/browser-client.d.ts.map +1 -0
  29. package/dist/browser/client/browser-client.js +138 -0
  30. package/dist/browser/client/browser-client.js.map +1 -0
  31. package/dist/browser/client/workspace-client.d.ts +29 -0
  32. package/dist/browser/client/workspace-client.d.ts.map +1 -0
  33. package/dist/browser/client/workspace-client.js +38 -0
  34. package/dist/browser/client/workspace-client.js.map +1 -0
  35. package/dist/browser/contracts.d.ts +246 -0
  36. package/dist/browser/contracts.d.ts.map +1 -0
  37. package/dist/browser/contracts.js +38 -0
  38. package/dist/browser/contracts.js.map +1 -0
  39. package/dist/browser/index.d.ts +6 -0
  40. package/dist/browser/index.d.ts.map +1 -0
  41. package/dist/browser/index.js +7 -0
  42. package/dist/browser/index.js.map +1 -0
  43. package/dist/browser/plugin.d.ts +3 -0
  44. package/dist/browser/plugin.d.ts.map +1 -0
  45. package/dist/browser/plugin.js +3 -0
  46. package/dist/browser/plugin.js.map +1 -0
  47. package/dist/browser/runtime/backend/kind.d.ts +23 -0
  48. package/dist/browser/runtime/backend/kind.d.ts.map +1 -0
  49. package/dist/browser/runtime/backend/kind.js +12 -0
  50. package/dist/browser/runtime/backend/kind.js.map +1 -0
  51. package/dist/browser/runtime/backend/playwright.descriptor.d.ts +20 -0
  52. package/dist/browser/runtime/backend/playwright.descriptor.d.ts.map +1 -0
  53. package/dist/browser/runtime/backend/playwright.descriptor.js +20 -0
  54. package/dist/browser/runtime/backend/playwright.descriptor.js.map +1 -0
  55. package/dist/browser/runtime/backend/resolve.d.ts +8 -0
  56. package/dist/browser/runtime/backend/resolve.d.ts.map +1 -0
  57. package/dist/browser/runtime/backend/resolve.js +43 -0
  58. package/dist/browser/runtime/backend/resolve.js.map +1 -0
  59. package/dist/browser/runtime/backend/types.d.ts +12 -0
  60. package/dist/browser/runtime/backend/types.d.ts.map +1 -0
  61. package/dist/browser/runtime/backend/types.js +12 -0
  62. package/dist/browser/runtime/backend/types.js.map +1 -0
  63. package/dist/browser/runtime/backends/playwright.backend.d.ts +71 -0
  64. package/dist/browser/runtime/backends/playwright.backend.d.ts.map +1 -0
  65. package/dist/browser/runtime/backends/playwright.backend.js +177 -0
  66. package/dist/browser/runtime/backends/playwright.backend.js.map +1 -0
  67. package/dist/browser/runtime/index.d.ts +3 -0
  68. package/dist/browser/runtime/index.d.ts.map +1 -0
  69. package/dist/browser/runtime/index.js +2 -0
  70. package/dist/browser/runtime/index.js.map +1 -0
  71. package/dist/browser/runtime/launcher.d.ts +18 -0
  72. package/dist/browser/runtime/launcher.d.ts.map +1 -0
  73. package/dist/browser/runtime/launcher.js +123 -0
  74. package/dist/browser/runtime/launcher.js.map +1 -0
  75. package/dist/browser/runtime/manager-host.d.ts +22 -0
  76. package/dist/browser/runtime/manager-host.d.ts.map +1 -0
  77. package/dist/browser/runtime/manager-host.js +102 -0
  78. package/dist/browser/runtime/manager-host.js.map +1 -0
  79. package/dist/browser/runtime/manager.context.d.ts +19 -0
  80. package/dist/browser/runtime/manager.context.d.ts.map +1 -0
  81. package/dist/browser/runtime/manager.context.descriptor.d.ts +30 -0
  82. package/dist/browser/runtime/manager.context.descriptor.d.ts.map +1 -0
  83. package/dist/browser/runtime/manager.context.descriptor.js +7 -0
  84. package/dist/browser/runtime/manager.context.descriptor.js.map +1 -0
  85. package/dist/browser/runtime/manager.context.impl.consumer.d.ts +6 -0
  86. package/dist/browser/runtime/manager.context.impl.consumer.d.ts.map +1 -0
  87. package/dist/browser/runtime/manager.context.impl.consumer.js +7 -0
  88. package/dist/browser/runtime/manager.context.impl.consumer.js.map +1 -0
  89. package/dist/browser/runtime/manager.context.js +19 -0
  90. package/dist/browser/runtime/manager.context.js.map +1 -0
  91. package/dist/browser/runtime/manager.d.ts +97 -0
  92. package/dist/browser/runtime/manager.d.ts.map +1 -0
  93. package/dist/browser/runtime/manager.js +731 -0
  94. package/dist/browser/runtime/manager.js.map +1 -0
  95. package/dist/browser/runtime/safe-url.d.ts +27 -0
  96. package/dist/browser/runtime/safe-url.d.ts.map +1 -0
  97. package/dist/browser/runtime/safe-url.js +77 -0
  98. package/dist/browser/runtime/safe-url.js.map +1 -0
  99. package/dist/browser/runtime/session-lease.d.ts +24 -0
  100. package/dist/browser/runtime/session-lease.d.ts.map +1 -0
  101. package/dist/browser/runtime/session-lease.js +65 -0
  102. package/dist/browser/runtime/session-lease.js.map +1 -0
  103. package/dist/browser/runtime/step-executor.d.ts +14 -0
  104. package/dist/browser/runtime/step-executor.d.ts.map +1 -0
  105. package/dist/browser/runtime/step-executor.js +97 -0
  106. package/dist/browser/runtime/step-executor.js.map +1 -0
  107. package/dist/browser/runtime/types.d.ts +54 -0
  108. package/dist/browser/runtime/types.d.ts.map +1 -0
  109. package/dist/browser/runtime/types.js +5 -0
  110. package/dist/browser/runtime/types.js.map +1 -0
  111. package/dist/browser/schemas/backend.d.ts +79 -0
  112. package/dist/browser/schemas/backend.d.ts.map +1 -0
  113. package/dist/browser/schemas/backend.js +33 -0
  114. package/dist/browser/schemas/backend.js.map +1 -0
  115. package/dist/browser/schemas/cli.d.ts +55 -0
  116. package/dist/browser/schemas/cli.d.ts.map +1 -0
  117. package/dist/browser/schemas/cli.js +37 -0
  118. package/dist/browser/schemas/cli.js.map +1 -0
  119. package/dist/browser/schemas/client.d.ts +28 -0
  120. package/dist/browser/schemas/client.d.ts.map +1 -0
  121. package/dist/browser/schemas/client.js +7 -0
  122. package/dist/browser/schemas/client.js.map +1 -0
  123. package/dist/browser/schemas/page.d.ts +71 -0
  124. package/dist/browser/schemas/page.d.ts.map +1 -0
  125. package/dist/browser/schemas/page.js +32 -0
  126. package/dist/browser/schemas/page.js.map +1 -0
  127. package/dist/browser/schemas/profile.d.ts +14 -0
  128. package/dist/browser/schemas/profile.d.ts.map +1 -0
  129. package/dist/browser/schemas/profile.js +14 -0
  130. package/dist/browser/schemas/profile.js.map +1 -0
  131. package/dist/browser/schemas/recipe.d.ts +218 -0
  132. package/dist/browser/schemas/recipe.d.ts.map +1 -0
  133. package/dist/browser/schemas/recipe.js +91 -0
  134. package/dist/browser/schemas/recipe.js.map +1 -0
  135. package/dist/browser/schemas/session.d.ts +42 -0
  136. package/dist/browser/schemas/session.d.ts.map +1 -0
  137. package/dist/browser/schemas/session.js +22 -0
  138. package/dist/browser/schemas/session.js.map +1 -0
  139. package/dist/browser/schemas/tab.d.ts +38 -0
  140. package/dist/browser/schemas/tab.d.ts.map +1 -0
  141. package/dist/browser/schemas/tab.js +20 -0
  142. package/dist/browser/schemas/tab.js.map +1 -0
  143. package/dist/browser/schemas/tool-card.d.ts +68 -0
  144. package/dist/browser/schemas/tool-card.d.ts.map +1 -0
  145. package/dist/browser/schemas/tool-card.js +29 -0
  146. package/dist/browser/schemas/tool-card.js.map +1 -0
  147. package/dist/browser/schemas/webview.d.ts +40 -0
  148. package/dist/browser/schemas/webview.d.ts.map +1 -0
  149. package/dist/browser/schemas/webview.js +5 -0
  150. package/dist/browser/schemas/webview.js.map +1 -0
  151. package/dist/browser/schemas/workspace.d.ts +8 -0
  152. package/dist/browser/schemas/workspace.d.ts.map +1 -0
  153. package/dist/browser/schemas/workspace.js +7 -0
  154. package/dist/browser/schemas/workspace.js.map +1 -0
  155. package/dist/browser/shared/ai-client.d.ts +26 -0
  156. package/dist/browser/shared/ai-client.d.ts.map +1 -0
  157. package/dist/browser/shared/ai-client.js +27 -0
  158. package/dist/browser/shared/ai-client.js.map +1 -0
  159. package/dist/browser/shared/ai-request.d.ts +26 -0
  160. package/dist/browser/shared/ai-request.d.ts.map +1 -0
  161. package/dist/browser/shared/ai-request.js +32 -0
  162. package/dist/browser/shared/ai-request.js.map +1 -0
  163. package/dist/browser/shared/cleanup.d.ts +5 -0
  164. package/dist/browser/shared/cleanup.d.ts.map +1 -0
  165. package/dist/browser/shared/cleanup.js +15 -0
  166. package/dist/browser/shared/cleanup.js.map +1 -0
  167. package/dist/browser/shared/constants.d.ts +19 -0
  168. package/dist/browser/shared/constants.d.ts.map +1 -0
  169. package/dist/browser/shared/constants.js +13 -0
  170. package/dist/browser/shared/constants.js.map +1 -0
  171. package/dist/browser/shared/json.d.ts +5 -0
  172. package/dist/browser/shared/json.d.ts.map +1 -0
  173. package/dist/browser/shared/json.js +3 -0
  174. package/dist/browser/shared/json.js.map +1 -0
  175. package/dist/browser/shared/paths.d.ts +33 -0
  176. package/dist/browser/shared/paths.d.ts.map +1 -0
  177. package/dist/browser/shared/paths.js +55 -0
  178. package/dist/browser/shared/paths.js.map +1 -0
  179. package/dist/browser/shared/steps.d.ts +82 -0
  180. package/dist/browser/shared/steps.d.ts.map +1 -0
  181. package/dist/browser/shared/steps.js +88 -0
  182. package/dist/browser/shared/steps.js.map +1 -0
  183. package/dist/browser/shared/storage-state.d.ts +23 -0
  184. package/dist/browser/shared/storage-state.d.ts.map +1 -0
  185. package/dist/browser/shared/storage-state.js +5 -0
  186. package/dist/browser/shared/storage-state.js.map +1 -0
  187. package/dist/browser/shared/tool-summary.d.ts +48 -0
  188. package/dist/browser/shared/tool-summary.d.ts.map +1 -0
  189. package/dist/browser/shared/tool-summary.js +183 -0
  190. package/dist/browser/shared/tool-summary.js.map +1 -0
  191. package/dist/browser/storage/browser-profile.record.descriptor.d.ts +28 -0
  192. package/dist/browser/storage/browser-profile.record.descriptor.d.ts.map +1 -0
  193. package/dist/browser/storage/browser-profile.record.descriptor.js +129 -0
  194. package/dist/browser/storage/browser-profile.record.descriptor.js.map +1 -0
  195. package/dist/browser/storage/browser-recipe.record.descriptor.d.ts +29 -0
  196. package/dist/browser/storage/browser-recipe.record.descriptor.d.ts.map +1 -0
  197. package/dist/browser/storage/browser-recipe.record.descriptor.js +103 -0
  198. package/dist/browser/storage/browser-recipe.record.descriptor.js.map +1 -0
  199. package/dist/browser/storage/browser-session.record.descriptor.d.ts +28 -0
  200. package/dist/browser/storage/browser-session.record.descriptor.d.ts.map +1 -0
  201. package/dist/browser/storage/browser-session.record.descriptor.js +147 -0
  202. package/dist/browser/storage/browser-session.record.descriptor.js.map +1 -0
  203. package/dist/browser/storage/browser-tab.record.descriptor.d.ts +28 -0
  204. package/dist/browser/storage/browser-tab.record.descriptor.d.ts.map +1 -0
  205. package/dist/browser/storage/browser-tab.record.descriptor.js +153 -0
  206. package/dist/browser/storage/browser-tab.record.descriptor.js.map +1 -0
  207. package/dist/browser/storage/database.d.ts +9 -0
  208. package/dist/browser/storage/database.d.ts.map +1 -0
  209. package/dist/browser/storage/database.js +16 -0
  210. package/dist/browser/storage/database.js.map +1 -0
  211. package/dist/browser/storage/index.d.ts +6 -0
  212. package/dist/browser/storage/index.d.ts.map +1 -0
  213. package/dist/browser/storage/index.js +5 -0
  214. package/dist/browser/storage/index.js.map +1 -0
  215. package/dist/browser/storage/types.d.ts +78 -0
  216. package/dist/browser/storage/types.d.ts.map +1 -0
  217. package/dist/browser/storage/types.js +5 -0
  218. package/dist/browser/storage/types.js.map +1 -0
  219. package/dist/browser/tools/cdp/implementation.d.ts +6 -0
  220. package/dist/browser/tools/cdp/implementation.d.ts.map +1 -0
  221. package/dist/browser/tools/cdp/implementation.js +20 -0
  222. package/dist/browser/tools/cdp/implementation.js.map +1 -0
  223. package/dist/browser/tools/control/implementation.d.ts +7 -0
  224. package/dist/browser/tools/control/implementation.d.ts.map +1 -0
  225. package/dist/browser/tools/control/implementation.js +185 -0
  226. package/dist/browser/tools/control/implementation.js.map +1 -0
  227. package/dist/browser/tools/control/prompts/index.d.ts +113 -0
  228. package/dist/browser/tools/control/prompts/index.d.ts.map +1 -0
  229. package/dist/browser/tools/control/prompts/index.js +5 -0
  230. package/dist/browser/tools/control/prompts/index.js.map +1 -0
  231. package/dist/browser/tools/control/prompts/plan-request.prompt.descriptor.d.ts +114 -0
  232. package/dist/browser/tools/control/prompts/plan-request.prompt.descriptor.d.ts.map +1 -0
  233. package/dist/browser/tools/control/prompts/plan-request.prompt.descriptor.js +57 -0
  234. package/dist/browser/tools/control/prompts/plan-request.prompt.descriptor.js.map +1 -0
  235. package/dist/browser/tools/control/prompts/planner.prompt.descriptor.d.ts +113 -0
  236. package/dist/browser/tools/control/prompts/planner.prompt.descriptor.d.ts.map +1 -0
  237. package/dist/browser/tools/control/prompts/planner.prompt.descriptor.js +15 -0
  238. package/dist/browser/tools/control/prompts/planner.prompt.descriptor.js.map +1 -0
  239. package/dist/browser/tools/control/schemas.d.ts +220 -0
  240. package/dist/browser/tools/control/schemas.d.ts.map +1 -0
  241. package/dist/browser/tools/control/schemas.js +49 -0
  242. package/dist/browser/tools/control/schemas.js.map +1 -0
  243. package/dist/browser/tools/direct/implementation.d.ts +7 -0
  244. package/dist/browser/tools/direct/implementation.d.ts.map +1 -0
  245. package/dist/browser/tools/direct/implementation.js +63 -0
  246. package/dist/browser/tools/direct/implementation.js.map +1 -0
  247. package/dist/browser/tools/direct/schemas.d.ts +209 -0
  248. package/dist/browser/tools/direct/schemas.d.ts.map +1 -0
  249. package/dist/browser/tools/direct/schemas.js +68 -0
  250. package/dist/browser/tools/direct/schemas.js.map +1 -0
  251. package/dist/browser/tools/index.d.ts +9 -0
  252. package/dist/browser/tools/index.d.ts.map +1 -0
  253. package/dist/browser/tools/index.js +9 -0
  254. package/dist/browser/tools/index.js.map +1 -0
  255. package/dist/browser/tools/observe/implementation.d.ts +7 -0
  256. package/dist/browser/tools/observe/implementation.d.ts.map +1 -0
  257. package/dist/browser/tools/observe/implementation.js +59 -0
  258. package/dist/browser/tools/observe/implementation.js.map +1 -0
  259. package/dist/browser/tools/observe/schemas.d.ts +63 -0
  260. package/dist/browser/tools/observe/schemas.d.ts.map +1 -0
  261. package/dist/browser/tools/observe/schemas.js +38 -0
  262. package/dist/browser/tools/observe/schemas.js.map +1 -0
  263. package/dist/browser/tools/observe/vision.d.ts +21 -0
  264. package/dist/browser/tools/observe/vision.d.ts.map +1 -0
  265. package/dist/browser/tools/observe/vision.js +73 -0
  266. package/dist/browser/tools/observe/vision.js.map +1 -0
  267. package/dist/browser/tools/recipe/implementation.d.ts +4 -0
  268. package/dist/browser/tools/recipe/implementation.d.ts.map +1 -0
  269. package/dist/browser/tools/recipe/implementation.js +259 -0
  270. package/dist/browser/tools/recipe/implementation.js.map +1 -0
  271. package/dist/browser/tools/recipe/schemas.d.ts +646 -0
  272. package/dist/browser/tools/recipe/schemas.d.ts.map +1 -0
  273. package/dist/browser/tools/recipe/schemas.js +126 -0
  274. package/dist/browser/tools/recipe/schemas.js.map +1 -0
  275. package/dist/browser/tools/session/implementation.d.ts +7 -0
  276. package/dist/browser/tools/session/implementation.d.ts.map +1 -0
  277. package/dist/browser/tools/session/implementation.js +111 -0
  278. package/dist/browser/tools/session/implementation.js.map +1 -0
  279. package/dist/browser/tools/session/index.d.ts +5 -0
  280. package/dist/browser/tools/session/index.d.ts.map +1 -0
  281. package/dist/browser/tools/session/index.js +6 -0
  282. package/dist/browser/tools/session/index.js.map +1 -0
  283. package/dist/browser/tools/session/schemas.d.ts +78 -0
  284. package/dist/browser/tools/session/schemas.d.ts.map +1 -0
  285. package/dist/browser/tools/session/schemas.js +60 -0
  286. package/dist/browser/tools/session/schemas.js.map +1 -0
  287. package/dist/browser/tools/unified/browser-recipe.prompt.descriptor.d.ts +114 -0
  288. package/dist/browser/tools/unified/browser-recipe.prompt.descriptor.d.ts.map +1 -0
  289. package/dist/browser/tools/unified/browser-recipe.prompt.descriptor.js +22 -0
  290. package/dist/browser/tools/unified/browser-recipe.prompt.descriptor.js.map +1 -0
  291. package/dist/browser/tools/unified/browser.impl.cloud.d.ts +8 -0
  292. package/dist/browser/tools/unified/browser.impl.cloud.d.ts.map +1 -0
  293. package/dist/browser/tools/unified/browser.impl.cloud.js +381 -0
  294. package/dist/browser/tools/unified/browser.impl.cloud.js.map +1 -0
  295. package/dist/browser/tools/unified/browser.impl.consumer.d.ts +14 -0
  296. package/dist/browser/tools/unified/browser.impl.consumer.d.ts.map +1 -0
  297. package/dist/browser/tools/unified/browser.impl.consumer.js +87 -0
  298. package/dist/browser/tools/unified/browser.impl.consumer.js.map +1 -0
  299. package/dist/browser/tools/unified/browser.unified.descriptor.d.ts +587 -0
  300. package/dist/browser/tools/unified/browser.unified.descriptor.d.ts.map +1 -0
  301. package/dist/browser/tools/unified/browser.unified.descriptor.js +54 -0
  302. package/dist/browser/tools/unified/browser.unified.descriptor.js.map +1 -0
  303. package/dist/browser/tools/unified/execution-binding.d.ts +5 -0
  304. package/dist/browser/tools/unified/execution-binding.d.ts.map +1 -0
  305. package/dist/browser/tools/unified/execution-binding.js +51 -0
  306. package/dist/browser/tools/unified/execution-binding.js.map +1 -0
  307. package/dist/browser/tools/unified/index.d.ts +5 -0
  308. package/dist/browser/tools/unified/index.d.ts.map +1 -0
  309. package/dist/browser/tools/unified/index.js +6 -0
  310. package/dist/browser/tools/unified/index.js.map +1 -0
  311. package/dist/browser/tools/unified/scan-cache-wiring.d.ts +16 -0
  312. package/dist/browser/tools/unified/scan-cache-wiring.d.ts.map +1 -0
  313. package/dist/browser/tools/unified/scan-cache-wiring.js +87 -0
  314. package/dist/browser/tools/unified/scan-cache-wiring.js.map +1 -0
  315. package/dist/browser/tools/unified/schemas.d.ts +786 -0
  316. package/dist/browser/tools/unified/schemas.d.ts.map +1 -0
  317. package/dist/browser/tools/unified/schemas.js +354 -0
  318. package/dist/browser/tools/unified/schemas.js.map +1 -0
  319. package/dist/browser/tools/webmcp/detection-script.d.ts +19 -0
  320. package/dist/browser/tools/webmcp/detection-script.d.ts.map +1 -0
  321. package/dist/browser/tools/webmcp/detection-script.js +104 -0
  322. package/dist/browser/tools/webmcp/detection-script.js.map +1 -0
  323. package/dist/browser/tools/webmcp/implementation.d.ts +18 -0
  324. package/dist/browser/tools/webmcp/implementation.d.ts.map +1 -0
  325. package/dist/browser/tools/webmcp/implementation.js +61 -0
  326. package/dist/browser/tools/webmcp/implementation.js.map +1 -0
  327. package/dist/cli/browser/browser.cli-group.descriptor.d.ts +17 -0
  328. package/dist/cli/browser/browser.cli-group.descriptor.d.ts.map +1 -0
  329. package/dist/cli/browser/browser.cli-group.descriptor.js +17 -0
  330. package/dist/cli/browser/browser.cli-group.descriptor.js.map +1 -0
  331. package/dist/cli/browser/browser.cli.plugin.d.ts +12 -0
  332. package/dist/cli/browser/browser.cli.plugin.d.ts.map +1 -0
  333. package/dist/cli/browser/browser.cli.plugin.js +179 -0
  334. package/dist/cli/browser/browser.cli.plugin.js.map +1 -0
  335. package/dist/cli/browser/browser.recipe.cli-group.descriptor.d.ts +18 -0
  336. package/dist/cli/browser/browser.recipe.cli-group.descriptor.d.ts.map +1 -0
  337. package/dist/cli/browser/browser.recipe.cli-group.descriptor.js +18 -0
  338. package/dist/cli/browser/browser.recipe.cli-group.descriptor.js.map +1 -0
  339. package/dist/cli/browser/browser.session.cli-group.descriptor.d.ts +18 -0
  340. package/dist/cli/browser/browser.session.cli-group.descriptor.d.ts.map +1 -0
  341. package/dist/cli/browser/browser.session.cli-group.descriptor.js +18 -0
  342. package/dist/cli/browser/browser.session.cli-group.descriptor.js.map +1 -0
  343. package/dist/cli/browser/commands/control/browser.control.cli-command.descriptor.d.ts +36 -0
  344. package/dist/cli/browser/commands/control/browser.control.cli-command.descriptor.d.ts.map +1 -0
  345. package/dist/cli/browser/commands/control/browser.control.cli-command.descriptor.js +29 -0
  346. package/dist/cli/browser/commands/control/browser.control.cli-command.descriptor.js.map +1 -0
  347. package/dist/cli/browser/commands/control/browser.control.impl.d.ts +7 -0
  348. package/dist/cli/browser/commands/control/browser.control.impl.d.ts.map +1 -0
  349. package/dist/cli/browser/commands/control/browser.control.impl.js +67 -0
  350. package/dist/cli/browser/commands/control/browser.control.impl.js.map +1 -0
  351. package/dist/cli/browser/commands/direct/browser.direct.cli-command.descriptor.d.ts +38 -0
  352. package/dist/cli/browser/commands/direct/browser.direct.cli-command.descriptor.d.ts.map +1 -0
  353. package/dist/cli/browser/commands/direct/browser.direct.cli-command.descriptor.js +28 -0
  354. package/dist/cli/browser/commands/direct/browser.direct.cli-command.descriptor.js.map +1 -0
  355. package/dist/cli/browser/commands/direct/browser.direct.impl.d.ts +7 -0
  356. package/dist/cli/browser/commands/direct/browser.direct.impl.d.ts.map +1 -0
  357. package/dist/cli/browser/commands/direct/browser.direct.impl.js +85 -0
  358. package/dist/cli/browser/commands/direct/browser.direct.impl.js.map +1 -0
  359. package/dist/cli/browser/commands/observe/browser.observe.cli-command.descriptor.d.ts +30 -0
  360. package/dist/cli/browser/commands/observe/browser.observe.cli-command.descriptor.d.ts.map +1 -0
  361. package/dist/cli/browser/commands/observe/browser.observe.cli-command.descriptor.js +22 -0
  362. package/dist/cli/browser/commands/observe/browser.observe.cli-command.descriptor.js.map +1 -0
  363. package/dist/cli/browser/commands/observe/browser.observe.impl.d.ts +7 -0
  364. package/dist/cli/browser/commands/observe/browser.observe.impl.d.ts.map +1 -0
  365. package/dist/cli/browser/commands/observe/browser.observe.impl.js +59 -0
  366. package/dist/cli/browser/commands/observe/browser.observe.impl.js.map +1 -0
  367. package/dist/cli/browser/commands/recipe/create/browser.recipe.create.cli-command.descriptor.d.ts +38 -0
  368. package/dist/cli/browser/commands/recipe/create/browser.recipe.create.cli-command.descriptor.d.ts.map +1 -0
  369. package/dist/cli/browser/commands/recipe/create/browser.recipe.create.cli-command.descriptor.js +26 -0
  370. package/dist/cli/browser/commands/recipe/create/browser.recipe.create.cli-command.descriptor.js.map +1 -0
  371. package/dist/cli/browser/commands/recipe/create/browser.recipe.create.impl.d.ts +7 -0
  372. package/dist/cli/browser/commands/recipe/create/browser.recipe.create.impl.d.ts.map +1 -0
  373. package/dist/cli/browser/commands/recipe/create/browser.recipe.create.impl.js +60 -0
  374. package/dist/cli/browser/commands/recipe/create/browser.recipe.create.impl.js.map +1 -0
  375. package/dist/cli/browser/commands/recipe/delete/browser.recipe.delete.cli-command.descriptor.d.ts +25 -0
  376. package/dist/cli/browser/commands/recipe/delete/browser.recipe.delete.cli-command.descriptor.d.ts.map +1 -0
  377. package/dist/cli/browser/commands/recipe/delete/browser.recipe.delete.cli-command.descriptor.js +22 -0
  378. package/dist/cli/browser/commands/recipe/delete/browser.recipe.delete.cli-command.descriptor.js.map +1 -0
  379. package/dist/cli/browser/commands/recipe/delete/browser.recipe.delete.impl.d.ts +7 -0
  380. package/dist/cli/browser/commands/recipe/delete/browser.recipe.delete.impl.d.ts.map +1 -0
  381. package/dist/cli/browser/commands/recipe/delete/browser.recipe.delete.impl.js +35 -0
  382. package/dist/cli/browser/commands/recipe/delete/browser.recipe.delete.impl.js.map +1 -0
  383. package/dist/cli/browser/commands/recipe/get/browser.recipe.get.cli-command.descriptor.d.ts +25 -0
  384. package/dist/cli/browser/commands/recipe/get/browser.recipe.get.cli-command.descriptor.d.ts.map +1 -0
  385. package/dist/cli/browser/commands/recipe/get/browser.recipe.get.cli-command.descriptor.js +22 -0
  386. package/dist/cli/browser/commands/recipe/get/browser.recipe.get.cli-command.descriptor.js.map +1 -0
  387. package/dist/cli/browser/commands/recipe/get/browser.recipe.get.impl.d.ts +7 -0
  388. package/dist/cli/browser/commands/recipe/get/browser.recipe.get.impl.d.ts.map +1 -0
  389. package/dist/cli/browser/commands/recipe/get/browser.recipe.get.impl.js +88 -0
  390. package/dist/cli/browser/commands/recipe/get/browser.recipe.get.impl.js.map +1 -0
  391. package/dist/cli/browser/commands/recipe/list/browser.recipe.list.cli-command.descriptor.d.ts +20 -0
  392. package/dist/cli/browser/commands/recipe/list/browser.recipe.list.cli-command.descriptor.d.ts.map +1 -0
  393. package/dist/cli/browser/commands/recipe/list/browser.recipe.list.cli-command.descriptor.js +19 -0
  394. package/dist/cli/browser/commands/recipe/list/browser.recipe.list.cli-command.descriptor.js.map +1 -0
  395. package/dist/cli/browser/commands/recipe/list/browser.recipe.list.impl.d.ts +7 -0
  396. package/dist/cli/browser/commands/recipe/list/browser.recipe.list.impl.d.ts.map +1 -0
  397. package/dist/cli/browser/commands/recipe/list/browser.recipe.list.impl.js +34 -0
  398. package/dist/cli/browser/commands/recipe/list/browser.recipe.list.impl.js.map +1 -0
  399. package/dist/cli/browser/commands/recipe/run/browser.recipe.run.cli-command.descriptor.d.ts +37 -0
  400. package/dist/cli/browser/commands/recipe/run/browser.recipe.run.cli-command.descriptor.d.ts.map +1 -0
  401. package/dist/cli/browser/commands/recipe/run/browser.recipe.run.cli-command.descriptor.js +26 -0
  402. package/dist/cli/browser/commands/recipe/run/browser.recipe.run.cli-command.descriptor.js.map +1 -0
  403. package/dist/cli/browser/commands/recipe/run/browser.recipe.run.impl.d.ts +7 -0
  404. package/dist/cli/browser/commands/recipe/run/browser.recipe.run.impl.d.ts.map +1 -0
  405. package/dist/cli/browser/commands/recipe/run/browser.recipe.run.impl.js +88 -0
  406. package/dist/cli/browser/commands/recipe/run/browser.recipe.run.impl.js.map +1 -0
  407. package/dist/cli/browser/commands/recipe/update/browser.recipe.update.cli-command.descriptor.d.ts +37 -0
  408. package/dist/cli/browser/commands/recipe/update/browser.recipe.update.cli-command.descriptor.d.ts.map +1 -0
  409. package/dist/cli/browser/commands/recipe/update/browser.recipe.update.cli-command.descriptor.js +26 -0
  410. package/dist/cli/browser/commands/recipe/update/browser.recipe.update.cli-command.descriptor.js.map +1 -0
  411. package/dist/cli/browser/commands/recipe/update/browser.recipe.update.impl.d.ts +7 -0
  412. package/dist/cli/browser/commands/recipe/update/browser.recipe.update.impl.d.ts.map +1 -0
  413. package/dist/cli/browser/commands/recipe/update/browser.recipe.update.impl.js +63 -0
  414. package/dist/cli/browser/commands/recipe/update/browser.recipe.update.impl.js.map +1 -0
  415. package/dist/cli/browser/commands/session/close/browser.session.close.cli-command.descriptor.d.ts +28 -0
  416. package/dist/cli/browser/commands/session/close/browser.session.close.cli-command.descriptor.d.ts.map +1 -0
  417. package/dist/cli/browser/commands/session/close/browser.session.close.cli-command.descriptor.js +23 -0
  418. package/dist/cli/browser/commands/session/close/browser.session.close.cli-command.descriptor.js.map +1 -0
  419. package/dist/cli/browser/commands/session/close/browser.session.close.impl.d.ts +35 -0
  420. package/dist/cli/browser/commands/session/close/browser.session.close.impl.d.ts.map +1 -0
  421. package/dist/cli/browser/commands/session/close/browser.session.close.impl.js +75 -0
  422. package/dist/cli/browser/commands/session/close/browser.session.close.impl.js.map +1 -0
  423. package/dist/cli/browser/commands/session/dismiss/browser.session.dismiss.cli-command.descriptor.d.ts +16 -0
  424. package/dist/cli/browser/commands/session/dismiss/browser.session.dismiss.cli-command.descriptor.d.ts.map +1 -0
  425. package/dist/cli/browser/commands/session/dismiss/browser.session.dismiss.cli-command.descriptor.js +16 -0
  426. package/dist/cli/browser/commands/session/dismiss/browser.session.dismiss.cli-command.descriptor.js.map +1 -0
  427. package/dist/cli/browser/commands/session/dismiss/browser.session.dismiss.impl.d.ts +7 -0
  428. package/dist/cli/browser/commands/session/dismiss/browser.session.dismiss.impl.d.ts.map +1 -0
  429. package/dist/cli/browser/commands/session/dismiss/browser.session.dismiss.impl.js +14 -0
  430. package/dist/cli/browser/commands/session/dismiss/browser.session.dismiss.impl.js.map +1 -0
  431. package/dist/cli/browser/commands/session/get/browser.session.get.cli-command.descriptor.d.ts +25 -0
  432. package/dist/cli/browser/commands/session/get/browser.session.get.cli-command.descriptor.d.ts.map +1 -0
  433. package/dist/cli/browser/commands/session/get/browser.session.get.cli-command.descriptor.js +22 -0
  434. package/dist/cli/browser/commands/session/get/browser.session.get.cli-command.descriptor.js.map +1 -0
  435. package/dist/cli/browser/commands/session/get/browser.session.get.impl.d.ts +18 -0
  436. package/dist/cli/browser/commands/session/get/browser.session.get.impl.d.ts.map +1 -0
  437. package/dist/cli/browser/commands/session/get/browser.session.get.impl.js +61 -0
  438. package/dist/cli/browser/commands/session/get/browser.session.get.impl.js.map +1 -0
  439. package/dist/cli/browser/commands/session/list/browser.session.list.cli-command.descriptor.d.ts +27 -0
  440. package/dist/cli/browser/commands/session/list/browser.session.list.cli-command.descriptor.d.ts.map +1 -0
  441. package/dist/cli/browser/commands/session/list/browser.session.list.cli-command.descriptor.js +24 -0
  442. package/dist/cli/browser/commands/session/list/browser.session.list.cli-command.descriptor.js.map +1 -0
  443. package/dist/cli/browser/commands/session/list/browser.session.list.impl.d.ts +22 -0
  444. package/dist/cli/browser/commands/session/list/browser.session.list.impl.d.ts.map +1 -0
  445. package/dist/cli/browser/commands/session/list/browser.session.list.impl.js +73 -0
  446. package/dist/cli/browser/commands/session/list/browser.session.list.impl.js.map +1 -0
  447. package/dist/cli/browser/commands/session/present/browser.session.present.cli-command.descriptor.d.ts +25 -0
  448. package/dist/cli/browser/commands/session/present/browser.session.present.cli-command.descriptor.d.ts.map +1 -0
  449. package/dist/cli/browser/commands/session/present/browser.session.present.cli-command.descriptor.js +22 -0
  450. package/dist/cli/browser/commands/session/present/browser.session.present.cli-command.descriptor.js.map +1 -0
  451. package/dist/cli/browser/commands/session/present/browser.session.present.impl.d.ts +7 -0
  452. package/dist/cli/browser/commands/session/present/browser.session.present.impl.d.ts.map +1 -0
  453. package/dist/cli/browser/commands/session/present/browser.session.present.impl.js +29 -0
  454. package/dist/cli/browser/commands/session/present/browser.session.present.impl.js.map +1 -0
  455. package/dist/cli/browser/commands/session/resolve-session.d.ts +19 -0
  456. package/dist/cli/browser/commands/session/resolve-session.d.ts.map +1 -0
  457. package/dist/cli/browser/commands/session/resolve-session.js +11 -0
  458. package/dist/cli/browser/commands/session/resolve-session.js.map +1 -0
  459. package/dist/cli/browser/commands/session/session-age.d.ts +6 -0
  460. package/dist/cli/browser/commands/session/session-age.d.ts.map +1 -0
  461. package/dist/cli/browser/commands/session/session-age.js +34 -0
  462. package/dist/cli/browser/commands/session/session-age.js.map +1 -0
  463. package/dist/cli/browser/commands/session/sweep/browser.session.sweep.cli-command.descriptor.d.ts +26 -0
  464. package/dist/cli/browser/commands/session/sweep/browser.session.sweep.cli-command.descriptor.d.ts.map +1 -0
  465. package/dist/cli/browser/commands/session/sweep/browser.session.sweep.cli-command.descriptor.js +24 -0
  466. package/dist/cli/browser/commands/session/sweep/browser.session.sweep.cli-command.descriptor.js.map +1 -0
  467. package/dist/cli/browser/commands/session/sweep/browser.session.sweep.impl.d.ts +32 -0
  468. package/dist/cli/browser/commands/session/sweep/browser.session.sweep.impl.d.ts.map +1 -0
  469. package/dist/cli/browser/commands/session/sweep/browser.session.sweep.impl.js +112 -0
  470. package/dist/cli/browser/commands/session/sweep/browser.session.sweep.impl.js.map +1 -0
  471. package/dist/index.d.ts +25 -0
  472. package/dist/index.d.ts.map +1 -0
  473. package/dist/index.js +24 -0
  474. package/dist/index.js.map +1 -0
  475. package/dist/svelte/browser/BrowserWorkspace.svelte +450 -0
  476. package/dist/svelte/browser/BrowserWorkspace.svelte.d.ts +20 -0
  477. package/dist/svelte/browser/BrowserWorkspace.svelte.d.ts.map +1 -0
  478. package/dist/svelte/browser/browser-automation-svelte.plugin.d.ts +3 -0
  479. package/dist/svelte/browser/browser-automation-svelte.plugin.d.ts.map +1 -0
  480. package/dist/svelte/browser/browser-automation-svelte.plugin.js +25 -0
  481. package/dist/svelte/browser/docs/browser-automation-svelte.docs.descriptor.d.ts +4 -0
  482. package/dist/svelte/browser/docs/browser-automation-svelte.docs.descriptor.d.ts.map +1 -0
  483. package/dist/svelte/browser/docs/browser-automation-svelte.docs.descriptor.js +55 -0
  484. package/dist/svelte/browser/index.d.ts +6 -0
  485. package/dist/svelte/browser/index.d.ts.map +1 -0
  486. package/dist/svelte/browser/index.js +4 -0
  487. package/dist/svelte/browser/state.svelte.d.ts +28 -0
  488. package/dist/svelte/browser/state.svelte.d.ts.map +1 -0
  489. package/dist/svelte/browser/state.svelte.js +87 -0
  490. package/dist/svelte/browser/styles.css +10 -0
  491. package/dist/svelte/browser/tool-widgets/BrowserToolCard.svelte +268 -0
  492. package/dist/svelte/browser/tool-widgets/BrowserToolCard.svelte.d.ts +10 -0
  493. package/dist/svelte/browser/tool-widgets/BrowserToolCard.svelte.d.ts.map +1 -0
  494. package/dist/svelte/browser/tool-widgets/index.d.ts +2 -0
  495. package/dist/svelte/browser/tool-widgets/index.d.ts.map +1 -0
  496. package/dist/svelte/browser/tool-widgets/index.js +1 -0
  497. package/dist/svelte/browser/tool-widgets/summary.d.ts +2 -0
  498. package/dist/svelte/browser/tool-widgets/summary.d.ts.map +1 -0
  499. package/dist/svelte/browser/tool-widgets/summary.js +1 -0
  500. package/dist/svelte/browser/types.d.ts +16 -0
  501. package/dist/svelte/browser/types.d.ts.map +1 -0
  502. package/dist/svelte/browser/types.js +1 -0
  503. package/dist/tui/browser/browser-sessions.app.descriptor.d.ts +33 -0
  504. package/dist/tui/browser/browser-sessions.app.descriptor.d.ts.map +1 -0
  505. package/dist/tui/browser/browser-sessions.app.descriptor.js +33 -0
  506. package/dist/tui/browser/browser-sessions.app.descriptor.js.map +1 -0
  507. package/dist/tui/browser/browser-sessions.app.impl.d.ts +4 -0
  508. package/dist/tui/browser/browser-sessions.app.impl.d.ts.map +1 -0
  509. package/dist/tui/browser/browser-sessions.app.impl.js +231 -0
  510. package/dist/tui/browser/browser-sessions.app.impl.js.map +1 -0
  511. package/dist/tui/browser/browser.tui.plugin.d.ts +13 -0
  512. package/dist/tui/browser/browser.tui.plugin.d.ts.map +1 -0
  513. package/dist/tui/browser/browser.tui.plugin.js +52 -0
  514. package/dist/tui/browser/browser.tui.plugin.js.map +1 -0
  515. package/dist/tui/browser/tool-widgets/BrowserToolWidget.impl.consumer.d.ts +4 -0
  516. package/dist/tui/browser/tool-widgets/BrowserToolWidget.impl.consumer.d.ts.map +1 -0
  517. package/dist/tui/browser/tool-widgets/BrowserToolWidget.impl.consumer.js +31 -0
  518. package/dist/tui/browser/tool-widgets/BrowserToolWidget.impl.consumer.js.map +1 -0
  519. package/dist/tui/browser/tool-widgets/summary.d.ts +40 -0
  520. package/dist/tui/browser/tool-widgets/summary.d.ts.map +1 -0
  521. package/dist/tui/browser/tool-widgets/summary.js +16 -0
  522. package/dist/tui/browser/tool-widgets/summary.js.map +1 -0
  523. package/package.json +212 -4
@@ -0,0 +1,731 @@
1
+ /**
2
+ * Browser Runtime Manager
3
+ */
4
+ import { resolveFileSystemAdapter, statChecked } from '@vibesdotdev/filesystem';
5
+ import { getLogger } from '@vibesdotdev/logging';
6
+ import { CapabilityError, settle, composeChildEnv, CaughtFailureSchema } from '@vibesdotdev/kernel';
7
+ import { runCapture } from '@vibesdotdev/kernel/execution';
8
+ import { resolveProfilesDir, resolveStorageDir } from "../shared/paths.js";
9
+ import { DEFAULT_MAX_ACTIVE_SESSIONS, DEFAULT_SESSION_IDLE_TIMEOUT_MS, DEFAULT_CLEANUP_INTERVAL_MS } from "../shared/constants.js";
10
+ import { launchBrowserContext } from "./launcher.js";
11
+ import { assertSafeBrowserUrl, launchTrustedBrowserOrigins, normalizeTrustedBrowserOrigins } from "./safe-url.js";
12
+ import { closeBrowserSessionLease, withBrowserSessionLease } from "./session-lease.js";
13
+ /** Map the legacy launch-options shape onto the backend launch input. */
14
+ function toBackendLaunchInput(runtime, opts, extra) {
15
+ return {
16
+ runtime,
17
+ profileDir: extra.profileDir,
18
+ extensions: extra.extensions,
19
+ storageStatePath: extra.storageStatePath,
20
+ headless: opts?.headless,
21
+ viewport: opts?.viewport,
22
+ recordVideo: opts?.recordVideo?.enabled
23
+ ? { dir: opts.recordVideo.dir, size: opts.recordVideo.size }
24
+ : undefined,
25
+ trustedOrigins: extra.trustedOrigins
26
+ };
27
+ }
28
+ /** The exact origin a session's base URL declares; none when it has no base URL. */
29
+ function sessionBaseOrigins(baseUrl) {
30
+ if (!baseUrl)
31
+ return [];
32
+ if (!URL.canParse(baseUrl))
33
+ throw new Error(`Browser session base URL is invalid: ${baseUrl}`);
34
+ return [...normalizeTrustedBrowserOrigins([new URL(baseUrl).origin])];
35
+ }
36
+ /** A session's navigation trust: its base origin, else the runtime's declared local proxy origins. */
37
+ function sessionTrustedOrigins(runtime, baseUrl) {
38
+ return launchTrustedBrowserOrigins(runtime, sessionBaseOrigins(baseUrl));
39
+ }
40
+ function sessionTrustedOriginList(baseUrl) {
41
+ const origins = sessionBaseOrigins(baseUrl);
42
+ return origins.length > 0 ? origins : undefined;
43
+ }
44
+ function cleanupErrorDetail(error) {
45
+ if (error instanceof AggregateError) {
46
+ const nested = error.errors.map((cause) => cleanupErrorDetail(CaughtFailureSchema.parse(cause))).join('; ');
47
+ return nested ? `${error.message}: ${nested}` : error.message;
48
+ }
49
+ if (error instanceof Error) {
50
+ return error.cause === undefined
51
+ ? error.message
52
+ : `${error.message}: ${cleanupErrorDetail(CaughtFailureSchema.parse(error.cause))}`;
53
+ }
54
+ return error.description;
55
+ }
56
+ function cleanupFailure(resource, error) {
57
+ const detail = cleanupErrorDetail(error);
58
+ return new Error(`Failed to close browser resource '${resource}': ${detail}`, { cause: error });
59
+ }
60
+ function throwCleanupFailures(failures, operation) {
61
+ if (failures.length === 0)
62
+ return;
63
+ throw new AggregateError(failures, `${operation} failed for ${failures.length} resource${failures.length === 1 ? '' : 's'}`);
64
+ }
65
+ export async function activatePresentationWindow(runtime) {
66
+ const platform = runtime.localEnvironment.getPlatform?.();
67
+ if (!platform) {
68
+ throw new CapabilityError('Browser presentation requires a declared host platform.', 'UNAVAILABLE', {
69
+ reason: 'host-platform-undeclared'
70
+ });
71
+ }
72
+ if (platform !== 'darwin')
73
+ return;
74
+ const script = [
75
+ 'tell application "System Events"',
76
+ ' try',
77
+ ' set p to first process whose name contains "Chromium"',
78
+ ' set frontmost of p to true',
79
+ ' end try',
80
+ 'end tell'
81
+ ].join('\n');
82
+ const result = await runCapture(runtime, 'osascript', ['-e', script], {
83
+ envMode: 'replace',
84
+ env: composeChildEnv(runtime, {}),
85
+ signal: runtime.lifecycle.signal
86
+ });
87
+ if (result.exitCode !== 0) {
88
+ throw new CapabilityError('Browser presentation activation failed.', 'UNAVAILABLE', {
89
+ reason: 'presentation-activation-failed',
90
+ details: { exitCode: result.exitCode }
91
+ });
92
+ }
93
+ }
94
+ export class BrowserRuntimeManager {
95
+ runtime;
96
+ workspacePath;
97
+ backend;
98
+ maxActive;
99
+ presentationLauncher;
100
+ presentationActivator;
101
+ sessions = new Map();
102
+ sessionAliases = new Map();
103
+ ephemeralSessions = new Set();
104
+ sessionActivity = new Map();
105
+ tabs = new Map();
106
+ closedTabs = new Set();
107
+ closedContexts = new Set();
108
+ stopCleanupTimer = null;
109
+ closeAllPromise = null;
110
+ instanceId = crypto.randomUUID();
111
+ idleTimeout = DEFAULT_SESSION_IDLE_TIMEOUT_MS;
112
+ presentationBrowser = null;
113
+ // Storage descriptors
114
+ sessionsStorage;
115
+ tabsStorage;
116
+ profilesStorage;
117
+ storageInitialized = false;
118
+ constructor(runtime, workspacePath,
119
+ /** Runtime-selected browser provider. Construction never invents a fallback. */
120
+ backend, maxActive = DEFAULT_MAX_ACTIVE_SESSIONS, presentationLauncher = launchBrowserContext, presentationActivator = () => activatePresentationWindow(runtime)) {
121
+ this.runtime = runtime;
122
+ this.workspacePath = workspacePath;
123
+ this.backend = backend;
124
+ this.maxActive = maxActive;
125
+ this.presentationLauncher = presentationLauncher;
126
+ this.presentationActivator = presentationActivator;
127
+ this.startCleanupInterval();
128
+ }
129
+ getBackendId() {
130
+ return this.backend.id;
131
+ }
132
+ async resolveStorageRecord(id) {
133
+ return this.runtime
134
+ .query('storage/record')
135
+ .withId(id)
136
+ .enabled()
137
+ .resolve();
138
+ }
139
+ async ensureStorage() {
140
+ if (this.storageInitialized)
141
+ return;
142
+ this.sessionsStorage = await this.resolveStorageRecord('browser.sessions');
143
+ this.tabsStorage = await this.resolveStorageRecord('browser.tabs');
144
+ this.profilesStorage = await this.resolveStorageRecord('browser.profiles');
145
+ this.storageInitialized = true;
146
+ }
147
+ setMaxActiveSessions(maxActive) {
148
+ this.maxActive = maxActive;
149
+ }
150
+ setIdleTimeout(timeoutMs) {
151
+ this.idleTimeout = timeoutMs;
152
+ }
153
+ /** Start periodic cleanup of idle sessions */
154
+ startCleanupInterval() {
155
+ if (this.stopCleanupTimer)
156
+ return;
157
+ // A finite host (the CLI) starts no autonomous background work; its sessions are
158
+ // closed when the runtime host disposes (BrowserRuntimeManagerHost.dispose).
159
+ if (this.runtime.scope.lifecycle === 'finite')
160
+ return;
161
+ const logger = getLogger('control:browser-manager', this.runtime);
162
+ this.stopCleanupTimer = this.runtime.lifecycle.interval(async () => {
163
+ const cleaned = await settle(async () => {
164
+ await this.heartbeatSessions();
165
+ await this.cleanupIdleSessions();
166
+ });
167
+ if (!cleaned.ok)
168
+ logger.warn('browser session cleanup tick failed', { error: cleaned.cause });
169
+ }, DEFAULT_CLEANUP_INTERVAL_MS);
170
+ }
171
+ async heartbeatSessions() {
172
+ if (this.sessions.size === 0)
173
+ return;
174
+ await this.ensureStorage();
175
+ await Promise.all([...this.sessions.values()].map(async (runtimeSession) => this.sessionsStorage.update(runtimeSession.session.id, {
176
+ metadata: await withBrowserSessionLease(this.runtime, runtimeSession.session.metadata, {
177
+ instanceId: this.instanceId,
178
+ persistence: this.ephemeralSessions.has(runtimeSession.session.id)
179
+ ? 'ephemeral'
180
+ : 'persistent'
181
+ })
182
+ })));
183
+ }
184
+ /** Stop the cleanup interval */
185
+ stopCleanupInterval() {
186
+ this.stopCleanupTimer?.();
187
+ this.stopCleanupTimer = null;
188
+ }
189
+ /** Update activity timestamp for a session */
190
+ touchSession(sessionId) {
191
+ this.sessionActivity.set(sessionId, Date.now());
192
+ }
193
+ /** Get oldest idle session ID */
194
+ getOldestIdleSession() {
195
+ let oldest = null;
196
+ for (const [id, time] of this.sessionActivity.entries()) {
197
+ if (!oldest || time < oldest.time) {
198
+ oldest = { id, time };
199
+ }
200
+ }
201
+ return oldest?.id ?? null;
202
+ }
203
+ /** Close sessions that have been idle too long */
204
+ async cleanupIdleSessions() {
205
+ const now = Date.now();
206
+ const toClose = [];
207
+ for (const [id, lastActivity] of this.sessionActivity.entries()) {
208
+ if (now - lastActivity > this.idleTimeout) {
209
+ toClose.push(id);
210
+ }
211
+ }
212
+ const results = await Promise.allSettled(toClose.map((id) => this.closeSession(id)));
213
+ const failures = [];
214
+ for (const [index, result] of results.entries()) {
215
+ if (result.status === 'rejected')
216
+ failures.push(cleanupFailure(`idle-session:${toClose[index]}`, CaughtFailureSchema.parse(result.reason)));
217
+ }
218
+ throwCleanupFailures(failures, 'Idle browser session cleanup');
219
+ return toClose.length;
220
+ }
221
+ /** Ensure capacity, closing oldest idle session if needed */
222
+ async ensureCapacity() {
223
+ if (this.sessions.size < this.maxActive)
224
+ return;
225
+ // Try to close oldest idle session first
226
+ const oldest = this.getOldestIdleSession();
227
+ if (oldest) {
228
+ await this.closeSession(oldest);
229
+ return;
230
+ }
231
+ throw new Error(`Maximum active browser sessions (${this.maxActive}) exceeded`);
232
+ }
233
+ async getOrCreateSession(sessionOptions, launchOptions) {
234
+ // Validate host-declared trust before creating records, profiles, or browsers.
235
+ sessionBaseOrigins(sessionOptions?.baseUrl);
236
+ await this.ensureStorage();
237
+ const mode = sessionOptions?.mode ?? 'ephemeral';
238
+ const shouldPersist = sessionOptions?.persist === true || mode !== 'ephemeral';
239
+ if (shouldPersist && !this.backend.capabilities.storageStateFile) {
240
+ throw new CapabilityError(`Browser backend '${this.backend.id}' does not support persistent session storage`, 'UNAVAILABLE', { reason: 'browser-backend-capability-unsupported', details: { backendId: this.backend.id, feature: 'storage-state' } });
241
+ }
242
+ if (sessionOptions?.profile && !this.backend.capabilities.profiles) {
243
+ throw new CapabilityError(`Browser backend '${this.backend.id}' does not support profiles`, 'UNAVAILABLE', { reason: 'browser-backend-capability-unsupported', details: { backendId: this.backend.id } });
244
+ }
245
+ if (launchOptions?.recordVideo?.enabled && !this.backend.capabilities.recording) {
246
+ throw new CapabilityError(`Browser backend '${this.backend.id}' does not support video recording`, 'UNAVAILABLE', { reason: 'browser-backend-capability-unsupported', details: { backendId: this.backend.id } });
247
+ }
248
+ const requestedIdOrName = sessionOptions?.id ?? sessionOptions?.name ?? '';
249
+ if (requestedIdOrName) {
250
+ const existing = this.sessions.get(requestedIdOrName);
251
+ if (existing)
252
+ return existing;
253
+ const aliasId = this.sessionAliases.get(requestedIdOrName);
254
+ const aliased = aliasId ? this.sessions.get(aliasId) : undefined;
255
+ if (aliased)
256
+ return aliased;
257
+ }
258
+ let sessionRecord = null;
259
+ if (requestedIdOrName && shouldPersist) {
260
+ sessionRecord = await this.sessionsStorage.get(requestedIdOrName);
261
+ // Fall back to name-based lookup when requestedIdOrName is not a UUID
262
+ if (!sessionRecord) {
263
+ const byName = await this.sessionsStorage.list({
264
+ where: { name: requestedIdOrName },
265
+ limit: 1
266
+ });
267
+ sessionRecord = byName.items[0] ?? null;
268
+ }
269
+ }
270
+ if (!sessionRecord && mode === 'load' && shouldPersist) {
271
+ throw new Error(`Browser session not found: ${requestedIdOrName}`);
272
+ }
273
+ if (!sessionRecord) {
274
+ await this.ensureCapacity();
275
+ const sessionId = sessionOptions?.id ?? crypto.randomUUID();
276
+ const name = sessionOptions?.name ?? `browser-session-${sessionId.slice(0, 8)}`;
277
+ const storageDir = resolveStorageDir(this.workspacePath);
278
+ const storageStatePath = shouldPersist ? `${storageDir}/${sessionId}.json` : undefined;
279
+ let profileId;
280
+ let profileDir;
281
+ if (sessionOptions?.profile?.name || sessionOptions?.profile?.id) {
282
+ const profileKey = sessionOptions.profile.id ?? sessionOptions.profile.name ?? '';
283
+ const profileMode = sessionOptions.profile.mode ?? 'upsert';
284
+ const existingProfile = profileKey ? await this.profilesStorage.get(profileKey) : null;
285
+ if (!existingProfile && profileMode === 'load') {
286
+ throw new Error(`Browser profile not found: ${profileKey}`);
287
+ }
288
+ if (existingProfile) {
289
+ profileId = existingProfile.id;
290
+ profileDir = existingProfile.dirPath;
291
+ await this.profilesStorage.update(existingProfile.id, {
292
+ lastUsedAt: new Date().toISOString()
293
+ });
294
+ }
295
+ else {
296
+ const newProfileId = sessionOptions.profile.id ?? crypto.randomUUID();
297
+ profileDir = `${resolveProfilesDir(this.workspacePath)}/${newProfileId}`;
298
+ const newProfile = await this.profilesStorage.create({
299
+ id: newProfileId,
300
+ name: sessionOptions.profile.name ?? `profile-${newProfileId.slice(0, 8)}`,
301
+ dirPath: profileDir,
302
+ createdAt: new Date().toISOString(),
303
+ lastUsedAt: new Date().toISOString()
304
+ });
305
+ profileId = newProfile.id;
306
+ }
307
+ }
308
+ // Always persist session to DB to satisfy FK constraint for tabs.
309
+ // Ephemeral sessions can be cleaned up when the session closes.
310
+ sessionRecord = await this.sessionsStorage.create({
311
+ id: sessionId,
312
+ name,
313
+ baseUrl: sessionOptions?.baseUrl,
314
+ profileId,
315
+ storageStatePath,
316
+ createdAt: new Date().toISOString(),
317
+ lastUsedAt: new Date().toISOString(),
318
+ status: 'active',
319
+ metadata: await withBrowserSessionLease(this.runtime, undefined, {
320
+ instanceId: this.instanceId,
321
+ persistence: shouldPersist ? 'persistent' : 'ephemeral'
322
+ })
323
+ });
324
+ }
325
+ const storageStatePath = sessionRecord.storageStatePath;
326
+ const hasStorageState = storageStatePath
327
+ ? (await statChecked(await resolveFileSystemAdapter(this.runtime), storageStatePath)).found
328
+ : false;
329
+ const profileDir = sessionRecord.profileId
330
+ ? (await this.profilesStorage.get(sessionRecord.profileId))?.dirPath
331
+ : undefined;
332
+ const launched = await this.backend.launch(toBackendLaunchInput(this.runtime, launchOptions, {
333
+ profileDir,
334
+ extensions: sessionOptions?.extensions,
335
+ storageStatePath: hasStorageState ? storageStatePath : undefined,
336
+ trustedOrigins: sessionTrustedOriginList(sessionRecord.baseUrl)
337
+ }));
338
+ const runtimeSession = {
339
+ session: sessionRecord,
340
+ context: launched.context,
341
+ persistent: launched.persistent
342
+ };
343
+ this.sessions.set(sessionRecord.id, runtimeSession);
344
+ this.sessionAliases.set(sessionRecord.name, sessionRecord.id);
345
+ this.touchSession(sessionRecord.id);
346
+ if (!shouldPersist) {
347
+ this.ephemeralSessions.add(sessionRecord.id);
348
+ }
349
+ await this.sessionsStorage.update(sessionRecord.id, {
350
+ lastUsedAt: new Date().toISOString(),
351
+ status: 'active',
352
+ metadata: await withBrowserSessionLease(this.runtime, sessionRecord.metadata, {
353
+ instanceId: this.instanceId,
354
+ persistence: shouldPersist ? 'persistent' : 'ephemeral'
355
+ })
356
+ });
357
+ return runtimeSession;
358
+ }
359
+ async getOrCreateTab(runtimeSession, url, tabOptions) {
360
+ await this.ensureStorage();
361
+ const trustedOrigins = sessionTrustedOrigins(this.runtime, runtimeSession.session.baseUrl);
362
+ const tabId = tabOptions?.id;
363
+ const forceNew = tabOptions?.newTab === true;
364
+ // Return specific tab by ID if it exists
365
+ const existingTab = tabId ? this.tabs.get(tabId) : undefined;
366
+ if (existingTab && !forceNew)
367
+ return existingTab;
368
+ // Reuse the most recent open tab for this session when no tab is specified
369
+ if (!tabId && !forceNew) {
370
+ const sessionTab = this.getActiveTabForSession(runtimeSession.session.id);
371
+ if (sessionTab) {
372
+ // Navigate if URL provided and different from current
373
+ if (url && sessionTab.page.url() !== url) {
374
+ await sessionTab.page.goto(assertSafeBrowserUrl(url, trustedOrigins), {
375
+ waitUntil: 'domcontentloaded',
376
+ timeout: 30000
377
+ });
378
+ }
379
+ this.touchSession(runtimeSession.session.id);
380
+ return sessionTab;
381
+ }
382
+ }
383
+ const page = await runtimeSession.context.newPage();
384
+ if (url) {
385
+ await page.goto(assertSafeBrowserUrl(url, trustedOrigins), {
386
+ waitUntil: 'domcontentloaded',
387
+ timeout: 30000
388
+ });
389
+ }
390
+ const newTabId = forceNew ? crypto.randomUUID() : (tabId ?? crypto.randomUUID());
391
+ const tabRecord = await this.tabsStorage.create({
392
+ id: newTabId,
393
+ sessionId: runtimeSession.session.id,
394
+ url: url ?? undefined,
395
+ createdAt: new Date().toISOString(),
396
+ lastActiveAt: new Date().toISOString(),
397
+ status: 'open'
398
+ });
399
+ const runtimeTab = { tab: tabRecord, page };
400
+ this.tabs.set(newTabId, runtimeTab);
401
+ this.touchSession(runtimeSession.session.id);
402
+ return runtimeTab;
403
+ }
404
+ /** Find the most recent active tab for a session */
405
+ getActiveTabForSession(sessionId) {
406
+ let latestTab;
407
+ let latestTime = 0;
408
+ for (const tab of this.tabs.values()) {
409
+ if (tab.tab.sessionId === sessionId && tab.tab.status === 'open') {
410
+ const time = new Date(tab.tab.lastActiveAt).getTime();
411
+ if (!latestTab || time > latestTime) {
412
+ latestTab = tab;
413
+ latestTime = time;
414
+ }
415
+ }
416
+ }
417
+ return latestTab;
418
+ }
419
+ async updateTabUrl(tabId, page) {
420
+ await this.ensureStorage();
421
+ await this.tabsStorage.update(tabId, {
422
+ url: page.url(),
423
+ status: 'open',
424
+ lastActiveAt: new Date().toISOString()
425
+ });
426
+ }
427
+ async closeTab(tabId) {
428
+ await this.ensureStorage();
429
+ const runtimeTab = this.tabs.get(tabId);
430
+ if (!runtimeTab)
431
+ return;
432
+ if (!this.closedTabs.has(tabId)) {
433
+ await runtimeTab.page.close();
434
+ this.closedTabs.add(tabId);
435
+ }
436
+ await this.tabsStorage.update(tabId, {
437
+ status: 'closed',
438
+ lastActiveAt: new Date().toISOString()
439
+ });
440
+ this.tabs.delete(tabId);
441
+ this.closedTabs.delete(tabId);
442
+ }
443
+ async closeSession(sessionId) {
444
+ const runtimeSession = this.sessions.get(sessionId);
445
+ if (!runtimeSession)
446
+ return;
447
+ const failures = [];
448
+ const wasEphemeral = this.ephemeralSessions.has(sessionId);
449
+ const sessionTabs = [...this.tabs.entries()].filter(([, tab]) => tab.tab.sessionId === sessionId);
450
+ if (!this.closedContexts.has(sessionId)) {
451
+ const results = await Promise.allSettled(sessionTabs.map(async ([tabId, tab]) => {
452
+ if (!this.closedTabs.has(tabId)) {
453
+ await tab.page.close();
454
+ this.closedTabs.add(tabId);
455
+ }
456
+ }));
457
+ for (const [index, result] of results.entries()) {
458
+ if (result.status === 'rejected') {
459
+ failures.push(cleanupFailure(`session:${sessionId}:tab:${sessionTabs[index]?.[0]}`, CaughtFailureSchema.parse(result.reason)));
460
+ }
461
+ }
462
+ const closed = await settle(() => runtimeSession.context.close());
463
+ if (closed.ok) {
464
+ this.closedContexts.add(sessionId);
465
+ for (const [tabId] of sessionTabs)
466
+ this.closedTabs.add(tabId);
467
+ }
468
+ else {
469
+ failures.push(cleanupFailure(`session:${sessionId}:context`, closed.cause));
470
+ }
471
+ }
472
+ throwCleanupFailures(failures, `Browser session '${sessionId}' cleanup`);
473
+ // Keep the complete session and tab custody until every storage operation
474
+ // succeeds. A retry skips resources already closed, then retries persistence.
475
+ await this.ensureStorage();
476
+ for (const [tabId] of sessionTabs) {
477
+ if (wasEphemeral)
478
+ await this.tabsStorage.delete(tabId);
479
+ else
480
+ await this.tabsStorage.update(tabId, { status: 'closed', lastActiveAt: new Date().toISOString() });
481
+ }
482
+ if (wasEphemeral)
483
+ await this.sessionsStorage.delete(sessionId);
484
+ else
485
+ await this.sessionsStorage.update(sessionId, {
486
+ status: 'closed',
487
+ metadata: closeBrowserSessionLease(runtimeSession.session.metadata, 'closed')
488
+ });
489
+ for (const [tabId] of sessionTabs) {
490
+ this.tabs.delete(tabId);
491
+ this.closedTabs.delete(tabId);
492
+ }
493
+ this.closedContexts.delete(sessionId);
494
+ this.ephemeralSessions.delete(sessionId);
495
+ this.sessions.delete(sessionId);
496
+ this.sessionAliases.delete(runtimeSession.session.name);
497
+ this.sessionActivity.delete(sessionId);
498
+ }
499
+ async persistSessionState(runtimeSession) {
500
+ if (!this.backend.capabilities.storageStateFile) {
501
+ throw new CapabilityError(`Browser backend '${this.backend.id}' does not support persistent session storage`, 'UNAVAILABLE', { reason: 'browser-backend-capability-unsupported', details: { backendId: this.backend.id, feature: 'storage-state' } });
502
+ }
503
+ await this.ensureStorage();
504
+ let path = runtimeSession.session.storageStatePath;
505
+ if (!path) {
506
+ // Upgrade ephemeral session to persistent: assign a storage path and stop treating
507
+ // it as ephemeral so closeSession won't delete the DB record on cleanup.
508
+ const storageDir = resolveStorageDir(this.workspacePath);
509
+ await (await resolveFileSystemAdapter(this.runtime)).mkdir(storageDir, { recursive: true });
510
+ path = `${storageDir}/${runtimeSession.session.id}.json`;
511
+ }
512
+ await runtimeSession.context.storageState({ path });
513
+ await this.sessionsStorage.update(runtimeSession.session.id, {
514
+ storageStatePath: path,
515
+ lastUsedAt: new Date().toISOString()
516
+ });
517
+ runtimeSession.session.storageStatePath = path;
518
+ this.ephemeralSessions.delete(runtimeSession.session.id);
519
+ this.touchSession(runtimeSession.session.id);
520
+ }
521
+ /**
522
+ * Get a runtime session by ID/name from memory, or re-load it from the DB
523
+ * (re-creating its Playwright context) if the MCP server restarted.
524
+ */
525
+ async getOrLoadSession(idOrName) {
526
+ // Check in-memory first
527
+ const inMemory = this.getRuntimeSession(idOrName);
528
+ if (inMemory)
529
+ return inMemory;
530
+ if (!this.backend.capabilities.storageStateFile) {
531
+ throw new Error(`Browser backend '${this.backend.id}' does not support loading persistent sessions`);
532
+ }
533
+ // Try to load from DB by ID or name
534
+ await this.ensureStorage();
535
+ let sessionRecord = await this.sessionsStorage.get(idOrName);
536
+ if (!sessionRecord) {
537
+ const byName = await this.sessionsStorage.list({ where: { name: idOrName }, limit: 1 });
538
+ sessionRecord = byName.items[0] ?? null;
539
+ }
540
+ if (!sessionRecord)
541
+ return null;
542
+ // Re-create the Playwright context from stored state
543
+ const storageStatePath = sessionRecord.storageStatePath;
544
+ const hasStorageState = storageStatePath
545
+ ? (await statChecked(await resolveFileSystemAdapter(this.runtime), storageStatePath)).found
546
+ : false;
547
+ const launched = await this.backend.launch(toBackendLaunchInput(this.runtime, { headless: true }, {
548
+ storageStatePath: hasStorageState ? storageStatePath : undefined,
549
+ trustedOrigins: sessionTrustedOriginList(sessionRecord.baseUrl)
550
+ }));
551
+ const runtimeSession = {
552
+ session: sessionRecord,
553
+ context: launched.context,
554
+ persistent: launched.persistent
555
+ };
556
+ this.sessions.set(sessionRecord.id, runtimeSession);
557
+ this.sessionAliases.set(sessionRecord.name, sessionRecord.id);
558
+ this.touchSession(sessionRecord.id);
559
+ await this.sessionsStorage.update(sessionRecord.id, { lastUsedAt: new Date().toISOString() });
560
+ return runtimeSession;
561
+ }
562
+ /**
563
+ * Present a session in a headed browser window and raise it to the foreground.
564
+ *
565
+ * Persists the session's cookies/storage state and opens a new headed browser
566
+ * pre-loaded with that state. On macOS, activates the window via System Events.
567
+ * Call dismissPresentation() to close the presentation browser.
568
+ */
569
+ async presentSession(runtimeSessionInput, url) {
570
+ if (!this.backend.capabilities.present) {
571
+ throw new CapabilityError(`Browser backend '${this.backend.id}' does not support headed presentation`, 'UNAVAILABLE', { reason: 'browser-backend-capability-unsupported', details: { backendId: this.backend.id } });
572
+ }
573
+ const sessionId = runtimeSessionInput.session.id;
574
+ const presentedPages = this.presentationBrowser?.sessionId === sessionId
575
+ ? this.presentationBrowser.context.pages()
576
+ : [];
577
+ const presentedUrl = presentedPages[presentedPages.length - 1]?.url();
578
+ const activeTabUrl = this.getActiveTabForSession(sessionId)?.page.url();
579
+ const current = this.sessions.get(sessionId);
580
+ const contextPages = current?.context === runtimeSessionInput.context
581
+ ? await current.context.pages()
582
+ : [];
583
+ const contextUrl = contextPages[contextPages.length - 1]?.url();
584
+ const targetUrl = url ??
585
+ [presentedUrl, activeTabUrl, contextUrl, runtimeSessionInput.session.baseUrl].find((candidate) => candidate && candidate !== 'about:blank');
586
+ const safeTargetUrl = targetUrl
587
+ ? assertSafeBrowserUrl(targetUrl, sessionTrustedOrigins(this.runtime, runtimeSessionInput.session.baseUrl))
588
+ : undefined;
589
+ // Close any existing presentation first (saves state before closing)
590
+ await this.dismissPresentation();
591
+ // Dismissal intentionally evicts the old headless context after copying the
592
+ // headed browser's auth state. Always re-resolve so repeated presentation
593
+ // never persists or navigates a context that dismissal just closed.
594
+ const runtimeSession = await this.getOrLoadSession(sessionId);
595
+ if (!runtimeSession) {
596
+ throw new Error(`Browser session not found: ${sessionId}`);
597
+ }
598
+ // Persist state so the presentation browser loads the same cookies/storage
599
+ await this.persistSessionState(runtimeSession);
600
+ const storageStatePath = runtimeSession.session.storageStatePath;
601
+ // Launch a headed browser with the saved state
602
+ const presRuntime = await this.presentationLauncher(this.runtime, {
603
+ options: { headless: false },
604
+ storageStatePath: storageStatePath ?? undefined
605
+ });
606
+ this.presentationBrowser = {
607
+ context: presRuntime.context,
608
+ browser: presRuntime.browser,
609
+ sessionId: runtimeSession.session.id,
610
+ storageStatePath
611
+ };
612
+ // Navigate to the target URL
613
+ const page = await presRuntime.context.newPage();
614
+ if (safeTargetUrl) {
615
+ await page.goto(safeTargetUrl, {
616
+ waitUntil: 'domcontentloaded',
617
+ timeout: 30000
618
+ });
619
+ }
620
+ // Bring to front within Playwright's context
621
+ await page.bringToFront();
622
+ // Retain custody before activation so a refused activation can still be disposed.
623
+ await this.presentationActivator();
624
+ return { url: page.url() };
625
+ }
626
+ /**
627
+ * Dismiss the current presentation browser (if any).
628
+ * Saves the presentation browser's auth state back to the headless session before closing,
629
+ * so that any credentials entered in the headed browser are available to subsequent tool calls.
630
+ */
631
+ async dismissPresentation(evictSession = true) {
632
+ if (!this.presentationBrowser)
633
+ return;
634
+ const presentation = this.presentationBrowser;
635
+ const { context, browser, sessionId } = presentation;
636
+ const failures = [];
637
+ // Auth state must reach storage before its only context can be discarded.
638
+ const runtimeSession = sessionId ? this.sessions.get(sessionId) : undefined;
639
+ const path = presentation.storageStatePath ?? runtimeSession?.session.storageStatePath;
640
+ if (path && !presentation.contextClosed)
641
+ await context.storageState({ path });
642
+ if (!presentation.contextClosed) {
643
+ const closed = await settle(() => context.close());
644
+ if (closed.ok)
645
+ presentation.contextClosed = true;
646
+ else
647
+ failures.push(cleanupFailure(`presentation:${sessionId ?? 'unbound'}:context`, closed.cause));
648
+ }
649
+ if (browser && !presentation.browserClosed) {
650
+ const closed = await settle(() => browser.close());
651
+ if (closed.ok)
652
+ presentation.browserClosed = true;
653
+ else
654
+ failures.push(cleanupFailure(`presentation:${sessionId ?? 'unbound'}:browser`, closed.cause));
655
+ }
656
+ throwCleanupFailures(failures, 'Browser presentation cleanup');
657
+ // Evict stale headless custody only after both presentation resources close.
658
+ if (runtimeSession && sessionId && evictSession) {
659
+ await runtimeSession.context.close();
660
+ this.sessions.delete(sessionId);
661
+ this.sessionAliases.delete(runtimeSession.session.name);
662
+ for (const [tabId, tab] of this.tabs) {
663
+ if (tab.tab.sessionId === sessionId) {
664
+ this.tabs.delete(tabId);
665
+ this.closedTabs.delete(tabId);
666
+ }
667
+ }
668
+ this.sessionActivity.delete(sessionId);
669
+ }
670
+ this.presentationBrowser = null;
671
+ }
672
+ /** Close all active sessions under an explicit runtime/host lifecycle owner. */
673
+ closeAllSessions() {
674
+ if (this.closeAllPromise)
675
+ return this.closeAllPromise;
676
+ this.stopCleanupInterval();
677
+ const closeOperation = (async () => {
678
+ const failures = [];
679
+ const dismissed = await settle(() => this.dismissPresentation(false));
680
+ if (!dismissed.ok)
681
+ failures.push(cleanupFailure('presentation', dismissed.cause));
682
+ const sessionIds = [...this.sessions.keys()];
683
+ const results = await Promise.allSettled(sessionIds.map((id) => this.closeSession(id)));
684
+ for (let index = 0; index < results.length; index++) {
685
+ const result = results[index];
686
+ if (result?.status !== 'rejected')
687
+ continue;
688
+ const id = sessionIds[index] ?? `session-${index + 1}`;
689
+ failures.push(cleanupFailure(`session:${id}`, CaughtFailureSchema.parse(result.reason)));
690
+ }
691
+ throwCleanupFailures(failures, 'Browser manager cleanup');
692
+ })();
693
+ this.closeAllPromise = closeOperation.finally(() => {
694
+ this.closeAllPromise = null;
695
+ });
696
+ return this.closeAllPromise;
697
+ }
698
+ /** Get active session count */
699
+ getActiveSessionCount() {
700
+ return this.sessions.size;
701
+ }
702
+ /** Get session IDs with their last activity time */
703
+ getSessionActivity() {
704
+ return new Map(this.sessionActivity);
705
+ }
706
+ /**
707
+ * Get an active runtime session by ID or name.
708
+ * If idOrName is omitted, returns the most recently active session.
709
+ */
710
+ getRuntimeSession(idOrName) {
711
+ if (!idOrName) {
712
+ // Most recently active session
713
+ let latestId = null;
714
+ let latestTime = 0;
715
+ for (const [id, time] of this.sessionActivity.entries()) {
716
+ if (time > latestTime) {
717
+ latestTime = time;
718
+ latestId = id;
719
+ }
720
+ }
721
+ return latestId ? this.sessions.get(latestId) : undefined;
722
+ }
723
+ if (this.sessions.has(idOrName))
724
+ return this.sessions.get(idOrName);
725
+ const aliasId = this.sessionAliases.get(idOrName);
726
+ if (aliasId)
727
+ return this.sessions.get(aliasId);
728
+ return undefined;
729
+ }
730
+ }
731
+ //# sourceMappingURL=manager.js.map