@browserbasehq/orca 3.2.0-preview.3 → 3.2.0-preview.5

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 (313) hide show
  1. package/dist/cjs/lib/inference.d.ts +3 -1
  2. package/dist/cjs/lib/inference.js +2 -2
  3. package/dist/cjs/lib/inference.js.map +1 -1
  4. package/dist/cjs/lib/prompt.d.ts +1 -1
  5. package/dist/cjs/lib/prompt.js +11 -2
  6. package/dist/cjs/lib/prompt.js.map +1 -1
  7. package/dist/cjs/lib/utils.d.ts +1 -0
  8. package/dist/cjs/lib/utils.js +4 -0
  9. package/dist/cjs/lib/utils.js.map +1 -1
  10. package/dist/cjs/lib/v3/agent/AgentClient.d.ts +8 -0
  11. package/dist/cjs/lib/v3/agent/AgentClient.js +13 -0
  12. package/dist/cjs/lib/v3/agent/AgentClient.js.map +1 -1
  13. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js +6 -7
  14. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
  15. package/dist/cjs/lib/v3/agent/GoogleCUAClient.js +6 -7
  16. package/dist/cjs/lib/v3/agent/GoogleCUAClient.js.map +1 -1
  17. package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.js +1 -0
  18. package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.js.map +1 -1
  19. package/dist/cjs/lib/v3/agent/OpenAICUAClient.d.ts +4 -4
  20. package/dist/cjs/lib/v3/agent/OpenAICUAClient.js +67 -8
  21. package/dist/cjs/lib/v3/agent/OpenAICUAClient.js.map +1 -1
  22. package/dist/cjs/lib/v3/agent/prompts/agentSystemPrompt.d.ts +2 -2
  23. package/dist/cjs/lib/v3/agent/prompts/agentSystemPrompt.js +10 -11
  24. package/dist/cjs/lib/v3/agent/prompts/agentSystemPrompt.js.map +1 -1
  25. package/dist/cjs/lib/v3/agent/tools/act.js +1 -10
  26. package/dist/cjs/lib/v3/agent/tools/act.js.map +1 -1
  27. package/dist/cjs/lib/v3/agent/tools/ariaTree.js +1 -12
  28. package/dist/cjs/lib/v3/agent/tools/ariaTree.js.map +1 -1
  29. package/dist/cjs/lib/v3/agent/tools/braveSearch.js.map +1 -1
  30. package/dist/cjs/lib/v3/agent/tools/browserbaseSearch.js.map +1 -1
  31. package/dist/cjs/lib/v3/agent/tools/click.js.map +1 -1
  32. package/dist/cjs/lib/v3/agent/tools/clickAndHold.js.map +1 -1
  33. package/dist/cjs/lib/v3/agent/tools/dragAndDrop.js.map +1 -1
  34. package/dist/cjs/lib/v3/agent/tools/extract.js +1 -10
  35. package/dist/cjs/lib/v3/agent/tools/extract.js.map +1 -1
  36. package/dist/cjs/lib/v3/agent/tools/fillFormVision.js.map +1 -1
  37. package/dist/cjs/lib/v3/agent/tools/fillform.d.ts +0 -1
  38. package/dist/cjs/lib/v3/agent/tools/fillform.js +8 -20
  39. package/dist/cjs/lib/v3/agent/tools/fillform.js.map +1 -1
  40. package/dist/cjs/lib/v3/agent/tools/index.d.ts +2 -2
  41. package/dist/cjs/lib/v3/agent/tools/index.js +53 -5
  42. package/dist/cjs/lib/v3/agent/tools/index.js.map +1 -1
  43. package/dist/cjs/lib/v3/agent/tools/keys.d.ts +1 -1
  44. package/dist/cjs/lib/v3/agent/tools/keys.js.map +1 -1
  45. package/dist/cjs/lib/v3/agent/tools/type.js.map +1 -1
  46. package/dist/cjs/lib/v3/agent/utils/captchaSolver.d.ts +76 -0
  47. package/dist/cjs/lib/v3/agent/utils/captchaSolver.js +175 -0
  48. package/dist/cjs/lib/v3/agent/utils/captchaSolver.js.map +1 -0
  49. package/dist/cjs/lib/v3/agent/utils/variables.d.ts +5 -0
  50. package/dist/cjs/lib/v3/agent/utils/variables.js +9 -0
  51. package/dist/cjs/lib/v3/agent/utils/variables.js.map +1 -1
  52. package/dist/cjs/lib/v3/flowlogger/EventEmitter.d.ts +7 -0
  53. package/dist/cjs/lib/v3/flowlogger/EventEmitter.js +30 -0
  54. package/dist/cjs/lib/v3/flowlogger/EventEmitter.js.map +1 -0
  55. package/dist/cjs/lib/v3/flowlogger/EventSink.d.ts +44 -0
  56. package/dist/cjs/lib/v3/flowlogger/EventSink.js +217 -0
  57. package/dist/cjs/lib/v3/flowlogger/EventSink.js.map +1 -0
  58. package/dist/cjs/lib/v3/flowlogger/EventStore.d.ts +26 -0
  59. package/dist/cjs/lib/v3/flowlogger/EventStore.js +135 -0
  60. package/dist/cjs/lib/v3/flowlogger/EventStore.js.map +1 -0
  61. package/dist/cjs/lib/v3/flowlogger/FlowLogger.d.ts +99 -0
  62. package/dist/cjs/lib/v3/flowlogger/FlowLogger.js +591 -0
  63. package/dist/cjs/lib/v3/flowlogger/FlowLogger.js.map +1 -0
  64. package/dist/cjs/lib/v3/flowlogger/prettify.d.ts +6 -0
  65. package/dist/cjs/lib/v3/flowlogger/prettify.js +395 -0
  66. package/dist/cjs/lib/v3/flowlogger/prettify.js.map +1 -0
  67. package/dist/cjs/lib/v3/handlers/handlerUtils/actHandlerUtils.js +43 -57
  68. package/dist/cjs/lib/v3/handlers/handlerUtils/actHandlerUtils.js.map +1 -1
  69. package/dist/cjs/lib/v3/handlers/observeHandler.js +2 -1
  70. package/dist/cjs/lib/v3/handlers/observeHandler.js.map +1 -1
  71. package/dist/cjs/lib/v3/handlers/v3AgentHandler.d.ts +2 -5
  72. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +112 -78
  73. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  74. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.d.ts +5 -0
  75. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js +134 -14
  76. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  77. package/dist/cjs/lib/v3/llm/aisdk.js +11 -17
  78. package/dist/cjs/lib/v3/llm/aisdk.js.map +1 -1
  79. package/dist/cjs/lib/v3/types/private/cache.d.ts +0 -1
  80. package/dist/cjs/lib/v3/types/private/cache.js.map +1 -1
  81. package/dist/cjs/lib/v3/types/private/handlers.d.ts +1 -0
  82. package/dist/cjs/lib/v3/types/private/handlers.js.map +1 -1
  83. package/dist/cjs/lib/v3/types/public/api.d.ts +24 -7
  84. package/dist/cjs/lib/v3/types/public/api.js +41 -14
  85. package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
  86. package/dist/cjs/lib/v3/types/public/methods.d.ts +1 -0
  87. package/dist/cjs/lib/v3/types/public/methods.js.map +1 -1
  88. package/dist/cjs/lib/v3/types/public/options.d.ts +7 -0
  89. package/dist/cjs/lib/v3/types/public/options.js.map +1 -1
  90. package/dist/cjs/lib/v3/types/public/variables.d.ts +7 -0
  91. package/dist/cjs/lib/v3/types/public/variables.js +22 -0
  92. package/dist/cjs/lib/v3/types/public/variables.js.map +1 -0
  93. package/dist/cjs/lib/v3/understudy/cdp.d.ts +3 -12
  94. package/dist/cjs/lib/v3/understudy/cdp.js +134 -21
  95. package/dist/cjs/lib/v3/understudy/cdp.js.map +1 -1
  96. package/dist/cjs/lib/v3/understudy/page.js +28 -18
  97. package/dist/cjs/lib/v3/understudy/page.js.map +1 -1
  98. package/dist/cjs/lib/v3/v3.d.ts +12 -2
  99. package/dist/cjs/lib/v3/v3.js +194 -160
  100. package/dist/cjs/lib/v3/v3.js.map +1 -1
  101. package/dist/cjs/lib/version.d.ts +1 -1
  102. package/dist/cjs/lib/version.js +1 -1
  103. package/dist/cjs/lib/version.js.map +1 -1
  104. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.d.ts +1 -0
  105. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js +56 -0
  106. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js.map +1 -0
  107. package/dist/cjs/tests/integration/agent-hybrid-mode.spec.js +6 -6
  108. package/dist/cjs/tests/integration/agent-hybrid-mode.spec.js.map +1 -1
  109. package/dist/cjs/tests/integration/flowLogger.spec.d.ts +1 -0
  110. package/dist/cjs/tests/integration/flowLogger.spec.js +714 -0
  111. package/dist/cjs/tests/integration/flowLogger.spec.js.map +1 -0
  112. package/dist/cjs/tests/integration/testUtils.d.ts +33 -0
  113. package/dist/cjs/tests/integration/testUtils.js +144 -0
  114. package/dist/cjs/tests/integration/testUtils.js.map +1 -1
  115. package/dist/cjs/tests/integration/timeouts.spec.js +113 -3
  116. package/dist/cjs/tests/integration/timeouts.spec.js.map +1 -1
  117. package/dist/cjs/tests/unit/agent-captcha-hooks.test.d.ts +1 -0
  118. package/dist/cjs/tests/unit/agent-captcha-hooks.test.js +285 -0
  119. package/dist/cjs/tests/unit/agent-captcha-hooks.test.js.map +1 -0
  120. package/dist/cjs/tests/unit/agent-execution-model.test.js +25 -3
  121. package/dist/cjs/tests/unit/agent-execution-model.test.js.map +1 -1
  122. package/dist/cjs/tests/unit/agent-system-prompt-variables.test.d.ts +1 -0
  123. package/dist/cjs/tests/unit/agent-system-prompt-variables.test.js +23 -0
  124. package/dist/cjs/tests/unit/agent-system-prompt-variables.test.js.map +1 -0
  125. package/dist/cjs/tests/unit/api-client-observe-variables.test.d.ts +1 -0
  126. package/dist/cjs/tests/unit/api-client-observe-variables.test.js +86 -0
  127. package/dist/cjs/tests/unit/api-client-observe-variables.test.js.map +1 -0
  128. package/dist/cjs/tests/unit/api-variables-schema.test.d.ts +1 -0
  129. package/dist/cjs/tests/unit/api-variables-schema.test.js +37 -0
  130. package/dist/cjs/tests/unit/api-variables-schema.test.js.map +1 -0
  131. package/dist/cjs/tests/unit/browserbase-session-accessors.test.js +20 -0
  132. package/dist/cjs/tests/unit/browserbase-session-accessors.test.js.map +1 -1
  133. package/dist/cjs/tests/unit/captcha-solver.test.d.ts +1 -0
  134. package/dist/cjs/tests/unit/captcha-solver.test.js +154 -0
  135. package/dist/cjs/tests/unit/captcha-solver.test.js.map +1 -0
  136. package/dist/cjs/tests/unit/flowlogger-capturing-cdp.test.d.ts +1 -0
  137. package/dist/cjs/tests/unit/flowlogger-capturing-cdp.test.js +95 -0
  138. package/dist/cjs/tests/unit/flowlogger-capturing-cdp.test.js.map +1 -0
  139. package/dist/cjs/tests/unit/flowlogger-capturing-llm.test.d.ts +1 -0
  140. package/dist/cjs/tests/unit/flowlogger-capturing-llm.test.js +43 -0
  141. package/dist/cjs/tests/unit/flowlogger-capturing-llm.test.js.map +1 -0
  142. package/dist/cjs/tests/unit/flowlogger-eventstore.test.d.ts +1 -0
  143. package/dist/cjs/tests/unit/flowlogger-eventstore.test.js +250 -0
  144. package/dist/cjs/tests/unit/flowlogger-eventstore.test.js.map +1 -0
  145. package/dist/cjs/tests/unit/openai-cua-client.test.d.ts +1 -0
  146. package/dist/cjs/tests/unit/openai-cua-client.test.js +71 -0
  147. package/dist/cjs/tests/unit/openai-cua-client.test.js.map +1 -0
  148. package/dist/cjs/tests/unit/prompt-observe-variables.test.d.ts +1 -0
  149. package/dist/cjs/tests/unit/prompt-observe-variables.test.js +19 -0
  150. package/dist/cjs/tests/unit/prompt-observe-variables.test.js.map +1 -0
  151. package/dist/cjs/tests/unit/public-api/public-types.test.js.map +1 -1
  152. package/dist/cjs/tests/unit/timeout-handlers.test.js +50 -0
  153. package/dist/cjs/tests/unit/timeout-handlers.test.js.map +1 -1
  154. package/dist/esm/lib/inference.d.ts +3 -1
  155. package/dist/esm/lib/inference.js +2 -2
  156. package/dist/esm/lib/inference.js.map +1 -1
  157. package/dist/esm/lib/prompt.d.ts +1 -1
  158. package/dist/esm/lib/prompt.js +11 -2
  159. package/dist/esm/lib/prompt.js.map +1 -1
  160. package/dist/esm/lib/utils.d.ts +1 -0
  161. package/dist/esm/lib/utils.js +3 -0
  162. package/dist/esm/lib/utils.js.map +1 -1
  163. package/dist/esm/lib/v3/agent/AgentClient.d.ts +8 -0
  164. package/dist/esm/lib/v3/agent/AgentClient.js +13 -0
  165. package/dist/esm/lib/v3/agent/AgentClient.js.map +1 -1
  166. package/dist/esm/lib/v3/agent/AnthropicCUAClient.js +6 -7
  167. package/dist/esm/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
  168. package/dist/esm/lib/v3/agent/GoogleCUAClient.js +6 -7
  169. package/dist/esm/lib/v3/agent/GoogleCUAClient.js.map +1 -1
  170. package/dist/esm/lib/v3/agent/MicrosoftCUAClient.js +1 -0
  171. package/dist/esm/lib/v3/agent/MicrosoftCUAClient.js.map +1 -1
  172. package/dist/esm/lib/v3/agent/OpenAICUAClient.d.ts +4 -4
  173. package/dist/esm/lib/v3/agent/OpenAICUAClient.js +67 -8
  174. package/dist/esm/lib/v3/agent/OpenAICUAClient.js.map +1 -1
  175. package/dist/esm/lib/v3/agent/prompts/agentSystemPrompt.d.ts +2 -2
  176. package/dist/esm/lib/v3/agent/prompts/agentSystemPrompt.js +10 -11
  177. package/dist/esm/lib/v3/agent/prompts/agentSystemPrompt.js.map +1 -1
  178. package/dist/esm/lib/v3/agent/tools/act.js +1 -10
  179. package/dist/esm/lib/v3/agent/tools/act.js.map +1 -1
  180. package/dist/esm/lib/v3/agent/tools/ariaTree.js +1 -12
  181. package/dist/esm/lib/v3/agent/tools/ariaTree.js.map +1 -1
  182. package/dist/esm/lib/v3/agent/tools/braveSearch.js.map +1 -1
  183. package/dist/esm/lib/v3/agent/tools/browserbaseSearch.js.map +1 -1
  184. package/dist/esm/lib/v3/agent/tools/click.js.map +1 -1
  185. package/dist/esm/lib/v3/agent/tools/clickAndHold.js.map +1 -1
  186. package/dist/esm/lib/v3/agent/tools/dragAndDrop.js.map +1 -1
  187. package/dist/esm/lib/v3/agent/tools/extract.js +1 -10
  188. package/dist/esm/lib/v3/agent/tools/extract.js.map +1 -1
  189. package/dist/esm/lib/v3/agent/tools/fillFormVision.js.map +1 -1
  190. package/dist/esm/lib/v3/agent/tools/fillform.d.ts +0 -1
  191. package/dist/esm/lib/v3/agent/tools/fillform.js +8 -20
  192. package/dist/esm/lib/v3/agent/tools/fillform.js.map +1 -1
  193. package/dist/esm/lib/v3/agent/tools/index.d.ts +2 -2
  194. package/dist/esm/lib/v3/agent/tools/index.js +53 -5
  195. package/dist/esm/lib/v3/agent/tools/index.js.map +1 -1
  196. package/dist/esm/lib/v3/agent/tools/keys.d.ts +1 -1
  197. package/dist/esm/lib/v3/agent/tools/keys.js.map +1 -1
  198. package/dist/esm/lib/v3/agent/tools/type.js.map +1 -1
  199. package/dist/esm/lib/v3/agent/utils/captchaSolver.d.ts +76 -0
  200. package/dist/esm/lib/v3/agent/utils/captchaSolver.js +171 -0
  201. package/dist/esm/lib/v3/agent/utils/captchaSolver.js.map +1 -0
  202. package/dist/esm/lib/v3/agent/utils/variables.d.ts +5 -0
  203. package/dist/esm/lib/v3/agent/utils/variables.js +8 -0
  204. package/dist/esm/lib/v3/agent/utils/variables.js.map +1 -1
  205. package/dist/esm/lib/v3/flowlogger/EventEmitter.d.ts +7 -0
  206. package/dist/esm/lib/v3/flowlogger/EventEmitter.js +26 -0
  207. package/dist/esm/lib/v3/flowlogger/EventEmitter.js.map +1 -0
  208. package/dist/esm/lib/v3/flowlogger/EventSink.d.ts +44 -0
  209. package/dist/esm/lib/v3/flowlogger/EventSink.js +206 -0
  210. package/dist/esm/lib/v3/flowlogger/EventSink.js.map +1 -0
  211. package/dist/esm/lib/v3/flowlogger/EventStore.d.ts +26 -0
  212. package/dist/esm/lib/v3/flowlogger/EventStore.js +127 -0
  213. package/dist/esm/lib/v3/flowlogger/EventStore.js.map +1 -0
  214. package/dist/esm/lib/v3/flowlogger/FlowLogger.d.ts +99 -0
  215. package/dist/esm/lib/v3/flowlogger/FlowLogger.js +583 -0
  216. package/dist/esm/lib/v3/flowlogger/FlowLogger.js.map +1 -0
  217. package/dist/esm/lib/v3/flowlogger/prettify.d.ts +6 -0
  218. package/dist/esm/lib/v3/flowlogger/prettify.js +389 -0
  219. package/dist/esm/lib/v3/flowlogger/prettify.js.map +1 -0
  220. package/dist/esm/lib/v3/handlers/handlerUtils/actHandlerUtils.js +43 -57
  221. package/dist/esm/lib/v3/handlers/handlerUtils/actHandlerUtils.js.map +1 -1
  222. package/dist/esm/lib/v3/handlers/observeHandler.js +2 -1
  223. package/dist/esm/lib/v3/handlers/observeHandler.js.map +1 -1
  224. package/dist/esm/lib/v3/handlers/v3AgentHandler.d.ts +2 -5
  225. package/dist/esm/lib/v3/handlers/v3AgentHandler.js +112 -78
  226. package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  227. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.d.ts +5 -0
  228. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js +134 -14
  229. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  230. package/dist/esm/lib/v3/llm/aisdk.js +11 -17
  231. package/dist/esm/lib/v3/llm/aisdk.js.map +1 -1
  232. package/dist/esm/lib/v3/types/private/cache.d.ts +0 -1
  233. package/dist/esm/lib/v3/types/private/cache.js.map +1 -1
  234. package/dist/esm/lib/v3/types/private/handlers.d.ts +1 -0
  235. package/dist/esm/lib/v3/types/private/handlers.js.map +1 -1
  236. package/dist/esm/lib/v3/types/public/api.d.ts +24 -7
  237. package/dist/esm/lib/v3/types/public/api.js +36 -12
  238. package/dist/esm/lib/v3/types/public/api.js.map +1 -1
  239. package/dist/esm/lib/v3/types/public/methods.d.ts +1 -0
  240. package/dist/esm/lib/v3/types/public/methods.js.map +1 -1
  241. package/dist/esm/lib/v3/types/public/options.d.ts +7 -0
  242. package/dist/esm/lib/v3/types/public/options.js.map +1 -1
  243. package/dist/esm/lib/v3/types/public/variables.d.ts +7 -0
  244. package/dist/esm/lib/v3/types/public/variables.js +19 -0
  245. package/dist/esm/lib/v3/types/public/variables.js.map +1 -0
  246. package/dist/esm/lib/v3/understudy/cdp.d.ts +3 -12
  247. package/dist/esm/lib/v3/understudy/cdp.js +134 -21
  248. package/dist/esm/lib/v3/understudy/cdp.js.map +1 -1
  249. package/dist/esm/lib/v3/understudy/page.js +28 -18
  250. package/dist/esm/lib/v3/understudy/page.js.map +1 -1
  251. package/dist/esm/lib/v3/v3.d.ts +12 -2
  252. package/dist/esm/lib/v3/v3.js +194 -160
  253. package/dist/esm/lib/v3/v3.js.map +1 -1
  254. package/dist/esm/lib/version.d.ts +1 -1
  255. package/dist/esm/lib/version.js +1 -1
  256. package/dist/esm/lib/version.js.map +1 -1
  257. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.d.ts +1 -0
  258. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js +54 -0
  259. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js.map +1 -0
  260. package/dist/esm/tests/integration/agent-hybrid-mode.spec.js +6 -6
  261. package/dist/esm/tests/integration/agent-hybrid-mode.spec.js.map +1 -1
  262. package/dist/esm/tests/integration/flowLogger.spec.d.ts +1 -0
  263. package/dist/esm/tests/integration/flowLogger.spec.js +712 -0
  264. package/dist/esm/tests/integration/flowLogger.spec.js.map +1 -0
  265. package/dist/esm/tests/integration/testUtils.d.ts +33 -0
  266. package/dist/esm/tests/integration/testUtils.js +138 -0
  267. package/dist/esm/tests/integration/testUtils.js.map +1 -1
  268. package/dist/esm/tests/integration/timeouts.spec.js +113 -3
  269. package/dist/esm/tests/integration/timeouts.spec.js.map +1 -1
  270. package/dist/esm/tests/unit/agent-captcha-hooks.test.d.ts +1 -0
  271. package/dist/esm/tests/unit/agent-captcha-hooks.test.js +283 -0
  272. package/dist/esm/tests/unit/agent-captcha-hooks.test.js.map +1 -0
  273. package/dist/esm/tests/unit/agent-execution-model.test.js +25 -3
  274. package/dist/esm/tests/unit/agent-execution-model.test.js.map +1 -1
  275. package/dist/esm/tests/unit/agent-system-prompt-variables.test.d.ts +1 -0
  276. package/dist/esm/tests/unit/agent-system-prompt-variables.test.js +21 -0
  277. package/dist/esm/tests/unit/agent-system-prompt-variables.test.js.map +1 -0
  278. package/dist/esm/tests/unit/api-client-observe-variables.test.d.ts +1 -0
  279. package/dist/esm/tests/unit/api-client-observe-variables.test.js +84 -0
  280. package/dist/esm/tests/unit/api-client-observe-variables.test.js.map +1 -0
  281. package/dist/esm/tests/unit/api-variables-schema.test.d.ts +1 -0
  282. package/dist/esm/tests/unit/api-variables-schema.test.js +35 -0
  283. package/dist/esm/tests/unit/api-variables-schema.test.js.map +1 -0
  284. package/dist/esm/tests/unit/browserbase-session-accessors.test.js +20 -0
  285. package/dist/esm/tests/unit/browserbase-session-accessors.test.js.map +1 -1
  286. package/dist/esm/tests/unit/captcha-solver.test.d.ts +1 -0
  287. package/dist/esm/tests/unit/captcha-solver.test.js +152 -0
  288. package/dist/esm/tests/unit/captcha-solver.test.js.map +1 -0
  289. package/dist/esm/tests/unit/flowlogger-capturing-cdp.test.d.ts +1 -0
  290. package/dist/esm/tests/unit/flowlogger-capturing-cdp.test.js +93 -0
  291. package/dist/esm/tests/unit/flowlogger-capturing-cdp.test.js.map +1 -0
  292. package/dist/esm/tests/unit/flowlogger-capturing-llm.test.d.ts +1 -0
  293. package/dist/esm/tests/unit/flowlogger-capturing-llm.test.js +41 -0
  294. package/dist/esm/tests/unit/flowlogger-capturing-llm.test.js.map +1 -0
  295. package/dist/esm/tests/unit/flowlogger-eventstore.test.d.ts +1 -0
  296. package/dist/esm/tests/unit/flowlogger-eventstore.test.js +248 -0
  297. package/dist/esm/tests/unit/flowlogger-eventstore.test.js.map +1 -0
  298. package/dist/esm/tests/unit/openai-cua-client.test.d.ts +1 -0
  299. package/dist/esm/tests/unit/openai-cua-client.test.js +69 -0
  300. package/dist/esm/tests/unit/openai-cua-client.test.js.map +1 -0
  301. package/dist/esm/tests/unit/prompt-observe-variables.test.d.ts +1 -0
  302. package/dist/esm/tests/unit/prompt-observe-variables.test.js +17 -0
  303. package/dist/esm/tests/unit/prompt-observe-variables.test.js.map +1 -0
  304. package/dist/esm/tests/unit/public-api/public-types.test.js.map +1 -1
  305. package/dist/esm/tests/unit/timeout-handlers.test.js +50 -0
  306. package/dist/esm/tests/unit/timeout-handlers.test.js.map +1 -1
  307. package/package.json +4 -2
  308. package/dist/cjs/lib/v3/flowLogger.d.ts +0 -139
  309. package/dist/cjs/lib/v3/flowLogger.js +0 -881
  310. package/dist/cjs/lib/v3/flowLogger.js.map +0 -1
  311. package/dist/esm/lib/v3/flowLogger.d.ts +0 -139
  312. package/dist/esm/lib/v3/flowLogger.js +0 -868
  313. package/dist/esm/lib/v3/flowLogger.js.map +0 -1
