@fusengine/browser-mcp 0.1.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 (353) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +175 -0
  3. package/dist/actions/act-by-ref.d.ts +13 -0
  4. package/dist/actions/act-by-ref.d.ts.map +1 -0
  5. package/dist/actions/act-by-ref.js +25 -0
  6. package/dist/actions/act-by-ref.js.map +1 -0
  7. package/dist/actions/human.d.ts +8 -0
  8. package/dist/actions/human.d.ts.map +1 -0
  9. package/dist/actions/human.js +6 -0
  10. package/dist/actions/human.js.map +1 -0
  11. package/dist/actions/login.d.ts +17 -0
  12. package/dist/actions/login.d.ts.map +1 -0
  13. package/dist/actions/login.js +11 -0
  14. package/dist/actions/login.js.map +1 -0
  15. package/dist/actions/navigation.d.ts +15 -0
  16. package/dist/actions/navigation.d.ts.map +1 -0
  17. package/dist/actions/navigation.js +33 -0
  18. package/dist/actions/navigation.js.map +1 -0
  19. package/dist/actions/perform.d.ts +15 -0
  20. package/dist/actions/perform.d.ts.map +1 -0
  21. package/dist/actions/perform.js +41 -0
  22. package/dist/actions/perform.js.map +1 -0
  23. package/dist/actions/smart-click.d.ts +9 -0
  24. package/dist/actions/smart-click.d.ts.map +1 -0
  25. package/dist/actions/smart-click.js +55 -0
  26. package/dist/actions/smart-click.js.map +1 -0
  27. package/dist/actions/smart-fill.d.ts +9 -0
  28. package/dist/actions/smart-fill.d.ts.map +1 -0
  29. package/dist/actions/smart-fill.js +46 -0
  30. package/dist/actions/smart-fill.js.map +1 -0
  31. package/dist/actions/wait-for.d.ts +21 -0
  32. package/dist/actions/wait-for.d.ts.map +1 -0
  33. package/dist/actions/wait-for.js +28 -0
  34. package/dist/actions/wait-for.js.map +1 -0
  35. package/dist/agent/actions-loop.d.ts +18 -0
  36. package/dist/agent/actions-loop.d.ts.map +1 -0
  37. package/dist/agent/actions-loop.js +44 -0
  38. package/dist/agent/actions-loop.js.map +1 -0
  39. package/dist/agent/browser-agent.d.ts +24 -0
  40. package/dist/agent/browser-agent.d.ts.map +1 -0
  41. package/dist/agent/browser-agent.js +36 -0
  42. package/dist/agent/browser-agent.js.map +1 -0
  43. package/dist/agent/compact.d.ts +8 -0
  44. package/dist/agent/compact.d.ts.map +1 -0
  45. package/dist/agent/compact.js +24 -0
  46. package/dist/agent/compact.js.map +1 -0
  47. package/dist/agent/config.d.ts +30 -0
  48. package/dist/agent/config.d.ts.map +1 -0
  49. package/dist/agent/config.js +49 -0
  50. package/dist/agent/config.js.map +1 -0
  51. package/dist/agent/detect.d.ts +17 -0
  52. package/dist/agent/detect.d.ts.map +1 -0
  53. package/dist/agent/detect.js +9 -0
  54. package/dist/agent/detect.js.map +1 -0
  55. package/dist/agent/network.d.ts +16 -0
  56. package/dist/agent/network.d.ts.map +1 -0
  57. package/dist/agent/network.js +16 -0
  58. package/dist/agent/network.js.map +1 -0
  59. package/dist/agent/probe-run.d.ts +6 -0
  60. package/dist/agent/probe-run.d.ts.map +1 -0
  61. package/dist/agent/probe-run.js +90 -0
  62. package/dist/agent/probe-run.js.map +1 -0
  63. package/dist/agent/report.d.ts +29 -0
  64. package/dist/agent/report.d.ts.map +1 -0
  65. package/dist/agent/report.js +53 -0
  66. package/dist/agent/report.js.map +1 -0
  67. package/dist/agent/run-steps.d.ts +22 -0
  68. package/dist/agent/run-steps.d.ts.map +1 -0
  69. package/dist/agent/run-steps.js +59 -0
  70. package/dist/agent/run-steps.js.map +1 -0
  71. package/dist/bin/cli.d.ts +3 -0
  72. package/dist/bin/cli.d.ts.map +1 -0
  73. package/dist/bin/cli.js +84 -0
  74. package/dist/bin/cli.js.map +1 -0
  75. package/dist/bin/mcp.d.ts +3 -0
  76. package/dist/bin/mcp.d.ts.map +1 -0
  77. package/dist/bin/mcp.js +28 -0
  78. package/dist/bin/mcp.js.map +1 -0
  79. package/dist/captcha/solve.d.ts +17 -0
  80. package/dist/captcha/solve.d.ts.map +1 -0
  81. package/dist/captcha/solve.js +42 -0
  82. package/dist/captcha/solve.js.map +1 -0
  83. package/dist/consent/booking-currency.d.ts +14 -0
  84. package/dist/consent/booking-currency.d.ts.map +1 -0
  85. package/dist/consent/booking-currency.js +82 -0
  86. package/dist/consent/booking-currency.js.map +1 -0
  87. package/dist/consent/consent.d.ts +11 -0
  88. package/dist/consent/consent.d.ts.map +1 -0
  89. package/dist/consent/consent.js +27 -0
  90. package/dist/consent/consent.js.map +1 -0
  91. package/dist/consent/currency-url.d.ts +10 -0
  92. package/dist/consent/currency-url.d.ts.map +1 -0
  93. package/dist/consent/currency-url.js +18 -0
  94. package/dist/consent/currency-url.js.map +1 -0
  95. package/dist/consent/currency.d.ts +14 -0
  96. package/dist/consent/currency.d.ts.map +1 -0
  97. package/dist/consent/currency.js +48 -0
  98. package/dist/consent/currency.js.map +1 -0
  99. package/dist/engine/cdp-engine.d.ts +21 -0
  100. package/dist/engine/cdp-engine.d.ts.map +1 -0
  101. package/dist/engine/cdp-engine.js +36 -0
  102. package/dist/engine/cdp-engine.js.map +1 -0
  103. package/dist/engine/cdp-launch.d.ts +11 -0
  104. package/dist/engine/cdp-launch.d.ts.map +1 -0
  105. package/dist/engine/cdp-launch.js +54 -0
  106. package/dist/engine/cdp-launch.js.map +1 -0
  107. package/dist/engine/context.d.ts +14 -0
  108. package/dist/engine/context.d.ts.map +1 -0
  109. package/dist/engine/context.js +22 -0
  110. package/dist/engine/context.js.map +1 -0
  111. package/dist/engine/launch.d.ts +6 -0
  112. package/dist/engine/launch.d.ts.map +1 -0
  113. package/dist/engine/launch.js +53 -0
  114. package/dist/engine/launch.js.map +1 -0
  115. package/dist/engine/loader.d.ts +13 -0
  116. package/dist/engine/loader.d.ts.map +1 -0
  117. package/dist/engine/loader.js +24 -0
  118. package/dist/engine/loader.js.map +1 -0
  119. package/dist/engine/patchright-engine.d.ts +4 -0
  120. package/dist/engine/patchright-engine.d.ts.map +1 -0
  121. package/dist/engine/patchright-engine.js +10 -0
  122. package/dist/engine/patchright-engine.js.map +1 -0
  123. package/dist/engine/playwright-engine.d.ts +8 -0
  124. package/dist/engine/playwright-engine.d.ts.map +1 -0
  125. package/dist/engine/playwright-engine.js +24 -0
  126. package/dist/engine/playwright-engine.js.map +1 -0
  127. package/dist/engine/registry.d.ts +13 -0
  128. package/dist/engine/registry.d.ts.map +1 -0
  129. package/dist/engine/registry.js +18 -0
  130. package/dist/engine/registry.js.map +1 -0
  131. package/dist/extraction/challenges.d.ts +9 -0
  132. package/dist/extraction/challenges.d.ts.map +1 -0
  133. package/dist/extraction/challenges.js +24 -0
  134. package/dist/extraction/challenges.js.map +1 -0
  135. package/dist/extraction/hotel-offers.d.ts +11 -0
  136. package/dist/extraction/hotel-offers.d.ts.map +1 -0
  137. package/dist/extraction/hotel-offers.js +63 -0
  138. package/dist/extraction/hotel-offers.js.map +1 -0
  139. package/dist/extraction/main-text.d.ts +13 -0
  140. package/dist/extraction/main-text.d.ts.map +1 -0
  141. package/dist/extraction/main-text.js +20 -0
  142. package/dist/extraction/main-text.js.map +1 -0
  143. package/dist/extraction/prices.d.ts +18 -0
  144. package/dist/extraction/prices.d.ts.map +1 -0
  145. package/dist/extraction/prices.js +74 -0
  146. package/dist/extraction/prices.js.map +1 -0
  147. package/dist/extraction/snapshot-diff.d.ts +28 -0
  148. package/dist/extraction/snapshot-diff.d.ts.map +1 -0
  149. package/dist/extraction/snapshot-diff.js +30 -0
  150. package/dist/extraction/snapshot-diff.js.map +1 -0
  151. package/dist/extraction/snapshot.d.ts +14 -0
  152. package/dist/extraction/snapshot.d.ts.map +1 -0
  153. package/dist/extraction/snapshot.js +26 -0
  154. package/dist/extraction/snapshot.js.map +1 -0
  155. package/dist/extraction/structured.d.ts +26 -0
  156. package/dist/extraction/structured.d.ts.map +1 -0
  157. package/dist/extraction/structured.js +28 -0
  158. package/dist/extraction/structured.js.map +1 -0
  159. package/dist/extraction/visual.d.ts +9 -0
  160. package/dist/extraction/visual.d.ts.map +1 -0
  161. package/dist/extraction/visual.js +29 -0
  162. package/dist/extraction/visual.js.map +1 -0
  163. package/dist/guardrails/preflight.d.ts +25 -0
  164. package/dist/guardrails/preflight.d.ts.map +1 -0
  165. package/dist/guardrails/preflight.js +27 -0
  166. package/dist/guardrails/preflight.js.map +1 -0
  167. package/dist/identity/country-profiles.d.ts +12 -0
  168. package/dist/identity/country-profiles.d.ts.map +1 -0
  169. package/dist/identity/country-profiles.js +58 -0
  170. package/dist/identity/country-profiles.js.map +1 -0
  171. package/dist/identity/identity.d.ts +19 -0
  172. package/dist/identity/identity.d.ts.map +1 -0
  173. package/dist/identity/identity.js +31 -0
  174. package/dist/identity/identity.js.map +1 -0
  175. package/dist/identity/resolve.d.ts +25 -0
  176. package/dist/identity/resolve.d.ts.map +1 -0
  177. package/dist/identity/resolve.js +21 -0
  178. package/dist/identity/resolve.js.map +1 -0
  179. package/dist/index.d.ts +12 -0
  180. package/dist/index.d.ts.map +1 -0
  181. package/dist/index.js +10 -0
  182. package/dist/index.js.map +1 -0
  183. package/dist/interfaces/engine-types.d.ts +15 -0
  184. package/dist/interfaces/engine-types.d.ts.map +1 -0
  185. package/dist/interfaces/engine-types.js +6 -0
  186. package/dist/interfaces/engine-types.js.map +1 -0
  187. package/dist/interfaces/engine.d.ts +30 -0
  188. package/dist/interfaces/engine.d.ts.map +1 -0
  189. package/dist/interfaces/engine.js +2 -0
  190. package/dist/interfaces/engine.js.map +1 -0
  191. package/dist/interfaces/extraction.d.ts +63 -0
  192. package/dist/interfaces/extraction.d.ts.map +1 -0
  193. package/dist/interfaces/extraction.js +6 -0
  194. package/dist/interfaces/extraction.js.map +1 -0
  195. package/dist/interfaces/net.d.ts +48 -0
  196. package/dist/interfaces/net.d.ts.map +1 -0
  197. package/dist/interfaces/net.js +6 -0
  198. package/dist/interfaces/net.js.map +1 -0
  199. package/dist/interfaces/report.d.ts +87 -0
  200. package/dist/interfaces/report.d.ts.map +1 -0
  201. package/dist/interfaces/report.js +2 -0
  202. package/dist/interfaces/report.js.map +1 -0
  203. package/dist/interfaces/types.d.ts +90 -0
  204. package/dist/interfaces/types.d.ts.map +1 -0
  205. package/dist/interfaces/types.js +6 -0
  206. package/dist/interfaces/types.js.map +1 -0
  207. package/dist/lib/errors.d.ts +19 -0
  208. package/dist/lib/errors.d.ts.map +1 -0
  209. package/dist/lib/errors.js +30 -0
  210. package/dist/lib/errors.js.map +1 -0
  211. package/dist/lib/evaluate.d.ts +17 -0
  212. package/dist/lib/evaluate.d.ts.map +1 -0
  213. package/dist/lib/evaluate.js +10 -0
  214. package/dist/lib/evaluate.js.map +1 -0
  215. package/dist/lib/fs.d.ts +11 -0
  216. package/dist/lib/fs.d.ts.map +1 -0
  217. package/dist/lib/fs.js +34 -0
  218. package/dist/lib/fs.js.map +1 -0
  219. package/dist/lib/logger.d.ts +14 -0
  220. package/dist/lib/logger.d.ts.map +1 -0
  221. package/dist/lib/logger.js +22 -0
  222. package/dist/lib/logger.js.map +1 -0
  223. package/dist/lib/output-dir.d.ts +12 -0
  224. package/dist/lib/output-dir.d.ts.map +1 -0
  225. package/dist/lib/output-dir.js +37 -0
  226. package/dist/lib/output-dir.js.map +1 -0
  227. package/dist/lib/retry.d.ts +28 -0
  228. package/dist/lib/retry.d.ts.map +1 -0
  229. package/dist/lib/retry.js +41 -0
  230. package/dist/lib/retry.js.map +1 -0
  231. package/dist/lib/text.d.ts +9 -0
  232. package/dist/lib/text.d.ts.map +1 -0
  233. package/dist/lib/text.js +13 -0
  234. package/dist/lib/text.js.map +1 -0
  235. package/dist/net/captcha-client.d.ts +10 -0
  236. package/dist/net/captcha-client.d.ts.map +1 -0
  237. package/dist/net/captcha-client.js +48 -0
  238. package/dist/net/captcha-client.js.map +1 -0
  239. package/dist/net/captcha-inject.d.ts +10 -0
  240. package/dist/net/captcha-inject.d.ts.map +1 -0
  241. package/dist/net/captcha-inject.js +24 -0
  242. package/dist/net/captcha-inject.js.map +1 -0
  243. package/dist/net/navigate.d.ts +19 -0
  244. package/dist/net/navigate.d.ts.map +1 -0
  245. package/dist/net/navigate.js +32 -0
  246. package/dist/net/navigate.js.map +1 -0
  247. package/dist/net/throttle.d.ts +3 -0
  248. package/dist/net/throttle.d.ts.map +1 -0
  249. package/dist/net/throttle.js +23 -0
  250. package/dist/net/throttle.js.map +1 -0
  251. package/dist/proxy/country-map.d.ts +13 -0
  252. package/dist/proxy/country-map.d.ts.map +1 -0
  253. package/dist/proxy/country-map.js +38 -0
  254. package/dist/proxy/country-map.js.map +1 -0
  255. package/dist/server/env-defaults.d.ts +11 -0
  256. package/dist/server/env-defaults.d.ts.map +1 -0
  257. package/dist/server/env-defaults.js +20 -0
  258. package/dist/server/env-defaults.js.map +1 -0
  259. package/dist/server/map-options.d.ts +6 -0
  260. package/dist/server/map-options.d.ts.map +1 -0
  261. package/dist/server/map-options.js +43 -0
  262. package/dist/server/map-options.js.map +1 -0
  263. package/dist/server/resources.d.ts +4 -0
  264. package/dist/server/resources.d.ts.map +1 -0
  265. package/dist/server/resources.js +28 -0
  266. package/dist/server/resources.js.map +1 -0
  267. package/dist/server/result.d.ts +12 -0
  268. package/dist/server/result.d.ts.map +1 -0
  269. package/dist/server/result.js +18 -0
  270. package/dist/server/result.js.map +1 -0
  271. package/dist/server/schemas.d.ts +191 -0
  272. package/dist/server/schemas.d.ts.map +1 -0
  273. package/dist/server/schemas.js +72 -0
  274. package/dist/server/schemas.js.map +1 -0
  275. package/dist/server/server.d.ts +14 -0
  276. package/dist/server/server.d.ts.map +1 -0
  277. package/dist/server/server.js +37 -0
  278. package/dist/server/server.js.map +1 -0
  279. package/dist/server/tools/act.d.ts +10 -0
  280. package/dist/server/tools/act.d.ts.map +1 -0
  281. package/dist/server/tools/act.js +62 -0
  282. package/dist/server/tools/act.js.map +1 -0
  283. package/dist/server/tools/connect.d.ts +10 -0
  284. package/dist/server/tools/connect.d.ts.map +1 -0
  285. package/dist/server/tools/connect.js +37 -0
  286. package/dist/server/tools/connect.js.map +1 -0
  287. package/dist/server/tools/extract-schema.d.ts +9 -0
  288. package/dist/server/tools/extract-schema.d.ts.map +1 -0
  289. package/dist/server/tools/extract-schema.js +29 -0
  290. package/dist/server/tools/extract-schema.js.map +1 -0
  291. package/dist/server/tools/extract.d.ts +9 -0
  292. package/dist/server/tools/extract.d.ts.map +1 -0
  293. package/dist/server/tools/extract.js +35 -0
  294. package/dist/server/tools/extract.js.map +1 -0
  295. package/dist/server/tools/navigate.d.ts +9 -0
  296. package/dist/server/tools/navigate.d.ts.map +1 -0
  297. package/dist/server/tools/navigate.js +27 -0
  298. package/dist/server/tools/navigate.js.map +1 -0
  299. package/dist/server/tools/probe.d.ts +8 -0
  300. package/dist/server/tools/probe.d.ts.map +1 -0
  301. package/dist/server/tools/probe.js +44 -0
  302. package/dist/server/tools/probe.js.map +1 -0
  303. package/dist/server/tools/run.d.ts +10 -0
  304. package/dist/server/tools/run.d.ts.map +1 -0
  305. package/dist/server/tools/run.js +30 -0
  306. package/dist/server/tools/run.js.map +1 -0
  307. package/dist/server/tools/screenshot.d.ts +10 -0
  308. package/dist/server/tools/screenshot.d.ts.map +1 -0
  309. package/dist/server/tools/screenshot.js +26 -0
  310. package/dist/server/tools/screenshot.js.map +1 -0
  311. package/dist/server/tools/session.d.ts +9 -0
  312. package/dist/server/tools/session.d.ts.map +1 -0
  313. package/dist/server/tools/session.js +33 -0
  314. package/dist/server/tools/session.js.map +1 -0
  315. package/dist/server/tools/snapshot.d.ts +12 -0
  316. package/dist/server/tools/snapshot.d.ts.map +1 -0
  317. package/dist/server/tools/snapshot.js +59 -0
  318. package/dist/server/tools/snapshot.js.map +1 -0
  319. package/dist/server/tools/wait.d.ts +9 -0
  320. package/dist/server/tools/wait.d.ts.map +1 -0
  321. package/dist/server/tools/wait.js +32 -0
  322. package/dist/server/tools/wait.js.map +1 -0
  323. package/dist/server/tools/with-session.d.ts +10 -0
  324. package/dist/server/tools/with-session.d.ts.map +1 -0
  325. package/dist/server/tools/with-session.js +16 -0
  326. package/dist/server/tools/with-session.js.map +1 -0
  327. package/dist/session/manager.d.ts +39 -0
  328. package/dist/session/manager.d.ts.map +1 -0
  329. package/dist/session/manager.js +76 -0
  330. package/dist/session/manager.js.map +1 -0
  331. package/dist/session/session.d.ts +28 -0
  332. package/dist/session/session.d.ts.map +1 -0
  333. package/dist/session/session.js +51 -0
  334. package/dist/session/session.js.map +1 -0
  335. package/dist/state/dom-signature.d.ts +8 -0
  336. package/dist/state/dom-signature.d.ts.map +1 -0
  337. package/dist/state/dom-signature.js +13 -0
  338. package/dist/state/dom-signature.js.map +1 -0
  339. package/dist/state/realtime.d.ts +11 -0
  340. package/dist/state/realtime.d.ts.map +1 -0
  341. package/dist/state/realtime.js +34 -0
  342. package/dist/state/realtime.js.map +1 -0
  343. package/dist/state/replay.d.ts +4 -0
  344. package/dist/state/replay.d.ts.map +1 -0
  345. package/dist/state/replay.js +21 -0
  346. package/dist/state/replay.js.map +1 -0
  347. package/dist/state/site-memory.d.ts +35 -0
  348. package/dist/state/site-memory.d.ts.map +1 -0
  349. package/dist/state/site-memory.js +56 -0
  350. package/dist/state/site-memory.js.map +1 -0
  351. package/package.json +70 -0
  352. package/proxies.example.json +9 -0
  353. package/scripts/postinstall.mjs +24 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-steps.d.ts","sourceRoot":"","sources":["../../src/agent/run-steps.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AASvC,+EAA+E;AAC/E,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,mCAAmC;AACnC,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAqCD,yDAAyD;AACzD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,SAAS,UAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAWrG"}
