@amalgm/browser 0.1.2-preview.35541635545 → 0.1.2-preview.37254096068

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 (390) hide show
  1. package/PURPOSE.md +119 -97
  2. package/README.md +51 -56
  3. package/SECURITY.md +10 -8
  4. package/dist/bin/amalgm-browser-mcp.js +2 -3
  5. package/dist/bin/amalgm-browser-mcp.js.map +1 -1
  6. package/dist/bin/amalgm-browser-rest.js +8 -18
  7. package/dist/bin/amalgm-browser-rest.js.map +1 -1
  8. package/dist/src/account.d.ts +8 -0
  9. package/dist/src/account.js +42 -0
  10. package/dist/src/account.js.map +1 -0
  11. package/dist/src/action.d.ts +1 -2
  12. package/dist/src/action.js +3 -7
  13. package/dist/src/action.js.map +1 -1
  14. package/dist/src/adapters/cli/actions.d.ts +0 -1
  15. package/dist/src/adapters/cli/actions.js +0 -7
  16. package/dist/src/adapters/cli/actions.js.map +1 -1
  17. package/dist/src/adapters/cli/help.d.ts +1 -1
  18. package/dist/src/adapters/cli/help.js +1 -4
  19. package/dist/src/adapters/cli/help.js.map +1 -1
  20. package/dist/src/adapters/cli/resources.js +0 -22
  21. package/dist/src/adapters/cli/resources.js.map +1 -1
  22. package/dist/src/adapters/cli/run.js +25 -19
  23. package/dist/src/adapters/cli/run.js.map +1 -1
  24. package/dist/src/adapters/execute.js +2 -2
  25. package/dist/src/adapters/execute.js.map +1 -1
  26. package/dist/src/adapters/http/events.d.ts +5 -2
  27. package/dist/src/adapters/http/events.js +18 -2
  28. package/dist/src/adapters/http/events.js.map +1 -1
  29. package/dist/src/adapters/http/internal-routes.js +9 -4
  30. package/dist/src/adapters/http/internal-routes.js.map +1 -1
  31. package/dist/src/adapters/http/navigation-stream.d.ts +4 -0
  32. package/dist/src/adapters/http/navigation-stream.js +17 -0
  33. package/dist/src/adapters/http/navigation-stream.js.map +1 -0
  34. package/dist/src/adapters/http/openapi.js +2 -8
  35. package/dist/src/adapters/http/openapi.js.map +1 -1
  36. package/dist/src/adapters/http/server.js +54 -14
  37. package/dist/src/adapters/http/server.js.map +1 -1
  38. package/dist/src/adapters/http/session-routes.js +0 -1
  39. package/dist/src/adapters/http/session-routes.js.map +1 -1
  40. package/dist/src/adapters/http/stream.d.ts +6 -0
  41. package/dist/src/adapters/http/stream.js +89 -0
  42. package/dist/src/adapters/http/stream.js.map +1 -0
  43. package/dist/src/adapters/mcp/server.js +2 -2
  44. package/dist/src/adapters/mcp/server.js.map +1 -1
  45. package/dist/src/adapters/mcp/tools.js +2 -4
  46. package/dist/src/adapters/mcp/tools.js.map +1 -1
  47. package/dist/src/adapters/mcp/types.d.ts +3 -2
  48. package/dist/src/adapters/toolbox/manifest.js +1 -1
  49. package/dist/src/adapters/toolbox/manifest.js.map +1 -1
  50. package/dist/src/auth/login.d.ts +3 -1
  51. package/dist/src/auth/login.js +48 -33
  52. package/dist/src/auth/login.js.map +1 -1
  53. package/dist/src/auth/service.js +56 -67
  54. package/dist/src/auth/service.js.map +1 -1
  55. package/dist/src/{drivers/cdp → cdp}/capture.d.ts +1 -1
  56. package/dist/src/{drivers/cdp → cdp}/capture.js +1 -1
  57. package/dist/src/cdp/capture.js.map +1 -0
  58. package/dist/src/{drivers/cdp → cdp}/client.d.ts +3 -1
  59. package/dist/src/{drivers/cdp → cdp}/client.js +51 -14
  60. package/dist/src/cdp/client.js.map +1 -0
  61. package/dist/src/cdp/input.js.map +1 -0
  62. package/dist/src/cdp/navigation.d.ts +5 -0
  63. package/dist/src/cdp/navigation.js +47 -0
  64. package/dist/src/cdp/navigation.js.map +1 -0
  65. package/dist/src/{drivers/cdp → cdp}/screencast.js +1 -1
  66. package/dist/src/cdp/screencast.js.map +1 -0
  67. package/dist/src/chrome/cookie-adapter.d.ts +23 -0
  68. package/dist/src/chrome/cookie-adapter.js +74 -0
  69. package/dist/src/chrome/cookie-adapter.js.map +1 -0
  70. package/dist/src/chrome/cookie-changes.d.ts +12 -0
  71. package/dist/src/chrome/cookie-changes.js +100 -0
  72. package/dist/src/chrome/cookie-changes.js.map +1 -0
  73. package/dist/src/chrome/cookie-observer.d.ts +20 -0
  74. package/dist/src/chrome/cookie-observer.js +44 -0
  75. package/dist/src/chrome/cookie-observer.js.map +1 -0
  76. package/dist/src/chrome/executable.d.ts +1 -0
  77. package/dist/src/chrome/executable.js +55 -0
  78. package/dist/src/chrome/executable.js.map +1 -0
  79. package/dist/src/chrome/flags.d.ts +7 -0
  80. package/dist/src/chrome/flags.js +59 -0
  81. package/dist/src/chrome/flags.js.map +1 -0
  82. package/dist/src/chrome/host.d.ts +25 -0
  83. package/dist/src/chrome/host.js +137 -0
  84. package/dist/src/chrome/host.js.map +1 -0
  85. package/dist/src/chrome/launch.d.ts +11 -0
  86. package/dist/src/chrome/launch.js +105 -0
  87. package/dist/src/chrome/launch.js.map +1 -0
  88. package/dist/src/chrome/relay/editing.d.ts +2 -0
  89. package/dist/src/chrome/relay/editing.js +14 -0
  90. package/dist/src/chrome/relay/editing.js.map +1 -0
  91. package/dist/src/chrome/relay/server.d.ts +18 -0
  92. package/dist/src/chrome/relay/server.js +120 -0
  93. package/dist/src/chrome/relay/server.js.map +1 -0
  94. package/dist/src/chrome/relay/targets.d.ts +11 -0
  95. package/dist/src/chrome/relay/targets.js +59 -0
  96. package/dist/src/chrome/relay/targets.js.map +1 -0
  97. package/dist/src/chrome/relay/view.d.ts +34 -0
  98. package/dist/src/chrome/relay/view.js +185 -0
  99. package/dist/src/chrome/relay/view.js.map +1 -0
  100. package/dist/src/cookies/adapter-credential.d.ts +6 -0
  101. package/dist/src/cookies/adapter-credential.js +33 -0
  102. package/dist/src/cookies/adapter-credential.js.map +1 -0
  103. package/dist/src/cookies/coordinator.d.ts +14 -13
  104. package/dist/src/cookies/coordinator.js +157 -75
  105. package/dist/src/cookies/coordinator.js.map +1 -1
  106. package/dist/src/cookies/database.d.ts +29 -0
  107. package/dist/src/cookies/database.js +113 -0
  108. package/dist/src/cookies/database.js.map +1 -0
  109. package/dist/src/cookies/diff.d.ts +6 -0
  110. package/dist/src/cookies/diff.js +19 -0
  111. package/dist/src/cookies/diff.js.map +1 -0
  112. package/dist/src/cookies/http-store.d.ts +7 -0
  113. package/dist/src/cookies/http-store.js +105 -0
  114. package/dist/src/cookies/http-store.js.map +1 -0
  115. package/dist/src/cookies/jar.d.ts +12 -11
  116. package/dist/src/cookies/jar.js +128 -120
  117. package/dist/src/cookies/jar.js.map +1 -1
  118. package/dist/src/cookies/policy.js +10 -4
  119. package/dist/src/cookies/policy.js.map +1 -1
  120. package/dist/src/cookies/secret-file.d.ts +4 -0
  121. package/dist/src/cookies/secret-file.js +47 -9
  122. package/dist/src/cookies/secret-file.js.map +1 -1
  123. package/dist/src/cookies/types.d.ts +34 -2
  124. package/dist/src/cookies.d.ts +2 -0
  125. package/dist/src/cookies.js +2 -0
  126. package/dist/src/cookies.js.map +1 -1
  127. package/dist/src/defaults.d.ts +1 -5
  128. package/dist/src/defaults.js +49 -58
  129. package/dist/src/defaults.js.map +1 -1
  130. package/dist/src/driver/cli-policy.d.ts +1 -0
  131. package/dist/src/driver/cli-policy.js +17 -0
  132. package/dist/src/driver/cli-policy.js.map +1 -0
  133. package/dist/src/{drivers/headless → driver}/command.d.ts +3 -7
  134. package/dist/src/{drivers/headless → driver}/command.js +29 -29
  135. package/dist/src/driver/command.js.map +1 -0
  136. package/dist/src/{drivers/headless → driver}/driver.d.ts +13 -10
  137. package/dist/src/{drivers/headless → driver}/driver.js +67 -82
  138. package/dist/src/driver/driver.js.map +1 -0
  139. package/dist/src/{interaction/delta.d.ts → driver/evidence.d.ts} +3 -2
  140. package/dist/src/{interaction/delta.js → driver/evidence.js} +6 -3
  141. package/dist/src/driver/evidence.js.map +1 -0
  142. package/dist/src/driver/executable.js.map +1 -0
  143. package/dist/src/driver/stream.d.ts +1 -0
  144. package/dist/src/driver/stream.js +22 -0
  145. package/dist/src/driver/stream.js.map +1 -0
  146. package/dist/src/driver/wait.d.ts +6 -0
  147. package/dist/src/driver/wait.js +28 -0
  148. package/dist/src/driver/wait.js.map +1 -0
  149. package/dist/src/electron/adblock/cache.js.map +1 -0
  150. package/dist/src/electron/adblock/cosmetics.js.map +1 -0
  151. package/dist/src/{drivers/electron/native → electron}/adblock/index.d.ts +0 -1
  152. package/dist/src/{drivers/electron/native → electron}/adblock/index.js +0 -1
  153. package/dist/src/{drivers/electron/native → electron}/adblock/index.js.map +1 -1
  154. package/dist/src/electron/adblock/policy.js.map +1 -0
  155. package/dist/src/electron/adblock/preload.js.map +1 -0
  156. package/dist/src/electron/adblock/settings.js.map +1 -0
  157. package/dist/src/{drivers/electron/native → electron}/contracts.d.ts +0 -14
  158. package/dist/src/{drivers/electron/native → electron}/contracts.js +0 -1
  159. package/dist/src/electron/contracts.js.map +1 -0
  160. package/dist/src/{drivers/electron → electron}/cookie-adapter.d.ts +4 -4
  161. package/dist/src/{drivers/electron → electron}/cookie-adapter.js +9 -6
  162. package/dist/src/electron/cookie-adapter.js.map +1 -0
  163. package/dist/src/electron/cookie-sync.d.ts +6 -0
  164. package/dist/src/electron/cookie-sync.js +18 -0
  165. package/dist/src/electron/cookie-sync.js.map +1 -0
  166. package/dist/src/electron/policy.js.map +1 -0
  167. package/dist/src/electron/session.d.ts +2 -0
  168. package/dist/src/electron/session.js +9 -0
  169. package/dist/src/electron/session.js.map +1 -0
  170. package/dist/src/electron/shell/adblock-ipc.js.map +1 -0
  171. package/dist/src/electron/shell/context-menu.js.map +1 -0
  172. package/dist/src/electron/shell/downloads.js.map +1 -0
  173. package/dist/src/electron/shell/helpers.js.map +1 -0
  174. package/dist/src/electron/shell/permissions.js.map +1 -0
  175. package/dist/src/{drivers/electron/native → electron}/shell/sites.d.ts +1 -3
  176. package/dist/src/{drivers/electron/native → electron}/shell/sites.js +2 -34
  177. package/dist/src/electron/shell/sites.js.map +1 -0
  178. package/dist/src/{drivers/electron/native → electron}/shell/types.d.ts +0 -1
  179. package/dist/src/electron/shell/types.js.map +1 -0
  180. package/dist/src/electron/shell.d.ts +13 -0
  181. package/dist/src/electron/shell.js +73 -0
  182. package/dist/src/electron/shell.js.map +1 -0
  183. package/dist/src/electron/surface/commands.js.map +1 -0
  184. package/dist/src/{drivers/electron/native → electron}/surface/create.js +0 -6
  185. package/dist/src/electron/surface/create.js.map +1 -0
  186. package/dist/src/{drivers/electron/native → electron}/surface/events.js +1 -13
  187. package/dist/src/electron/surface/events.js.map +1 -0
  188. package/dist/src/{drivers/electron/native → electron}/surface/presentation.d.ts +2 -9
  189. package/dist/src/electron/surface/presentation.js +29 -0
  190. package/dist/src/electron/surface/presentation.js.map +1 -0
  191. package/dist/src/{drivers/electron/native → electron}/surface/state.d.ts +5 -0
  192. package/dist/src/{drivers/electron/native → electron}/surface/state.js +10 -4
  193. package/dist/src/electron/surface/state.js.map +1 -0
  194. package/dist/src/{drivers/electron/native → electron}/surface/types.d.ts +2 -8
  195. package/dist/src/electron/surface/types.js.map +1 -0
  196. package/dist/src/{drivers/electron/native → electron}/surface-controller.js +9 -12
  197. package/dist/src/electron/surface-controller.js.map +1 -0
  198. package/dist/src/electron-preload.cjs +1 -1
  199. package/dist/src/electron.cjs +587 -820
  200. package/dist/src/electron.d.cts +4 -14
  201. package/dist/src/electron.d.ts +4 -14
  202. package/dist/src/electron.js +4 -14
  203. package/dist/src/electron.js.map +1 -1
  204. package/dist/src/errors.d.ts +1 -1
  205. package/dist/src/errors.js.map +1 -1
  206. package/dist/src/index.d.ts +2 -3
  207. package/dist/src/index.js +0 -2
  208. package/dist/src/index.js.map +1 -1
  209. package/dist/src/migration/legacy-migration.d.ts +0 -1
  210. package/dist/src/migration/legacy-migration.js +3 -9
  211. package/dist/src/migration/legacy-migration.js.map +1 -1
  212. package/dist/src/migration/legacy-rows.d.ts +1 -2
  213. package/dist/src/migration/legacy-rows.js +0 -14
  214. package/dist/src/migration/legacy-rows.js.map +1 -1
  215. package/dist/src/ports.d.ts +12 -15
  216. package/dist/src/ports.js.map +1 -1
  217. package/dist/src/process.d.ts +1 -0
  218. package/dist/src/process.js +11 -0
  219. package/dist/src/process.js.map +1 -1
  220. package/dist/src/product-service.d.ts +4 -6
  221. package/dist/src/product-service.js +21 -15
  222. package/dist/src/product-service.js.map +1 -1
  223. package/dist/src/recording/encoder.js +1 -1
  224. package/dist/src/recording/encoder.js.map +1 -1
  225. package/dist/src/recording/service.d.ts +4 -0
  226. package/dist/src/recording/service.js +72 -62
  227. package/dist/src/recording/service.js.map +1 -1
  228. package/dist/src/recording/source.js +1 -1
  229. package/dist/src/recording/source.js.map +1 -1
  230. package/dist/src/registry.d.ts +4 -0
  231. package/dist/src/registry.js +17 -0
  232. package/dist/src/registry.js.map +1 -1
  233. package/dist/src/service-options.d.ts +5 -7
  234. package/dist/src/service.d.ts +16 -18
  235. package/dist/src/service.js +108 -108
  236. package/dist/src/service.js.map +1 -1
  237. package/dist/src/sessions/operations.d.ts +12 -0
  238. package/dist/src/sessions/operations.js +56 -0
  239. package/dist/src/sessions/operations.js.map +1 -0
  240. package/dist/src/testing.d.ts +8 -4
  241. package/dist/src/testing.js +7 -5
  242. package/dist/src/testing.js.map +1 -1
  243. package/dist/src/types.d.ts +0 -39
  244. package/docs/ACTIONS.md +0 -4
  245. package/docs/ARCHITECTURE.md +51 -55
  246. package/docs/AUTHENTICATION.md +41 -36
  247. package/docs/AXIOMS.md +13 -11
  248. package/docs/CHROME.md +143 -0
  249. package/docs/CLI.md +63 -31
  250. package/docs/COMPATIBILITY.md +14 -23
  251. package/docs/COOKIES.md +95 -52
  252. package/docs/ELECTRON_INTEGRATION.md +84 -77
  253. package/docs/EVENTS.md +5 -9
  254. package/docs/MCP.md +10 -6
  255. package/docs/MIGRATION.md +43 -36
  256. package/docs/OPERATIONS.md +48 -40
  257. package/docs/README.md +5 -5
  258. package/docs/REALTIME_BOUNDARY.md +3 -3
  259. package/docs/RECORDING.md +16 -15
  260. package/docs/REST.md +57 -26
  261. package/docs/SDK.md +65 -55
  262. package/docs/SHELL_INTEGRATION.md +78 -36
  263. package/docs/TESTING.md +58 -42
  264. package/docs/TOOLBOX_INTEGRATION.md +9 -4
  265. package/docs/TROUBLESHOOTING.md +68 -40
  266. package/examples/basic.ts +1 -0
  267. package/package.json +8 -15
  268. package/skills/use-amalgm-browser/SKILL.md +16 -29
  269. package/skills/use-amalgm-browser/references/actions.md +2 -2
  270. package/dist/src/adapters/http/profile-routes.d.ts +0 -2
  271. package/dist/src/adapters/http/profile-routes.js +0 -42
  272. package/dist/src/adapters/http/profile-routes.js.map +0 -1
  273. package/dist/src/auth/transport.d.ts +0 -8
  274. package/dist/src/auth/transport.js +0 -45
  275. package/dist/src/auth/transport.js.map +0 -1
  276. package/dist/src/drivers/cdp/capture.js.map +0 -1
  277. package/dist/src/drivers/cdp/client.js.map +0 -1
  278. package/dist/src/drivers/cdp/input.js.map +0 -1
  279. package/dist/src/drivers/cdp/screencast.js.map +0 -1
  280. package/dist/src/drivers/cdp/target.d.ts +0 -4
  281. package/dist/src/drivers/cdp/target.js +0 -34
  282. package/dist/src/drivers/cdp/target.js.map +0 -1
  283. package/dist/src/drivers/electron/advertisement.d.ts +0 -12
  284. package/dist/src/drivers/electron/advertisement.js +0 -57
  285. package/dist/src/drivers/electron/advertisement.js.map +0 -1
  286. package/dist/src/drivers/electron/contracts.d.ts +0 -45
  287. package/dist/src/drivers/electron/contracts.js +0 -10
  288. package/dist/src/drivers/electron/contracts.js.map +0 -1
  289. package/dist/src/drivers/electron/cookie-adapter.js.map +0 -1
  290. package/dist/src/drivers/electron/driver.d.ts +0 -19
  291. package/dist/src/drivers/electron/driver.js +0 -115
  292. package/dist/src/drivers/electron/driver.js.map +0 -1
  293. package/dist/src/drivers/electron/native/adblock/cache.js.map +0 -1
  294. package/dist/src/drivers/electron/native/adblock/cosmetics.js.map +0 -1
  295. package/dist/src/drivers/electron/native/adblock/policy.js.map +0 -1
  296. package/dist/src/drivers/electron/native/adblock/preload.js.map +0 -1
  297. package/dist/src/drivers/electron/native/adblock/settings.js.map +0 -1
  298. package/dist/src/drivers/electron/native/config.d.ts +0 -4
  299. package/dist/src/drivers/electron/native/config.js +0 -9
  300. package/dist/src/drivers/electron/native/config.js.map +0 -1
  301. package/dist/src/drivers/electron/native/contracts.js.map +0 -1
  302. package/dist/src/drivers/electron/native/policy.js.map +0 -1
  303. package/dist/src/drivers/electron/native/session.d.ts +0 -4
  304. package/dist/src/drivers/electron/native/session.js +0 -11
  305. package/dist/src/drivers/electron/native/session.js.map +0 -1
  306. package/dist/src/drivers/electron/native/shell/adblock-ipc.js.map +0 -1
  307. package/dist/src/drivers/electron/native/shell/context-menu.js.map +0 -1
  308. package/dist/src/drivers/electron/native/shell/downloads.js.map +0 -1
  309. package/dist/src/drivers/electron/native/shell/helpers.js.map +0 -1
  310. package/dist/src/drivers/electron/native/shell/permissions.js.map +0 -1
  311. package/dist/src/drivers/electron/native/shell/sites.js.map +0 -1
  312. package/dist/src/drivers/electron/native/shell/types.js.map +0 -1
  313. package/dist/src/drivers/electron/native/shell.d.ts +0 -14
  314. package/dist/src/drivers/electron/native/shell.js +0 -115
  315. package/dist/src/drivers/electron/native/shell.js.map +0 -1
  316. package/dist/src/drivers/electron/native/surface/commands.js.map +0 -1
  317. package/dist/src/drivers/electron/native/surface/create.js.map +0 -1
  318. package/dist/src/drivers/electron/native/surface/events.js.map +0 -1
  319. package/dist/src/drivers/electron/native/surface/presentation.js +0 -87
  320. package/dist/src/drivers/electron/native/surface/presentation.js.map +0 -1
  321. package/dist/src/drivers/electron/native/surface/state.js.map +0 -1
  322. package/dist/src/drivers/electron/native/surface/types.js.map +0 -1
  323. package/dist/src/drivers/electron/native/surface-controller.js.map +0 -1
  324. package/dist/src/drivers/electron/policy.d.ts +0 -4
  325. package/dist/src/drivers/electron/policy.js +0 -39
  326. package/dist/src/drivers/electron/policy.js.map +0 -1
  327. package/dist/src/drivers/electron/session.d.ts +0 -4
  328. package/dist/src/drivers/electron/session.js +0 -5
  329. package/dist/src/drivers/electron/session.js.map +0 -1
  330. package/dist/src/drivers/headless/command.js.map +0 -1
  331. package/dist/src/drivers/headless/cookie-adapter.d.ts +0 -16
  332. package/dist/src/drivers/headless/cookie-adapter.js +0 -59
  333. package/dist/src/drivers/headless/cookie-adapter.js.map +0 -1
  334. package/dist/src/drivers/headless/driver.js.map +0 -1
  335. package/dist/src/drivers/headless/executable.js.map +0 -1
  336. package/dist/src/drivers/headless/screencast.d.ts +0 -3
  337. package/dist/src/drivers/headless/screencast.js +0 -21
  338. package/dist/src/drivers/headless/screencast.js.map +0 -1
  339. package/dist/src/headless.d.ts +0 -3
  340. package/dist/src/headless.js +0 -4
  341. package/dist/src/headless.js.map +0 -1
  342. package/dist/src/interaction/delta.js.map +0 -1
  343. package/dist/src/interaction/typing.d.ts +0 -39
  344. package/dist/src/interaction/typing.js +0 -189
  345. package/dist/src/interaction/typing.js.map +0 -1
  346. package/dist/src/profiles/directories.d.ts +0 -9
  347. package/dist/src/profiles/directories.js +0 -57
  348. package/dist/src/profiles/directories.js.map +0 -1
  349. package/dist/src/profiles/service.d.ts +0 -30
  350. package/dist/src/profiles/service.js +0 -89
  351. package/dist/src/profiles/service.js.map +0 -1
  352. package/dist/src/runtime-selector.d.ts +0 -12
  353. package/dist/src/runtime-selector.js +0 -72
  354. package/dist/src/runtime-selector.js.map +0 -1
  355. package/docs/HEADLESS_RUNTIME.md +0 -58
  356. package/examples/custom-driver.ts +0 -45
  357. /package/dist/src/{drivers/cdp → cdp}/input.d.ts +0 -0
  358. /package/dist/src/{drivers/cdp → cdp}/input.js +0 -0
  359. /package/dist/src/{drivers/cdp → cdp}/screencast.d.ts +0 -0
  360. /package/dist/src/{drivers/headless → driver}/executable.d.ts +0 -0
  361. /package/dist/src/{drivers/headless → driver}/executable.js +0 -0
  362. /package/dist/src/{drivers/electron/native → electron}/adblock/cache.d.ts +0 -0
  363. /package/dist/src/{drivers/electron/native → electron}/adblock/cache.js +0 -0
  364. /package/dist/src/{drivers/electron/native → electron}/adblock/cosmetics.d.ts +0 -0
  365. /package/dist/src/{drivers/electron/native → electron}/adblock/cosmetics.js +0 -0
  366. /package/dist/src/{drivers/electron/native → electron}/adblock/policy.d.ts +0 -0
  367. /package/dist/src/{drivers/electron/native → electron}/adblock/policy.js +0 -0
  368. /package/dist/src/{drivers/electron/native → electron}/adblock/preload.d.ts +0 -0
  369. /package/dist/src/{drivers/electron/native → electron}/adblock/preload.js +0 -0
  370. /package/dist/src/{drivers/electron/native → electron}/adblock/settings.d.ts +0 -0
  371. /package/dist/src/{drivers/electron/native → electron}/adblock/settings.js +0 -0
  372. /package/dist/src/{drivers/electron/native → electron}/policy.d.ts +0 -0
  373. /package/dist/src/{drivers/electron/native → electron}/policy.js +0 -0
  374. /package/dist/src/{drivers/electron/native → electron}/shell/adblock-ipc.d.ts +0 -0
  375. /package/dist/src/{drivers/electron/native → electron}/shell/adblock-ipc.js +0 -0
  376. /package/dist/src/{drivers/electron/native → electron}/shell/context-menu.d.ts +0 -0
  377. /package/dist/src/{drivers/electron/native → electron}/shell/context-menu.js +0 -0
  378. /package/dist/src/{drivers/electron/native → electron}/shell/downloads.d.ts +0 -0
  379. /package/dist/src/{drivers/electron/native → electron}/shell/downloads.js +0 -0
  380. /package/dist/src/{drivers/electron/native → electron}/shell/helpers.d.ts +0 -0
  381. /package/dist/src/{drivers/electron/native → electron}/shell/helpers.js +0 -0
  382. /package/dist/src/{drivers/electron/native → electron}/shell/permissions.d.ts +0 -0
  383. /package/dist/src/{drivers/electron/native → electron}/shell/permissions.js +0 -0
  384. /package/dist/src/{drivers/electron/native → electron}/shell/types.js +0 -0
  385. /package/dist/src/{drivers/electron/native → electron}/surface/commands.d.ts +0 -0
  386. /package/dist/src/{drivers/electron/native → electron}/surface/commands.js +0 -0
  387. /package/dist/src/{drivers/electron/native → electron}/surface/create.d.ts +0 -0
  388. /package/dist/src/{drivers/electron/native → electron}/surface/events.d.ts +0 -0
  389. /package/dist/src/{drivers/electron/native → electron}/surface/types.js +0 -0
  390. /package/dist/src/{drivers/electron/native → electron}/surface-controller.d.ts +0 -0
