@browserbasehq/orca 3.2.0-preview.4 → 3.2.1-preview.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 (308) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/lib/inference.d.ts +3 -1
  3. package/dist/cjs/lib/inference.js +3 -3
  4. package/dist/cjs/lib/inference.js.map +1 -1
  5. package/dist/cjs/lib/prompt.d.ts +1 -1
  6. package/dist/cjs/lib/prompt.js +24 -18
  7. package/dist/cjs/lib/prompt.js.map +1 -1
  8. package/dist/cjs/lib/v3/agent/AgentClient.d.ts +8 -0
  9. package/dist/cjs/lib/v3/agent/AgentClient.js +13 -0
  10. package/dist/cjs/lib/v3/agent/AgentClient.js.map +1 -1
  11. package/dist/cjs/lib/v3/agent/AgentProvider.js +1 -0
  12. package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
  13. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.d.ts +3 -1
  14. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js +61 -9
  15. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
  16. package/dist/cjs/lib/v3/agent/GoogleCUAClient.js +1 -0
  17. package/dist/cjs/lib/v3/agent/GoogleCUAClient.js.map +1 -1
  18. package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.js +16 -0
  19. package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.js.map +1 -1
  20. package/dist/cjs/lib/v3/agent/OpenAICUAClient.d.ts +12 -6
  21. package/dist/cjs/lib/v3/agent/OpenAICUAClient.js +164 -49
  22. package/dist/cjs/lib/v3/agent/OpenAICUAClient.js.map +1 -1
  23. package/dist/cjs/lib/v3/agent/prompts/agentSystemPrompt.d.ts +2 -2
  24. package/dist/cjs/lib/v3/agent/prompts/agentSystemPrompt.js +10 -11
  25. package/dist/cjs/lib/v3/agent/prompts/agentSystemPrompt.js.map +1 -1
  26. package/dist/cjs/lib/v3/agent/tools/fillform.d.ts +0 -1
  27. package/dist/cjs/lib/v3/agent/tools/fillform.js +7 -10
  28. package/dist/cjs/lib/v3/agent/tools/fillform.js.map +1 -1
  29. package/dist/cjs/lib/v3/agent/tools/index.js +1 -1
  30. package/dist/cjs/lib/v3/agent/tools/index.js.map +1 -1
  31. package/dist/cjs/lib/v3/agent/tools/keys.d.ts +2 -1
  32. package/dist/cjs/lib/v3/agent/tools/keys.js +57 -49
  33. package/dist/cjs/lib/v3/agent/tools/keys.js.map +1 -1
  34. package/dist/cjs/lib/v3/agent/utils/captchaSolver.d.ts +76 -0
  35. package/dist/cjs/lib/v3/agent/utils/captchaSolver.js +175 -0
  36. package/dist/cjs/lib/v3/agent/utils/captchaSolver.js.map +1 -0
  37. package/dist/cjs/lib/v3/agent/utils/coordinateNormalization.js +3 -5
  38. package/dist/cjs/lib/v3/agent/utils/coordinateNormalization.js.map +1 -1
  39. package/dist/cjs/lib/v3/agent/utils/variables.d.ts +5 -0
  40. package/dist/cjs/lib/v3/agent/utils/variables.js +9 -0
  41. package/dist/cjs/lib/v3/agent/utils/variables.js.map +1 -1
  42. package/dist/cjs/lib/v3/api.d.ts +5 -3
  43. package/dist/cjs/lib/v3/api.js +5 -15
  44. package/dist/cjs/lib/v3/api.js.map +1 -1
  45. package/dist/cjs/lib/v3/cache/AgentCache.js +5 -3
  46. package/dist/cjs/lib/v3/cache/AgentCache.js.map +1 -1
  47. package/dist/cjs/lib/v3/flowlogger/EventStore.js +1 -1
  48. package/dist/cjs/lib/v3/flowlogger/EventStore.js.map +1 -1
  49. package/dist/cjs/lib/v3/handlers/observeHandler.js +2 -1
  50. package/dist/cjs/lib/v3/handlers/observeHandler.js.map +1 -1
  51. package/dist/cjs/lib/v3/handlers/v3AgentHandler.d.ts +2 -1
  52. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +110 -46
  53. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  54. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.d.ts +5 -0
  55. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js +131 -16
  56. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  57. package/dist/cjs/lib/v3/index.d.ts +1 -1
  58. package/dist/cjs/lib/v3/llm/LLMProvider.d.ts +5 -2
  59. package/dist/cjs/lib/v3/llm/LLMProvider.js +14 -6
  60. package/dist/cjs/lib/v3/llm/LLMProvider.js.map +1 -1
  61. package/dist/cjs/lib/v3/llm/OpenAIClient.js +1 -0
  62. package/dist/cjs/lib/v3/llm/OpenAIClient.js.map +1 -1
  63. package/dist/cjs/lib/v3/llm/aisdk.d.ts +3 -1
  64. package/dist/cjs/lib/v3/llm/aisdk.js +67 -17
  65. package/dist/cjs/lib/v3/llm/aisdk.js.map +1 -1
  66. package/dist/cjs/lib/v3/types/private/cache.d.ts +0 -1
  67. package/dist/cjs/lib/v3/types/private/cache.js.map +1 -1
  68. package/dist/cjs/lib/v3/types/private/handlers.d.ts +1 -0
  69. package/dist/cjs/lib/v3/types/private/handlers.js.map +1 -1
  70. package/dist/cjs/lib/v3/types/public/agent.d.ts +8 -3
  71. package/dist/cjs/lib/v3/types/public/agent.js +1 -0
  72. package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
  73. package/dist/cjs/lib/v3/types/public/api.d.ts +54 -7
  74. package/dist/cjs/lib/v3/types/public/api.js +47 -16
  75. package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
  76. package/dist/cjs/lib/v3/types/public/methods.d.ts +1 -0
  77. package/dist/cjs/lib/v3/types/public/methods.js.map +1 -1
  78. package/dist/cjs/lib/v3/types/public/model.d.ts +32 -2
  79. package/dist/cjs/lib/v3/types/public/model.js.map +1 -1
  80. package/dist/cjs/lib/v3/types/public/variables.d.ts +7 -0
  81. package/dist/cjs/lib/v3/types/public/variables.js +22 -0
  82. package/dist/cjs/lib/v3/types/public/variables.js.map +1 -0
  83. package/dist/cjs/lib/v3/understudy/context.js +11 -3
  84. package/dist/cjs/lib/v3/understudy/context.js.map +1 -1
  85. package/dist/cjs/lib/v3/understudy/page.js +1 -1
  86. package/dist/cjs/lib/v3/understudy/page.js.map +1 -1
  87. package/dist/cjs/lib/v3/v3.d.ts +23 -2
  88. package/dist/cjs/lib/v3/v3.js +111 -13
  89. package/dist/cjs/lib/v3/v3.js.map +1 -1
  90. package/dist/cjs/lib/version.d.ts +1 -1
  91. package/dist/cjs/lib/version.js +1 -1
  92. package/dist/cjs/lib/version.js.map +1 -1
  93. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.d.ts +1 -0
  94. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js +56 -0
  95. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js.map +1 -0
  96. package/dist/cjs/tests/integration/agent-hybrid-mode.spec.js +6 -6
  97. package/dist/cjs/tests/integration/agent-hybrid-mode.spec.js.map +1 -1
  98. package/dist/cjs/tests/integration/chrome-newtab-page-tracking.spec.d.ts +1 -0
  99. package/dist/cjs/tests/integration/chrome-newtab-page-tracking.spec.js +56 -0
  100. package/dist/cjs/tests/integration/chrome-newtab-page-tracking.spec.js.map +1 -0
  101. package/dist/cjs/tests/integration/timeouts.spec.js +1 -1
  102. package/dist/cjs/tests/integration/timeouts.spec.js.map +1 -1
  103. package/dist/cjs/tests/unit/agent-captcha-hooks.test.d.ts +1 -0
  104. package/dist/cjs/tests/unit/agent-captcha-hooks.test.js +341 -0
  105. package/dist/cjs/tests/unit/agent-captcha-hooks.test.js.map +1 -0
  106. package/dist/cjs/tests/unit/agent-execution-model.test.js +25 -3
  107. package/dist/cjs/tests/unit/agent-execution-model.test.js.map +1 -1
  108. package/dist/cjs/tests/unit/agent-metrics.test.d.ts +1 -0
  109. package/dist/cjs/tests/unit/agent-metrics.test.js +112 -0
  110. package/dist/cjs/tests/unit/agent-metrics.test.js.map +1 -0
  111. package/dist/cjs/tests/unit/agent-system-prompt-variables.test.d.ts +1 -0
  112. package/dist/cjs/tests/unit/agent-system-prompt-variables.test.js +23 -0
  113. package/dist/cjs/tests/unit/agent-system-prompt-variables.test.js.map +1 -0
  114. package/dist/cjs/tests/unit/aisdk-clients.test.d.ts +1 -0
  115. package/dist/cjs/tests/unit/aisdk-clients.test.js +90 -0
  116. package/dist/cjs/tests/unit/aisdk-clients.test.js.map +1 -0
  117. package/dist/cjs/tests/unit/anthropic-cua-adaptive-thinking.test.d.ts +1 -0
  118. package/dist/cjs/tests/unit/anthropic-cua-adaptive-thinking.test.js +250 -0
  119. package/dist/cjs/tests/unit/anthropic-cua-adaptive-thinking.test.js.map +1 -0
  120. package/dist/cjs/tests/unit/api-client-observe-variables.test.d.ts +1 -0
  121. package/dist/cjs/tests/unit/api-client-observe-variables.test.js +86 -0
  122. package/dist/cjs/tests/unit/api-client-observe-variables.test.js.map +1 -0
  123. package/dist/cjs/tests/unit/api-optional-model-api-key.test.d.ts +1 -0
  124. package/dist/cjs/tests/unit/api-optional-model-api-key.test.js +95 -0
  125. package/dist/cjs/tests/unit/api-optional-model-api-key.test.js.map +1 -0
  126. package/dist/cjs/tests/unit/api-variables-schema.test.d.ts +1 -0
  127. package/dist/cjs/tests/unit/api-variables-schema.test.js +37 -0
  128. package/dist/cjs/tests/unit/api-variables-schema.test.js.map +1 -0
  129. package/dist/cjs/tests/unit/browserbase-session-accessors.test.js +40 -0
  130. package/dist/cjs/tests/unit/browserbase-session-accessors.test.js.map +1 -1
  131. package/dist/cjs/tests/unit/captcha-solver.test.d.ts +1 -0
  132. package/dist/cjs/tests/unit/captcha-solver.test.js +154 -0
  133. package/dist/cjs/tests/unit/captcha-solver.test.js.map +1 -0
  134. package/dist/cjs/tests/unit/flowlogger-eventstore.test.js +1 -1
  135. package/dist/cjs/tests/unit/flowlogger-eventstore.test.js.map +1 -1
  136. package/dist/cjs/tests/unit/llm-middleware.test.d.ts +1 -0
  137. package/dist/cjs/tests/unit/llm-middleware.test.js +495 -0
  138. package/dist/cjs/tests/unit/llm-middleware.test.js.map +1 -0
  139. package/dist/cjs/tests/unit/microsoft-cua-client.test.d.ts +1 -0
  140. package/dist/cjs/tests/unit/microsoft-cua-client.test.js +86 -0
  141. package/dist/cjs/tests/unit/microsoft-cua-client.test.js.map +1 -0
  142. package/dist/cjs/tests/unit/openai-cua-client.test.d.ts +1 -0
  143. package/dist/cjs/tests/unit/openai-cua-client.test.js +71 -0
  144. package/dist/cjs/tests/unit/openai-cua-client.test.js.map +1 -0
  145. package/dist/cjs/tests/unit/prompt-observe-variables.test.d.ts +1 -0
  146. package/dist/cjs/tests/unit/prompt-observe-variables.test.js +19 -0
  147. package/dist/cjs/tests/unit/prompt-observe-variables.test.js.map +1 -0
  148. package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js +1 -0
  149. package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
  150. package/dist/cjs/tests/unit/public-api/public-types.test.js.map +1 -1
  151. package/dist/cjs/tests/unit/timeout-handlers.test.js +50 -0
  152. package/dist/cjs/tests/unit/timeout-handlers.test.js.map +1 -1
  153. package/dist/esm/lib/inference.d.ts +3 -1
  154. package/dist/esm/lib/inference.js +3 -3
  155. package/dist/esm/lib/inference.js.map +1 -1
  156. package/dist/esm/lib/prompt.d.ts +1 -1
  157. package/dist/esm/lib/prompt.js +24 -18
  158. package/dist/esm/lib/prompt.js.map +1 -1
  159. package/dist/esm/lib/v3/agent/AgentClient.d.ts +8 -0
  160. package/dist/esm/lib/v3/agent/AgentClient.js +13 -0
  161. package/dist/esm/lib/v3/agent/AgentClient.js.map +1 -1
  162. package/dist/esm/lib/v3/agent/AgentProvider.js +1 -0
  163. package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
  164. package/dist/esm/lib/v3/agent/AnthropicCUAClient.d.ts +3 -1
  165. package/dist/esm/lib/v3/agent/AnthropicCUAClient.js +61 -9
  166. package/dist/esm/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
  167. package/dist/esm/lib/v3/agent/GoogleCUAClient.js +1 -0
  168. package/dist/esm/lib/v3/agent/GoogleCUAClient.js.map +1 -1
  169. package/dist/esm/lib/v3/agent/MicrosoftCUAClient.js +16 -0
  170. package/dist/esm/lib/v3/agent/MicrosoftCUAClient.js.map +1 -1
  171. package/dist/esm/lib/v3/agent/OpenAICUAClient.d.ts +12 -6
  172. package/dist/esm/lib/v3/agent/OpenAICUAClient.js +164 -49
  173. package/dist/esm/lib/v3/agent/OpenAICUAClient.js.map +1 -1
  174. package/dist/esm/lib/v3/agent/prompts/agentSystemPrompt.d.ts +2 -2
  175. package/dist/esm/lib/v3/agent/prompts/agentSystemPrompt.js +10 -11
  176. package/dist/esm/lib/v3/agent/prompts/agentSystemPrompt.js.map +1 -1
  177. package/dist/esm/lib/v3/agent/tools/fillform.d.ts +0 -1
  178. package/dist/esm/lib/v3/agent/tools/fillform.js +7 -10
  179. package/dist/esm/lib/v3/agent/tools/fillform.js.map +1 -1
  180. package/dist/esm/lib/v3/agent/tools/index.js +1 -1
  181. package/dist/esm/lib/v3/agent/tools/index.js.map +1 -1
  182. package/dist/esm/lib/v3/agent/tools/keys.d.ts +2 -1
  183. package/dist/esm/lib/v3/agent/tools/keys.js +57 -49
  184. package/dist/esm/lib/v3/agent/tools/keys.js.map +1 -1
  185. package/dist/esm/lib/v3/agent/utils/captchaSolver.d.ts +76 -0
  186. package/dist/esm/lib/v3/agent/utils/captchaSolver.js +171 -0
  187. package/dist/esm/lib/v3/agent/utils/captchaSolver.js.map +1 -0
  188. package/dist/esm/lib/v3/agent/utils/coordinateNormalization.js +3 -5
  189. package/dist/esm/lib/v3/agent/utils/coordinateNormalization.js.map +1 -1
  190. package/dist/esm/lib/v3/agent/utils/variables.d.ts +5 -0
  191. package/dist/esm/lib/v3/agent/utils/variables.js +8 -0
  192. package/dist/esm/lib/v3/agent/utils/variables.js.map +1 -1
  193. package/dist/esm/lib/v3/api.d.ts +5 -3
  194. package/dist/esm/lib/v3/api.js +5 -15
  195. package/dist/esm/lib/v3/api.js.map +1 -1
  196. package/dist/esm/lib/v3/cache/AgentCache.js +5 -3
  197. package/dist/esm/lib/v3/cache/AgentCache.js.map +1 -1
  198. package/dist/esm/lib/v3/flowlogger/EventStore.js +1 -1
  199. package/dist/esm/lib/v3/flowlogger/EventStore.js.map +1 -1
  200. package/dist/esm/lib/v3/handlers/observeHandler.js +2 -1
  201. package/dist/esm/lib/v3/handlers/observeHandler.js.map +1 -1
  202. package/dist/esm/lib/v3/handlers/v3AgentHandler.d.ts +2 -1
  203. package/dist/esm/lib/v3/handlers/v3AgentHandler.js +110 -46
  204. package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  205. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.d.ts +5 -0
  206. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js +131 -16
  207. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  208. package/dist/esm/lib/v3/index.d.ts +1 -1
  209. package/dist/esm/lib/v3/llm/LLMProvider.d.ts +5 -2
  210. package/dist/esm/lib/v3/llm/LLMProvider.js +15 -7
  211. package/dist/esm/lib/v3/llm/LLMProvider.js.map +1 -1
  212. package/dist/esm/lib/v3/llm/OpenAIClient.js +1 -0
  213. package/dist/esm/lib/v3/llm/OpenAIClient.js.map +1 -1
  214. package/dist/esm/lib/v3/llm/aisdk.d.ts +3 -1
  215. package/dist/esm/lib/v3/llm/aisdk.js +67 -17
  216. package/dist/esm/lib/v3/llm/aisdk.js.map +1 -1
  217. package/dist/esm/lib/v3/types/private/cache.d.ts +0 -1
  218. package/dist/esm/lib/v3/types/private/cache.js.map +1 -1
  219. package/dist/esm/lib/v3/types/private/handlers.d.ts +1 -0
  220. package/dist/esm/lib/v3/types/private/handlers.js.map +1 -1
  221. package/dist/esm/lib/v3/types/public/agent.d.ts +8 -3
  222. package/dist/esm/lib/v3/types/public/agent.js +1 -0
  223. package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
  224. package/dist/esm/lib/v3/types/public/api.d.ts +54 -7
  225. package/dist/esm/lib/v3/types/public/api.js +42 -14
  226. package/dist/esm/lib/v3/types/public/api.js.map +1 -1
  227. package/dist/esm/lib/v3/types/public/methods.d.ts +1 -0
  228. package/dist/esm/lib/v3/types/public/methods.js.map +1 -1
  229. package/dist/esm/lib/v3/types/public/model.d.ts +32 -2
  230. package/dist/esm/lib/v3/types/public/model.js.map +1 -1
  231. package/dist/esm/lib/v3/types/public/variables.d.ts +7 -0
  232. package/dist/esm/lib/v3/types/public/variables.js +19 -0
  233. package/dist/esm/lib/v3/types/public/variables.js.map +1 -0
  234. package/dist/esm/lib/v3/understudy/context.js +11 -3
  235. package/dist/esm/lib/v3/understudy/context.js.map +1 -1
  236. package/dist/esm/lib/v3/understudy/page.js +1 -1
  237. package/dist/esm/lib/v3/understudy/page.js.map +1 -1
  238. package/dist/esm/lib/v3/v3.d.ts +23 -2
  239. package/dist/esm/lib/v3/v3.js +111 -14
  240. package/dist/esm/lib/v3/v3.js.map +1 -1
  241. package/dist/esm/lib/version.d.ts +1 -1
  242. package/dist/esm/lib/version.js +1 -1
  243. package/dist/esm/lib/version.js.map +1 -1
  244. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.d.ts +1 -0
  245. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js +54 -0
  246. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js.map +1 -0
  247. package/dist/esm/tests/integration/agent-hybrid-mode.spec.js +6 -6
  248. package/dist/esm/tests/integration/agent-hybrid-mode.spec.js.map +1 -1
  249. package/dist/esm/tests/integration/chrome-newtab-page-tracking.spec.d.ts +1 -0
  250. package/dist/esm/tests/integration/chrome-newtab-page-tracking.spec.js +54 -0
  251. package/dist/esm/tests/integration/chrome-newtab-page-tracking.spec.js.map +1 -0
  252. package/dist/esm/tests/integration/timeouts.spec.js +1 -1
  253. package/dist/esm/tests/integration/timeouts.spec.js.map +1 -1
  254. package/dist/esm/tests/unit/agent-captcha-hooks.test.d.ts +1 -0
  255. package/dist/esm/tests/unit/agent-captcha-hooks.test.js +339 -0
  256. package/dist/esm/tests/unit/agent-captcha-hooks.test.js.map +1 -0
  257. package/dist/esm/tests/unit/agent-execution-model.test.js +25 -3
  258. package/dist/esm/tests/unit/agent-execution-model.test.js.map +1 -1
  259. package/dist/esm/tests/unit/agent-metrics.test.d.ts +1 -0
  260. package/dist/esm/tests/unit/agent-metrics.test.js +110 -0
  261. package/dist/esm/tests/unit/agent-metrics.test.js.map +1 -0
  262. package/dist/esm/tests/unit/agent-system-prompt-variables.test.d.ts +1 -0
  263. package/dist/esm/tests/unit/agent-system-prompt-variables.test.js +21 -0
  264. package/dist/esm/tests/unit/agent-system-prompt-variables.test.js.map +1 -0
  265. package/dist/esm/tests/unit/aisdk-clients.test.d.ts +1 -0
  266. package/dist/esm/tests/unit/aisdk-clients.test.js +88 -0
  267. package/dist/esm/tests/unit/aisdk-clients.test.js.map +1 -0
  268. package/dist/esm/tests/unit/anthropic-cua-adaptive-thinking.test.d.ts +1 -0
  269. package/dist/esm/tests/unit/anthropic-cua-adaptive-thinking.test.js +245 -0
  270. package/dist/esm/tests/unit/anthropic-cua-adaptive-thinking.test.js.map +1 -0
  271. package/dist/esm/tests/unit/api-client-observe-variables.test.d.ts +1 -0
  272. package/dist/esm/tests/unit/api-client-observe-variables.test.js +84 -0
  273. package/dist/esm/tests/unit/api-client-observe-variables.test.js.map +1 -0
  274. package/dist/esm/tests/unit/api-optional-model-api-key.test.d.ts +1 -0
  275. package/dist/esm/tests/unit/api-optional-model-api-key.test.js +93 -0
  276. package/dist/esm/tests/unit/api-optional-model-api-key.test.js.map +1 -0
  277. package/dist/esm/tests/unit/api-variables-schema.test.d.ts +1 -0
  278. package/dist/esm/tests/unit/api-variables-schema.test.js +35 -0
  279. package/dist/esm/tests/unit/api-variables-schema.test.js.map +1 -0
  280. package/dist/esm/tests/unit/browserbase-session-accessors.test.js +40 -0
  281. package/dist/esm/tests/unit/browserbase-session-accessors.test.js.map +1 -1
  282. package/dist/esm/tests/unit/captcha-solver.test.d.ts +1 -0
  283. package/dist/esm/tests/unit/captcha-solver.test.js +152 -0
  284. package/dist/esm/tests/unit/captcha-solver.test.js.map +1 -0
  285. package/dist/esm/tests/unit/flowlogger-eventstore.test.js +1 -1
  286. package/dist/esm/tests/unit/flowlogger-eventstore.test.js.map +1 -1
  287. package/dist/esm/tests/unit/llm-middleware.test.d.ts +1 -0
  288. package/dist/esm/tests/unit/llm-middleware.test.js +460 -0
  289. package/dist/esm/tests/unit/llm-middleware.test.js.map +1 -0
  290. package/dist/esm/tests/unit/microsoft-cua-client.test.d.ts +1 -0
  291. package/dist/esm/tests/unit/microsoft-cua-client.test.js +84 -0
  292. package/dist/esm/tests/unit/microsoft-cua-client.test.js.map +1 -0
  293. package/dist/esm/tests/unit/openai-cua-client.test.d.ts +1 -0
  294. package/dist/esm/tests/unit/openai-cua-client.test.js +69 -0
  295. package/dist/esm/tests/unit/openai-cua-client.test.js.map +1 -0
  296. package/dist/esm/tests/unit/prompt-observe-variables.test.d.ts +1 -0
  297. package/dist/esm/tests/unit/prompt-observe-variables.test.js +17 -0
  298. package/dist/esm/tests/unit/prompt-observe-variables.test.js.map +1 -0
  299. package/dist/esm/tests/unit/public-api/llm-and-agents.test.js +1 -0
  300. package/dist/esm/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
  301. package/dist/esm/tests/unit/public-api/public-types.test.js.map +1 -1
  302. package/dist/esm/tests/unit/timeout-handlers.test.js +50 -0
  303. package/dist/esm/tests/unit/timeout-handlers.test.js.map +1 -1
  304. package/package.json +5 -9
  305. package/dist/cjs/lib/v3/dom/build/rerender-index.js +0 -1
  306. package/dist/cjs/lib/v3/dom/build/v3-index.js +0 -1
  307. package/dist/esm/lib/v3/dom/build/rerender-index.js +0 -1
  308. package/dist/esm/lib/v3/dom/build/v3-index.js +0 -1