@@ -0,0 +1,59 @@
1
+ import { performAction } from "../actions/perform.js";
2
+ import { waitForCondition } from "../actions/wait-for.js";
3
+ import { detectChallenges } from "../extraction/challenges.js";
4
+ import { extractHotelOffers } from "../extraction/hotel-offers.js";
5
+ import { mainText } from "../extraction/main-text.js";
6
+ import { extractPrices } from "../extraction/prices.js";
7
+ import { gotoWithRetry } from "../net/navigate.js";
8
+ async function runWait(page, step) {
9
+ const r = await waitForCondition(page, {
10
+ text: step.text,
11
+ selector: step.selector,
12
+ urlContains: step.urlContains,
13
+ gone: step.gone,
14
+ timeoutMs: step.timeoutMs,
15
+ });
16
+ return { index: 0, type: "wait_for", ok: r.ok, data: r, error: r.ok ? undefined : String(r.error) };
17
+ }
18
+ async function runExtract(page, step) {
19
+ const text = await mainText(page);
20
+ const data = { url: page.url() };
21
+ const kind = step.kind ?? "all";
22
+ if (kind === "text" || kind === "all")
23
+ data.text = text;
24
+ if (kind === "prices" || kind === "all") {
25
+ data.prices = extractPrices(text);
26
+ data.hotelOffers = extractHotelOffers(text);
27
+ }
28
+ if (kind === "challenges" || kind === "all")
29
+ data.challenges = await detectChallenges(page, text);
30
+ return { index: 0, type: "extract", ok: true, data };
31
+ }
32
+ async function runOne(page, step, humanMode) {
33
+ if (step.type === "navigate") {
34
+ await gotoWithRetry(page, String(step.url), { waitUntil: "domcontentloaded", timeout: 30_000 });
35
+ return { index: 0, type: "navigate", ok: true, data: { url: page.url(), title: await page.title() } };
36
+ }
37
+ if (step.type === "wait_for")
38
+ return runWait(page, step);
39
+ if (step.type === "extract")
40
+ return runExtract(page, step);
41
+ const r = await performAction(page, step, humanMode);
42
+ return { index: 0, type: step.type, ok: r.ok, data: r, error: r.ok ? undefined : String(r.error ?? "failed") };
43
+ }
44
+ /** Run steps in order, stopping at the first failure. */
45
+ export async function runSteps(page, steps, humanMode = false) {
46
+ const results = [];
47
+ for (let i = 0; i < steps.length; i += 1) {
48
+ const step = steps[i];
49
+ if (!step)
50
+ continue;
51
+ const r = await runOne(page, step, humanMode);
52
+ r.index = i;
53
+ results.push(r);
54
+ if (!r.ok)
55
+ break;
56
+ }
57
+ return results;
58
+ }
59
+ //# sourceMappingURL=run-steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-steps.js","sourceRoot":"","sources":["../../src/agent/run-steps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/bin/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * fuse-browser CLI entry point (`probe` subcommand).
4
+ * @module bin/cli
5
+ */
6
+ import { parseArgs } from "node:util";
7
+ import { BrowserAgent } from "../agent/browser-agent.js";
8
+ import { compactReport } from "../agent/compact.js";
9
+ import { GuardrailViolation } from "../lib/errors.js";
10
+ const { positionals, values } = parseArgs({
11
+ allowPositionals: true,
12
+ options: {
13
+ engine: { type: "string" },
14
+ country: { type: "string" },
15
+ currency: { type: "string" },
16
+ headed: { type: "boolean" },
17
+ "auto-consent": { type: "boolean" },
18
+ "extract-prices": { type: "boolean" },
19
+ "detect-challenges": { type: "boolean" },
20
+ "observe-visual": { type: "boolean" },
21
+ "human-mode": { type: "boolean" },
22
+ approved: { type: "boolean" },
23
+ replay: { type: "boolean" },
24
+ "wait-ms": { type: "string" },
25
+ "output-dir": { type: "string" },
26
+ "storage-state": { type: "string" },
27
+ proxy: { type: "string" },
28
+ "proxy-map": { type: "string" },
29
+ "user-data-dir": { type: "string" },
30
+ "site-memory-dir": { type: "string" },
31
+ click: { type: "string", multiple: true },
32
+ fill: { type: "string", multiple: true },
33
+ },
34
+ });
35
+ const [command, url] = positionals;
36
+ if (command !== "probe" || !url) {
37
+ process.stderr.write("usage: fuse-browser probe <url> [--click TEXT] [--fill TARGET=VALUE] [--country US] [--headed] ...\n");
38
+ process.exit(1);
39
+ }
40
+ const actions = [];
41
+ for (const item of (values.fill ?? [])) {
42
+ const eq = item.indexOf("=");
43
+ if (eq < 0) {
44
+ process.stderr.write("--fill must be TARGET=VALUE\n");
45
+ process.exit(1);
46
+ }
47
+ actions.push({ type: "fill", target: item.slice(0, eq), value: item.slice(eq + 1) });
48
+ }
49
+ for (const target of (values.click ?? []))
50
+ actions.push({ type: "click", target });
51
+ const agent = new BrowserAgent({
52
+ engine: values.engine,
53
+ countryCode: values.country,
54
+ currency: values.currency,
55
+ headless: !values.headed,
56
+ humanMode: Boolean(values["human-mode"]),
57
+ outputDir: values["output-dir"],
58
+ storageStatePath: values["storage-state"],
59
+ proxyUrl: values.proxy,
60
+ proxyMapPath: values["proxy-map"],
61
+ userDataDir: values["user-data-dir"],
62
+ replayEnabled: Boolean(values.replay),
63
+ siteMemoryDir: values["site-memory-dir"],
64
+ });
65
+ try {
66
+ const report = await agent.probe(url, {
67
+ actions,
68
+ humanApproved: Boolean(values.approved),
69
+ autoConsent: Boolean(values["auto-consent"]),
70
+ extractPrices: Boolean(values["extract-prices"]),
71
+ detectChallenges: Boolean(values["detect-challenges"]),
72
+ observeVisual: Boolean(values["observe-visual"]),
73
+ waitMs: values["wait-ms"] ? Number(values["wait-ms"]) : 0,
74
+ });
75
+ process.stdout.write(`${JSON.stringify(compactReport(report), null, 2)}\n`);
76
+ }
77
+ catch (err) {
78
+ if (err instanceof GuardrailViolation) {
79
+ process.stderr.write(`BLOCKED: ${err.message}\n`);
80
+ process.exit(2);
81
+ }
82
+ throw err;
83
+ }
84
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/bin/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/bin/mcp.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * fuse-browser MCP server entry point (stdio transport).
4
+ * @module bin/mcp
5
+ */
6
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
+ import { logger } from "../lib/logger.js";
8
+ import { createServer } from "../server/server.js";
9
+ async function main() {
10
+ const { server, sessions } = createServer();
11
+ let closing = false;
12
+ const shutdown = async () => {
13
+ if (closing)
14
+ return;
15
+ closing = true;
16
+ await sessions.closeAll();
17
+ process.exit(0);
18
+ };
19
+ process.on("SIGINT", () => void shutdown());
20
+ process.on("SIGTERM", () => void shutdown());
21
+ await server.connect(new StdioServerTransport());
22
+ logger.info("fuse-browser MCP server running on stdio");
23
+ }
24
+ main().catch((err) => {
25
+ logger.error("fatal", { err: String(err) });
26
+ process.exit(1);
27
+ });
28
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/bin/mcp.ts"],"names":[],"mappings":";AACA;;;GAGG;AACH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE,CAAC;IAC5C,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,GAAG,IAAI,CAAC;QACf,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,EAAE,CAAC,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;IACjD,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;AAC1D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Captcha-solving orchestrator: detect kind, read sitekey, solve, inject.
3
+ * Opt-in and for authorized testing only; failures are reported, never thrown.
4
+ * @module captcha/solve
5
+ */
6
+ import type { Page } from "playwright";
7
+ import type { ResolvedConfig } from "../agent/config.js";
8
+ import type { Challenges } from "../interfaces/extraction.js";
9
+ import type { CaptchaConfig, CaptchaOutcome } from "../interfaces/net.js";
10
+ import type { ProbeOptions } from "../interfaces/types.js";
11
+ type MaybeChallenges = Challenges | Record<string, never>;
12
+ /** Solve a detected captcha. No-op (attempted=false) when none is solvable. */
13
+ export declare function maybeSolveCaptcha(page: Page, challenges: MaybeChallenges, cfg: CaptchaConfig): Promise<CaptchaOutcome>;
14
+ /** Solve only when opted-in (`solveCaptcha`) and configured; else undefined. */
15
+ export declare function solveIfEnabled(page: Page, challenges: MaybeChallenges, options: ProbeOptions, config: ResolvedConfig): Promise<CaptchaOutcome> | undefined;
16
+ export {};
17
+ //# sourceMappingURL=solve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solve.d.ts","sourceRoot":"","sources":["../../src/captcha/solve.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAe,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAK3D,KAAK,eAAe,GAAG,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAS1D,+EAA+E;AAC/E,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,eAAe,EAC3B,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,cAAc,CAAC,CAmBzB;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,eAAe,EAC3B,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,CAGrC"}
@@ -0,0 +1,42 @@
1
+ import { logger } from "../lib/logger.js";
2
+ import { solveToken } from "../net/captcha-client.js";
3
+ import { injectToken, readSitekey } from "../net/captcha-inject.js";
4
+ /** Pick the solvable captcha kind present on the page, if any. */
5
+ function pickKind(challenges) {
6
+ if ("turnstile" in challenges && challenges.turnstile)
7
+ return "turnstile";
8
+ if ("captcha" in challenges && challenges.captcha)
9
+ return "recaptcha";
10
+ return null;
11
+ }
12
+ /** Solve a detected captcha. No-op (attempted=false) when none is solvable. */
13
+ export async function maybeSolveCaptcha(page, challenges, cfg) {
14
+ const kind = pickKind(challenges);
15
+ if (!kind)
16
+ return { attempted: false, solved: false };
17
+ try {
18
+ const websiteKey = await readSitekey(page);
19
+ if (!websiteKey)
20
+ return { attempted: true, solved: false, kind, reason: "sitekey-not-found" };
21
+ const token = await solveToken(cfg, { kind, websiteURL: page.url(), websiteKey });
22
+ const injected = await injectToken(page, token);
23
+ return {
24
+ attempted: true,
25
+ solved: injected,
26
+ kind,
27
+ provider: cfg.provider,
28
+ reason: injected ? undefined : "token-injection-failed",
29
+ };
30
+ }
31
+ catch (error) {
32
+ logger.warn("captcha solve failed", { err: String(error) });
33
+ return { attempted: true, solved: false, kind, provider: cfg.provider, reason: String(error) };
34
+ }
35
+ }
36
+ /** Solve only when opted-in (`solveCaptcha`) and configured; else undefined. */
37
+ export function solveIfEnabled(page, challenges, options, config) {
38
+ if (!options.solveCaptcha || !config.captcha)
39
+ return undefined;
40
+ return maybeSolveCaptcha(page, challenges, config.captcha);
41
+ }
42
+ //# sourceMappingURL=solve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solve.js","sourceRoot":"","sources":["../../src/captcha/solve.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAIpE,kEAAkE;AAClE,SAAS,QAAQ,CAAC,UAA2B;IAC3C,IAAI,WAAW,IAAI,UAAU,IAAI,UAAU,CAAC,SAAS;QAAE,OAAO,WAAW,CAAC;IAC1E,IAAI,SAAS,IAAI,UAAU,IAAI,UAAU,CAAC,OAAO;QAAE,OAAO,WAAW,CAAC;IACtE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAAU,EACV,UAA2B,EAC3B,GAAkB;IAElB,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACtD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;QAC9F,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChD,OAAO;YACL,SAAS,EAAE,IAAI;YACf,MAAM,EAAE,QAAQ;YAChB,IAAI;YACJ,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,wBAAwB;SACxD,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5D,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACjG,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,cAAc,CAC5B,IAAU,EACV,UAA2B,EAC3B,OAAqB,EACrB,MAAsB;IAEtB,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/D,OAAO,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Force the currency on booking.com (cookies + header picker).
3
+ * @module consent/booking-currency
4
+ */
5
+ import type { Page } from "playwright";
6
+ /** Supported currency display labels (single source of truth). */
7
+ export declare const CURRENCY_LABELS: Record<string, string[]>;
8
+ /** Currency codes derived from {@link CURRENCY_LABELS}. */
9
+ export declare const SUPPORTED_CURRENCIES: string[];
10
+ /** Pre-position the currency via cookies + booking setup page. */
11
+ export declare function prepareBookingCurrency(page: Page, currency: string): Promise<void>;
12
+ /** Open the booking currency picker and choose the requested currency. */
13
+ export declare function selectBookingCurrency(page: Page, currency: string): Promise<boolean>;
14
+ //# sourceMappingURL=booking-currency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"booking-currency.d.ts","sourceRoot":"","sources":["../../src/consent/booking-currency.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAUvC,kEAAkE;AAClE,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAKpD,CAAC;AAEF,2DAA2D;AAC3D,eAAO,MAAM,oBAAoB,UAA+B,CAAC;AAyBjE,kEAAkE;AAClE,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYxF;AAED,0EAA0E;AAC1E,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAyB1F"}
@@ -0,0 +1,82 @@
1
+ import { evalScript, evalScriptArg } from "../lib/evaluate.js";
2
+ import { waitForRealtimeSettle } from "../state/realtime.js";
3
+ /** booking.com origin and cookie domain. */
4
+ const BOOKING_ORIGIN = "https://www.booking.com";
5
+ const BOOKING_COOKIE_DOMAIN = ".booking.com";
6
+ /** Header currency picker trigger selector. */
7
+ const CURRENCY_TRIGGER_SELECTOR = '[data-testid="header-currency-picker-trigger"]';
8
+ /** Supported currency display labels (single source of truth). */
9
+ export const CURRENCY_LABELS = {
10
+ CHF: ["CHF", "Swiss Franc"],
11
+ USD: ["USD", "U.S. Dollar", "US Dollar"],
12
+ GBP: ["GBP", "Pound Sterling", "British Pound"],
13
+ EUR: ["EUR", "Euro"],
14
+ };
15
+ /** Currency codes derived from {@link CURRENCY_LABELS}. */
16
+ export const SUPPORTED_CURRENCIES = Object.keys(CURRENCY_LABELS);
17
+ const bookingSetupUrl = (currency) => `${BOOKING_ORIGIN}/?change_currency=1;selected_currency=${currency};top_currency=1`;
18
+ const bookingCookie = (name, value) => ({
19
+ name,
20
+ value,
21
+ domain: BOOKING_COOKIE_DOMAIN,
22
+ path: "/",
23
+ });
24
+ const CLICK_TRIGGER = `() => document.querySelector('${CURRENCY_TRIGGER_SELECTOR}')?.click()`;
25
+ const PICK_LABEL = `(labels) => {
26
+ const buttons = [...document.querySelectorAll('button,[role=button]')];
27
+ const el = buttons.find(button => {
28
+ const text = (button.innerText || '').replace(/\\s+/g, ' ').trim();
29
+ return labels.some(label => text.includes(label));
30
+ });
31
+ if (!el) return false;
32
+ el.click();
33
+ return true;
34
+ }`;
35
+ /** Pre-position the currency via cookies + booking setup page. */
36
+ export async function prepareBookingCurrency(page, currency) {
37
+ try {
38
+ await page.context().addCookies([
39
+ bookingCookie("cur_curr", currency),
40
+ bookingCookie("selected_currency", currency),
41
+ bookingCookie("changed_currency", "1"),
42
+ ]);
43
+ await page.goto(bookingSetupUrl(currency), { waitUntil: "domcontentloaded", timeout: 20_000 });
44
+ await page.waitForTimeout(800);
45
+ }
46
+ catch {
47
+ /* best-effort */
48
+ }
49
+ }
50
+ /** Open the booking currency picker and choose the requested currency. */
51
+ export async function selectBookingCurrency(page, currency) {
52
+ const labels = CURRENCY_LABELS[currency] ?? [currency];
53
+ const rx = new RegExp(`^(${SUPPORTED_CURRENCIES.join("|")})$`, "i");
54
+ try {
55
+ let opener = page.locator(CURRENCY_TRIGGER_SELECTOR).first();
56
+ if ((await opener.count()) === 0)
57
+ opener = page.locator("button").filter({ hasText: rx }).first();
58
+ if ((await opener.count()) === 0)
59
+ opener = page.getByText(rx).first();
60
+ if ((await opener.count()) === 0)
61
+ return false;
62
+ await evalScript(page, CLICK_TRIGGER);
63
+ await page.waitForTimeout(1_000);
64
+ const clicked = await evalScriptArg(page, PICK_LABEL, labels);
65
+ if (clicked) {
66
+ await page.waitForTimeout(500);
67
+ try {
68
+ await page.reload({ waitUntil: "domcontentloaded", timeout: 20_000 });
69
+ }
70
+ catch {
71
+ /* ignore */
72
+ }
73
+ await waitForRealtimeSettle(page);
74
+ return true;
75
+ }
76
+ }
77
+ catch {
78
+ return false;
79
+ }
80
+ return false;
81
+ }
82
+ //# sourceMappingURL=booking-currency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"booking-currency.js","sourceRoot":"","sources":["../../src/consent/booking-currency.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,4CAA4C;AAC5C,MAAM,cAAc,GAAG,yBAAyB,CAAC;AACjD,MAAM,qBAAqB,GAAG,cAAc,CAAC;AAC7C,+CAA+C;AAC/C,MAAM,yBAAyB,GAAG,gDAAgD,CAAC;AAEnF,kEAAkE;AAClE,MAAM,CAAC,MAAM,eAAe,GAA6B;IACvD,GAAG,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC;IAC3B,GAAG,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,CAAC;IACxC,GAAG,EAAE,CAAC,KAAK,EAAE,gBAAgB,EAAE,eAAe,CAAC;IAC/C,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,2DAA2D;AAC3D,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAEjE,MAAM,eAAe,GAAG,CAAC,QAAgB,EAAU,EAAE,CACnD,GAAG,cAAc,yCAAyC,QAAQ,iBAAiB,CAAC;AAEtF,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE,CAAC,CAAC;IACtD,IAAI;IACJ,KAAK;IACL,MAAM,EAAE,qBAAqB;IAC7B,IAAI,EAAE,GAAG;CACV,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,iCAAiC,yBAAyB,aAAa,CAAC;AAE9F,MAAM,UAAU,GAAG;;;;;;;;;EASjB,CAAC;AAEH,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,IAAU,EAAE,QAAgB;IACvE,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC;YAC9B,aAAa,CAAC,UAAU,EAAE,QAAQ,CAAC;YACnC,aAAa,CAAC,mBAAmB,EAAE,QAAQ,CAAC;YAC5C,aAAa,CAAC,kBAAkB,EAAE,GAAG,CAAC;SACvC,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAC/F,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAU,EAAE,QAAgB;IACtE,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvD,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,KAAK,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACpE,IAAI,CAAC;QACH,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,KAAK,EAAE,CAAC;QAC7D,IAAI,CAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC;YAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QAClG,IAAI,CAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC;YAAE,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QACtE,IAAI,CAAC,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/C,MAAM,UAAU,CAAO,IAAI,EAAE,aAAa,CAAC,CAAC;QAC5C,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,aAAa,CAAoB,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QACjF,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YACxE,CAAC;YAAC,MAAM,CAAC;gBACP,YAAY;YACd,CAAC;YACD,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Best-effort handling of common consent banners.
3
+ * @module consent/consent
4
+ */
5
+ import type { Page } from "playwright";
6
+ import type { ConsentResult } from "../interfaces/report.js";
7
+ /** Frequent consent button labels (reject first). */
8
+ export declare const COMMON_CONSENT_TARGETS: readonly ["Reject all", "Refuser tout", "Tout refuser", "Decline all", "Accept all", "Accepter tout", "Tout accepter", "J'accepte", "I agree", "Agree"];
9
+ /** Try to click a known consent button; return the result. */
10
+ export declare function handleCommonConsent(page: Page, humanMode?: boolean): Promise<ConsentResult>;
11
+ //# sourceMappingURL=consent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent.d.ts","sourceRoot":"","sources":["../../src/consent/consent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAG7D,qDAAqD;AACrD,eAAO,MAAM,sBAAsB,yJAWzB,CAAC;AAEX,8DAA8D;AAC9D,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,UAAQ,GAAG,OAAO,CAAC,aAAa,CAAC,CAS/F"}
@@ -0,0 +1,27 @@
1
+ import { smartClick } from "../actions/smart-click.js";
2
+ import { waitForRealtimeSettle } from "../state/realtime.js";
3
+ /** Frequent consent button labels (reject first). */
4
+ export const COMMON_CONSENT_TARGETS = [
5
+ "Reject all",
6
+ "Refuser tout",
7
+ "Tout refuser",
8
+ "Decline all",
9
+ "Accept all",
10
+ "Accepter tout",
11
+ "Tout accepter",
12
+ "J'accepte",
13
+ "I agree",
14
+ "Agree",
15
+ ];
16
+ /** Try to click a known consent button; return the result. */
17
+ export async function handleCommonConsent(page, humanMode = false) {
18
+ for (const target of COMMON_CONSENT_TARGETS) {
19
+ const result = await smartClick(page, target, "", humanMode);
20
+ if (result.ok) {
21
+ await waitForRealtimeSettle(page);
22
+ return { handled: true, target, strategy: result.strategy };
23
+ }
24
+ }
25
+ return { handled: false };
26
+ }
27
+ //# sourceMappingURL=consent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent.js","sourceRoot":"","sources":["../../src/consent/consent.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,qDAAqD;AACrD,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,YAAY;IACZ,cAAc;IACd,cAAc;IACd,aAAa;IACb,YAAY;IACZ,eAAe;IACf,eAAe;IACf,WAAW;IACX,SAAS;IACT,OAAO;CACC,CAAC;AAEX,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,IAAU,EAAE,SAAS,GAAG,KAAK;IACrE,KAAK,MAAM,MAAM,IAAI,sBAAsB,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,CAAC,CAAC;QAC7D,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;YACd,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;YAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC9D,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Inject the preferred currency into Booking URLs (pure, testable).
3
+ * @module consent/currency-url
4
+ */
5
+ /**
6
+ * Add `selected_currency` to booking.com URLs when absent.
7
+ * No-op for other domains or when no currency is given.
8
+ */
9
+ export declare function urlWithCurrency(url: string, currency: string | null | undefined): string;
10
+ //# sourceMappingURL=currency-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency-url.d.ts","sourceRoot":"","sources":["../../src/consent/currency-url.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAOxF"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Inject the preferred currency into Booking URLs (pure, testable).
3
+ * @module consent/currency-url
4
+ */
5
+ /**
6
+ * Add `selected_currency` to booking.com URLs when absent.
7
+ * No-op for other domains or when no currency is given.
8
+ */
9
+ export function urlWithCurrency(url, currency) {
10
+ if (!url.includes("booking.com") || !currency)
11
+ return url;
12
+ const parsed = new URL(url);
13
+ if (!parsed.searchParams.has("selected_currency")) {
14
+ parsed.searchParams.set("selected_currency", currency);
15
+ }
16
+ return parsed.toString();
17
+ }
18
+ //# sourceMappingURL=currency-url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency-url.js","sourceRoot":"","sources":["../../src/consent/currency-url.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,QAAmC;IAC9E,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ;QAAE,OAAO,GAAG,CAAC;IAC1D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAClD,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Detect and align the visible currency.
3
+ * @module consent/currency
4
+ */
5
+ import type { Page } from "playwright";
6
+ import type { CurrencyResult } from "../interfaces/report.js";
7
+ /** Detect the currency shown in the page body (codes then symbols). */
8
+ export declare function detectVisibleCurrency(page: Page): Promise<string | null>;
9
+ /**
10
+ * Align the visible currency with the preferred one (booking case handled),
11
+ * and report any persistent mismatch.
12
+ */
13
+ export declare function applyCurrencyPreference(page: Page, currency: string, countryCode: string): Promise<CurrencyResult>;
14
+ //# sourceMappingURL=currency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency.d.ts","sourceRoot":"","sources":["../../src/consent/currency.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAW9D,uEAAuE;AACvE,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAc9E;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,cAAc,CAAC,CAezB"}
@@ -0,0 +1,48 @@
1
+ import { selectBookingCurrency, SUPPORTED_CURRENCIES } from "./booking-currency.js";
2
+ const SYMBOL_CURRENCIES = [
3
+ ["$", "USD"],
4
+ ["€", "EUR"],
5
+ ["£", "GBP"],
6
+ ];
7
+ const MISMATCH_REASON = "site_kept_currency_despite_locale_geolocation_and_currency_request";
8
+ /** Detect the currency shown in the page body (codes then symbols). */
9
+ export async function detectVisibleCurrency(page) {
10
+ let text;
11
+ try {
12
+ text = await page.locator("body").innerText({ timeout: 2_000 });
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ for (const currency of SUPPORTED_CURRENCIES) {
18
+ if (new RegExp(`(^|\\n|\\s)${currency}($|\\n|\\s)`).test(text))
19
+ return currency;
20
+ }
21
+ for (const [symbol, currency] of SYMBOL_CURRENCIES) {
22
+ if (text.includes(symbol))
23
+ return currency;
24
+ }
25
+ return null;
26
+ }
27
+ /**
28
+ * Align the visible currency with the preferred one (booking case handled),
29
+ * and report any persistent mismatch.
30
+ */
31
+ export async function applyCurrencyPreference(page, currency, countryCode) {
32
+ const detected = await detectVisibleCurrency(page);
33
+ const result = { countryCode, preferred: currency, detected, handled: false };
34
+ if (!currency || detected === currency) {
35
+ result.mismatch = false;
36
+ return result;
37
+ }
38
+ if (page.url().includes("booking.com")) {
39
+ result.handled = await selectBookingCurrency(page, currency);
40
+ result.detectedAfter = await detectVisibleCurrency(page);
41
+ }
42
+ const final = result.detectedAfter ?? result.detected;
43
+ result.mismatch = Boolean(final && final !== currency);
44
+ if (result.mismatch)
45
+ result.reason = MISMATCH_REASON;
46
+ return result;
47
+ }
48
+ //# sourceMappingURL=currency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency.js","sourceRoot":"","sources":["../../src/consent/currency.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEpF,MAAM,iBAAiB,GAA4B;IACjD,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,GAAG,EAAE,KAAK,CAAC;IACZ,CAAC,GAAG,EAAE,KAAK,CAAC;CACb,CAAC;AAEF,MAAM,eAAe,GAAG,oEAAoE,CAAC;AAE7F,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAU;IACpD,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,oBAAoB,EAAE,CAAC;QAC5C,IAAI,IAAI,MAAM,CAAC,cAAc,QAAQ,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,QAAQ,CAAC;IAClF,CAAC;IACD,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,iBAAiB,EAAE,CAAC;QACnD,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,QAAQ,CAAC;IAC7C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,IAAU,EACV,QAAgB,EAChB,WAAmB;IAEnB,MAAM,QAAQ,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACnD,MAAM,MAAM,GAAmB,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC9F,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC;QACxB,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACvC,MAAM,CAAC,OAAO,GAAG,MAAM,qBAAqB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC7D,MAAM,CAAC,aAAa,GAAG,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,QAAQ,CAAC;IACtD,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,KAAK,QAAQ,CAAC,CAAC;IACvD,IAAI,MAAM,CAAC,QAAQ;QAAE,MAAM,CAAC,MAAM,GAAG,eAAe,CAAC;IACrD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * CDP attach engine: connect to a user's already-running Chromium browser
3
+ * (Chrome, Edge, Dia, Arc, Brave…) started with --remote-debugging-port.
4
+ * Reuses the existing default context and a reliable tab; never closes the
5
+ * user's browser. CDP is Chromium-only (Firefox/WebKit not supported).
6
+ * @module engine/cdp-engine
7
+ */
8
+ import type { BrowserContext, Page } from "playwright";
9
+ import type { BrowserEngine, OpenedContext } from "../interfaces/engine.js";
10
+ /**
11
+ * Pick a usable page from a freshly-attached context. A just-launched browser
12
+ * may expose a transient about:blank tab that closes during init, or no page at
13
+ * all — so we skip closed pages, briefly wait for one to appear, then fall back
14
+ * to creating a fresh tab.
15
+ */
16
+ export declare function pickReliablePage(context: BrowserContext): Promise<Page>;
17
+ /** Attach to a running browser over the Chrome DevTools Protocol. */
18
+ export declare function attachOverCdp(endpoint: string): Promise<OpenedContext>;
19
+ /** Engine that attaches to an existing browser via `config.cdpEndpoint`. */
20
+ export declare const cdpEngine: BrowserEngine;
21
+ //# sourceMappingURL=cdp-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdp-engine.d.ts","sourceRoot":"","sources":["../../src/engine/cdp-engine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvD,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAG5E;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7E;AAED,qEAAqE;AACrE,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAM5E;AAED,4EAA4E;AAC5E,eAAO,MAAM,SAAS,EAAE,aAQvB,CAAC"}
@@ -0,0 +1,36 @@
1
+ import { loadBrowserType } from "./loader.js";
2
+ /**
3
+ * Pick a usable page from a freshly-attached context. A just-launched browser
4
+ * may expose a transient about:blank tab that closes during init, or no page at
5
+ * all — so we skip closed pages, briefly wait for one to appear, then fall back
6
+ * to creating a fresh tab.
7
+ */
8
+ export async function pickReliablePage(context) {
9
+ const open = () => context.pages().find((p) => !p.isClosed());
10
+ let page = open();
11
+ if (!page) {
12
+ page = await context.waitForEvent("page", { timeout: 3_000 }).catch(() => undefined);
13
+ }
14
+ if (!page || page.isClosed())
15
+ page = await context.newPage();
16
+ return page;
17
+ }
18
+ /** Attach to a running browser over the Chrome DevTools Protocol. */
19
+ export async function attachOverCdp(endpoint) {
20
+ const chromium = await loadBrowserType("playwright");
21
+ const browser = await chromium.connectOverCDP(endpoint, { timeout: 20_000 });
22
+ const context = browser.contexts()[0] ?? (await browser.newContext());
23
+ const page = await pickReliablePage(context);
24
+ return { context, browser, connected: true, page };
25
+ }
26
+ /** Engine that attaches to an existing browser via `config.cdpEndpoint`. */
27
+ export const cdpEngine = {
28
+ name: "cdp",
29
+ async open(config) {
30
+ if (!config.cdpEndpoint) {
31
+ throw new Error("cdpEndpoint is required for the CDP attach engine");
32
+ }
33
+ return attachOverCdp(config.cdpEndpoint);
34
+ },
35
+ };
36
+ //# sourceMappingURL=cdp-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdp-engine.js","sourceRoot":"","sources":["../../src/engine/cdp-engine.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAuB;IAC5D,MAAM,IAAI,GAAG,GAAqB,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IAChF,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC;IAClB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IACvF,CAAC;IACD,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE;QAAE,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IAC7D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,YAAY,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACtE,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC7C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACrD,CAAC;AAED,4EAA4E;AAC5E,MAAM,CAAC,MAAM,SAAS,GAAkB;IACtC,IAAI,EAAE,KAAK;IACX,KAAK,CAAC,IAAI,CAAC,MAAsB;QAC/B,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;CACF,CAAC"}