openchrome-mcp 1.9.6 → 1.10.0

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 (346) hide show
  1. package/README.md +48 -0
  2. package/config/audit-redaction.json +48 -0
  3. package/dist/actions/action-cache.d.ts +26 -0
  4. package/dist/actions/action-cache.d.ts.map +1 -0
  5. package/dist/actions/action-cache.js +75 -0
  6. package/dist/actions/action-cache.js.map +1 -0
  7. package/dist/actions/action-parser.d.ts +23 -0
  8. package/dist/actions/action-parser.d.ts.map +1 -0
  9. package/dist/actions/action-parser.js +321 -0
  10. package/dist/actions/action-parser.js.map +1 -0
  11. package/dist/actions/action-templates.d.ts +29 -0
  12. package/dist/actions/action-templates.d.ts.map +1 -0
  13. package/dist/actions/action-templates.js +128 -0
  14. package/dist/actions/action-templates.js.map +1 -0
  15. package/dist/auth/adapters/bitwarden-adapter.d.ts +22 -0
  16. package/dist/auth/adapters/bitwarden-adapter.d.ts.map +1 -0
  17. package/dist/auth/adapters/bitwarden-adapter.js +113 -0
  18. package/dist/auth/adapters/bitwarden-adapter.js.map +1 -0
  19. package/dist/auth/adapters/index.d.ts +7 -0
  20. package/dist/auth/adapters/index.d.ts.map +1 -0
  21. package/dist/auth/adapters/index.js +13 -0
  22. package/dist/auth/adapters/index.js.map +1 -0
  23. package/dist/auth/adapters/local-adapter.d.ts +27 -0
  24. package/dist/auth/adapters/local-adapter.d.ts.map +1 -0
  25. package/dist/auth/adapters/local-adapter.js +59 -0
  26. package/dist/auth/adapters/local-adapter.js.map +1 -0
  27. package/dist/auth/adapters/onepassword-adapter.d.ts +22 -0
  28. package/dist/auth/adapters/onepassword-adapter.d.ts.map +1 -0
  29. package/dist/auth/adapters/onepassword-adapter.js +126 -0
  30. package/dist/auth/adapters/onepassword-adapter.js.map +1 -0
  31. package/dist/auth/api-key-store.d.ts +28 -0
  32. package/dist/auth/api-key-store.d.ts.map +1 -0
  33. package/dist/auth/api-key-store.js +489 -0
  34. package/dist/auth/api-key-store.js.map +1 -0
  35. package/dist/auth/api-key-types.d.ts +29 -0
  36. package/dist/auth/api-key-types.d.ts.map +1 -0
  37. package/dist/auth/api-key-types.js +5 -0
  38. package/dist/auth/api-key-types.js.map +1 -0
  39. package/dist/auth/credential-provider.d.ts +23 -0
  40. package/dist/auth/credential-provider.d.ts.map +1 -0
  41. package/dist/auth/credential-provider.js +30 -0
  42. package/dist/auth/credential-provider.js.map +1 -0
  43. package/dist/auth/credential-store.d.ts +29 -0
  44. package/dist/auth/credential-store.d.ts.map +1 -0
  45. package/dist/auth/credential-store.js +295 -0
  46. package/dist/auth/credential-store.js.map +1 -0
  47. package/dist/auth/jwt-verifier.d.ts +13 -0
  48. package/dist/auth/jwt-verifier.d.ts.map +1 -0
  49. package/dist/auth/jwt-verifier.js +107 -0
  50. package/dist/auth/jwt-verifier.js.map +1 -0
  51. package/dist/auth/scope-policy.d.ts +8 -0
  52. package/dist/auth/scope-policy.d.ts.map +1 -0
  53. package/dist/auth/scope-policy.js +140 -0
  54. package/dist/auth/scope-policy.js.map +1 -0
  55. package/dist/auth/totp-manager.d.ts +35 -0
  56. package/dist/auth/totp-manager.d.ts.map +1 -0
  57. package/dist/auth/totp-manager.js +133 -0
  58. package/dist/auth/totp-manager.js.map +1 -0
  59. package/dist/auth/twofa-detector.d.ts +30 -0
  60. package/dist/auth/twofa-detector.d.ts.map +1 -0
  61. package/dist/auth/twofa-detector.js +302 -0
  62. package/dist/auth/twofa-detector.js.map +1 -0
  63. package/dist/auth/twofa-handler.d.ts +32 -0
  64. package/dist/auth/twofa-handler.d.ts.map +1 -0
  65. package/dist/auth/twofa-handler.js +175 -0
  66. package/dist/auth/twofa-handler.js.map +1 -0
  67. package/dist/captcha/detect.d.ts +7 -0
  68. package/dist/captcha/detect.d.ts.map +1 -0
  69. package/dist/captcha/detect.js +54 -0
  70. package/dist/captcha/detect.js.map +1 -0
  71. package/dist/captcha/handler.d.ts +28 -0
  72. package/dist/captcha/handler.d.ts.map +1 -0
  73. package/dist/captcha/handler.js +196 -0
  74. package/dist/captcha/handler.js.map +1 -0
  75. package/dist/captcha/index.d.ts +13 -0
  76. package/dist/captcha/index.d.ts.map +1 -0
  77. package/dist/captcha/index.js +20 -0
  78. package/dist/captcha/index.js.map +1 -0
  79. package/dist/captcha/inject-solution.d.ts +14 -0
  80. package/dist/captcha/inject-solution.d.ts.map +1 -0
  81. package/dist/captcha/inject-solution.js +103 -0
  82. package/dist/captcha/inject-solution.js.map +1 -0
  83. package/dist/captcha/providers/anticaptcha.d.ts +18 -0
  84. package/dist/captcha/providers/anticaptcha.d.ts.map +1 -0
  85. package/dist/captcha/providers/anticaptcha.js +132 -0
  86. package/dist/captcha/providers/anticaptcha.js.map +1 -0
  87. package/dist/captcha/providers/capsolver.d.ts +18 -0
  88. package/dist/captcha/providers/capsolver.d.ts.map +1 -0
  89. package/dist/captcha/providers/capsolver.js +136 -0
  90. package/dist/captcha/providers/capsolver.js.map +1 -0
  91. package/dist/captcha/providers/twocaptcha.d.ts +18 -0
  92. package/dist/captcha/providers/twocaptcha.d.ts.map +1 -0
  93. package/dist/captcha/providers/twocaptcha.js +132 -0
  94. package/dist/captcha/providers/twocaptcha.js.map +1 -0
  95. package/dist/captcha/solver-interface.d.ts +68 -0
  96. package/dist/captcha/solver-interface.d.ts.map +1 -0
  97. package/dist/captcha/solver-interface.js +31 -0
  98. package/dist/captcha/solver-interface.js.map +1 -0
  99. package/dist/captcha/solver-registry.d.ts +45 -0
  100. package/dist/captcha/solver-registry.d.ts.map +1 -0
  101. package/dist/captcha/solver-registry.js +174 -0
  102. package/dist/captcha/solver-registry.js.map +1 -0
  103. package/dist/cdp/client.d.ts +18 -3
  104. package/dist/cdp/client.d.ts.map +1 -1
  105. package/dist/cdp/client.js +114 -53
  106. package/dist/cdp/client.js.map +1 -1
  107. package/dist/cdp/errors.d.ts +23 -0
  108. package/dist/cdp/errors.d.ts.map +1 -0
  109. package/dist/cdp/errors.js +36 -0
  110. package/dist/cdp/errors.js.map +1 -0
  111. package/dist/chrome/launcher.d.ts +31 -0
  112. package/dist/chrome/launcher.d.ts.map +1 -1
  113. package/dist/chrome/launcher.js +104 -11
  114. package/dist/chrome/launcher.js.map +1 -1
  115. package/dist/chrome/profile-manager.d.ts +1 -1
  116. package/dist/chrome/profile-manager.d.ts.map +1 -1
  117. package/dist/chrome/profile-manager.js +24 -2
  118. package/dist/chrome/profile-manager.js.map +1 -1
  119. package/dist/cli/admin-keys.d.ts +56 -0
  120. package/dist/cli/admin-keys.js +234 -0
  121. package/dist/cli/admin-keys.js.map +1 -0
  122. package/dist/cli/index.js +93 -0
  123. package/dist/cli/index.js.map +1 -1
  124. package/dist/cli/totp-store.d.ts +51 -0
  125. package/dist/cli/totp-store.js +255 -0
  126. package/dist/cli/totp-store.js.map +1 -0
  127. package/dist/config/defaults.d.ts +24 -0
  128. package/dist/config/defaults.d.ts.map +1 -1
  129. package/dist/config/defaults.js +27 -2
  130. package/dist/config/defaults.js.map +1 -1
  131. package/dist/config/tool-tiers.d.ts.map +1 -1
  132. package/dist/config/tool-tiers.js +11 -0
  133. package/dist/config/tool-tiers.js.map +1 -1
  134. package/dist/errors/abort.d.ts +10 -0
  135. package/dist/errors/abort.d.ts.map +1 -0
  136. package/dist/errors/abort.js +21 -0
  137. package/dist/errors/abort.js.map +1 -0
  138. package/dist/extraction/index.d.ts +5 -0
  139. package/dist/extraction/index.d.ts.map +1 -0
  140. package/dist/extraction/index.js +13 -0
  141. package/dist/extraction/index.js.map +1 -0
  142. package/dist/extraction/schema-validator.d.ts +32 -0
  143. package/dist/extraction/schema-validator.d.ts.map +1 -0
  144. package/dist/extraction/schema-validator.js +121 -0
  145. package/dist/extraction/schema-validator.js.map +1 -0
  146. package/dist/extraction/strategies.d.ts +12 -0
  147. package/dist/extraction/strategies.d.ts.map +1 -0
  148. package/dist/extraction/strategies.js +23 -0
  149. package/dist/extraction/strategies.js.map +1 -0
  150. package/dist/hints/rules/blocking-page.d.ts +1 -3
  151. package/dist/hints/rules/blocking-page.d.ts.map +1 -1
  152. package/dist/hints/rules/blocking-page.js +16 -12
  153. package/dist/hints/rules/blocking-page.js.map +1 -1
  154. package/dist/index.js +69 -15
  155. package/dist/index.js.map +1 -1
  156. package/dist/mcp-server.d.ts +75 -4
  157. package/dist/mcp-server.d.ts.map +1 -1
  158. package/dist/mcp-server.js +459 -74
  159. package/dist/mcp-server.js.map +1 -1
  160. package/dist/metrics/collector.d.ts +27 -0
  161. package/dist/metrics/collector.d.ts.map +1 -1
  162. package/dist/metrics/collector.js +54 -1
  163. package/dist/metrics/collector.js.map +1 -1
  164. package/dist/middleware/auth.d.ts +46 -0
  165. package/dist/middleware/auth.d.ts.map +1 -0
  166. package/dist/middleware/auth.js +171 -0
  167. package/dist/middleware/auth.js.map +1 -0
  168. package/dist/middleware/tenant-extractor.d.ts +52 -0
  169. package/dist/middleware/tenant-extractor.d.ts.map +1 -0
  170. package/dist/middleware/tenant-extractor.js +93 -0
  171. package/dist/middleware/tenant-extractor.js.map +1 -0
  172. package/dist/observability/logger.d.ts +6 -0
  173. package/dist/observability/logger.d.ts.map +1 -0
  174. package/dist/observability/logger.js +34 -0
  175. package/dist/observability/logger.js.map +1 -0
  176. package/dist/observability/redaction.d.ts +37 -0
  177. package/dist/observability/redaction.d.ts.map +1 -0
  178. package/dist/observability/redaction.js +338 -0
  179. package/dist/observability/redaction.js.map +1 -0
  180. package/dist/observability/request-id.d.ts +41 -0
  181. package/dist/observability/request-id.d.ts.map +1 -0
  182. package/dist/observability/request-id.js +121 -0
  183. package/dist/observability/request-id.js.map +1 -0
  184. package/dist/recording/action-recorder.d.ts +82 -0
  185. package/dist/recording/action-recorder.d.ts.map +1 -0
  186. package/dist/recording/action-recorder.js +249 -0
  187. package/dist/recording/action-recorder.js.map +1 -0
  188. package/dist/recording/html-template.d.ts +15 -0
  189. package/dist/recording/html-template.d.ts.map +1 -0
  190. package/dist/recording/html-template.js +610 -0
  191. package/dist/recording/html-template.js.map +1 -0
  192. package/dist/recording/index.d.ts +10 -0
  193. package/dist/recording/index.d.ts.map +1 -0
  194. package/dist/recording/index.js +26 -0
  195. package/dist/recording/index.js.map +1 -0
  196. package/dist/recording/recording-store.d.ts +104 -0
  197. package/dist/recording/recording-store.d.ts.map +1 -0
  198. package/dist/recording/recording-store.js +301 -0
  199. package/dist/recording/recording-store.js.map +1 -0
  200. package/dist/recording/replay-viewer.d.ts +45 -0
  201. package/dist/recording/replay-viewer.d.ts.map +1 -0
  202. package/dist/recording/replay-viewer.js +224 -0
  203. package/dist/recording/replay-viewer.js.map +1 -0
  204. package/dist/recording/types.d.ts +74 -0
  205. package/dist/recording/types.d.ts.map +1 -0
  206. package/dist/recording/types.js +18 -0
  207. package/dist/recording/types.js.map +1 -0
  208. package/dist/security/audit-logger.d.ts +28 -1
  209. package/dist/security/audit-logger.d.ts.map +1 -1
  210. package/dist/security/audit-logger.js +163 -35
  211. package/dist/security/audit-logger.js.map +1 -1
  212. package/dist/session-manager.d.ts +52 -5
  213. package/dist/session-manager.d.ts.map +1 -1
  214. package/dist/session-manager.js +108 -14
  215. package/dist/session-manager.js.map +1 -1
  216. package/dist/tenant/manager.d.ts +90 -0
  217. package/dist/tenant/manager.d.ts.map +1 -0
  218. package/dist/tenant/manager.js +253 -0
  219. package/dist/tenant/manager.js.map +1 -0
  220. package/dist/tenant/registry.d.ts +30 -0
  221. package/dist/tenant/registry.d.ts.map +1 -0
  222. package/dist/tenant/registry.js +71 -0
  223. package/dist/tenant/registry.js.map +1 -0
  224. package/dist/tenant/types.d.ts +30 -0
  225. package/dist/tenant/types.d.ts.map +1 -0
  226. package/dist/tenant/types.js +13 -0
  227. package/dist/tenant/types.js.map +1 -0
  228. package/dist/tools/act.d.ts +9 -0
  229. package/dist/tools/act.d.ts.map +1 -0
  230. package/dist/tools/act.js +469 -0
  231. package/dist/tools/act.js.map +1 -0
  232. package/dist/tools/crawl-sitemap.d.ts +11 -0
  233. package/dist/tools/crawl-sitemap.d.ts.map +1 -0
  234. package/dist/tools/crawl-sitemap.js +489 -0
  235. package/dist/tools/crawl-sitemap.js.map +1 -0
  236. package/dist/tools/crawl.d.ts +11 -0
  237. package/dist/tools/crawl.d.ts.map +1 -0
  238. package/dist/tools/crawl.js +483 -0
  239. package/dist/tools/crawl.js.map +1 -0
  240. package/dist/tools/extract-data.d.ts +6 -0
  241. package/dist/tools/extract-data.d.ts.map +1 -0
  242. package/dist/tools/extract-data.js +195 -0
  243. package/dist/tools/extract-data.js.map +1 -0
  244. package/dist/tools/fill-form.d.ts.map +1 -1
  245. package/dist/tools/fill-form.js +5 -0
  246. package/dist/tools/fill-form.js.map +1 -1
  247. package/dist/tools/find.d.ts.map +1 -1
  248. package/dist/tools/find.js +53 -0
  249. package/dist/tools/find.js.map +1 -1
  250. package/dist/tools/index.d.ts.map +1 -1
  251. package/dist/tools/index.js +26 -0
  252. package/dist/tools/index.js.map +1 -1
  253. package/dist/tools/interact.d.ts.map +1 -1
  254. package/dist/tools/interact.js +3 -0
  255. package/dist/tools/interact.js.map +1 -1
  256. package/dist/tools/javascript.d.ts.map +1 -1
  257. package/dist/tools/javascript.js +11 -16
  258. package/dist/tools/javascript.js.map +1 -1
  259. package/dist/tools/navigate.d.ts.map +1 -1
  260. package/dist/tools/navigate.js +46 -0
  261. package/dist/tools/navigate.js.map +1 -1
  262. package/dist/tools/read-page.d.ts.map +1 -1
  263. package/dist/tools/read-page.js +8 -6
  264. package/dist/tools/read-page.js.map +1 -1
  265. package/dist/tools/recording.d.ts +7 -0
  266. package/dist/tools/recording.d.ts.map +1 -0
  267. package/dist/tools/recording.js +399 -0
  268. package/dist/tools/recording.js.map +1 -0
  269. package/dist/tools/totp-generate.d.ts +6 -0
  270. package/dist/tools/totp-generate.d.ts.map +1 -0
  271. package/dist/tools/totp-generate.js +105 -0
  272. package/dist/tools/totp-generate.js.map +1 -0
  273. package/dist/tools/vision-find.d.ts +12 -0
  274. package/dist/tools/vision-find.d.ts.map +1 -0
  275. package/dist/tools/vision-find.js +115 -0
  276. package/dist/tools/vision-find.js.map +1 -0
  277. package/dist/transports/http.d.ts +68 -3
  278. package/dist/transports/http.d.ts.map +1 -1
  279. package/dist/transports/http.js +398 -33
  280. package/dist/transports/http.js.map +1 -1
  281. package/dist/transports/index.d.ts +18 -2
  282. package/dist/transports/index.d.ts.map +1 -1
  283. package/dist/transports/index.js +4 -2
  284. package/dist/transports/index.js.map +1 -1
  285. package/dist/transports/stdio.d.ts +1 -1
  286. package/dist/transports/stdio.d.ts.map +1 -1
  287. package/dist/transports/stdio.js.map +1 -1
  288. package/dist/types/captcha.d.ts +16 -0
  289. package/dist/types/captcha.d.ts.map +1 -0
  290. package/dist/types/captcha.js +6 -0
  291. package/dist/types/captcha.js.map +1 -0
  292. package/dist/types/mcp.d.ts +10 -0
  293. package/dist/types/mcp.d.ts.map +1 -1
  294. package/dist/types/mcp.js +14 -0
  295. package/dist/types/mcp.js.map +1 -1
  296. package/dist/types/session.d.ts +14 -0
  297. package/dist/types/session.d.ts.map +1 -1
  298. package/dist/utils/auth-token.d.ts +18 -0
  299. package/dist/utils/auth-token.d.ts.map +1 -0
  300. package/dist/utils/auth-token.js +95 -0
  301. package/dist/utils/auth-token.js.map +1 -0
  302. package/dist/utils/budget.d.ts +54 -0
  303. package/dist/utils/budget.d.ts.map +1 -0
  304. package/dist/utils/budget.js +84 -0
  305. package/dist/utils/budget.js.map +1 -0
  306. package/dist/utils/cdp-abort.d.ts +19 -0
  307. package/dist/utils/cdp-abort.d.ts.map +1 -0
  308. package/dist/utils/cdp-abort.js +39 -0
  309. package/dist/utils/cdp-abort.js.map +1 -0
  310. package/dist/utils/crawl-utils.d.ts +104 -0
  311. package/dist/utils/crawl-utils.d.ts.map +1 -0
  312. package/dist/utils/crawl-utils.js +354 -0
  313. package/dist/utils/crawl-utils.js.map +1 -0
  314. package/dist/utils/page-diagnostics.d.ts +6 -0
  315. package/dist/utils/page-diagnostics.d.ts.map +1 -1
  316. package/dist/utils/page-diagnostics.js +44 -49
  317. package/dist/utils/page-diagnostics.js.map +1 -1
  318. package/dist/utils/rate-limiter.d.ts +17 -6
  319. package/dist/utils/rate-limiter.d.ts.map +1 -1
  320. package/dist/utils/rate-limiter.js +24 -9
  321. package/dist/utils/rate-limiter.js.map +1 -1
  322. package/dist/utils/safe-listener.d.ts +36 -0
  323. package/dist/utils/safe-listener.d.ts.map +1 -0
  324. package/dist/utils/safe-listener.js +74 -0
  325. package/dist/utils/safe-listener.js.map +1 -0
  326. package/dist/utils/with-timeout.d.ts +8 -3
  327. package/dist/utils/with-timeout.d.ts.map +1 -1
  328. package/dist/utils/with-timeout.js +25 -4
  329. package/dist/utils/with-timeout.js.map +1 -1
  330. package/dist/vision/auto-detect.d.ts +26 -0
  331. package/dist/vision/auto-detect.d.ts.map +1 -0
  332. package/dist/vision/auto-detect.js +100 -0
  333. package/dist/vision/auto-detect.js.map +1 -0
  334. package/dist/vision/config.d.ts +21 -0
  335. package/dist/vision/config.d.ts.map +1 -0
  336. package/dist/vision/config.js +39 -0
  337. package/dist/vision/config.js.map +1 -0
  338. package/dist/vision/screenshot-analyzer.d.ts +53 -0
  339. package/dist/vision/screenshot-analyzer.d.ts.map +1 -0
  340. package/dist/vision/screenshot-analyzer.js +310 -0
  341. package/dist/vision/screenshot-analyzer.js.map +1 -0
  342. package/dist/vision/types.d.ts +51 -0
  343. package/dist/vision/types.d.ts.map +1 -0
  344. package/dist/vision/types.js +8 -0
  345. package/dist/vision/types.js.map +1 -0
  346. package/package.json +4 -1