package/docs/TESTING.md CHANGED
@@ -1,62 +1,78 @@
1
1
  # Testing
2
2
 
3
3
  Tests are organized by invariant rather than implementation file. The default
4
- suite is deterministic and uses injected drivers/stores; opt-in suites exercise
5
- real browser processes.
4
+ suite is deterministic and uses injected drivers and stores; the real suite
5
+ drives real Chrome.
6
6
 
7
7
  ```sh
8
8
  npm run check # tree hygiene and strict TypeScript
9
9
  npm test # unit and transport contracts
10
10
  npx --no-install agent-browser install # provision Chrome for Testing
11
- npm run test:real # real headless Chromium
12
- npm run test:electron # real Electron; macOS
11
+ npm run test:real # real Chrome and agent-browser
13
12
  npm run verify # check, build, test, package/install
14
13
  ```
15
14
 
16
15
  ## Contract coverage
17
16
 
18
- - immutable backend/profile binding, restart reopen, leases, cancellation
19
- - all 22 actions reachable through SDK, CLI, MCP, REST, and Toolbox
20
- - capability honesty and typed errors
21
- - two-surface identity, ambiguity, loss, and one verified reattach
22
- - isolated Electron partition and trusted cookie adapter
23
- - record-level cookie merges, tombstones, stale snapshots, retry, and feedback
24
- - protected hosts, partition keys, encryption integrity, wrong-key redaction
25
- - auth filtering, token TTL/hash, live login, portable import/export
26
- - profile locks, references, deletion refusal, and ephemeral pruning
27
- - CSS-pixel/DPR capture and page-scoped native input
28
- - recording viability, latest-frame buffer, backpressure, cancellation, ffmpeg
29
- - SQLite cross-process writes and encrypted legacy migration fixtures
30
- - REST auth/limits/SSE and MCP cancellation
31
- - argv process safety, bounded output/termination, asar resolution
32
- - native Electron URL/popup/download/permission/ad-block policies
33
-
34
- ## Real boundaries
35
-
36
- Source CI provisions Chrome for Testing through the locked `agent-browser`
37
- dependency before the headless suite, which launches that real browser and ffmpeg.
38
- The suite records command phases and the live CDP browser identity; it never logs
39
- page data, process output, or command arguments. Provisioning and browser action
40
- deadlines are separate, and the action deadlines remain unchanged. The Electron harness
41
- launches the actual Electron binary with two `WebContentsView` surfaces and
42
- checks partition identity, isolation, capture, remount, and WebM recording.
43
- These tests exist because mocks cannot validate CDP target identity or physical
44
- partition behavior.
17
+ - one browsing identity: every session browses as the account, and a root
18
+ cannot be reassigned to another account
19
+ - restart reopen, cross-process leases, one action per session, cancellation
20
+ - a session's own live view, and closing the runtime releases Chrome
21
+ - all 22 actions reachable through SDK, CLI, MCP, REST, and Toolbox, from one
22
+ action manifest; an MCP call without a session uses its chat's session
23
+ - two-way cookie sync: sign-ins and sign-outs reach the account, failed
24
+ applies retry without echo, partitioned cookies, protected hosts
25
+ - record-level merges, tombstones, corrupt-jar health, wrong-key redaction
26
+ - auth filtering, login token TTL and hashing, deprecated-input compatibility,
27
+ serialized live login transitions
28
+ - recording frame pacing, backpressure, ffmpeg checks, viability deadline,
29
+ cancellation, and dead-owner recovery
30
+ - SQLite cross-process writes and the encrypted legacy import
31
+ - REST auth, loopback binding, SSE, redaction, and MCP cancellation
32
+ - argv process safety, bounded output and termination, asar resolution
33
+ - Electron URL, popup, permission, download, and ad-block policy, and the
34
+ Electron cookie adapter against an injected store
35
+
36
+ ## Real browser
37
+
38
+ `npm run test:real` sets `AMALGM_BROWSER_REAL=1` and drives real Chrome
39
+ through the MCP adapter against a public site. It checks that:
40
+
41
+ - two chats browse side by side in one Chrome as one signed-in account;
42
+ - a viewer watches and drives one chat's live view, only with the runtime
43
+ token;
44
+ - the account stays signed in across restarts and follows sign-outs;
45
+ - a chat keeps browsing, still signed in, after Chrome is killed;
46
+ - loopback cookies never enter the account;
47
+ - a competing owner cannot replace or stop the live Chrome;
48
+ - captures and input follow the selected tab even with repeated URLs;
49
+ - session and service shutdown drain work, HTTP requests, SSE and viewers;
50
+ - raw CDP and advanced CLI calls cannot escape their session;
51
+ - repeated login activation preserves the page, terminal states remain final,
52
+ and recorded imagery can be decoded.
53
+
54
+ CI provisions Chrome for Testing through the locked `agent-browser`
55
+ dependency before this suite. Mocks cannot validate these paths.
56
+
57
+ UI's `test:browser` source examination additionally drives its canonical web
58
+ and Electron browser surfaces through the actual UI routes and Shell gateway.
59
+ It covers human input, companion ownership, login handoff, native cookie
60
+ sharing and deletion, account switching, sign-out, and fractional native bounds.
45
61
 