@@ -0,0 +1,21 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildAgentSystemPrompt } from "../../lib/v3/agent/prompts/agentSystemPrompt.js";
3
+ describe("buildAgentSystemPrompt variables", () => {
4
+ it("includes variable descriptions when present", () => {
5
+ const prompt = buildAgentSystemPrompt({
6
+ url: "https://example.com",
7
+ executionInstruction: "Fill the form",
8
+ mode: "dom",
9
+ variables: {
10
+ username: {
11
+ value: "john@example.com",
12
+ description: "The login email",
13
+ },
14
+ password: "secret123",
15
+ },
16
+ });
17
+ expect(prompt).toContain('<variable name="username">The login email</variable>');
18
+ expect(prompt).toContain('<variable name="password" />');
19
+ });
20
+ });
21
+ //# sourceMappingURL=agent-system-prompt-variables.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-system-prompt-variables.test.js","sourceRoot":"","sources":["../../../../tests/unit/agent-system-prompt-variables.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAC;AAEzF,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,sBAAsB,CAAC;YACpC,GAAG,EAAE,qBAAqB;YAC1B,oBAAoB,EAAE,eAAe;YACrC,IAAI,EAAE,KAAK;YACX,SAAS,EAAE;gBACT,QAAQ,EAAE;oBACR,KAAK,EAAE,kBAAkB;oBACzB,WAAW,EAAE,iBAAiB;iBAC/B;gBACD,QAAQ,EAAE,WAAW;aACtB;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CACtB,sDAAsD,CACvD,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { buildAgentSystemPrompt } from \"../../lib/v3/agent/prompts/agentSystemPrompt.js\";\n\ndescribe(\"buildAgentSystemPrompt variables\", () => {\n it(\"includes variable descriptions when present\", () => {\n const prompt = buildAgentSystemPrompt({\n url: \"https://example.com\",\n executionInstruction: \"Fill the form\",\n mode: \"dom\",\n variables: {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret123\",\n },\n });\n\n expect(prompt).toContain(\n '<variable name=\"username\">The login email</variable>',\n );\n expect(prompt).toContain('<variable name=\"password\" />');\n });\n});\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,88 @@
1
+ import { generateObject } from "ai";
2
+ import { z } from "zod";
3
+ import { beforeEach, describe, expect, it, vi } from "vitest";
4
+ import { AISdkClient } from "../../lib/v3/llm/aisdk.js";
5
+ vi.mock("ai", async () => {
6
+ const actual = await vi.importActual("ai");
7
+ return {
8
+ ...actual,
9
+ generateObject: vi.fn(),
10
+ };
11
+ });
12
+ const mockGenerateObject = vi.mocked(generateObject);
13
+ function createModel(modelId) {
14
+ return {
15
+ modelId,
16
+ specificationVersion: "v2",
17
+ };
18
+ }
19
+ describe("AISdkClient structured output provider options", () => {
20
+ beforeEach(() => {
21
+ mockGenerateObject.mockReset();
22
+ mockGenerateObject.mockResolvedValue({
23
+ object: { ok: true },
24
+ usage: {
25
+ inputTokens: 1,
26
+ outputTokens: 2,
27
+ reasoningTokens: 0,
28
+ cachedInputTokens: 0,
29
+ totalTokens: 3,
30
+ },
31
+ });
32
+ });
33
+ it.each([
34
+ ["openai/gpt-4.1", { openai: { strictJsonSchema: true } }],
35
+ ["azure/gpt-4.1", { azure: { strictJsonSchema: true } }],
36
+ ["google/gemini-2.5-pro", { google: { structuredOutputs: true } }],
37
+ ["vertex/gemini-2.5-pro", { vertex: { structuredOutputs: true } }],
38
+ [
39
+ "anthropic/claude-sonnet-4-20250514",
40
+ { anthropic: { structuredOutputMode: "auto" } },
41
+ ],
42
+ ["groq/llama-3.3-70b-versatile", { groq: { structuredOutputs: true } }],
43
+ ["cerebras/llama-4-scout", { cerebras: { strictJsonSchema: true } }],
44
+ [
45
+ "mistral/mistral-large-latest",
46
+ { mistral: { structuredOutputs: true, strictJsonSchema: true } },
47
+ ],
48
+ ])("passes provider structured-output options for %s", async (modelId, providerOptions) => {
49
+ const client = new AISdkClient({
50
+ model: createModel(modelId),
51
+ logger: vi.fn(),
52
+ });
53
+ await client.createChatCompletion({
54
+ options: {
55
+ messages: [{ role: "user", content: "hello" }],
56
+ response_model: {
57
+ name: "test",
58
+ schema: z.object({ ok: z.boolean() }),
59
+ },
60
+ },
61
+ logger: vi.fn(),
62
+ });
63
+ expect(mockGenerateObject).toHaveBeenCalledWith(expect.objectContaining({
64
+ providerOptions,
65
+ }));
66
+ });
67
+ it("omits temperature for claude-opus-4-7 structured calls", async () => {
68
+ const client = new AISdkClient({
69
+ model: createModel("anthropic/claude-opus-4-7"),
70
+ logger: vi.fn(),
71
+ });
72
+ await client.createChatCompletion({
73
+ options: {
74
+ messages: [{ role: "user", content: "hello" }],
75
+ response_model: {
76
+ name: "test",
77
+ schema: z.object({ ok: z.boolean() }),
78
+ },
79
+ temperature: 0.1,
80
+ },
81
+ logger: vi.fn(),
82
+ });
83
+ expect(mockGenerateObject).toHaveBeenCalledWith(expect.objectContaining({
84
+ temperature: undefined,
85
+ }));
86
+ });
87
+ });
88
+ //# sourceMappingURL=aisdk-clients.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aisdk-clients.test.js","sourceRoot":"","sources":["../../../../tests/unit/aisdk-clients.test.ts"],"names":[],"mappings":"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","sourcesContent":["import type { LanguageModelV2 } from \"@ai-sdk/provider\";\nimport { generateObject } from \"ai\";\nimport { z } from \"zod\";\nimport { beforeEach, describe, expect, it, vi } from \"vitest\";\nimport { AISdkClient } from \"../../lib/v3/llm/aisdk.js\";\n\nvi.mock(\"ai\", async () => {\n const actual = await vi.importActual<typeof import(\"ai\")>(\"ai\");\n return {\n ...actual,\n generateObject: vi.fn(),\n };\n});\n\nconst mockGenerateObject = vi.mocked(generateObject);\n\nfunction createModel(modelId: string) {\n return {\n modelId,\n specificationVersion: \"v2\",\n } as unknown as LanguageModelV2;\n}\n\ndescribe(\"AISdkClient structured output provider options\", () => {\n beforeEach(() => {\n mockGenerateObject.mockReset();\n mockGenerateObject.mockResolvedValue({\n object: { ok: true },\n usage: {\n inputTokens: 1,\n outputTokens: 2,\n reasoningTokens: 0,\n cachedInputTokens: 0,\n totalTokens: 3,\n },\n } as never);\n });\n\n it.each([\n [\"openai/gpt-4.1\", { openai: { strictJsonSchema: true } }],\n [\"azure/gpt-4.1\", { azure: { strictJsonSchema: true } }],\n [\"google/gemini-2.5-pro\", { google: { structuredOutputs: true } }],\n [\"vertex/gemini-2.5-pro\", { vertex: { structuredOutputs: true } }],\n [\n \"anthropic/claude-sonnet-4-20250514\",\n { anthropic: { structuredOutputMode: \"auto\" } },\n ],\n [\"groq/llama-3.3-70b-versatile\", { groq: { structuredOutputs: true } }],\n [\"cerebras/llama-4-scout\", { cerebras: { strictJsonSchema: true } }],\n [\n \"mistral/mistral-large-latest\",\n { mistral: { structuredOutputs: true, strictJsonSchema: true } },\n ],\n ])(\n \"passes provider structured-output options for %s\",\n async (modelId, providerOptions) => {\n const client = new AISdkClient({\n model: createModel(modelId),\n logger: vi.fn(),\n });\n\n await client.createChatCompletion({\n options: {\n messages: [{ role: \"user\", content: \"hello\" }],\n response_model: {\n name: \"test\",\n schema: z.object({ ok: z.boolean() }),\n },\n },\n logger: vi.fn(),\n });\n\n expect(mockGenerateObject).toHaveBeenCalledWith(\n expect.objectContaining({\n providerOptions,\n }),\n );\n },\n );\n\n it(\"omits temperature for claude-opus-4-7 structured calls\", async () => {\n const client = new AISdkClient({\n model: createModel(\"anthropic/claude-opus-4-7\"),\n logger: vi.fn(),\n });\n\n await client.createChatCompletion({\n options: {\n messages: [{ role: \"user\", content: \"hello\" }],\n response_model: {\n name: \"test\",\n schema: z.object({ ok: z.boolean() }),\n },\n temperature: 0.1,\n },\n logger: vi.fn(),\n });\n\n expect(mockGenerateObject).toHaveBeenCalledWith(\n expect.objectContaining({\n temperature: undefined,\n }),\n );\n });\n});\n"]}
@@ -0,0 +1,245 @@
1
+ import { describe, expect, it, vi, beforeEach } from "vitest";
2
+ import { AnthropicCUAClient } from "../../lib/v3/agent/AnthropicCUAClient.js";
3
+ import Anthropic from "@anthropic-ai/sdk";
4
+ // Mock the Anthropic SDK's beta.messages.create method
5
+ vi.mock("@anthropic-ai/sdk", () => {
6
+ const mockCreate = vi.fn().mockResolvedValue({
7
+ id: "test-id",
8
+ content: [{ type: "text", text: "test response" }],
9
+ usage: { input_tokens: 10, output_tokens: 20 },
10
+ });
11
+ return {
12
+ default: class MockAnthropic {
13
+ beta = {
14
+ messages: {
15
+ create: mockCreate,
16
+ },
17
+ };
18
+ },
19
+ };
20
+ });
21
+ describe("AnthropicCUAClient adaptive thinking", () => {
22
+ let mockCreate;
23
+ beforeEach(() => {
24
+ vi.clearAllMocks();
25
+ // Get the mock create function from a new instance
26
+ const anthropic = new Anthropic({ apiKey: "test" });
27
+ mockCreate = anthropic.beta.messages.create;
28
+ mockCreate.mockResolvedValue({
29
+ id: "test-id",
30
+ content: [{ type: "text", text: "test response" }],
31
+ usage: { input_tokens: 10, output_tokens: 20 },
32
+ });
33
+ });
34
+ describe("Claude 4.6 models (adaptive thinking)", () => {
35
+ it("should use thinking.type: 'adaptive' for claude-opus-4-6 when thinkingEffort is set", async () => {
36
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
37
+ apiKey: "test-key",
38
+ thinkingEffort: "high",
39
+ });
40
+ client.setViewport(1280, 720);
41
+ await client.getAction([{ role: "user", content: "test" }]);
42
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
43
+ thinking: { type: "adaptive" },
44
+ output_config: { effort: "high" },
45
+ temperature: 1,
46
+ }));
47
+ // Should NOT have budget_tokens
48
+ const callArgs = mockCreate.mock.calls[0][0];
49
+ expect(callArgs.thinking).not.toHaveProperty("budget_tokens");
50
+ });
51
+ it("should use thinking.type: 'adaptive' for claude-sonnet-4-6 when thinkingEffort is set", async () => {
52
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-6", undefined, {
53
+ apiKey: "test-key",
54
+ thinkingEffort: "medium",
55
+ });
56
+ client.setViewport(1280, 720);
57
+ await client.getAction([{ role: "user", content: "test" }]);
58
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
59
+ thinking: { type: "adaptive" },
60
+ output_config: { effort: "medium" },
61
+ temperature: 1,
62
+ }));
63
+ });
64
+ it("should support 'max' effort level for claude-opus-4-6", async () => {
65
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
66
+ apiKey: "test-key",
67
+ thinkingEffort: "max",
68
+ });
69
+ client.setViewport(1280, 720);
70
+ await client.getAction([{ role: "user", content: "test" }]);
71
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
72
+ thinking: { type: "adaptive" },
73
+ output_config: { effort: "max" },
74
+ temperature: 1,
75
+ }));
76
+ });
77
+ it("should support 'low' effort level", async () => {
78
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-6", undefined, {
79
+ apiKey: "test-key",
80
+ thinkingEffort: "low",
81
+ });
82
+ client.setViewport(1280, 720);
83
+ await client.getAction([{ role: "user", content: "test" }]);
84
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
85
+ thinking: { type: "adaptive" },
86
+ output_config: { effort: "low" },
87
+ temperature: 1,
88
+ }));
89
+ });
90
+ it("should default to adaptive thinking with 'medium' effort when thinkingEffort is not set for 4.6 models", async () => {
91
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
92
+ apiKey: "test-key",
93
+ });
94
+ client.setViewport(1280, 720);
95
+ await client.getAction([{ role: "user", content: "test" }]);
96
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
97
+ thinking: { type: "adaptive" },
98
+ output_config: { effort: "medium" },
99
+ temperature: 1,
100
+ }));
101
+ });
102
+ it("should set temperature to 1 when adaptive thinking is enabled", async () => {
103
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
104
+ apiKey: "test-key",
105
+ thinkingEffort: "high",
106
+ });
107
+ client.setViewport(1280, 720);
108
+ await client.getAction([{ role: "user", content: "test" }]);
109
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
110
+ temperature: 1,
111
+ }));
112
+ });
113
+ it("should set temperature to 1 for claude-sonnet-4-6 with adaptive thinking", async () => {
114
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-6", undefined, {
115
+ apiKey: "test-key",
116
+ thinkingEffort: "low",
117
+ });
118
+ client.setViewport(1280, 720);
119
+ await client.getAction([{ role: "user", content: "test" }]);
120
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
121
+ thinking: { type: "adaptive" },
122
+ output_config: { effort: "low" },
123
+ temperature: 1,
124
+ }));
125
+ });
126
+ it("should disable adaptive thinking when thinkingEffort is 'none'", async () => {
127
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
128
+ apiKey: "test-key",
129
+ thinkingEffort: "none",
130
+ });
131
+ client.setViewport(1280, 720);
132
+ await client.getAction([{ role: "user", content: "test" }]);
133
+ const callArgs = mockCreate.mock.calls[0][0];
134
+ expect(callArgs.thinking).toBeUndefined();
135
+ expect(callArgs.output_config).toBeUndefined();
136
+ expect(callArgs.temperature).toBeUndefined();
137
+ });
138
+ it("should log a debug warning when thinkingBudget is set on a 4.6 model", async () => {
139
+ const logger = vi.fn();
140
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
141
+ apiKey: "test-key",
142
+ thinkingBudget: 10000,
143
+ });
144
+ client.setViewport(1280, 720);
145
+ await client.getAction([{ role: "user", content: "test" }], logger);
146
+ expect(logger).toHaveBeenCalledWith(expect.objectContaining({
147
+ category: "agent",
148
+ message: expect.stringContaining("thinkingBudget is ignored"),
149
+ level: 2,
150
+ }));
151
+ // Should still use adaptive thinking, not budget_tokens
152
+ const callArgs = mockCreate.mock.calls[0][0];
153
+ expect(callArgs.thinking).toEqual({ type: "adaptive" });
154
+ });
155
+ it("should log a debug warning when user-specified temperature is overridden", async () => {
156
+ const logger = vi.fn();
157
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
158
+ apiKey: "test-key",
159
+ thinkingEffort: "high",
160
+ temperature: 0.5,
161
+ });
162
+ client.setViewport(1280, 720);
163
+ await client.getAction([{ role: "user", content: "test" }], logger);
164
+ expect(logger).toHaveBeenCalledWith(expect.objectContaining({
165
+ category: "agent",
166
+ message: expect.stringContaining("overriding user-specified temperature=0.5"),
167
+ level: 2,
168
+ }));
169
+ // Temperature should still be forced to 1
170
+ const callArgs = mockCreate.mock.calls[0][0];
171
+ expect(callArgs.temperature).toBe(1);
172
+ });
173
+ });
174
+ describe("older Claude models (budget_tokens - deprecated)", () => {
175
+ it("should use thinking.type: 'enabled' with budget_tokens for claude-sonnet-4-5 when thinkingBudget is set", async () => {
176
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-5-20250929", undefined, {
177
+ apiKey: "test-key",
178
+ thinkingBudget: 8000,
179
+ });
180
+ client.setViewport(1280, 720);
181
+ await client.getAction([{ role: "user", content: "test" }]);
182
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
183
+ thinking: { type: "enabled", budget_tokens: 8000 },
184
+ }));
185
+ // Should NOT have output_config for older models
186
+ const callArgs = mockCreate.mock.calls[0][0];
187
+ expect(callArgs.output_config).toBeUndefined();
188
+ });
189
+ it("should use thinking.type: 'enabled' with budget_tokens for claude-opus-4-5 when thinkingBudget is set", async () => {
190
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-5-20251101", undefined, {
191
+ apiKey: "test-key",
192
+ thinkingBudget: 10000,
193
+ });
194
+ client.setViewport(1280, 720);
195
+ await client.getAction([{ role: "user", content: "test" }]);
196
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
197
+ thinking: { type: "enabled", budget_tokens: 10000 },
198
+ }));
199
+ });
200
+ it("should NOT force temperature to 1 for older models with budget_tokens", async () => {
201
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-5-20250929", undefined, {
202
+ apiKey: "test-key",
203
+ thinkingBudget: 8000,
204
+ });
205
+ client.setViewport(1280, 720);
206
+ await client.getAction([{ role: "user", content: "test" }]);
207
+ const callArgs = mockCreate.mock.calls[0][0];
208
+ // Temperature should not be explicitly set to 1 for older models
209
+ expect(callArgs.temperature).toBeUndefined();
210
+ });
211
+ });
212
+ describe("model detection", () => {
213
+ it("should detect claude-opus-4-6 as a 4.6 model", async () => {
214
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
215
+ apiKey: "test-key",
216
+ thinkingEffort: "high",
217
+ });
218
+ client.setViewport(1280, 720);
219
+ await client.getAction([{ role: "user", content: "test" }]);
220
+ const callArgs = mockCreate.mock.calls[0][0];
221
+ expect(callArgs.thinking.type).toBe("adaptive");
222
+ });
223
+ it("should detect claude-sonnet-4-6 as a 4.6 model", async () => {
224
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-6", undefined, {
225
+ apiKey: "test-key",
226
+ thinkingEffort: "high",
227
+ });
228
+ client.setViewport(1280, 720);
229
+ await client.getAction([{ role: "user", content: "test" }]);
230
+ const callArgs = mockCreate.mock.calls[0][0];
231
+ expect(callArgs.thinking.type).toBe("adaptive");
232
+ });
233
+ it("should handle provider-prefixed model names (anthropic/claude-opus-4-6)", async () => {
234
+ const client = new AnthropicCUAClient("anthropic", "anthropic/claude-opus-4-6", undefined, {
235
+ apiKey: "test-key",
236
+ thinkingEffort: "high",
237
+ });
238
+ client.setViewport(1280, 720);
239
+ await client.getAction([{ role: "user", content: "test" }]);
240
+ const callArgs = mockCreate.mock.calls[0][0];
241
+ expect(callArgs.thinking.type).toBe("adaptive");
242
+ });
243
+ });
244
+ });
245
+ //# sourceMappingURL=anthropic-cua-adaptive-thinking.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-cua-adaptive-thinking.test.js","sourceRoot":"","sources":["../../../../tests/unit/anthropic-cua-adaptive-thinking.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi, beforeEach } from \"vitest\";\nimport { AnthropicCUAClient } from \"../../lib/v3/agent/AnthropicCUAClient.js\";\nimport Anthropic from \"@anthropic-ai/sdk\";\n\n// Mock the Anthropic SDK's beta.messages.create method\nvi.mock(\"@anthropic-ai/sdk\", () => {\n const mockCreate = vi.fn().mockResolvedValue({\n id: \"test-id\",\n content: [{ type: \"text\", text: \"test response\" }],\n usage: { input_tokens: 10, output_tokens: 20 },\n });\n\n return {\n default: class MockAnthropic {\n beta = {\n messages: {\n create: mockCreate,\n },\n };\n },\n };\n});\n\ndescribe(\"AnthropicCUAClient adaptive thinking\", () => {\n let mockCreate: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n vi.clearAllMocks();\n // Get the mock create function from a new instance\n const anthropic = new Anthropic({ apiKey: \"test\" });\n mockCreate = anthropic.beta.messages.create as ReturnType<typeof vi.fn>;\n mockCreate.mockResolvedValue({\n id: \"test-id\",\n content: [{ type: \"text\", text: \"test response\" }],\n usage: { input_tokens: 10, output_tokens: 20 },\n });\n });\n\n describe(\"Claude 4.6 models (adaptive thinking)\", () => {\n it(\"should use thinking.type: 'adaptive' for claude-opus-4-6 when thinkingEffort is set\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"high\" },\n temperature: 1,\n }),\n );\n\n // Should NOT have budget_tokens\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking).not.toHaveProperty(\"budget_tokens\");\n });\n\n it(\"should use thinking.type: 'adaptive' for claude-sonnet-4-6 when thinkingEffort is set\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"medium\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"medium\" },\n temperature: 1,\n }),\n );\n });\n\n it(\"should support 'max' effort level for claude-opus-4-6\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"max\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"max\" },\n temperature: 1,\n }),\n );\n });\n\n it(\"should support 'low' effort level\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"low\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"low\" },\n temperature: 1,\n }),\n );\n });\n\n it(\"should default to adaptive thinking with 'medium' effort when thinkingEffort is not set for 4.6 models\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"medium\" },\n temperature: 1,\n }),\n );\n });\n\n it(\"should set temperature to 1 when adaptive thinking is enabled\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n temperature: 1,\n }),\n );\n });\n\n it(\"should set temperature to 1 for claude-sonnet-4-6 with adaptive thinking\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"low\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"low\" },\n temperature: 1,\n }),\n );\n });\n\n it(\"should disable adaptive thinking when thinkingEffort is 'none'\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"none\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking).toBeUndefined();\n expect(callArgs.output_config).toBeUndefined();\n expect(callArgs.temperature).toBeUndefined();\n });\n\n it(\"should log a debug warning when thinkingBudget is set on a 4.6 model\", async () => {\n const logger = vi.fn();\n\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingBudget: 10000,\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }], logger);\n\n expect(logger).toHaveBeenCalledWith(\n expect.objectContaining({\n category: \"agent\",\n message: expect.stringContaining(\"thinkingBudget is ignored\"),\n level: 2,\n }),\n );\n\n // Should still use adaptive thinking, not budget_tokens\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking).toEqual({ type: \"adaptive\" });\n });\n\n it(\"should log a debug warning when user-specified temperature is overridden\", async () => {\n const logger = vi.fn();\n\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n temperature: 0.5,\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }], logger);\n\n expect(logger).toHaveBeenCalledWith(\n expect.objectContaining({\n category: \"agent\",\n message: expect.stringContaining(\n \"overriding user-specified temperature=0.5\",\n ),\n level: 2,\n }),\n );\n\n // Temperature should still be forced to 1\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.temperature).toBe(1);\n });\n });\n\n describe(\"older Claude models (budget_tokens - deprecated)\", () => {\n it(\"should use thinking.type: 'enabled' with budget_tokens for claude-sonnet-4-5 when thinkingBudget is set\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-5-20250929\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingBudget: 8000,\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"enabled\", budget_tokens: 8000 },\n }),\n );\n\n // Should NOT have output_config for older models\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.output_config).toBeUndefined();\n });\n\n it(\"should use thinking.type: 'enabled' with budget_tokens for claude-opus-4-5 when thinkingBudget is set\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-5-20251101\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingBudget: 10000,\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"enabled\", budget_tokens: 10000 },\n }),\n );\n });\n\n it(\"should NOT force temperature to 1 for older models with budget_tokens\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-5-20250929\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingBudget: 8000,\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n const callArgs = mockCreate.mock.calls[0][0];\n // Temperature should not be explicitly set to 1 for older models\n expect(callArgs.temperature).toBeUndefined();\n });\n });\n\n describe(\"model detection\", () => {\n it(\"should detect claude-opus-4-6 as a 4.6 model\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking.type).toBe(\"adaptive\");\n });\n\n it(\"should detect claude-sonnet-4-6 as a 4.6 model\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking.type).toBe(\"adaptive\");\n });\n\n it(\"should handle provider-prefixed model names (anthropic/claude-opus-4-6)\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"anthropic/claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking.type).toBe(\"adaptive\");\n });\n });\n});\n"]}
@@ -0,0 +1,84 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { StagehandAPIClient } from "../../lib/v3/api.js";
3
+ describe("StagehandAPIClient variable serialization", () => {
4
+ it("preserves rich variables when sending the act request", async () => {
5
+ const client = new StagehandAPIClient({
6
+ apiKey: "bb-test",
7
+ logger: vi.fn(),
8
+ });
9
+ const executeMock = vi.fn().mockResolvedValue({
10
+ success: true,
11
+ message: "ok",
12
+ actionDescription: "typed",
13
+ actions: [],
14
+ });
15
+ client.execute = executeMock;
16
+ await client.act({
17
+ input: "type %username% into the email field",
18
+ options: {
19
+ variables: {
20
+ username: {
21
+ value: "john@example.com",
22
+ description: "The login email",
23
+ },
24
+ password: "secret",
25
+ },
26
+ },
27
+ });
28
+ expect(executeMock).toHaveBeenCalledWith({
29
+ method: "act",
30
+ args: {
31
+ input: "type %username% into the email field",
32
+ options: {
33
+ variables: {
34
+ username: {
35
+ value: "john@example.com",
36
+ description: "The login email",
37
+ },
38
+ password: "secret",
39
+ },
40
+ },
41
+ frameId: undefined,
42
+ },
43
+ serverCache: undefined,
44
+ });
45
+ });
46
+ it("preserves rich variables when sending the observe request", async () => {
47
+ const client = new StagehandAPIClient({
48
+ apiKey: "bb-test",
49
+ logger: vi.fn(),
50
+ });
51
+ const executeMock = vi.fn().mockResolvedValue([]);
52
+ client.execute = executeMock;
53
+ await client.observe({
54
+ instruction: "find the field where %username% should be entered",
55
+ options: {
56
+ variables: {
57
+ username: {
58
+ value: "john@example.com",
59
+ description: "The login email",
60
+ },
61
+ password: "secret",
62
+ },
63
+ },
64
+ });
65
+ expect(executeMock).toHaveBeenCalledWith({
66
+ method: "observe",
67
+ args: {
68
+ instruction: "find the field where %username% should be entered",
69
+ options: {
70
+ variables: {
71
+ username: {
72
+ value: "john@example.com",
73
+ description: "The login email",
74
+ },
75
+ password: "secret",
76
+ },
77
+ },
78
+ frameId: undefined,
79
+ },
80
+ serverCache: undefined,
81
+ });
82
+ });
83
+ });
84
+ //# sourceMappingURL=api-client-observe-variables.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client-observe-variables.test.js","sourceRoot":"","sources":["../../../../tests/unit/api-client-observe-variables.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,QAAQ,CAAC,2CAA2C,EAAE,GAAG,EAAE;IACzD,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC;YACpC,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE;SAChB,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;YAC5C,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,IAAI;YACb,iBAAiB,EAAE,OAAO;YAC1B,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;QAGD,MAGD,CAAC,OAAO,GAAG,WAAW,CAAC;QAExB,MAAM,MAAM,CAAC,GAAG,CAAC;YACf,KAAK,EAAE,sCAAsC;YAC7C,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,QAAQ,EAAE,QAAQ;iBACnB;aACF;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,CAAC,oBAAoB,CAAC;YACvC,MAAM,EAAE,KAAK;YACb,IAAI,EAAE;gBACJ,KAAK,EAAE,sCAAsC;gBAC7C,OAAO,EAAE;oBACP,SAAS,EAAE;wBACT,QAAQ,EAAE;4BACR,KAAK,EAAE,kBAAkB;4BACzB,WAAW,EAAE,iBAAiB;yBAC/B;wBACD,QAAQ,EAAE,QAAQ;qBACnB;iBACF;gBACD,OAAO,EAAE,SAAS;aACnB;YACD,WAAW,EAAE,SAAS;SACvB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC;YACpC,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE;SAChB,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC,CAAC;QAGhD,MAGD,CAAC,OAAO,GAAG,WAAW,CAAC;QAExB,MAAM,MAAM,CAAC,OAAO,CAAC;YACnB,WAAW,EAAE,mDAAmD;YAChE,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,QAAQ,EAAE,QAAQ;iBACnB;aACF;SACF,CAAC,CAAC;QAEH,MAAM,CAAC,WAAW,CAAC,CAAC,oBAAoB,CAAC;YACvC,MAAM,EAAE,SAAS;YACjB,IAAI,EAAE;gBACJ,WAAW,EAAE,mDAAmD;gBAChE,OAAO,EAAE;oBACP,SAAS,EAAE;wBACT,QAAQ,EAAE;4BACR,KAAK,EAAE,kBAAkB;4BACzB,WAAW,EAAE,iBAAiB;yBAC/B;wBACD,QAAQ,EAAE,QAAQ;qBACnB;iBACF;gBACD,OAAO,EAAE,SAAS;aACnB;YACD,WAAW,EAAE,SAAS;SACvB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\nimport { StagehandAPIClient } from \"../../lib/v3/api.js\";\n\ndescribe(\"StagehandAPIClient variable serialization\", () => {\n it(\"preserves rich variables when sending the act request\", async () => {\n const client = new StagehandAPIClient({\n apiKey: \"bb-test\",\n logger: vi.fn(),\n });\n const executeMock = vi.fn().mockResolvedValue({\n success: true,\n message: \"ok\",\n actionDescription: \"typed\",\n actions: [],\n });\n\n (\n client as unknown as {\n execute: typeof executeMock;\n }\n ).execute = executeMock;\n\n await client.act({\n input: \"type %username% into the email field\",\n options: {\n variables: {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret\",\n },\n },\n });\n\n expect(executeMock).toHaveBeenCalledWith({\n method: \"act\",\n args: {\n input: \"type %username% into the email field\",\n options: {\n variables: {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret\",\n },\n },\n frameId: undefined,\n },\n serverCache: undefined,\n });\n });\n\n it(\"preserves rich variables when sending the observe request\", async () => {\n const client = new StagehandAPIClient({\n apiKey: \"bb-test\",\n logger: vi.fn(),\n });\n const executeMock = vi.fn().mockResolvedValue([]);\n\n (\n client as unknown as {\n execute: typeof executeMock;\n }\n ).execute = executeMock;\n\n await client.observe({\n instruction: \"find the field where %username% should be entered\",\n options: {\n variables: {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret\",\n },\n },\n });\n\n expect(executeMock).toHaveBeenCalledWith({\n method: \"observe\",\n args: {\n instruction: \"find the field where %username% should be entered\",\n options: {\n variables: {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret\",\n },\n },\n frameId: undefined,\n },\n serverCache: undefined,\n });\n });\n});\n"]}
@@ -0,0 +1,93 @@
1
+ import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
2
+ import { StagehandAPIClient } from "../../lib/v3/api";
3
+ /**
4
+ * Tests that modelApiKey is optional when calling StagehandAPIClient.init().
5
+ *
6
+ * Previously, init() would throw "modelApiKey is required" if the key was not
7
+ * provided. After the fix, sessions can be started without a model API key
8
+ * (the server may provide its own key or the user may not need one).
9
+ * When provided, the key should still be sent via the x-model-api-key header.
10
+ */
11
+ describe("StagehandAPIClient - optional modelApiKey", () => {
12
+ const logger = vi.fn();
13
+ // We mock fetch to avoid real network calls; we just need to verify
14
+ // that init() doesn't throw when modelApiKey is omitted and that
15
+ // the header is conditionally included.
16
+ let originalFetch;
17
+ function createSessionStartResponse(sessionId) {
18
+ return new Response(JSON.stringify({
19
+ success: true,
20
+ data: { sessionId, available: true },
21
+ }), {
22
+ status: 200,
23
+ headers: { "Content-Type": "application/json" },
24
+ });
25
+ }
26
+ beforeEach(() => {
27
+ originalFetch = globalThis.fetch;
28
+ });
29
+ afterEach(() => {
30
+ globalThis.fetch = originalFetch;
31
+ vi.restoreAllMocks();
32
+ });
33
+ it("should NOT throw when modelApiKey is omitted", async () => {
34
+ globalThis.fetch = vi
35
+ .fn()
36
+ .mockResolvedValue(createSessionStartResponse("sess-123"));
37
+ const client = new StagehandAPIClient({
38
+ apiKey: "test-api-key",
39
+ logger,
40
+ });
41
+ // Should not throw "modelApiKey is required"
42
+ await expect(client.init({
43
+ modelName: "openai/gpt-4.1-mini",
44
+ })).resolves.toBeDefined();
45
+ });
46
+ it("should NOT throw when modelApiKey is undefined", async () => {
47
+ globalThis.fetch = vi
48
+ .fn()
49
+ .mockResolvedValue(createSessionStartResponse("sess-456"));
50
+ const client = new StagehandAPIClient({
51
+ apiKey: "test-api-key",
52
+ logger,
53
+ });
54
+ await expect(client.init({
55
+ modelName: "openai/gpt-4.1-mini",
56
+ modelApiKey: undefined,
57
+ })).resolves.toBeDefined();
58
+ });
59
+ it("should send x-model-api-key header when modelApiKey IS provided", async () => {
60
+ const fetchSpy = vi
61
+ .fn()
62
+ .mockResolvedValue(createSessionStartResponse("sess-789"));
63
+ globalThis.fetch = fetchSpy;
64
+ const client = new StagehandAPIClient({
65
+ apiKey: "test-api-key",
66
+ logger,
67
+ });
68
+ await client.init({
69
+ modelName: "openai/gpt-4.1-mini",
70
+ modelApiKey: "my-model-key",
71
+ });
72
+ // Verify the fetch was called with x-model-api-key header
73
+ const [, requestInit] = fetchSpy.mock.calls[0];
74
+ expect(requestInit.headers["x-model-api-key"]).toBe("my-model-key");
75
+ });
76
+ it("should NOT send x-model-api-key header when modelApiKey is omitted", async () => {
77
+ const fetchSpy = vi
78
+ .fn()
79
+ .mockResolvedValue(createSessionStartResponse("sess-012"));
80
+ globalThis.fetch = fetchSpy;
81
+ const client = new StagehandAPIClient({
82
+ apiKey: "test-api-key",
83
+ logger,
84
+ });
85
+ await client.init({
86
+ modelName: "openai/gpt-4.1-mini",
87
+ });
88
+ // Verify x-model-api-key header is NOT present
89
+ const [, requestInit] = fetchSpy.mock.calls[0];
90
+ expect(requestInit.headers["x-model-api-key"]).toBeUndefined();
91
+ });
92
+ });
93
+ //# sourceMappingURL=api-optional-model-api-key.test.js.map