package/README.md CHANGED
@@ -409,6 +409,48 @@ Tier 3 launches a real headed Chrome window with a genuine user-agent (`Chrome/.
409
409
 
410
410
  ---
411
411
 
412
+ ## FAQ: Comparison with Other Browser MCPs
413
+
414
+ Common questions from users evaluating OpenChrome against Chrome DevTools MCP, Firefox DevTools MCP, and similar tools (see [#612](https://github.com/shaun0927/openchrome/issues/612)).
415
+
416
+ ### Can multiple MCP clients share tabs safely?
417
+
418
+ **Yes — tabs cannot clobber each other across clients.**
419
+
420
+ OpenChrome identifies every tab by its CDP `targetId` — a stable, browser-assigned string — not by a visible 1/2/3 index. On top of stable IDs, two layers of isolation are specifically designed for multi-client scenarios:
421
+
422
+ - **`workerId`** — logical tab groups per client or parallel lane. A new tab under one `workerId` is invisible to another and never replaces one.
423
+ - **`profileDirectory`** — launches a fully separate Chrome instance bound to that profile, giving OS-level cookie / storage / extension isolation.
424
+
425
+ If client A opens five tabs and client B opens five tabs, all ten `tabId`s are distinct and stable; a new tab from A can never displace B's tab #3.
426
+
427
+ ### How do I handle sites that require interactive login (password, 2FA, CAPTCHA)?
428
+
429
+ Two mechanisms, used together in practice:
430
+
431
+ **1. Persistent-profile headless — log in once, automate forever.**
432
+ Point OpenChrome at a persistent `userDataDir` (+ optional `profileDirectory`) and cookies / `localStorage` / IndexedDB survive across runs. After the first login, subsequent **headless** runs stay logged in until the site invalidates the session.
433
+
434
+ **2. Headed fallback for the initial login or WAF-blocked sites.**
435
+ When a human action is genuinely required (first-time login, 2FA, CAPTCHA, WebAuthn) or when a Tier-1/Tier-2 headless attempt is blocked by a CDN/WAF, OpenChrome lazy-launches a separate headed Chrome on a different debug port. Cookies are sync'd from the real Chrome profile before launch, and the headed page is registered back into the same logical session so the surrounding workflow continues seamlessly.
436
+
437
+ **Typical pattern:** bootstrap the login once via the headed path → the persistent profile carries the cookies → all subsequent automation runs headless without a window.
438
+
439
+ ### Does OpenChrome steal focus with popup windows?
440
+
441
+ **No — the "recurring popup interruptions" problem does not occur in OpenChrome.**
442
+
443
+ The headed-browser focus-stealing pattern that users encounter with some MCP servers (cross-Space jumps on macOS, un-minimizable popups, per-tool-call window raises) comes from designs where the MCP drives a user-visible browser and creates OS windows as it works. OpenChrome is architected differently:
444
+
445
+ - **Default mode is headless** — no window exists, so there is nothing to take focus.
446
+ - **`tabs_create` opens a tab, not an OS window.** New tabs are created via CDP inside the already-running Chrome, and OpenChrome never calls `page.bringToFront()` anywhere in the codebase.
447
+ - **The headed fallback is lazy and reused.** When it is needed, it launches **once** per server lifetime; every later navigation/tab runs inside that same instance. At worst you see one focus grab the very first time the fallback activates — not one per action, never one per tab.
448
+ - **The headed fallback is optional.** If persistent-profile headless is sufficient for your sites, you will never see a browser window.
449
+
450
+ The only scenario in which a window appears at all is the first time the Tier-3 headed fallback activates in a given session.
451
+
452
+ ---
453
+
412
454
  ## Benchmarks
413
455
 
414
456
  Measure token efficiency and parallel performance:
@@ -514,6 +556,12 @@ openchrome serve \
514
556
 
515
557
  ---
516
558
 
559
+ ## Authentication
560
+
561
+ OpenChrome supports per-tenant API keys, JWT/OAuth, a legacy shared token, and an unauthenticated mode. See **[docs/auth.md](docs/auth.md)** for the full guide including quickstart, scope table, key rotation, revocation, and troubleshooting.
562
+
563
+ ---
564
+
517
565
  ## Under the Hood: 8-Layer Reliability
518
566
 
519
567
  OpenChrome has **49 distinct reliability mechanisms** across 8 defense layers — ensuring no single failure can hang the MCP server.
@@ -0,0 +1,48 @@
1
+ {
2
+ "$schema": "./audit-redaction.schema.json",
3
+ "description": "Per-tool redaction rules applied to audit log entries. Each rule identifies a sensitive field by a JSON-path-like key and describes how the value should be recorded: 'redact' replaces with [REDACTED], 'hash' stores sha256:<hex>, 'truncate' keeps the first N bytes and appends a hash of the full value.",
4
+ "defaultSensitiveFieldNames": [
5
+ "password",
6
+ "passwd",
7
+ "pwd",
8
+ "secret",
9
+ "token",
10
+ "authorization",
11
+ "auth",
12
+ "api_key",
13
+ "apikey",
14
+ "access_key",
15
+ "refresh_token",
16
+ "id_token",
17
+ "session_token",
18
+ "cookie",
19
+ "set-cookie",
20
+ "credit_card",
21
+ "ssn",
22
+ "private_key"
23
+ ],
24
+ "tools": {
25
+ "cookies": [
26
+ { "path": "value", "mode": "hash" }
27
+ ],
28
+ "cookies.set": [
29
+ { "path": "value", "mode": "hash" },
30
+ { "path": "cookies[*].value", "mode": "hash" }
31
+ ],
32
+ "fill_form": [
33
+ { "path": "fields[*].value", "mode": "redactIfSensitiveName" }
34
+ ],
35
+ "form_input": [
36
+ { "path": "value", "mode": "redact" }
37
+ ],
38
+ "type": [
39
+ { "path": "text", "mode": "truncate", "maxBytes": 200 }
40
+ ],
41
+ "javascript_tool": [
42
+ { "path": "code", "mode": "truncate", "maxBytes": 200 }
43
+ ],
44
+ "storage": [
45
+ { "path": "value", "mode": "truncate", "maxBytes": 200 }
46
+ ]
47
+ }
48
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Action Cache - Domain memory integration for caching successful action sequences.
3
+ *
4
+ * After a successful `act` execution, saves the instruction→sequence mapping.
5
+ * On repeat visits to the same domain, tries the cached sequence first.
6
+ */
7
+ import { ParsedAction } from './action-parser';
8
+ export interface CachedSequence {
9
+ instruction: string;
10
+ actions: ParsedAction[];
11
+ cachedAt: number;
12
+ }
13
+ /**
14
+ * Look up a cached action sequence for the given instruction and domain.
15
+ * Returns null if no cache hit or confidence is too low.
16
+ */
17
+ export declare function getCachedSequence(url: string, instruction: string): CachedSequence | null;
18
+ /**
19
+ * Cache a successful action sequence for the given domain.
20
+ */
21
+ export declare function cacheSequence(url: string, instruction: string, actions: ParsedAction[]): void;
22
+ /**
23
+ * Report success/failure for a cached sequence to adjust confidence.
24
+ */
25
+ export declare function validateCachedSequence(url: string, instruction: string, success: boolean): void;
26
+ //# sourceMappingURL=action-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-cache.d.ts","sourceRoot":"","sources":["../../src/actions/action-cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAK/C,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAmBzF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI,CAa7F;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAW/F"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ /**
3
+ * Action Cache - Domain memory integration for caching successful action sequences.
4
+ *
5
+ * After a successful `act` execution, saves the instruction→sequence mapping.
6
+ * On repeat visits to the same domain, tries the cached sequence first.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.getCachedSequence = getCachedSequence;
10
+ exports.cacheSequence = cacheSequence;
11
+ exports.validateCachedSequence = validateCachedSequence;
12
+ const domain_memory_1 = require("../memory/domain-memory");
13
+ const CACHE_KEY_PREFIX = 'act-sequence:';
14
+ const MIN_CONFIDENCE = 0.6;
15
+ /**
16
+ * Look up a cached action sequence for the given instruction and domain.
17
+ * Returns null if no cache hit or confidence is too low.
18
+ */
19
+ function getCachedSequence(url, instruction) {
20
+ const domain = (0, domain_memory_1.extractDomainFromUrl)(url);
21
+ if (!domain)
22
+ return null;
23
+ const key = CACHE_KEY_PREFIX + normalizeForCache(instruction);
24
+ const memory = (0, domain_memory_1.getDomainMemory)();
25
+ const entries = memory.query(domain, key);
26
+ if (entries.length === 0)
27
+ return null;
28
+ const best = entries[0]; // Already sorted by confidence desc
29
+ if (best.confidence < MIN_CONFIDENCE)
30
+ return null;
31
+ try {
32
+ const cached = JSON.parse(best.value);
33
+ return cached;
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ }
39
+ /**
40
+ * Cache a successful action sequence for the given domain.
41
+ */
42
+ function cacheSequence(url, instruction, actions) {
43
+ const domain = (0, domain_memory_1.extractDomainFromUrl)(url);
44
+ if (!domain)
45
+ return;
46
+ const key = CACHE_KEY_PREFIX + normalizeForCache(instruction);
47
+ const value = {
48
+ instruction,
49
+ actions,
50
+ cachedAt: Date.now(),
51
+ };
52
+ const memory = (0, domain_memory_1.getDomainMemory)();
53
+ memory.record(domain, key, JSON.stringify(value));
54
+ }
55
+ /**
56
+ * Report success/failure for a cached sequence to adjust confidence.
57
+ */
58
+ function validateCachedSequence(url, instruction, success) {
59
+ const domain = (0, domain_memory_1.extractDomainFromUrl)(url);
60
+ if (!domain)
61
+ return;
62
+ const key = CACHE_KEY_PREFIX + normalizeForCache(instruction);
63
+ const memory = (0, domain_memory_1.getDomainMemory)();
64
+ const entries = memory.query(domain, key);
65
+ if (entries.length > 0) {
66
+ memory.validate(entries[0].id, success);
67
+ }
68
+ }
69
+ /**
70
+ * Normalize instruction for cache key: lowercase, collapse whitespace, trim.
71
+ */
72
+ function normalizeForCache(instruction) {
73
+ return instruction.toLowerCase().replace(/\s+/g, ' ').trim();
74
+ }
75
+ //# sourceMappingURL=action-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-cache.js","sourceRoot":"","sources":["../../src/actions/action-cache.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAkBH,8CAmBC;AAKD,sCAaC;AAKD,wDAWC;AArED,2DAAgF;AAGhF,MAAM,gBAAgB,GAAG,eAAe,CAAC;AACzC,MAAM,cAAc,GAAG,GAAG,CAAC;AAQ3B;;;GAGG;AACH,SAAgB,iBAAiB,CAAC,GAAW,EAAE,WAAmB;IAChE,MAAM,MAAM,GAAG,IAAA,oCAAoB,EAAC,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,GAAG,GAAG,gBAAgB,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,IAAA,+BAAe,GAAE,CAAC;IACjC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE1C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,oCAAoC;IAC7D,IAAI,IAAI,CAAC,UAAU,GAAG,cAAc;QAAE,OAAO,IAAI,CAAC;IAElD,IAAI,CAAC;QACH,MAAM,MAAM,GAAmB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAAC,GAAW,EAAE,WAAmB,EAAE,OAAuB;IACrF,MAAM,MAAM,GAAG,IAAA,oCAAoB,EAAC,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,MAAM,GAAG,GAAG,gBAAgB,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAmB;QAC5B,WAAW;QACX,OAAO;QACP,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;KACrB,CAAC;IAEF,MAAM,MAAM,GAAG,IAAA,+BAAe,GAAE,CAAC;IACjC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,SAAgB,sBAAsB,CAAC,GAAW,EAAE,WAAmB,EAAE,OAAgB;IACvF,MAAM,MAAM,GAAG,IAAA,oCAAoB,EAAC,GAAG,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM;QAAE,OAAO;IAEpB,MAAM,GAAG,GAAG,gBAAgB,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,IAAA,+BAAe,GAAE,CAAC;IACjC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAE1C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,WAAmB;IAC5C,OAAO,WAAW,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Action Parser - Converts natural language instructions into structured action sequences.
3
+ * Uses pattern matching and keyword extraction only — no LLM calls.
4
+ */
5
+ export type ActionVerb = 'click' | 'type' | 'select' | 'check' | 'uncheck' | 'hover' | 'scroll' | 'wait' | 'navigate';
6
+ export interface ParsedAction {
7
+ action: ActionVerb;
8
+ target?: string;
9
+ value?: string;
10
+ condition?: string;
11
+ }
12
+ export interface ParseResult {
13
+ success: boolean;
14
+ actions: ParsedAction[];
15
+ error?: string;
16
+ suggestion?: string;
17
+ }
18
+ /**
19
+ * Parse a natural language browser instruction into a structured action sequence.
20
+ * Pure pattern-matching — no LLM calls, no network I/O.
21
+ */
22
+ export declare function parseInstruction(instruction: string): ParseResult;
23
+ //# sourceMappingURL=action-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-parser.d.ts","sourceRoot":"","sources":["../../src/actions/action-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAEtH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAkTD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,CA0CjE"}
@@ -0,0 +1,321 @@
1
+ "use strict";
2
+ /**
3
+ * Action Parser - Converts natural language instructions into structured action sequences.
4
+ * Uses pattern matching and keyword extraction only — no LLM calls.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.parseInstruction = parseInstruction;
8
+ // ---------------------------------------------------------------------------
9
+ // Verb detection patterns
10
+ // ---------------------------------------------------------------------------
11
+ /** Returns the ActionVerb for a given phrase prefix, or null if unrecognised. */
12
+ function detectVerb(phrase) {
13
+ const s = phrase.trim().toLowerCase();
14
+ // Korean — check first so multi-byte sequences don't interfere with ASCII patterns
15
+ if (/체크\s*해제|언체크/.test(s))
16
+ return 'uncheck';
17
+ if (/체크/.test(s))
18
+ return 'check';
19
+ if (/클릭|누르|탭/.test(s))
20
+ return 'click';
21
+ if (/입력|작성|쓰|타이핑/.test(s))
22
+ return 'type';
23
+ if (/선택|고르/.test(s))
24
+ return 'select';
25
+ if (/호버|마우스\s*오버/.test(s))
26
+ return 'hover';
27
+ if (/스크롤/.test(s))
28
+ return 'scroll';
29
+ if (/기다리|대기/.test(s))
30
+ return 'wait';
31
+ if (/이동|열|방문|접속/.test(s))
32
+ return 'navigate';
33
+ // English — longer phrases before shorter ones to avoid partial matches
34
+ if (/^(?:hover\s+over|mouse\s+over|hover)\b/.test(s))
35
+ return 'hover';
36
+ if (/^(?:scroll\s+(?:down|up|to)|scroll)\b/.test(s))
37
+ return 'scroll';
38
+ if (/^(?:wait\s+for|wait)\b/.test(s))
39
+ return 'wait';
40
+ if (/^(?:navigate\s+to|go\s+to|open|visit)\b/.test(s))
41
+ return 'navigate';
42
+ if (/^(?:fill\s+in|type|enter|input|write)\b/.test(s))
43
+ return 'type';
44
+ if (/^(?:select|choose|pick)\b/.test(s))
45
+ return 'select';
46
+ if (/^(?:uncheck|untick)\b/.test(s))
47
+ return 'uncheck';
48
+ if (/^(?:check|tick)\b/.test(s))
49
+ return 'check';
50
+ if (/^(?:click|press|tap)\b/.test(s))
51
+ return 'click';
52
+ return null;
53
+ }
54
+ /** True if the trimmed phrase starts with a recognised verb (English or Korean). */
55
+ function startsWithVerb(phrase) {
56
+ return detectVerb(phrase) !== null;
57
+ }
58
+ // ---------------------------------------------------------------------------
59
+ // Compound instruction splitter
60
+ // ---------------------------------------------------------------------------
61
+ /**
62
+ * Split a compound instruction into individual clauses.
63
+ * Splitting happens on:
64
+ * ", then " / ", and then "
65
+ * " then " — only when followed by a verb
66
+ * " and " — only when followed by a verb (avoids "name and email")
67
+ * "," — followed by a space and a verb
68
+ */
69
+ function splitIntoSegments(instruction) {
70
+ // Normalise whitespace
71
+ const text = instruction.trim().replace(/\s+/g, ' ');
72
+ // First pass: split on ", then " and ", and then " unconditionally
73
+ const parts = [];
74
+ const unconditional = text.split(/,\s*and\s+then\s+|,\s*then\s+/i);
75
+ for (const part of unconditional) {
76
+ // Second pass within each part: Korean conjunctions, then English conjunctions
77
+ const koreanParts = splitOnKoreanConjunctions(part.trim());
78
+ for (const kp of koreanParts) {
79
+ const subParts = splitOnConjunctions(kp.trim());
80
+ parts.push(...subParts);
81
+ }
82
+ }
83
+ return parts.filter(p => p.length > 0);
84
+ }
85
+ /**
86
+ * Split Korean compound sentences on conjunctive endings:
87
+ * "하고" (and do), "이고" (and), "고" after verb stem.
88
+ * e.g. "이메일을 입력하고 제출 버튼을 클릭해" → ["이메일을 입력하고", "제출 버튼을 클릭해"]
89
+ * We split AFTER the "하고/고" suffix so the first segment retains it for verb detection.
90
+ */
91
+ function splitOnKoreanConjunctions(text) {
92
+ // Split on "하고 " (connective "and") between two Korean segments
93
+ // Pattern: split at boundary after "하고" followed by a Korean character
94
+ const parts = [];
95
+ // Match "하고" or "이고" or "ㄱ고" connectives between clauses
96
+ const re = /하고\s+(?=\S)/gu;
97
+ let lastIndex = 0;
98
+ let match;
99
+ while ((match = re.exec(text)) !== null) {
100
+ // Include "하고" in the first segment so its verb can still be detected
101
+ parts.push(text.slice(lastIndex, match.index + 2).trim()); // up to and including "하고"
102
+ lastIndex = match.index + match[0].length;
103
+ }
104
+ parts.push(text.slice(lastIndex).trim());
105
+ return parts.filter(p => p.length > 0);
106
+ }
107
+ function splitOnConjunctions(text) {
108
+ // Split on "WORD, VERB" — comma followed by a verb-starting word
109
+ // or " then VERB" / " and VERB"
110
+ const result = [];
111
+ let remaining = text;
112
+ // Pattern: (", " | " then " | " and ") followed by a verb-starting token
113
+ const re = /(?:,\s+|\s+then\s+|\s+and\s+)(?=[a-z\u3131-\uD7A3\u4E00-\u9FFF])/gi;
114
+ let lastIndex = 0;
115
+ let match;
116
+ while ((match = re.exec(remaining)) !== null) {
117
+ const afterSplit = remaining.slice(match.index + match[0].length);
118
+ if (startsWithVerb(afterSplit)) {
119
+ result.push(remaining.slice(lastIndex, match.index).trim());
120
+ lastIndex = match.index + match[0].length;
121
+ }
122
+ }
123
+ result.push(remaining.slice(lastIndex).trim());
124
+ return result.filter(p => p.length > 0);
125
+ }
126
+ // ---------------------------------------------------------------------------
127
+ // Value / target extractors per verb
128
+ // ---------------------------------------------------------------------------
129
+ /** Detect a URL anywhere in a string. */
130
+ function extractUrl(text) {
131
+ const m = text.match(/https?:\/\/[^\s,"']+/);
132
+ return m ? m[0] : undefined;
133
+ }
134
+ function parseClickPhrase(phrase) {
135
+ const s = phrase.trim();
136
+ // Korean: "{target}을/를 클릭" or "{target} 클릭"
137
+ const krMatch = s.match(/^(.+?)(?:을|를)?\s+(?:클릭|누르|탭)/u);
138
+ if (krMatch) {
139
+ return { action: 'click', target: krMatch[1].trim() };
140
+ }
141
+ // English: strip leading verb words
142
+ const stripped = s.replace(/^(?:click|press|tap)\s+(?:on\s+)?(?:the\s+)?/i, '');
143
+ return { action: 'click', target: stripped || undefined };
144
+ }
145
+ function parseTypePhrase(phrase) {
146
+ const s = phrase.trim();
147
+ // Korean: "{target}에 {value}을/를 입력" or "{value}을/를 입력"
148
+ const krInTarget = s.match(/^(.+?)에\s+(.+?)(?:을|를)?\s+입력/u);
149
+ if (krInTarget) {
150
+ return { action: 'type', target: krInTarget[1].trim(), value: krInTarget[2].trim() };
151
+ }
152
+ const krNoTarget = s.match(/^(.+?)(?:을|를)?\s+입력/u);
153
+ if (krNoTarget) {
154
+ return { action: 'type', value: krNoTarget[1].trim() };
155
+ }
156
+ // English patterns:
157
+ // "type {value} in(to) the {target}"
158
+ const inMatch = s.match(/^(?:type|enter|input|fill\s+in|write)\s+(.+?)\s+in(?:to)?\s+(?:the\s+)?(.+)$/i);
159
+ if (inMatch) {
160
+ return { action: 'type', value: inMatch[1].trim(), target: inMatch[2].trim() };
161
+ }
162
+ // "type {value}"
163
+ const simpleMatch = s.match(/^(?:type|enter|input|fill\s+in|write)\s+(.+)$/i);
164
+ if (simpleMatch) {
165
+ return { action: 'type', value: simpleMatch[1].trim() };
166
+ }
167
+ return { action: 'type' };
168
+ }
169
+ function parseSelectPhrase(phrase) {
170
+ const s = phrase.trim();
171
+ // "select {value} from (the) {target}" / "choose {value} in (the) {target}"
172
+ const fromMatch = s.match(/^(?:select|choose|pick)\s+(.+?)\s+(?:from|in)\s+(?:the\s+)?(.+)$/i);
173
+ if (fromMatch) {
174
+ return { action: 'select', value: fromMatch[1].trim(), target: fromMatch[2].trim() };
175
+ }
176
+ // Korean: "{value}을/를 선택" or "{target}에서 {value} 선택"
177
+ const krSelect = s.match(/^(.+?)(?:을|를)?\s+선택/u);
178
+ if (krSelect) {
179
+ return { action: 'select', value: krSelect[1].trim() };
180
+ }
181
+ const stripped = s.replace(/^(?:select|choose|pick)\s+/i, '');
182
+ return { action: 'select', target: stripped || undefined };
183
+ }
184
+ function parseNavigatePhrase(phrase) {
185
+ const s = phrase.trim();
186
+ // Extract URL first
187
+ const url = extractUrl(s);
188
+ if (url) {
189
+ return { action: 'navigate', value: url };
190
+ }
191
+ // Korean: "{url}로 이동" / "{url}에 접속"
192
+ const krNav = s.match(/^(.+?)(?:로|에)\s+(?:이동|접속)/u);
193
+ if (krNav) {
194
+ return { action: 'navigate', value: krNav[1].trim() };
195
+ }
196
+ // English: strip verb prefix
197
+ const stripped = s.replace(/^(?:navigate\s+to|go\s+to|open|visit)\s+/i, '');
198
+ return { action: 'navigate', value: stripped || undefined };
199
+ }
200
+ function parseScrollPhrase(phrase) {
201
+ const s = phrase.trim();
202
+ // "scroll down to {target}" / "scroll up to {target}" / "scroll to {target}"
203
+ const toMatch = s.match(/^(?:스크롤\s+)?scroll\s+(?:down\s+to|up\s+to|to)\s+(?:the\s+)?(.+)$/i);
204
+ if (toMatch) {
205
+ return { action: 'scroll', target: toMatch[1].trim() };
206
+ }
207
+ // "scroll down" / "scroll up"
208
+ const dirMatch = s.match(/^(?:스크롤\s+)?scroll\s+(down|up)$/i);
209
+ if (dirMatch) {
210
+ return { action: 'scroll', value: dirMatch[1].toLowerCase() };
211
+ }
212
+ // Korean bare: "스크롤"
213
+ if (/^스크롤$/.test(s)) {
214
+ return { action: 'scroll' };
215
+ }
216
+ const stripped = s.replace(/^(?:스크롤|scroll)\s+/i, '');
217
+ return { action: 'scroll', target: stripped || undefined };
218
+ }
219
+ function parseWaitPhrase(phrase) {
220
+ const s = phrase.trim();
221
+ // "wait for {target} to {condition}"
222
+ const toCondMatch = s.match(/^(?:wait\s+for|wait)\s+(?:the\s+)?(.+?)\s+to\s+(appear|disappear|load)$/i);
223
+ if (toCondMatch) {
224
+ return { action: 'wait', target: toCondMatch[1].trim(), condition: toCondMatch[2].toLowerCase() };
225
+ }
226
+ // "wait for {target}"
227
+ const forMatch = s.match(/^(?:wait\s+for|wait)\s+(?:the\s+)?(.+)$/i);
228
+ if (forMatch) {
229
+ return { action: 'wait', target: forMatch[1].trim(), condition: 'appear' };
230
+ }
231
+ // Korean: "{target}을/를 기다리" or "기다리"
232
+ const krWait = s.match(/^(.+?)(?:을|를)?\s*(?:기다리|대기)/u);
233
+ if (krWait) {
234
+ return { action: 'wait', target: krWait[1].trim(), condition: 'appear' };
235
+ }
236
+ return { action: 'wait', condition: 'appear' };
237
+ }
238
+ function parseCheckPhrase(phrase, verb) {
239
+ const s = phrase.trim();
240
+ const stripped = s.replace(/^(?:uncheck|untick|check|tick|체크\s*해제|언체크|체크)\s+(?:the\s+)?/i, '');
241
+ return { action: verb, target: stripped || undefined };
242
+ }
243
+ function parseHoverPhrase(phrase) {
244
+ const s = phrase.trim();
245
+ const stripped = s.replace(/^(?:hover\s+over|mouse\s+over|hover|호버|마우스\s*오버)\s+(?:the\s+)?/i, '');
246
+ return { action: 'hover', target: stripped || undefined };
247
+ }
248
+ // ---------------------------------------------------------------------------
249
+ // Single-phrase parser
250
+ // ---------------------------------------------------------------------------
251
+ function parsePhrase(phrase) {
252
+ const trimmed = phrase.trim();
253
+ if (!trimmed)
254
+ return null;
255
+ const verb = detectVerb(trimmed);
256
+ if (!verb) {
257
+ // Check if it contains a URL — treat as navigate
258
+ const url = extractUrl(trimmed);
259
+ if (url)
260
+ return { action: 'navigate', value: url };
261
+ return null;
262
+ }
263
+ switch (verb) {
264
+ case 'click': return parseClickPhrase(trimmed);
265
+ case 'type': return parseTypePhrase(trimmed);
266
+ case 'select': return parseSelectPhrase(trimmed);
267
+ case 'navigate': return parseNavigatePhrase(trimmed);
268
+ case 'scroll': return parseScrollPhrase(trimmed);
269
+ case 'wait': return parseWaitPhrase(trimmed);
270
+ case 'check': return parseCheckPhrase(trimmed, 'check');
271
+ case 'uncheck': return parseCheckPhrase(trimmed, 'uncheck');
272
+ case 'hover': return parseHoverPhrase(trimmed);
273
+ }
274
+ }
275
+ // ---------------------------------------------------------------------------
276
+ // Public API
277
+ // ---------------------------------------------------------------------------
278
+ /**
279
+ * Parse a natural language browser instruction into a structured action sequence.
280
+ * Pure pattern-matching — no LLM calls, no network I/O.
281
+ */
282
+ function parseInstruction(instruction) {
283
+ if (!instruction || instruction.trim().length === 0) {
284
+ return {
285
+ success: false,
286
+ actions: [],
287
+ error: 'Instruction is empty',
288
+ suggestion: 'Provide a natural language instruction such as "click the login button" or "type hello in the search box".',
289
+ };
290
+ }
291
+ const segments = splitIntoSegments(instruction);
292
+ const actions = [];
293
+ const failed = [];
294
+ for (const segment of segments) {
295
+ const parsed = parsePhrase(segment);
296
+ if (parsed) {
297
+ actions.push(parsed);
298
+ }
299
+ else {
300
+ failed.push(segment);
301
+ }
302
+ }
303
+ if (actions.length === 0) {
304
+ return {
305
+ success: false,
306
+ actions: [],
307
+ error: `Could not parse instruction: "${instruction}"`,
308
+ suggestion: 'Try breaking the instruction into individual steps such as "click X", "type Y in Z", or "navigate to URL".',
309
+ };
310
+ }
311
+ if (failed.length > 0) {
312
+ // Partial parse — return what we have but still signal success for the parseable parts
313
+ return {
314
+ success: true,
315
+ actions,
316
+ suggestion: `Could not parse the following segment(s): ${failed.map(f => `"${f}"`).join(', ')}. Try breaking these into individual tool calls.`,
317
+ };
318
+ }
319
+ return { success: true, actions };
320
+ }
321
+ //# sourceMappingURL=action-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-parser.js","sourceRoot":"","sources":["../../src/actions/action-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Action Templates - Pre-compiled action sequences for common browser workflows.
3
+ *
4
+ * When the user's instruction matches a template, the cached sequence is used
5
+ * instead of NL parsing. This is faster and more reliable for known patterns.
6
+ */
7
+ import { ParsedAction } from './action-parser';
8
+ export interface ActionTemplate {
9
+ id: string;
10
+ name: string;
11
+ description: string;
12
+ /** Regex pattern to match the instruction. Named groups become template variables. */
13
+ pattern: RegExp;
14
+ /** Function that returns the action sequence, using captured groups as variables. */
15
+ build: (vars: Record<string, string>) => ParsedAction[];
16
+ }
17
+ /**
18
+ * Built-in action templates for common workflows.
19
+ */
20
+ export declare const ACTION_TEMPLATES: ActionTemplate[];
21
+ /**
22
+ * Try to match instruction against known templates.
23
+ * Returns the action sequence if matched, null otherwise.
24
+ */
25
+ export declare function matchTemplate(instruction: string): {
26
+ template: ActionTemplate;
27
+ actions: ParsedAction[];
28
+ } | null;
29
+ //# sourceMappingURL=action-templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-templates.d.ts","sourceRoot":"","sources":["../../src/actions/action-templates.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAoB,MAAM,iBAAiB,CAAC;AAEjE,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,qFAAqF;IACrF,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,YAAY,EAAE,CAAC;CACzD;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,cAAc,EAwF5C,CAAC;AAEF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,YAAY,EAAE,CAAA;CAAE,GAAG,IAAI,CAmB/G"}