46
62
  ## Package verification
47
63
 
48
- `verify:pack` runs `npm pack`, inspects contents for runtime data/secrets,
49
- checks the compiled CLI, installs the tarball into a temporary consumer without
50
- Electron, and imports the ESM core. Build output and temporary tarballs remain
51
- ignored.
64
+ `verify:pack` runs `npm pack`, checks the tarball for required files and for
65
+ runtime data or secrets, checks the compiled CLIs, installs the tarball into a
66
+ temporary consumer without Electron, imports the core entry points, and
67
+ confirms the Electron entry resolves to its CommonJS build.
52
68
 
53
- Production TypeScript in `src/` and `bin/` is limited to 220 lines per file.
54
- The tree check fails on generated-source evasions and tracked build/runtime
55
- artifacts.
69
+ TypeScript in `src/`, `bin/`, and `test/` is limited to 220 lines per file.
70
+ The tree check also fails on empty or untracked source files, JavaScript
71
+ source in `src/` or `bin/`, and tracked build or runtime artifacts.
56
72
 
57
73
  ## Adding behavior
58
74
 
59
- Update purpose/axioms if the model changes, then the typed SDK, shared action
60
- descriptor, every transport projection, documentation, and an invariant test.
61
- A new action that is not reachable through all five public surfaces must fail
62
- the parity suite.
75
+ Update the purpose and axioms if the model changes, then the typed SDK, the
76
+ shared action descriptor, every transport projection, the documentation, and
77
+ an invariant test. A new action that is not reachable through all five public
78
+ surfaces fails the parity suite.
@@ -18,12 +18,17 @@ import {
18
18
  } from '@amalgm/browser/toolbox';