@@ -60,6 +60,7 @@ describe("browserbase accessors", () => {
60
60
  await v3.init();
61
61
  expect(v3.browserbaseSessionURL).toBe(MOCK_SESSION_URL);
62
62
  expect(v3.browserbaseDebugURL).toBe(MOCK_DEBUG_URL);
63
+ expect(v3.isCaptchaAutoSolveEnabled).toBe(true);
63
64
  }
64
65
  finally {
65
66
  await v3.close().catch(() => { });
@@ -76,6 +77,25 @@ describe("browserbase accessors", () => {
76
77
  expect(v3.browserbaseSessionURL).toBeUndefined();
77
78
  expect(v3.browserbaseDebugURL).toBeUndefined();
78
79
  });
80
+ it("disables captcha solving when solveCaptchas is explicitly false", async () => {
81
+ const v3 = new V3({
82
+ env: "BROWSERBASE",
83
+ disableAPI: true,
84
+ verbose: 0,
85
+ browserbaseSessionCreateParams: {
86
+ browserSettings: {
87
+ solveCaptchas: false,
88
+ },
89
+ },
90
+ });
91
+ try {
92
+ await v3.init();
93
+ expect(v3.isCaptchaAutoSolveEnabled).toBe(false);
94
+ }
95
+ finally {
96
+ await v3.close().catch(() => { });
97
+ }
98
+ });
79
99
  });