19
19
 
20
20
  tools.register(browserToolboxManifest);
21
- const execute = createBrowserToolboxExecutor(browser, enabledActionIds);
21
+ const execute = createBrowserToolboxExecutor(browser, {
22
+ canExecute: (actionId, context) => enabledActionIds.includes(actionId),
23
+ });
24
+ await execute('browser.open', { url: 'https://example.com' }, context);
22
25
  ```
23
26
 
24
- The executor normalizes compatibility aliases once, verifies the action is
25
- granted, and dispatches the canonical action through the SDK. Disabled actions
26
- fail before session creation or browser execution.
27
+ The executor normalizes compatibility aliases once, asks the optional policy
28
+ whether the action is granted, and dispatches the canonical action through the
29
+ SDK. Disabled actions fail with `AUTHORIZATION_DENIED` before session creation
30
+ or browser execution. Session choice is the same as MCP: an explicit
31
+ `session`, else `context.callerId`, else `default`.
27
32
 
28
33
  Legacy individual `cua_*` actions, old prefixed IDs, and historical aggregate
29
34
  grants are adapter aliases. They do not create new SDK action identities. In
@@ -1,67 +1,95 @@
1
1
  # Troubleshooting
2
2
 
3
- ## A session unexpectedly uses headless
3
+ ## Chrome was not found
4
4
 
5
- Electron selection requires `clientKind: 'desktop'` and a live, loopback,
6
- protocol-5/6 host advertisement with a running PID. Check the advertisement
7
- path, CDP URL, protocol, and process. Backend selection cannot be changed after
8
- session creation; create a new session after fixing the host.
5
+ Install Google Chrome, run `npx agent-browser install` to download Chrome for
6
+ Testing, or set `AMALGM_BROWSER_EXECUTABLE_PATH`. A configured path that does
7
+ not exist fails with `PROCESS_FAILED` and is not replaced by a search. See
8
+ [Chrome runtime](./CHROME.md) for the search order.
9
9
 
10
- ## Surface identity mismatch
10
+ ## Chrome did not start
11
11
 
12
- Do not retry against an active tab or another target. Confirm the surface
13
- marker, stamp, ID, and protocol belong to the session. Browser permits one
14
- reattach only after a genuine target loss; mismatch is intentionally fail
15
- closed.
12
+ Browser waits 20 seconds for Chrome's DevTools port and reports the end of
13
+ Chrome's stderr. On Linux as root, Browser already adds `--no-sandbox` and
14
+ `--disable-dev-shm-usage`; check the executable runs by hand.
16
15
 
17
- ## Headless executable is missing
16
+ ## "This browser profile already has a live owner."
17
+
18
+ Another live process holds this root's Chrome lease (`chrome.lease.sqlite`). This happens
19
+ when a one-shot CLI command runs beside `mcp`, `serve`, or an embedding host on
20
+ the same root. Send the work to that process, stop it, or use another root.
21
+ Never delete the lease file or Chrome's lock files. An owner that has died
22
+ releases its lease automatically; the next start retires its orphaned Chrome
23
+ through the exact endpoint published by that profile.
24
+
25
+ ## Chrome crashed
26
+
27
+ The runtime logs "Chrome exited; it restarts on next use." An action caught by
28
+ the crash can fail; retry it. A later action starts a new Chrome filled with
29
+ the account's cookies from the jar, and the session keeps browsing. Open pages
30
+ are not restored.
31
+
32
+ ## SURFACE_IDENTITY_FAILED
33
+
34
+ Screenshots, CUA double-clicks, and recording need one page for the session.
35
+ Browser records the selected page's target identity through the session relay.
36
+ Repeated URLs are safe. If the target has disappeared or selection cannot be
37
+ proven, switch to the intended tab or open a page, then retry.
38
+
39
+ ## An element reference fails
40
+
41
+ Refs such as `@e3` belong to the latest snapshot. After the page changes, an
42
+ old ref fails with `PROCESS_FAILED`. Take a new snapshot.
43
+
44
+ ## agent-browser is missing
18
45
 
19
46
  Run `amalgm-browser doctor`, reinstall production dependencies, or set
20
- `AMALGM_AGENT_BROWSER_BIN`. In packaged Electron builds, ensure native assets
21
- are unpacked from `app.asar`.
47
+ `AMALGM_AGENT_BROWSER_BIN`. In packaged Electron builds, make sure native
48
+ assets are unpacked from `app.asar`.
22
49
 
23
- ## Recording cannot start
50
+ ## "Browser IPC requires a private, user-owned temporary directory"
24
51
 
25
- Set `AMALGM_FFMPEG` to a working binary and run `<binary> -version`. Browser
26
- verifies ffmpeg first, then requires a page frame within five seconds. Open a
27
- navigable page and check that the assigned driver advertises `recording`.
52
+ agent-browser's sockets live in `/tmp/amalgm-browser-<uid>`. It must be a
53
+ directory owned by the current user with no group or other permissions. Fix or
54
+ remove it.
28
55
 
29
- ## A profile cannot be deleted
56
+ ## Recording cannot start
30
57
 
31
- Inspect it through SDK/CLI/REST. A live session, pending login, auth bundle, or
32
- Chromium process lock intentionally protects the directory. Close/cancel the
33
- owner or remove the explicit reference; never delete lock files from a running
34
- profile.
58
+ Set `AMALGM_FFMPEG` to a working binary and run `<binary> -version`. Browser
59
+ checks ffmpeg first, then needs a page frame within five seconds, so open a
60
+ page before recording.
35
61
 
36
62
  ## Cookie jar reports unhealthy
37
63
 
38
- Ordinary browsing should continue with the physical profile store. Do not print
39
- or hand-edit encrypted payloads. Restore a matching jar/key backup or clear the
40
- damaged automatic jar only after accepting that cross-backend cookie state is
41
- lost. Named auth bundles are separate.
64
+ Browsing continues with the cookies Chrome already has, but sign-ins no longer
65
+ sync with other browser stores. Do not print or hand-edit encrypted files. Restore a
66
+ matching `cookie-jar.sqlite` and `browser.key` backup while the runtime is stopped,
67
+ using the SQLite-safe backup procedure in [Operations](./OPERATIONS.md).
68
+ Named auth bundles are separate.
42
69
 
43
- ## REST returns 401/403
70
+ ## REST returns 401 or 403
44
71
 
45
- Health is the only unauthenticated route. Supply the exact bearer token. Raw
46
- cookie routes additionally require `X-Browser-Adapter-Token`. Non-loopback
47
- listen also requires explicit remote authorization.
72
+ Health is the only unauthenticated route. Send the exact runtime token.
73
+ Internal cookie routes also need `X-Browser-Adapter-Token`. A live-view
74
+ WebSocket closing with `4401` is the same token failure. Non-loopback binding
75
+ requires explicit remote opt-in.
48
76
 
49
77
  ## Login handoff fails
50
78
 
51
79
  Tokens are one-time credentials returned only at creation, TTL is at most one
52
- hour, and completed/cancelled/expired sessions reject reuse. For noVNC, set a
53
- valid HTTP(S) `AMALGM_BROWSER_NOVNC_PUBLIC_URL`.
80
+ hour, and completed, cancelled, and expired logins reject reuse. The login page
81
+ uses the login session’s normal runtime stream; check that the selected runtime
82
+ is available.
54
83
 
55
84
  ## SQLite is busy or a session conflicts
56
85
 
57
- Another process may hold the session lease. Do not run two active owners for
58
- one browser session. Let the operation finish or cancel it through the owning
59
- service; stale leases expire. Avoid placing the DB on filesystems with broken
60
- SQLite locking.
86
+ Each session allows one action at a time, and another process may hold the
87
+ session's lease. Let the operation finish or cancel it through the owning
88
+ process; stale leases expire. Avoid filesystems with broken SQLite locking.
61
89
 
62
90
  ## Migration fails
63
91
 
64
- Keep old writers stopped. Verify the legacy DB exists, the source auth blob
65
- hashes match, and the legacy 32-byte key is available. The importer is
66
- transactional and does not mark completion on failure; fix the violated
67
- invariant and rerun rather than editing the migration marker.
92
+ Keep old writers stopped. Check that the legacy database exists, the source
93
+ auth blob hashes match, and the legacy 32-byte key is available. The importer
94
+ is transactional and does not mark completion on failure; fix the problem and
95
+ rerun rather than editing the migration marker.
package/examples/basic.ts CHANGED
@@ -5,3 +5,4 @@ const session = await browser.createSession({ id: 'example' });
5
5
  await browser.execute(session.id, { type: 'open', url: 'https://example.com' });
6
6
  console.log(await browser.execute(session.id, { type: 'snapshot' }));
7
7
  await browser.closeSession(session.id);
8
+ await browser.close();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@amalgm/browser",
3
- "version": "0.1.2-preview.35541635545",
4
- "description": "Safe persistent browser automation across headless Chromium and visible Electron surfaces.",
3
+ "version": "0.1.2-preview.37254096068",
4
+ "description": "The amalgm runtime's browser: one Chrome, a session per chat, and the account's cookies in every view.",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/amalgm-inc/amalgm-browser.git"
@@ -23,10 +23,6 @@
23
23
  "types": "./dist/src/index.d.ts",
24
24
  "import": "./dist/src/index.js"
25
25
  },
26
- "./headless": {
27
- "types": "./dist/src/headless.d.ts",
28
- "import": "./dist/src/headless.js"
29
- },
30
26
  "./electron": {
31
27
  "import": {
32
28
  "types": "./dist/src/electron.d.ts",
@@ -80,12 +76,10 @@
80
76
  ],
81
77
  "scripts": {
82
78
  "build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json && npm run build:electron-cjs && tsx scripts/finalize-build.ts",
83
- "build:electron-cjs": "esbuild src/electron.ts --bundle --platform=node --format=cjs --target=node20 --define:import.meta.dirname=__dirname --define:__AMALGM_BROWSER_ADBLOCK_PRELOAD__=\\\"electron-preload.cjs\\\" --outfile=dist/src/electron.cjs --external:electron && esbuild src/drivers/electron/native/adblock/preload.ts --bundle --platform=node --format=cjs --target=node20 --outfile=dist/src/electron-preload.cjs --external:electron",
79
+ "build:electron-cjs": "esbuild src/electron.ts --bundle --platform=node --format=cjs --target=node20 --define:import.meta.dirname=__dirname --define:__AMALGM_BROWSER_ADBLOCK_PRELOAD__=\\\"electron-preload.cjs\\\" --outfile=dist/src/electron.cjs --external:electron && esbuild src/electron/adblock/preload.ts --bundle --platform=node --format=cjs --target=node20 --outfile=dist/src/electron-preload.cjs --external:electron",
84
80
  "check": "tsx scripts/check-tree.ts && tsc -p tsconfig.json && tsc -p tsconfig.test.json",
85
81
  "test": "tsx --test --test-concurrency=1 --test-timeout=30000 test/*.test.ts",
86
- "test:real": "cross-env AMALGM_BROWSER_REAL=1 tsx --test --test-timeout=60000 test/real-headless.test.ts",
87
- "pretest:electron": "npm run build",
88
- "test:electron": "tsx scripts/run-electron-test.ts",
82
+ "test:real": "cross-env AMALGM_BROWSER_REAL=1 tsx --test --test-concurrency=1 --test-timeout=120000 test/real-*.test.ts",
89
83
  "verify": "npm run check && npm run build && npm test && npm run verify:pack",
90
84
  "verify:pack": "tsx scripts/verify-package.ts",
91
85
  "prepack": "npm run build",
@@ -132,8 +126,7 @@
132
126
  "workflow": "verify.yml",
133
127
  "jobs": [
134
128
  "verify",
135
- "real-headless",
136
- "real-electron"
129
+ "real-browser"
137
130
  ],
138
131
  "verify": "verify",
139
132
  "cli": [
@@ -157,11 +150,11 @@
157
150
  "@amalgm/core"
158
151
  ]
159
152
  },
160
- "gitHead": "f3c17f14ffd07ac7e89f57698f611b07db17545a",
153
+ "gitHead": "9a5d40729134e87c55fdbb7a52ad42711eef7163",
161
154
  "amalgmSource": {
162
155
  "repository": "amalgm-inc/amalgm-browser",
163
156
  "branch": "preview",
164
- "commit": "f3c17f14ffd07ac7e89f57698f611b07db17545a",
165
- "occurrence": "35541635545"
157
+ "commit": "9a5d40729134e87c55fdbb7a52ad42711eef7163",
158
+ "occurrence": "37254096068"
166
159
  }
167
160
  }
@@ -22,7 +22,7 @@ The package installs three executables alongside the SDK:
22
22
  - `amalgm-browser-mcp` — the MCP server (also reachable as `amalgm-browser mcp`).
23
23
  - `amalgm-browser-rest` — the authenticated loopback REST API (also `amalgm-browser serve --token <token>`).
24
24
 
25
- The `agent-browser` dependency supplies the launcher; its `install` command downloads Chrome for Testing. An existing Chrome installation can also supply the standalone headless browser. Setting `AMALGM_BROWSER_CDP_URL` attaches to a Chromium endpoint you already run instead.
25
+ Browser runs one headless Chrome per runtime and drives it through the bundled `agent-browser`. It uses an installed Chrome, Chromium, or Brave, or the Chrome for Testing that `agent-browser install` downloads; `AMALGM_BROWSER_EXECUTABLE_PATH` picks a specific executable.
26
26
 
27
27
  ### MCP setup
28
28
 
@@ -59,26 +59,18 @@ const snapshot = await browser.execute(session.id, { type: 'snapshot' });
59
59
  await browser.execute(session.id, { type: 'click', target: '@e3' });
60
60
 
61
61
  await browser.closeSession(session.id);
62
+ await browser.close(); // stops Chrome
62
63
  ```
63
64
 
64
- The same flow on the CLI — note that every invocation reuses one `--session` value:
65
+ Through MCP the identical sequence is `browser_open`, `browser_snapshot`, `browser_click`, `browser_close`, each taking an optional `session` field. Without it, a call uses the calling chat's session when the host names the chat, and `default` otherwise.
65
66
 
66
- ```bash
67
- amalgm-browser open https://example.com --session research
68
- amalgm-browser snapshot --session research
69
- amalgm-browser click @e3 --session research
70
- amalgm-browser close --session research
71
- ```
72
-
73
- Through MCP the identical sequence is `browser_open`, `browser_snapshot`, `browser_click`, `browser_close`, each taking an optional `session` field (defaulting to `default`).
67
+ Each CLI command is its own process: it starts Chrome, runs one step, and stops Chrome, so the next command starts on a new blank tab. Use the CLI for single steps such as `amalgm-browser open https://example.com`, and MCP, REST (`amalgm-browser serve`), or the SDK for multi-step flows.
74
68
 
75
69
  ## Core concepts
76
70
 
77
71
  ### Sessions
78
72
 
79
- A session is a persistent page context: one live browser state that survives across commands. Create it once at the start of a task, pass the same session id to every subsequent action, and close it when the task ends. Sessions are cheap to keep open and expensive to churn — reopening a page resets navigation state, cookies-in-flight, and every element reference you have collected.
80
-
81
- Backend selection (headless Chromium, an operator-supplied CDP endpoint, or a visible desktop surface when Browser is embedded in a host app) happens once, before session creation, and never changes during a session's lifetime. You do not choose a backend per command and should not ask users to.
73
+ A session is a persistent page context: its own tabs in the runtime's one Chrome. Every session browses as the same signed-in account and shares its cookies, so a sign-in in one session is visible in all of them. Create or name a session once at the start of a task, pass the same session id to every subsequent action, and close it when the task ends. Sessions are cheap to keep open and expensive to churn — reopening a page resets navigation state and every element reference you have collected.
82
74
 