80
100
  describe("local accessors", () => {
81
101
  it("stay empty for LOCAL environments", async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"browserbase-session-accessors.test.js","sourceRoot":"","sources":["../../../../tests/unit/browserbase-session-accessors.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi, beforeEach, afterEach } from \"vitest\";\nimport { V3 } from \"../../lib/v3/v3.js\";\n\nconst MOCK_SESSION_ID = \"session-123\";\nconst MOCK_SESSION_URL = `https://www.browserbase.com/sessions/${MOCK_SESSION_ID}`;\nconst MOCK_DEBUG_URL = `https://debug.browserbase.com/${MOCK_SESSION_ID}`;\n\nvi.mock(\"../../lib/v3/understudy/context\", () => {\n class MockConnection {\n onTransportClosed = vi.fn();\n offTransportClosed = vi.fn();\n send = vi.fn(async () => {});\n }\n\n class MockV3Context {\n static async create(): Promise<MockV3Context> {\n return new MockV3Context();\n }\n\n conn = new MockConnection();\n\n pages(): never[] {\n return [];\n }\n\n async close(): Promise<void> {\n // noop\n }\n }\n\n return { V3Context: MockV3Context };\n});\n\nvi.mock(\"../../lib/v3/launch/browserbase\", () => ({\n createBrowserbaseSession: vi.fn(async () => ({\n ws: \"wss://mock-browserbase\",\n sessionId: MOCK_SESSION_ID,\n bb: {\n sessions: {\n debug: vi.fn(async () => ({ debuggerUrl: MOCK_DEBUG_URL })),\n },\n },\n })),\n}));\n\nvi.mock(\"../../lib/v3/launch/local\", () => ({\n launchLocalChrome: vi.fn(async () => ({\n ws: \"ws://local-cdp\",\n chrome: { kill: vi.fn(async () => {}) },\n })),\n}));\n\ndescribe(\"browserbase accessors\", () => {\n beforeEach(() => {\n process.env.BROWSERBASE_API_KEY = \"fake-key\";\n process.env.BROWSERBASE_PROJECT_ID = \"fake-project\";\n });\n\n afterEach(() => {\n delete process.env.BROWSERBASE_API_KEY;\n delete process.env.BROWSERBASE_PROJECT_ID;\n vi.clearAllMocks();\n });\n\n it(\"exposes Browserbase session and debug URLs after init\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n });\n\n try {\n await v3.init();\n\n expect(v3.browserbaseSessionURL).toBe(MOCK_SESSION_URL);\n expect(v3.browserbaseDebugURL).toBe(MOCK_DEBUG_URL);\n } finally {\n await v3.close().catch(() => {});\n }\n });\n\n it(\"clears stored URLs after close\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n });\n\n await v3.init();\n await v3.close();\n\n expect(v3.browserbaseSessionURL).toBeUndefined();\n expect(v3.browserbaseDebugURL).toBeUndefined();\n });\n});\n\ndescribe(\"local accessors\", () => {\n it(\"stay empty for LOCAL environments\", async () => {\n const v3 = new V3({\n env: \"LOCAL\",\n disableAPI: true,\n verbose: 0,\n localBrowserLaunchOptions: {\n cdpUrl: \"ws://local-existing-session\",\n },\n });\n\n try {\n await v3.init();\n expect(v3.browserbaseSessionURL).toBeUndefined();\n expect(v3.browserbaseDebugURL).toBeUndefined();\n } finally {\n await v3.close().catch(() => {});\n }\n });\n});\n"]}
1
+ {"version":3,"file":"browserbase-session-accessors.test.js","sourceRoot":"","sources":["../../../../tests/unit/browserbase-session-accessors.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi, beforeEach, afterEach } from \"vitest\";\nimport { V3 } from \"../../lib/v3/v3.js\";\n\nconst MOCK_SESSION_ID = \"session-123\";\nconst MOCK_SESSION_URL = `https://www.browserbase.com/sessions/${MOCK_SESSION_ID}`;\nconst MOCK_DEBUG_URL = `https://debug.browserbase.com/${MOCK_SESSION_ID}`;\n\nvi.mock(\"../../lib/v3/understudy/context\", () => {\n class MockConnection {\n onTransportClosed = vi.fn();\n offTransportClosed = vi.fn();\n send = vi.fn(async () => {});\n }\n\n class MockV3Context {\n static async create(): Promise<MockV3Context> {\n return new MockV3Context();\n }\n\n conn = new MockConnection();\n\n pages(): never[] {\n return [];\n }\n\n async close(): Promise<void> {\n // noop\n }\n }\n\n return { V3Context: MockV3Context };\n});\n\nvi.mock(\"../../lib/v3/launch/browserbase\", () => ({\n createBrowserbaseSession: vi.fn(async () => ({\n ws: \"wss://mock-browserbase\",\n sessionId: MOCK_SESSION_ID,\n bb: {\n sessions: {\n debug: vi.fn(async () => ({ debuggerUrl: MOCK_DEBUG_URL })),\n },\n },\n })),\n}));\n\nvi.mock(\"../../lib/v3/launch/local\", () => ({\n launchLocalChrome: vi.fn(async () => ({\n ws: \"ws://local-cdp\",\n chrome: { kill: vi.fn(async () => {}) },\n })),\n}));\n\ndescribe(\"browserbase accessors\", () => {\n beforeEach(() => {\n process.env.BROWSERBASE_API_KEY = \"fake-key\";\n process.env.BROWSERBASE_PROJECT_ID = \"fake-project\";\n });\n\n afterEach(() => {\n delete process.env.BROWSERBASE_API_KEY;\n delete process.env.BROWSERBASE_PROJECT_ID;\n vi.clearAllMocks();\n });\n\n it(\"exposes Browserbase session and debug URLs after init\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n });\n\n try {\n await v3.init();\n\n expect(v3.browserbaseSessionURL).toBe(MOCK_SESSION_URL);\n expect(v3.browserbaseDebugURL).toBe(MOCK_DEBUG_URL);\n expect(v3.isCaptchaAutoSolveEnabled).toBe(true);\n } finally {\n await v3.close().catch(() => {});\n }\n });\n\n it(\"clears stored URLs after close\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n });\n\n await v3.init();\n await v3.close();\n\n expect(v3.browserbaseSessionURL).toBeUndefined();\n expect(v3.browserbaseDebugURL).toBeUndefined();\n });\n\n it(\"disables captcha solving when solveCaptchas is explicitly false\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n browserbaseSessionCreateParams: {\n browserSettings: {\n solveCaptchas: false,\n },\n },\n });\n\n try {\n await v3.init();\n expect(v3.isCaptchaAutoSolveEnabled).toBe(false);\n } finally {\n await v3.close().catch(() => {});\n }\n });\n});\n\ndescribe(\"local accessors\", () => {\n it(\"stay empty for LOCAL environments\", async () => {\n const v3 = new V3({\n env: \"LOCAL\",\n disableAPI: true,\n verbose: 0,\n localBrowserLaunchOptions: {\n cdpUrl: \"ws://local-existing-session\",\n },\n });\n\n try {\n await v3.init();\n expect(v3.browserbaseSessionURL).toBeUndefined();\n expect(v3.browserbaseDebugURL).toBeUndefined();\n } finally {\n await v3.close().catch(() => {});\n }\n });\n});\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,152 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { CaptchaSolver } from "../../lib/v3/agent/utils/captchaSolver.js";
3
+ const SOLVING_STARTED = "browserbase-solving-started";
4
+ const SOLVING_FINISHED = "browserbase-solving-finished";
5
+ const SOLVING_ERRORED = "browserbase-solving-errored";
6
+ class MockPage {
7
+ listeners = new Set();
8
+ onCalls = 0;
9
+ offCalls = 0;
10
+ on(event, listener) {
11
+ if (event !== "console")
12
+ return;
13
+ this.onCalls++;
14
+ this.listeners.add(listener);
15
+ }
16
+ off(event, listener) {
17
+ if (event !== "console")
18
+ return;
19
+ this.offCalls++;
20
+ this.listeners.delete(listener);
21
+ }
22
+ emitConsole(text) {
23
+ const message = { text: () => text };
24
+ for (const listener of this.listeners) {
25
+ listener(message);
26
+ }
27
+ }
28
+ listenerCount() {
29
+ return this.listeners.size;
30
+ }
31
+ }
32
+ describe("CaptchaSolver", () => {
33
+ it("resolves all concurrent waiters when a solve finishes", async () => {
34
+ const page = new MockPage();
35
+ const solver = new CaptchaSolver();
36
+ solver.init(async () => page);
37
+ await solver.ensureAttached();
38
+ page.emitConsole(SOLVING_STARTED);
39
+ const firstWait = solver.waitIfSolving();
40
+ const secondWait = solver.waitIfSolving();
41
+ await new Promise((resolve) => setTimeout(resolve, 0));
42
+ const sharedWaitPromise = solver.waitPromise;
43
+ expect(sharedWaitPromise).not.toBeNull();
44
+ expect(solver.waitPromise).toBe(sharedWaitPromise);
45
+ let firstResolved = false;
46
+ let secondResolved = false;
47
+ void firstWait.then(() => {
48
+ firstResolved = true;
49
+ });
50
+ void secondWait.then(() => {
51
+ secondResolved = true;
52
+ });
53
+ await Promise.resolve();
54
+ expect(firstResolved).toBe(false);
55
+ expect(secondResolved).toBe(false);
56
+ page.emitConsole(SOLVING_FINISHED);
57
+ await Promise.all([firstWait, secondWait]);
58
+ expect(firstResolved).toBe(true);
59
+ expect(secondResolved).toBe(true);
60
+ expect(solver.consumeSolveResult()).toEqual({
61
+ solved: true,
62
+ errored: false,
63
+ });
64
+ expect(solver.consumeSolveResult()).toEqual({
65
+ solved: false,
66
+ errored: false,
67
+ });
68
+ });
69
+ it("re-attaches to a new page and settles stale waiters when the active page changes", async () => {
70
+ const firstPage = new MockPage();
71
+ const secondPage = new MockPage();
72
+ let activePage = firstPage;
73
+ const solver = new CaptchaSolver();
74
+ solver.init(async () => activePage);
75
+ await solver.ensureAttached();
76
+ firstPage.emitConsole(SOLVING_STARTED);
77
+ const pendingWait = solver.waitIfSolving();
78
+ let settled = false;
79
+ void pendingWait.then(() => {
80
+ settled = true;
81
+ });
82
+ activePage = secondPage;
83
+ await solver.waitIfSolving();
84
+ await pendingWait;
85
+ expect(settled).toBe(true);
86
+ expect(firstPage.offCalls).toBe(1);
87
+ expect(firstPage.listenerCount()).toBe(0);
88
+ expect(secondPage.onCalls).toBe(1);
89
+ expect(secondPage.listenerCount()).toBe(1);
90
+ expect(solver.isSolving()).toBe(false);
91
+ });
92
+ it("surfaces solver errors exactly once per consume", async () => {
93
+ const page = new MockPage();
94
+ const solver = new CaptchaSolver();
95
+ solver.init(async () => page);
96
+ await solver.ensureAttached();
97
+ page.emitConsole(SOLVING_STARTED);
98
+ const wait = solver.waitIfSolving();
99
+ page.emitConsole(SOLVING_ERRORED);
100
+ await wait;
101
+ expect(solver.consumeSolveResult()).toEqual({
102
+ solved: false,
103
+ errored: true,
104
+ });
105
+ expect(solver.consumeSolveResult()).toEqual({
106
+ solved: false,
107
+ errored: false,
108
+ });
109
+ });
110
+ it("disposes cleanly while a solve is in progress", async () => {
111
+ const page = new MockPage();
112
+ const solver = new CaptchaSolver();
113
+ solver.init(async () => page);
114
+ await solver.ensureAttached();
115
+ page.emitConsole(SOLVING_STARTED);
116
+ const wait = solver.waitIfSolving();
117
+ await new Promise((resolve) => setTimeout(resolve, 0));
118
+ let settled = false;
119
+ void wait.then(() => {
120
+ settled = true;
121
+ });
122
+ solver.dispose();
123
+ await wait;
124
+ expect(settled).toBe(true);
125
+ expect(solver.isSolving()).toBe(false);
126
+ expect(page.listenerCount()).toBe(0);
127
+ expect(solver.consumeSolveResult()).toEqual({
128
+ solved: false,
129
+ errored: false,
130
+ });
131
+ });
132
+ it("marks errored when detached mid-solve due to page change", async () => {
133
+ const firstPage = new MockPage();
134
+ const secondPage = new MockPage();
135
+ let activePage = firstPage;
136
+ const solver = new CaptchaSolver();
137
+ solver.init(async () => activePage);
138
+ await solver.ensureAttached();
139
+ firstPage.emitConsole(SOLVING_STARTED);
140
+ const wait = solver.waitIfSolving();
141
+ // Switch to a new page while the solve is in progress
142
+ activePage = secondPage;
143
+ await solver.waitIfSolving();
144
+ await wait;
145
+ // The interrupted solve should be reported as errored
146
+ expect(solver.consumeSolveResult()).toEqual({
147
+ solved: false,
148
+ errored: true,
149
+ });
150
+ });
151
+ });
152
+ //# sourceMappingURL=captcha-solver.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captcha-solver.test.js","sourceRoot":"","sources":["../../../../tests/unit/captcha-solver.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { CaptchaSolver } from \"../../lib/v3/agent/utils/captchaSolver.js\";\n\nconst SOLVING_STARTED = \"browserbase-solving-started\";\nconst SOLVING_FINISHED = \"browserbase-solving-finished\";\nconst SOLVING_ERRORED = \"browserbase-solving-errored\";\n\ntype ConsoleListener = (message: { text: () => string }) => void;\n\nclass MockPage {\n private listeners = new Set<ConsoleListener>();\n public onCalls = 0;\n public offCalls = 0;\n\n on(event: string, listener: ConsoleListener): void {\n if (event !== \"console\") return;\n this.onCalls++;\n this.listeners.add(listener);\n }\n\n off(event: string, listener: ConsoleListener): void {\n if (event !== \"console\") return;\n this.offCalls++;\n this.listeners.delete(listener);\n }\n\n emitConsole(text: string): void {\n const message = { text: () => text };\n for (const listener of this.listeners) {\n listener(message);\n }\n }\n\n listenerCount(): number {\n return this.listeners.size;\n }\n}\n\ndescribe(\"CaptchaSolver\", () => {\n it(\"resolves all concurrent waiters when a solve finishes\", async () => {\n const page = new MockPage();\n const solver = new CaptchaSolver();\n solver.init(async () => page as never);\n\n await solver.ensureAttached();\n page.emitConsole(SOLVING_STARTED);\n\n const firstWait = solver.waitIfSolving();\n const secondWait = solver.waitIfSolving();\n await new Promise((resolve) => setTimeout(resolve, 0));\n\n const sharedWaitPromise = (\n solver as unknown as { waitPromise: Promise<void> | null }\n ).waitPromise;\n\n expect(sharedWaitPromise).not.toBeNull();\n expect(\n (solver as unknown as { waitPromise: Promise<void> | null }).waitPromise,\n ).toBe(sharedWaitPromise);\n\n let firstResolved = false;\n let secondResolved = false;\n void firstWait.then(() => {\n firstResolved = true;\n });\n void secondWait.then(() => {\n secondResolved = true;\n });\n\n await Promise.resolve();\n expect(firstResolved).toBe(false);\n expect(secondResolved).toBe(false);\n\n page.emitConsole(SOLVING_FINISHED);\n await Promise.all([firstWait, secondWait]);\n\n expect(firstResolved).toBe(true);\n expect(secondResolved).toBe(true);\n expect(solver.consumeSolveResult()).toEqual({\n solved: true,\n errored: false,\n });\n expect(solver.consumeSolveResult()).toEqual({\n solved: false,\n errored: false,\n });\n });\n\n it(\"re-attaches to a new page and settles stale waiters when the active page changes\", async () => {\n const firstPage = new MockPage();\n const secondPage = new MockPage();\n let activePage = firstPage;\n\n const solver = new CaptchaSolver();\n solver.init(async () => activePage as never);\n\n await solver.ensureAttached();\n firstPage.emitConsole(SOLVING_STARTED);\n\n const pendingWait = solver.waitIfSolving();\n let settled = false;\n void pendingWait.then(() => {\n settled = true;\n });\n\n activePage = secondPage;\n await solver.waitIfSolving();\n await pendingWait;\n\n expect(settled).toBe(true);\n expect(firstPage.offCalls).toBe(1);\n expect(firstPage.listenerCount()).toBe(0);\n expect(secondPage.onCalls).toBe(1);\n expect(secondPage.listenerCount()).toBe(1);\n expect(solver.isSolving()).toBe(false);\n });\n\n it(\"surfaces solver errors exactly once per consume\", async () => {\n const page = new MockPage();\n const solver = new CaptchaSolver();\n solver.init(async () => page as never);\n\n await solver.ensureAttached();\n page.emitConsole(SOLVING_STARTED);\n\n const wait = solver.waitIfSolving();\n page.emitConsole(SOLVING_ERRORED);\n await wait;\n\n expect(solver.consumeSolveResult()).toEqual({\n solved: false,\n errored: true,\n });\n expect(solver.consumeSolveResult()).toEqual({\n solved: false,\n errored: false,\n });\n });\n\n it(\"disposes cleanly while a solve is in progress\", async () => {\n const page = new MockPage();\n const solver = new CaptchaSolver();\n solver.init(async () => page as never);\n\n await solver.ensureAttached();\n page.emitConsole(SOLVING_STARTED);\n\n const wait = solver.waitIfSolving();\n await new Promise((resolve) => setTimeout(resolve, 0));\n let settled = false;\n void wait.then(() => {\n settled = true;\n });\n\n solver.dispose();\n await wait;\n\n expect(settled).toBe(true);\n expect(solver.isSolving()).toBe(false);\n expect(page.listenerCount()).toBe(0);\n expect(solver.consumeSolveResult()).toEqual({\n solved: false,\n errored: false,\n });\n });\n\n it(\"marks errored when detached mid-solve due to page change\", async () => {\n const firstPage = new MockPage();\n const secondPage = new MockPage();\n let activePage = firstPage;\n\n const solver = new CaptchaSolver();\n solver.init(async () => activePage as never);\n\n await solver.ensureAttached();\n firstPage.emitConsole(SOLVING_STARTED);\n\n const wait = solver.waitIfSolving();\n\n // Switch to a new page while the solve is in progress\n activePage = secondPage;\n await solver.waitIfSolving();\n await wait;\n\n // The interrupted solve should be reported as errored\n expect(solver.consumeSolveResult()).toEqual({\n solved: false,\n errored: true,\n });\n });\n});\n"]}
@@ -0,0 +1,93 @@
1
+ import { EventEmitter } from "node:events";
2
+ import { describe, it, expect } from "vitest";
3
+ import { CdpConnection } from "../../lib/v3/understudy/cdp.js";
4
+ import { InMemoryEventSink } from "../../lib/v3/flowlogger/EventSink.js";
5
+ import { EventEmitterWithWildcardSupport } from "../../lib/v3/flowlogger/EventEmitter.js";
6
+ import { EventStore } from "../../lib/v3/flowlogger/EventStore.js";
7
+ import { FlowEvent, FlowLogger } from "../../lib/v3/flowlogger/FlowLogger.js";
8
+ function attachEventStoreToBus(store, bus) {
9
+ const onFlowEvent = (event) => {
10
+ if (event instanceof FlowEvent) {
11
+ void store.emit(event);
12
+ }
13
+ };
14
+ bus.on("*", onFlowEvent);
15
+ return () => {
16
+ bus.off("*", onFlowEvent);
17
+ };
18
+ }
19
+ class FakeSocket extends EventEmitter {
20
+ sentPayloads = [];
21
+ readyState = 1;
22
+ send(payload) {
23
+ this.sentPayloads.push(payload);
24
+ }
25
+ close() {
26
+ this.readyState = 3;
27
+ this.emit("close", 1000, "");
28
+ }
29
+ }
30
+ function createConnection(socket) {
31
+ // The production constructor is private; tests instantiate it directly so
32
+ // they can drive raw websocket messages without a real browser.
33
+ const ConnectionCtor = CdpConnection;
34
+ return new ConnectionCtor(socket);
35
+ }
36
+ function requireEvent(events, predicate, description) {
37
+ const match = events.find(predicate);
38
+ expect(match, `missing ${description}`).toBeDefined();
39
+ return match;
40
+ }
41
+ describe("flow logger cdp context", () => {
42
+ it("preserves the active parent chain when a session event handler issues a nested CDP call", async () => {
43
+ const sessionId = "session-test";
44
+ const socket = new FakeSocket();
45
+ const eventBus = new EventEmitterWithWildcardSupport();
46
+ const sink = new InMemoryEventSink();
47
+ const eventStore = new EventStore(sessionId, undefined, sink);
48
+ const detachBus = attachEventStoreToBus(eventStore, eventBus);
49
+ const conn = createConnection(socket);
50
+ conn.flowLoggerContext = FlowLogger.init(sessionId, eventBus);
51
+ // Seed the target/session mapping the same way a real attach flow would
52
+ // before any session-scoped messages are dispatched.
53
+ conn.onMessage(JSON.stringify({
54
+ method: "Target.attachedToTarget",
55
+ params: {
56
+ sessionId: "target-session",
57
+ targetInfo: { targetId: "target-1" },
58
+ },
59
+ }));
60
+ const session = conn.getSession("target-session");
61
+ expect(session).toBeDefined();
62
+ session.on("Runtime.consoleAPICalled", () => {
63
+ // This nested send used to lose its parent chain because the callback ran
64
+ // after the original ALS scope had already unwound.
65
+ void session.send("Runtime.evaluate", {
66
+ expression: "2 + 2",
67
+ });
68
+ });
69
+ await FlowLogger.runWithLogging({
70
+ context: conn.flowLoggerContext,
71
+ eventType: "SyntheticParentEvent",
72
+ }, async () => {
73
+ void session.send("Page.navigate", {
74
+ url: "https://example.com",
75
+ });
76
+ }, []);
77
+ conn.onMessage(JSON.stringify({
78
+ method: "Runtime.consoleAPICalled",
79
+ sessionId: "target-session",
80
+ params: { type: "log" },
81
+ }));
82
+ // The nested Runtime.evaluate call should still attach under the synthetic
83
+ // parent event even though it was triggered by a later session callback.
84
+ const events = await eventStore.query({});
85
+ const parentEvent = requireEvent(events, (event) => event.eventType === "SyntheticParentEvent", "SyntheticParentEvent");
86
+ const nestedCallEvent = requireEvent(events, (event) => event.eventType === "CdpCallEvent" &&
87
+ String(event.data.method) === "Runtime.evaluate", "nested Runtime.evaluate CdpCallEvent");
88
+ expect(nestedCallEvent.eventParentIds).toEqual([parentEvent.eventId]);
89
+ detachBus();
90
+ await eventStore.destroy();
91
+ });
92
+ });
93
+ //# sourceMappingURL=flowlogger-capturing-cdp.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowlogger-capturing-cdp.test.js","sourceRoot":"","sources":["../../../../tests/unit/flowlogger-capturing-cdp.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter } from \"node:events\";\nimport { describe, it, expect } from \"vitest\";\nimport { CdpConnection } from \"../../lib/v3/understudy/cdp.js\";\nimport { InMemoryEventSink } from \"../../lib/v3/flowlogger/EventSink.js\";\nimport { EventEmitterWithWildcardSupport } from \"../../lib/v3/flowlogger/EventEmitter.js\";\nimport { EventStore } from \"../../lib/v3/flowlogger/EventStore.js\";\nimport { FlowEvent, FlowLogger } from \"../../lib/v3/flowlogger/FlowLogger.js\";\n\nfunction attachEventStoreToBus(\n store: EventStore,\n bus: EventEmitterWithWildcardSupport,\n): () => void {\n const onFlowEvent = (event: unknown) => {\n if (event instanceof FlowEvent) {\n void store.emit(event);\n }\n };\n\n bus.on(\"*\", onFlowEvent);\n return () => {\n bus.off(\"*\", onFlowEvent);\n };\n}\n\nclass FakeSocket extends EventEmitter {\n sentPayloads: string[] = [];\n readyState = 1;\n\n send(payload: string): void {\n this.sentPayloads.push(payload);\n }\n\n close(): void {\n this.readyState = 3;\n this.emit(\"close\", 1000, \"\");\n }\n}\n\nfunction createConnection(socket: FakeSocket): CdpConnection {\n // The production constructor is private; tests instantiate it directly so\n // they can drive raw websocket messages without a real browser.\n const ConnectionCtor = CdpConnection as unknown as {\n new (ws: FakeSocket): CdpConnection;\n };\n return new ConnectionCtor(socket);\n}\n\nfunction requireEvent(\n events: FlowEvent[],\n predicate: (event: FlowEvent) => boolean,\n description: string,\n): FlowEvent {\n const match = events.find(predicate);\n expect(match, `missing ${description}`).toBeDefined();\n return match as FlowEvent;\n}\n\ndescribe(\"flow logger cdp context\", () => {\n it(\"preserves the active parent chain when a session event handler issues a nested CDP call\", async () => {\n const sessionId = \"session-test\";\n const socket = new FakeSocket();\n const eventBus = new EventEmitterWithWildcardSupport();\n const sink = new InMemoryEventSink();\n const eventStore = new EventStore(sessionId, undefined, sink);\n\n const detachBus = attachEventStoreToBus(eventStore, eventBus);\n\n const conn = createConnection(socket);\n conn.flowLoggerContext = FlowLogger.init(sessionId, eventBus);\n\n // Seed the target/session mapping the same way a real attach flow would\n // before any session-scoped messages are dispatched.\n (conn as unknown as { onMessage(json: string): void }).onMessage(\n JSON.stringify({\n method: \"Target.attachedToTarget\",\n params: {\n sessionId: \"target-session\",\n targetInfo: { targetId: \"target-1\" },\n },\n }),\n );\n\n const session = conn.getSession(\"target-session\");\n expect(session).toBeDefined();\n\n session!.on(\"Runtime.consoleAPICalled\", () => {\n // This nested send used to lose its parent chain because the callback ran\n // after the original ALS scope had already unwound.\n void session!.send(\"Runtime.evaluate\", {\n expression: \"2 + 2\",\n });\n });\n\n await FlowLogger.runWithLogging(\n {\n context: conn.flowLoggerContext,\n eventType: \"SyntheticParentEvent\",\n },\n async () => {\n void session!.send(\"Page.navigate\", {\n url: \"https://example.com\",\n });\n },\n [],\n );\n\n (conn as unknown as { onMessage(json: string): void }).onMessage(\n JSON.stringify({\n method: \"Runtime.consoleAPICalled\",\n sessionId: \"target-session\",\n params: { type: \"log\" },\n }),\n );\n\n // The nested Runtime.evaluate call should still attach under the synthetic\n // parent event even though it was triggered by a later session callback.\n const events = await eventStore.query({});\n const parentEvent = requireEvent(\n events,\n (event) => event.eventType === \"SyntheticParentEvent\",\n \"SyntheticParentEvent\",\n );\n const nestedCallEvent = requireEvent(\n events,\n (event) =>\n event.eventType === \"CdpCallEvent\" &&\n String(event.data.method) === \"Runtime.evaluate\",\n \"nested Runtime.evaluate CdpCallEvent\",\n );\n\n expect(nestedCallEvent.eventParentIds).toEqual([parentEvent.eventId]);\n\n detachBus();\n await eventStore.destroy();\n });\n});\n"]}
@@ -0,0 +1,41 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { FlowLogger } from "../../lib/v3/flowlogger/FlowLogger.js";
3
+ describe("flow logger llm logging", () => {
4
+ it("no-ops direct llm logging calls when no flow context is active", () => {
5
+ // These helpers are called from multiple model adapters, so they must stay
6
+ // safe even when a test or utility invokes them outside any ALS flow scope.
7
+ expect(() => FlowLogger.logLlmRequest({
8
+ requestId: "req-1",
9
+ model: "mock-model",
10
+ prompt: "hello",
11
+ })).not.toThrow();
12
+ expect(() => FlowLogger.logLlmResponse({
13
+ requestId: "req-1",
14
+ model: "mock-model",
15
+ output: "world",
16
+ inputTokens: 1,
17
+ outputTokens: 1,
18
+ })).not.toThrow();
19
+ });
20
+ it("does not throw from llm middleware when no flow context is active", async () => {
21
+ const middleware = FlowLogger.createLlmLoggingMiddleware("mock-model");
22
+ // Missing flow context should degrade to a silent no-op and preserve the
23
+ // underlying model result.
24
+ await expect(middleware.wrapGenerate({
25
+ doGenerate: async () => ({
26
+ text: "done",
27
+ usage: {
28
+ inputTokens: 1,
29
+ outputTokens: 1,
30
+ totalTokens: 2,
31
+ },
32
+ }),
33
+ params: {
34
+ prompt: [],
35
+ },
36
+ })).resolves.toMatchObject({
37
+ text: "done",
38
+ });
39
+ });
40
+ });
41
+ //# sourceMappingURL=flowlogger-capturing-llm.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flowlogger-capturing-llm.test.js","sourceRoot":"","sources":["../../../../tests/unit/flowlogger-capturing-llm.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AAEnE,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,2EAA2E;QAC3E,4EAA4E;QAC5E,MAAM,CAAC,GAAG,EAAE,CACV,UAAU,CAAC,aAAa,CAAC;YACvB,SAAS,EAAE,OAAO;YAClB,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,OAAO;SAChB,CAAC,CACH,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAEhB,MAAM,CAAC,GAAG,EAAE,CACV,UAAU,CAAC,cAAc,CAAC;YACxB,SAAS,EAAE,OAAO;YAClB,KAAK,EAAE,YAAY;YACnB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,CAAC;YACd,YAAY,EAAE,CAAC;SAChB,CAAC,CACH,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,UAAU,GAAG,UAAU,CAAC,0BAA0B,CAAC,YAAY,CAAC,CAAC;QAEvE,yEAAyE;QACzE,2BAA2B;QAC3B,MAAM,MAAM,CACV,UAAU,CAAC,YAAY,CAAC;YACtB,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;gBACvB,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE;oBACL,WAAW,EAAE,CAAC;oBACd,YAAY,EAAE,CAAC;oBACf,WAAW,EAAE,CAAC;iBACf;aACF,CAAC;YACF,MAAM,EAAE;gBACN,MAAM,EAAE,EAAE;aACX;SACO,CAAC,CACZ,CAAC,QAAQ,CAAC,aAAa,CAAC;YACvB,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { FlowLogger } from \"../../lib/v3/flowlogger/FlowLogger.js\";\n\ndescribe(\"flow logger llm logging\", () => {\n it(\"no-ops direct llm logging calls when no flow context is active\", () => {\n // These helpers are called from multiple model adapters, so they must stay\n // safe even when a test or utility invokes them outside any ALS flow scope.\n expect(() =>\n FlowLogger.logLlmRequest({\n requestId: \"req-1\",\n model: \"mock-model\",\n prompt: \"hello\",\n }),\n ).not.toThrow();\n\n expect(() =>\n FlowLogger.logLlmResponse({\n requestId: \"req-1\",\n model: \"mock-model\",\n output: \"world\",\n inputTokens: 1,\n outputTokens: 1,\n }),\n ).not.toThrow();\n });\n\n it(\"does not throw from llm middleware when no flow context is active\", async () => {\n const middleware = FlowLogger.createLlmLoggingMiddleware(\"mock-model\");\n\n // Missing flow context should degrade to a silent no-op and preserve the\n // underlying model result.\n await expect(\n middleware.wrapGenerate({\n doGenerate: async () => ({\n text: \"done\",\n usage: {\n inputTokens: 1,\n outputTokens: 1,\n totalTokens: 2,\n },\n }),\n params: {\n prompt: [],\n },\n } as never),\n ).resolves.toMatchObject({\n text: \"done\",\n });\n });\n});\n"]}