83
75
  ### Tabs
84
76
 
@@ -100,8 +92,8 @@ Browser actions are individual commands over one shared session, and the orderin
100
92
  1. Call `open` once per page, not once per command. The session holds the page.
101
93
  2. Call `snapshot` to get refs, then act with those refs. Do not re-issue `tab` or `open` before each action — that resets the page context and every `@ref` you hold goes stale.
102
94
  3. Re-snapshot only when the page has actually changed: after navigation, after a tab switch, after a click that triggered new content.
103
- 4. When a multi-step sequence fails, classify the failure by the specific command that failed, not by the sequence as a whole. Every action returns a typed error with a stable code (see [Error handling](#error-handling)); a `NOT_FOUND` on step four means a stale ref or changed page at step four, not a broken session. Usually the fix is a fresh `snapshot` and a retry of that one step.
104
- 5. Keep one owner per session. Two processes driving the same session id conflict; the second gets a lease conflict rather than silently interleaving.
95
+ 4. When a multi-step sequence fails, classify the failure by the specific command that failed, not by the sequence as a whole. Every action returns a typed error with a stable code (see [Error handling](#error-handling)); a stale ref at step four fails step four with `PROCESS_FAILED`, not the session. Usually the fix is a fresh `snapshot` and a retry of that one step.
96
+ 5. Keep one owner per session. A session runs one action at a time, and two processes driving the same session id get `CONFLICT` rather than silently interleaving. Only one process can run a state root's Chrome; another process on the same root gets `CONFLICT` ("This browser profile already has a live owner.").
105
97
 
106
98
  ## Reading pages: snapshots vs screenshots
107
99
 
@@ -117,12 +109,10 @@ Screenshot and computer-use coordinates are CSS pixels with a 1:1 mapping betwee
117
109
 
118
110
  ## Forms and input
119
111
 
120
- The core input actions cover ordinary DOM forms:
112
+ The core input actions cover ordinary DOM forms. A `fill` input:
121
113
 
122
- ```bash
123
- amalgm-browser fill @e7 "jane@example.com" --session research
124
- amalgm-browser select @e9 "US" --session research
125
- amalgm-browser press Enter --session research
114
+ ```json
115
+ { "target": "@e7", "text": "jane@example.com", "submit": true }
126
116
  ```
127
117
 
128
118
  - `fill` sets a target's text; pass `submit: true` to submit the surrounding form in the same action.
@@ -151,7 +141,7 @@ When a task needs a human to log in, let the host provide the login interface. `
151
141
 
152
142
  ## MCP tools
153
143
 
154
- The MCP server exposes twenty-two tools — the canonical action names prefixed with `browser_`. Session actions accept an optional `session` string and default to `default`. `browser_record_list` and `browser_auth_list` list service-wide metadata, while `browser_auth_link_create` creates a separate login session; these three tools do not accept `session`.
144
+ The MCP server exposes twenty-two tools — the canonical action names prefixed with `browser_`. Session actions accept an optional `session` string; without it they use the calling chat's session when the host names the chat, and `default` otherwise. `browser_record_list` and `browser_auth_list` list service-wide metadata, while `browser_auth_link_create` creates a separate login session; these three tools do not accept `session`.
155
145
 
156
146
  | Group | Tools |
157
147
  | --- | --- |
@@ -164,7 +154,7 @@ The MCP server exposes twenty-two tools — the canonical action names prefixed
164
154
 
165
155
  `browser_cli` is the escape hatch: it runs an advanced `agent-browser` argv action for operations outside the canonical set. Prefer the named tools whenever one exists.
166
156
 
167
- The CLI provides direct commands for the fifteen core browsing and computer-use actions, such as `amalgm-browser open` and `amalgm-browser snapshot`. Use `amalgm-browser action <name> --input <json>` for any of the twenty-two product actions, including authentication and recording, or use the resource commands (`sessions`, `profiles`, `auth`, `recordings`, `capabilities`, `doctor`).
157
+ The CLI provides direct commands for the fifteen core browsing and computer-use actions, such as `amalgm-browser open` and `amalgm-browser snapshot`. Use `amalgm-browser action <name> --input <json>` for any of the twenty-two product actions, including authentication and recording, or use the resource commands (`sessions`, `auth`, `recordings`, `doctor`).
168
158
 
169
159
  ## Error handling
170
160
 
@@ -173,15 +163,12 @@ Failures are typed `BrowserError` values with stable codes:
173
163
  | Code | Meaning |
174
164
  | --- | --- |
175
165
  | `INVALID_INPUT` | Malformed action input; fix the call, do not retry as-is. |
176
- | `NOT_FOUND` | Target, session, or resource does not exist — often a stale `@ref`; re-snapshot. |
177
- | `CONFLICT` | Another owner holds the session or resource. |
178
- | `CAPABILITY_UNSUPPORTED` | The active backend does not implement this action group; nothing is silently approximated. |
166
+ | `NOT_FOUND` | The session, bundle, recording, or login does not exist. |
167
+ | `CONFLICT` | The session is busy or owned by another process, or another process runs this root's Chrome. |
179
168
  | `AUTHORIZATION_DENIED` | The caller is not permitted to perform the action. |
180
169
  | `TIMEOUT` / `ABORTED` | The operation ran out of time or was cancelled. |
181
- | `PROCESS_FAILED` | The underlying browser process failed. |
182
- | `SURFACE_IDENTITY_FAILED` | A visible desktop surface no longer matches the session; this fails closed. Retry once only after a genuine reconnection, never against a different surface. |
183
-
184
- Check `session.capabilities` before relying on optional groups (computer use, recording, auth, full-page capture) — a backend that lacks a capability refuses it explicitly rather than faking it.
170
+ | `PROCESS_FAILED` | agent-browser, Chrome, or ffmpeg failed — including a stale `@ref` or missing target; re-snapshot and retry that step. |
171
+ | `SURFACE_IDENTITY_FAILED` | A screenshot, computer-use double-click, or recording could not tell which of the session's tabs is its page; this fails closed. Switch to or close tabs, then retry. |
185
172
 
186
173
  CLI exit codes map the same taxonomy: `0` success, `2` invalid input, `3` authorization denied, `4` not found, `5` timeout or cancellation, `1` any other typed failure. Pass `--timeout <ms>` to bound any blocking CLI operation.
187
174
 
@@ -31,7 +31,7 @@ Use computer use for canvas, WebGL, image-only, or custom controls without DOM s
31
31
 
32
32
  ## Tabs and dialogs
33
33
 
34
- `tab` takes `action: "list" | "new" | "switch" | "close"`, with `id` identifying the tab for `switch` and `close`. Switching tabs invalidates snapshot refs; re-snapshot after switching. Sessions bound to a visible desktop surface may reject switching to a surface they do not own.
34
+ `tab` takes `action: "list" | "new" | "switch" | "close"`, with `id` identifying the tab for `switch` and `close`. Switching tabs invalidates snapshot refs; re-snapshot after switching.
35
35
 
36
36
  `dialog` takes `action: "accept" | "dismiss"`, with optional `text` supplied only for prompt dialogs.
37
37
 
@@ -46,7 +46,7 @@ Use computer use for canvas, WebGL, image-only, or custom controls without DOM s
46
46
  - `auth_load` — load a bundle into the session by `bundleId`.
47
47
  - `auth_list` — list sanitized profiles, bundles, and login sessions. Never returns raw cookie or token values.
48
48
 
49
- A profile is a browser state directory; an auth bundle is an explicitly saved, named credential snapshot. They are separate — loading a profile does not load a bundle.
49
+ Every session browses as the signed-in amalgm account, so it already carries that account's cookies. An auth bundle is an explicitly saved, named credential snapshot; loading one adds its state to the session.
50
50
 
51
51
  ## Recording
52
52
 
@@ -1,2 +0,0 @@
1
- import type { RouteContext } from './types.js';
2
- export declare function routeProfiles(context: RouteContext): Promise<boolean>;
@@ -1,42 +0,0 @@
1
- export async function routeProfiles(context) {
2
- const [resource, id] = context.path;
3
- if (resource !== 'profiles')
4
- return false;
5
- if (!id && context.method === 'GET') {
6
- context.json(200, { profiles: context.browser.listProfiles() });
7
- return true;
8
- }
9
- if (!id && context.method === 'POST') {
10
- const body = await context.body();
11
- context.json(201, { profile: context.browser.createProfile({
12
- ...(typeof body.id === 'string' ? { id: body.id } : {}),
13
- name: typeof body.name === 'string' ? body.name : String(body.id || 'profile'),
14
- kind: 'durable',
15
- }) });
16
- return true;
17
- }
18
- if (id === 'prune' && context.method === 'POST') {
19
- const body = await context.body();
20
- context.json(200, { removed: context.browser.pruneProfiles(Number(body.maxAgeMs) || undefined) });
21
- return true;
22
- }
23
- if (id && context.method === 'GET') {
24
- context.json(200, { status: context.browser.inspectProfile(id) });
25
- return true;
26
- }
27
- if (id && context.method === 'PATCH') {
28
- const body = await context.body();
29
- context.json(200, { profile: context.browser.updateProfile(id, {
30
- ...(typeof body.name === 'string' ? { name: body.name } : {}),
31
- ...(body.kind === 'durable' || body.kind === 'ephemeral' ? { kind: body.kind } : {}),
32
- }) });
33
- return true;
34
- }
35
- if (id && context.method === 'DELETE') {
36
- context.browser.deleteProfile(id);
37
- context.json(200, { deleted: id });
38
- return true;
39
- }
40
- return false;
41
- }
42
- //# sourceMappingURL=profile-routes.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"profile-routes.js","sourceRoot":"","sources":["../../../../src/adapters/http/profile-routes.ts"],"names":[],"mappings":"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"}
@@ -1,8 +0,0 @@
1
- import type { BrowserLoginSession, BrowserRuntimeContext } from '../types.js';
2
- export interface LoginTransportInput {
3
- transport?: string;
4
- liveUrl?: string;
5
- context?: BrowserRuntimeContext;
6
- }
7
- export declare function resolveLoginTransport(input: LoginTransportInput, env?: NodeJS.ProcessEnv): Pick<BrowserLoginSession, 'transport' | 'liveUrl' | 'setupStatus'>;
8
- export declare function noVncUrl(value: string | undefined): string | undefined;
@@ -1,45 +0,0 @@
1
- export function resolveLoginTransport(input, env = process.env) {
2
- const requested = normalizeTransport(input.transport || env.AMALGM_BROWSER_LOGIN_TRANSPORT);
3
- const liveUrl = noVncUrl(input.liveUrl || env.AMALGM_BROWSER_NOVNC_PUBLIC_URL || env.AMALGM_BROWSER_NOVNC_URL);
4
- if (requested === 'electron-surface' || (!requested && input.context?.clientKind === 'desktop')) {
5
- return { transport: 'electron-surface', setupStatus: 'ready' };
6
- }
7
- if (requested === 'novnc' || liveUrl) {
8
- return {
9
- transport: 'novnc',
10
- ...(liveUrl ? { liveUrl } : {}),
11
- setupStatus: liveUrl ? 'ready' : 'missing_novnc_url',
12
- };
13
- }
14
- return { transport: 'external', setupStatus: requested === 'manual' ? 'manual' : 'ready' };
15
- }
16
- export function noVncUrl(value) {
17
- if (!value)
18
- return undefined;
19
- try {
20
- const url = new URL(value);
21
- if (!['http:', 'https:'].includes(url.protocol))
22
- return undefined;
23
- if (!url.searchParams.has('autoconnect'))
24
- url.searchParams.set('autoconnect', '1');
25
- if (!url.searchParams.has('resize'))
26
- url.searchParams.set('resize', 'scale');
27
- return url.toString();
28
- }
29
- catch {
30
- return undefined;
31
- }
32
- }
33
- function normalizeTransport(value) {
34
- const clean = String(value || '').trim().toLowerCase();
35
- if (['electron', 'electron-splitview', 'desktop', 'electron-surface'].includes(clean))
36
- return 'electron-surface';
37
- if (['novnc', 'vnc', 'remote', 'remote-live-view'].includes(clean))
38
- return 'novnc';
39
- if (['none', 'manual'].includes(clean))
40
- return 'manual';
41
- if (['external', 'amalgm-live', 'live', 'browser-auth-live', 'cdp-live'].includes(clean))
42
- return 'external';
43
- return undefined;
44
- }
45
- //# sourceMappingURL=transport.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../src/auth/transport.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,qBAAqB,CACnC,KAA0B,EAC1B,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,SAAS,IAAI,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC5F,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,IAAI,GAAG,CAAC,+BAA+B,IAAI,GAAG,CAAC,wBAAwB,CAAC,CAAC;IAC/G,IAAI,SAAS,KAAK,kBAAkB,IAAI,CAAC,CAAC,SAAS,IAAI,KAAK,CAAC,OAAO,EAAE,UAAU,KAAK,SAAS,CAAC,EAAE,CAAC;QAChG,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IACjE,CAAC;IACD,IAAI,SAAS,KAAK,OAAO,IAAI,OAAO,EAAE,CAAC;QACrC,OAAO;YACL,SAAS,EAAE,OAAO;YAClB,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB;SACrD,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAyB;IAChD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,SAAS,CAAC;QAClE,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QACnF,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC7E,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,SAAS,CAAC;IAAC,CAAC;AAC/B,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAyB;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACvD,IAAI,CAAC,UAAU,EAAE,oBAAoB,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,kBAAkB,CAAC;IACjH,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACnF,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IACxD,IAAI,CAAC,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,mBAAmB,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC;IAC5G,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../../../src/drivers/cdp/capture.ts"],"names":[],"mappings":"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"}