@browserbasehq/orca 3.5.1-preview.0 → 3.7.0-preview.1

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 (242) hide show
  1. package/README.md +0 -12
  2. package/dist/cjs/lib/utils.d.ts +6 -0
  3. package/dist/cjs/lib/utils.js +11 -0
  4. package/dist/cjs/lib/utils.js.map +1 -1
  5. package/dist/cjs/lib/v3/agent/AgentClient.d.ts +2 -2
  6. package/dist/cjs/lib/v3/agent/AgentClient.js.map +1 -1
  7. package/dist/cjs/lib/v3/agent/AgentProvider.js +4 -3
  8. package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
  9. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.d.ts +4 -3
  10. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js +21 -18
  11. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
  12. package/dist/cjs/lib/v3/agent/GoogleCUAClient.d.ts +12 -3
  13. package/dist/cjs/lib/v3/agent/GoogleCUAClient.js +217 -36
  14. package/dist/cjs/lib/v3/agent/GoogleCUAClient.js.map +1 -1
  15. package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.d.ts +2 -2
  16. package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.js +2 -2
  17. package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.js.map +1 -1
  18. package/dist/cjs/lib/v3/agent/OpenAICUAClient.d.ts +6 -3
  19. package/dist/cjs/lib/v3/agent/OpenAICUAClient.js +13 -7
  20. package/dist/cjs/lib/v3/agent/OpenAICUAClient.js.map +1 -1
  21. package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.d.ts +1 -0
  22. package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.js +50 -3
  23. package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.js.map +1 -1
  24. package/dist/cjs/lib/v3/cache/ActCache.js +1 -1
  25. package/dist/cjs/lib/v3/cache/ActCache.js.map +1 -1
  26. package/dist/cjs/lib/v3/cache/utils.d.ts +7 -0
  27. package/dist/cjs/lib/v3/cache/utils.js +19 -0
  28. package/dist/cjs/lib/v3/cache/utils.js.map +1 -1
  29. package/dist/cjs/lib/v3/handlers/v3AgentHandler.d.ts +2 -1
  30. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +55 -16
  31. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  32. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js +32 -18
  33. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  34. package/dist/cjs/lib/v3/index.d.ts +3 -2
  35. package/dist/cjs/lib/v3/index.js.map +1 -1
  36. package/dist/cjs/lib/v3/launch/local.js +1 -0
  37. package/dist/cjs/lib/v3/launch/local.js.map +1 -1
  38. package/dist/cjs/lib/v3/llm/LLMProvider.d.ts +2 -2
  39. package/dist/cjs/lib/v3/llm/LLMProvider.js +1 -0
  40. package/dist/cjs/lib/v3/llm/LLMProvider.js.map +1 -1
  41. package/dist/cjs/lib/v3/llm/aisdk.js +4 -0
  42. package/dist/cjs/lib/v3/llm/aisdk.js.map +1 -1
  43. package/dist/cjs/lib/v3/llm/anthropicOptions.d.ts +57 -0
  44. package/dist/cjs/lib/v3/llm/anthropicOptions.js +115 -0
  45. package/dist/cjs/lib/v3/llm/anthropicOptions.js.map +1 -0
  46. package/dist/cjs/lib/v3/types/public/agent.d.ts +10 -1
  47. package/dist/cjs/lib/v3/types/public/agent.js +2 -0
  48. package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
  49. package/dist/cjs/lib/v3/types/public/context.d.ts +7 -0
  50. package/dist/cjs/lib/v3/types/public/context.js.map +1 -1
  51. package/dist/cjs/lib/v3/types/public/model.d.ts +3 -2
  52. package/dist/cjs/lib/v3/types/public/model.js.map +1 -1
  53. package/dist/cjs/lib/v3/types/public/sdkErrors.d.ts +4 -0
  54. package/dist/cjs/lib/v3/types/public/sdkErrors.js +9 -1
  55. package/dist/cjs/lib/v3/types/public/sdkErrors.js.map +1 -1
  56. package/dist/cjs/lib/v3/understudy/cdp.d.ts +2 -0
  57. package/dist/cjs/lib/v3/understudy/cdp.js +26 -12
  58. package/dist/cjs/lib/v3/understudy/cdp.js.map +1 -1
  59. package/dist/cjs/lib/v3/understudy/context.d.ts +13 -1
  60. package/dist/cjs/lib/v3/understudy/context.js +284 -1
  61. package/dist/cjs/lib/v3/understudy/context.js.map +1 -1
  62. package/dist/cjs/lib/v3/understudy/domainPolicy.d.ts +25 -0
  63. package/dist/cjs/lib/v3/understudy/domainPolicy.js +162 -0
  64. package/dist/cjs/lib/v3/understudy/domainPolicy.js.map +1 -0
  65. package/dist/cjs/lib/v3/understudy/page.js +1 -1
  66. package/dist/cjs/lib/v3/understudy/page.js.map +1 -1
  67. package/dist/cjs/lib/v3/v3.js +8 -2
  68. package/dist/cjs/lib/v3/v3.js.map +1 -1
  69. package/dist/cjs/lib/v3/verifier/errorTaxonomy.d.ts +35 -0
  70. package/dist/cjs/lib/v3/verifier/errorTaxonomy.js +291 -0
  71. package/dist/cjs/lib/v3/verifier/errorTaxonomy.js.map +1 -0
  72. package/dist/cjs/lib/v3/verifier/evidence.d.ts +44 -0
  73. package/dist/cjs/lib/v3/verifier/evidence.js +432 -0
  74. package/dist/cjs/lib/v3/verifier/evidence.js.map +1 -0
  75. package/dist/cjs/lib/v3/verifier/index.d.ts +1 -1
  76. package/dist/cjs/lib/v3/verifier/index.js.map +1 -1
  77. package/dist/cjs/lib/v3/verifier/prompts/batchedRelevance.d.ts +21 -0
  78. package/dist/cjs/lib/v3/verifier/prompts/batchedRelevance.js +71 -0
  79. package/dist/cjs/lib/v3/verifier/prompts/batchedRelevance.js.map +1 -0
  80. package/dist/cjs/lib/v3/verifier/prompts/firstPointOfFailure.d.ts +3 -0
  81. package/dist/cjs/lib/v3/verifier/prompts/firstPointOfFailure.js +166 -0
  82. package/dist/cjs/lib/v3/verifier/prompts/firstPointOfFailure.js.map +1 -0
  83. package/dist/cjs/lib/v3/verifier/prompts/fusedJudgment.d.ts +35 -0
  84. package/dist/cjs/lib/v3/verifier/prompts/fusedJudgment.js +158 -0
  85. package/dist/cjs/lib/v3/verifier/prompts/fusedJudgment.js.map +1 -0
  86. package/dist/cjs/lib/v3/verifier/prompts/fusedOutcome.d.ts +26 -0
  87. package/dist/cjs/lib/v3/verifier/prompts/fusedOutcome.js +137 -0
  88. package/dist/cjs/lib/v3/verifier/prompts/fusedOutcome.js.map +1 -0
  89. package/dist/cjs/lib/v3/verifier/prompts/index.d.ts +8 -0
  90. package/dist/cjs/lib/v3/verifier/prompts/index.js +22 -0
  91. package/dist/cjs/lib/v3/verifier/prompts/index.js.map +1 -0
  92. package/dist/cjs/lib/v3/verifier/prompts/perCriterionScore.d.ts +23 -0
  93. package/dist/cjs/lib/v3/verifier/prompts/perCriterionScore.js +77 -0
  94. package/dist/cjs/lib/v3/verifier/prompts/perCriterionScore.js.map +1 -0
  95. package/dist/cjs/lib/v3/verifier/prompts/render.d.ts +23 -0
  96. package/dist/cjs/lib/v3/verifier/prompts/render.js +45 -0
  97. package/dist/cjs/lib/v3/verifier/prompts/render.js.map +1 -0
  98. package/dist/cjs/lib/v3/verifier/prompts/rubricGeneration.d.ts +16 -0
  99. package/dist/cjs/lib/v3/verifier/prompts/rubricGeneration.js +321 -0
  100. package/dist/cjs/lib/v3/verifier/prompts/rubricGeneration.js.map +1 -0
  101. package/dist/cjs/lib/v3/verifier/prompts/taskValidity.d.ts +1 -0
  102. package/dist/cjs/lib/v3/verifier/prompts/taskValidity.js +116 -0
  103. package/dist/cjs/lib/v3/verifier/prompts/taskValidity.js.map +1 -0
  104. package/dist/cjs/lib/v3/verifier/rubricVerifier.d.ts +91 -0
  105. package/dist/cjs/lib/v3/verifier/rubricVerifier.js +1645 -0
  106. package/dist/cjs/lib/v3/verifier/rubricVerifier.js.map +1 -0
  107. package/dist/cjs/lib/v3/verifier/trajectory.d.ts +3 -3
  108. package/dist/cjs/lib/v3/verifier/trajectory.js +26 -26
  109. package/dist/cjs/lib/v3/verifier/trajectory.js.map +1 -1
  110. package/dist/cjs/lib/v3/verifier/types.d.ts +163 -15
  111. package/dist/cjs/lib/v3/verifier/types.js +0 -7
  112. package/dist/cjs/lib/v3/verifier/types.js.map +1 -1
  113. package/dist/cjs/lib/v3Evaluator.d.ts +5 -0
  114. package/dist/cjs/lib/v3Evaluator.js +47 -7
  115. package/dist/cjs/lib/v3Evaluator.js.map +1 -1
  116. package/dist/cjs/lib/version.d.ts +1 -1
  117. package/dist/cjs/lib/version.js +1 -1
  118. package/dist/cjs/lib/version.js.map +1 -1
  119. package/dist/esm/lib/utils.d.ts +6 -0
  120. package/dist/esm/lib/utils.js +10 -0
  121. package/dist/esm/lib/utils.js.map +1 -1
  122. package/dist/esm/lib/v3/agent/AgentClient.d.ts +2 -2
  123. package/dist/esm/lib/v3/agent/AgentClient.js.map +1 -1
  124. package/dist/esm/lib/v3/agent/AgentProvider.js +4 -3
  125. package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
  126. package/dist/esm/lib/v3/agent/AnthropicCUAClient.d.ts +4 -3
  127. package/dist/esm/lib/v3/agent/AnthropicCUAClient.js +21 -18
  128. package/dist/esm/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
  129. package/dist/esm/lib/v3/agent/GoogleCUAClient.d.ts +12 -3
  130. package/dist/esm/lib/v3/agent/GoogleCUAClient.js +217 -36
  131. package/dist/esm/lib/v3/agent/GoogleCUAClient.js.map +1 -1
  132. package/dist/esm/lib/v3/agent/MicrosoftCUAClient.d.ts +2 -2
  133. package/dist/esm/lib/v3/agent/MicrosoftCUAClient.js +2 -2
  134. package/dist/esm/lib/v3/agent/MicrosoftCUAClient.js.map +1 -1
  135. package/dist/esm/lib/v3/agent/OpenAICUAClient.d.ts +6 -3
  136. package/dist/esm/lib/v3/agent/OpenAICUAClient.js +13 -7
  137. package/dist/esm/lib/v3/agent/OpenAICUAClient.js.map +1 -1
  138. package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.d.ts +1 -0
  139. package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.js +49 -3
  140. package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.js.map +1 -1
  141. package/dist/esm/lib/v3/cache/ActCache.js +2 -2
  142. package/dist/esm/lib/v3/cache/ActCache.js.map +1 -1
  143. package/dist/esm/lib/v3/cache/utils.d.ts +7 -0
  144. package/dist/esm/lib/v3/cache/utils.js +18 -0
  145. package/dist/esm/lib/v3/cache/utils.js.map +1 -1
  146. package/dist/esm/lib/v3/handlers/v3AgentHandler.d.ts +2 -1
  147. package/dist/esm/lib/v3/handlers/v3AgentHandler.js +55 -16
  148. package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  149. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js +32 -18
  150. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  151. package/dist/esm/lib/v3/index.d.ts +3 -2
  152. package/dist/esm/lib/v3/index.js.map +1 -1
  153. package/dist/esm/lib/v3/launch/local.js +1 -0
  154. package/dist/esm/lib/v3/launch/local.js.map +1 -1
  155. package/dist/esm/lib/v3/llm/LLMProvider.d.ts +2 -2
  156. package/dist/esm/lib/v3/llm/LLMProvider.js +1 -0
  157. package/dist/esm/lib/v3/llm/LLMProvider.js.map +1 -1
  158. package/dist/esm/lib/v3/llm/aisdk.js +4 -0
  159. package/dist/esm/lib/v3/llm/aisdk.js.map +1 -1
  160. package/dist/esm/lib/v3/llm/anthropicOptions.d.ts +57 -0
  161. package/dist/esm/lib/v3/llm/anthropicOptions.js +106 -0
  162. package/dist/esm/lib/v3/llm/anthropicOptions.js.map +1 -0
  163. package/dist/esm/lib/v3/types/public/agent.d.ts +10 -1
  164. package/dist/esm/lib/v3/types/public/agent.js +2 -0
  165. package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
  166. package/dist/esm/lib/v3/types/public/context.d.ts +7 -0
  167. package/dist/esm/lib/v3/types/public/context.js.map +1 -1
  168. package/dist/esm/lib/v3/types/public/model.d.ts +3 -2
  169. package/dist/esm/lib/v3/types/public/model.js.map +1 -1
  170. package/dist/esm/lib/v3/types/public/sdkErrors.d.ts +4 -0
  171. package/dist/esm/lib/v3/types/public/sdkErrors.js +7 -0
  172. package/dist/esm/lib/v3/types/public/sdkErrors.js.map +1 -1
  173. package/dist/esm/lib/v3/understudy/cdp.d.ts +2 -0
  174. package/dist/esm/lib/v3/understudy/cdp.js +26 -12
  175. package/dist/esm/lib/v3/understudy/cdp.js.map +1 -1
  176. package/dist/esm/lib/v3/understudy/context.d.ts +13 -1
  177. package/dist/esm/lib/v3/understudy/context.js +285 -2
  178. package/dist/esm/lib/v3/understudy/context.js.map +1 -1
  179. package/dist/esm/lib/v3/understudy/domainPolicy.d.ts +25 -0
  180. package/dist/esm/lib/v3/understudy/domainPolicy.js +158 -0
  181. package/dist/esm/lib/v3/understudy/domainPolicy.js.map +1 -0
  182. package/dist/esm/lib/v3/understudy/page.js +1 -1
  183. package/dist/esm/lib/v3/understudy/page.js.map +1 -1
  184. package/dist/esm/lib/v3/v3.js +8 -2
  185. package/dist/esm/lib/v3/v3.js.map +1 -1
  186. package/dist/esm/lib/v3/verifier/errorTaxonomy.d.ts +35 -0
  187. package/dist/esm/lib/v3/verifier/errorTaxonomy.js +285 -0
  188. package/dist/esm/lib/v3/verifier/errorTaxonomy.js.map +1 -0
  189. package/dist/esm/lib/v3/verifier/evidence.d.ts +44 -0
  190. package/dist/esm/lib/v3/verifier/evidence.js +393 -0
  191. package/dist/esm/lib/v3/verifier/evidence.js.map +1 -0
  192. package/dist/esm/lib/v3/verifier/index.d.ts +1 -1
  193. package/dist/esm/lib/v3/verifier/index.js.map +1 -1
  194. package/dist/esm/lib/v3/verifier/prompts/batchedRelevance.d.ts +21 -0
  195. package/dist/esm/lib/v3/verifier/prompts/batchedRelevance.js +68 -0
  196. package/dist/esm/lib/v3/verifier/prompts/batchedRelevance.js.map +1 -0
  197. package/dist/esm/lib/v3/verifier/prompts/firstPointOfFailure.d.ts +3 -0
  198. package/dist/esm/lib/v3/verifier/prompts/firstPointOfFailure.js +162 -0
  199. package/dist/esm/lib/v3/verifier/prompts/firstPointOfFailure.js.map +1 -0
  200. package/dist/esm/lib/v3/verifier/prompts/fusedJudgment.d.ts +35 -0
  201. package/dist/esm/lib/v3/verifier/prompts/fusedJudgment.js +155 -0
  202. package/dist/esm/lib/v3/verifier/prompts/fusedJudgment.js.map +1 -0
  203. package/dist/esm/lib/v3/verifier/prompts/fusedOutcome.d.ts +26 -0
  204. package/dist/esm/lib/v3/verifier/prompts/fusedOutcome.js +134 -0
  205. package/dist/esm/lib/v3/verifier/prompts/fusedOutcome.js.map +1 -0
  206. package/dist/esm/lib/v3/verifier/prompts/index.d.ts +8 -0
  207. package/dist/esm/lib/v3/verifier/prompts/index.js +9 -0
  208. package/dist/esm/lib/v3/verifier/prompts/index.js.map +1 -0
  209. package/dist/esm/lib/v3/verifier/prompts/perCriterionScore.d.ts +23 -0
  210. package/dist/esm/lib/v3/verifier/prompts/perCriterionScore.js +74 -0
  211. package/dist/esm/lib/v3/verifier/prompts/perCriterionScore.js.map +1 -0
  212. package/dist/esm/lib/v3/verifier/prompts/render.d.ts +23 -0
  213. package/dist/esm/lib/v3/verifier/prompts/render.js +41 -0
  214. package/dist/esm/lib/v3/verifier/prompts/render.js.map +1 -0
  215. package/dist/esm/lib/v3/verifier/prompts/rubricGeneration.d.ts +16 -0
  216. package/dist/esm/lib/v3/verifier/prompts/rubricGeneration.js +318 -0
  217. package/dist/esm/lib/v3/verifier/prompts/rubricGeneration.js.map +1 -0
  218. package/dist/esm/lib/v3/verifier/prompts/taskValidity.d.ts +1 -0
  219. package/dist/esm/lib/v3/verifier/prompts/taskValidity.js +113 -0
  220. package/dist/esm/lib/v3/verifier/prompts/taskValidity.js.map +1 -0
  221. package/dist/esm/lib/v3/verifier/rubricVerifier.d.ts +91 -0
  222. package/dist/esm/lib/v3/verifier/rubricVerifier.js +1640 -0
  223. package/dist/esm/lib/v3/verifier/rubricVerifier.js.map +1 -0
  224. package/dist/esm/lib/v3/verifier/trajectory.d.ts +3 -3
  225. package/dist/esm/lib/v3/verifier/trajectory.js +26 -26
  226. package/dist/esm/lib/v3/verifier/trajectory.js.map +1 -1
  227. package/dist/esm/lib/v3/verifier/types.d.ts +163 -15
  228. package/dist/esm/lib/v3/verifier/types.js +0 -7
  229. package/dist/esm/lib/v3/verifier/types.js.map +1 -1
  230. package/dist/esm/lib/v3Evaluator.d.ts +5 -0
  231. package/dist/esm/lib/v3Evaluator.js +47 -7
  232. package/dist/esm/lib/v3Evaluator.js.map +1 -1
  233. package/dist/esm/lib/version.d.ts +1 -1
  234. package/dist/esm/lib/version.js +1 -1
  235. package/dist/esm/lib/version.js.map +1 -1
  236. package/package.json +10 -10
  237. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.d.ts +0 -24
  238. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js +0 -31
  239. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js.map +0 -1
  240. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.d.ts +0 -24
  241. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js +0 -28
  242. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js.map +0 -1
@@ -171,6 +171,8 @@ export class GoogleCUAClient extends AgentClient {
171
171
  await this.initializeHistory(instruction);
172
172
  let totalInputTokens = 0;
173
173
  let totalOutputTokens = 0;
174
+ let totalReasoningTokens = 0;
175
+ let totalCachedInputTokens = 0;
174
176
  let totalInferenceTime = 0;
175
177
  try {
176
178
  // Execute steps until completion or max steps reached
@@ -184,6 +186,8 @@ export class GoogleCUAClient extends AgentClient {
184
186
  const result = await this.executeStep(logger);
185
187
  totalInputTokens += result.usage.input_tokens;
186
188
  totalOutputTokens += result.usage.output_tokens;
189
+ totalReasoningTokens += result.usage.reasoning_tokens;
190
+ totalCachedInputTokens += result.usage.cached_input_tokens;
187
191
  totalInferenceTime += result.usage.inference_time_ms;
188
192
  // Add actions to the list
189
193
  actions.push(...result.actions);
@@ -206,6 +210,8 @@ export class GoogleCUAClient extends AgentClient {
206
210
  usage: {
207
211
  input_tokens: totalInputTokens,
208
212
  output_tokens: totalOutputTokens,
213
+ reasoning_tokens: totalReasoningTokens,
214
+ cached_input_tokens: totalCachedInputTokens,
209
215
  inference_time_ms: totalInferenceTime,
210
216
  },
211
217
  };
@@ -225,6 +231,8 @@ export class GoogleCUAClient extends AgentClient {
225
231
  usage: {
226
232
  input_tokens: totalInputTokens,
227
233
  output_tokens: totalOutputTokens,
234
+ reasoning_tokens: totalReasoningTokens,
235
+ cached_input_tokens: totalCachedInputTokens,
228
236
  inference_time_ms: totalInferenceTime,
229
237
  },
230
238
  };
@@ -362,9 +370,14 @@ export class GoogleCUAClient extends AgentClient {
362
370
  }
363
371
  // Execute actions and collect function responses
364
372
  const functionResponses = [];
365
- if (result.actions.length > 0) {
373
+ // Always process the model's response, even when it produced no
374
+ // executable action (e.g. a standalone take_screenshot). The model
375
+ // expects exactly one function response — a fresh screenshot — per
376
+ // computer-use call; skipping it when there are 0 actions leaves the
377
+ // model blind and it gives up after one empty turn.
378
+ {
366
379
  let hasError = false;
367
- // Execute all actions
380
+ // Execute all actions (a no-op when there are none).
368
381
  for (let i = 0; i < result.actions.length; i++) {
369
382
  const action = result.actions[i];
370
383
  logger({
@@ -382,6 +395,15 @@ export class GoogleCUAClient extends AgentClient {
382
395
  level: 2,
383
396
  });
384
397
  }
398
+ else if (action.type === "screenshot") {
399
+ // No interaction to perform — the screenshot captured below is
400
+ // returned to the model as this call's function response.
401
+ logger({
402
+ category: "agent",
403
+ message: "take_screenshot: capturing current page",
404
+ level: 2,
405
+ });
406
+ }
385
407
  else if (action.type === "custom_tool") {
386
408
  const toolName = action.name;
387
409
  const toolArgs = action.arguments;
@@ -435,7 +457,7 @@ export class GoogleCUAClient extends AgentClient {
435
457
  level: 2,
436
458
  });
437
459
  const screenshot = await this.captureScreenshot();
438
- const base64Data = screenshot.replace(/^data:image\/png;base64,/, "");
460
+ const base64Data = screenshot.base64;
439
461
  // Create one function response for each computer use function call
440
462
  // Following Python SDK pattern: FunctionResponse with parts containing inline_data
441
463
  for (const functionCall of computerUseFunctionCalls) {
@@ -457,7 +479,7 @@ export class GoogleCUAClient extends AgentClient {
457
479
  parts: [
458
480
  {
459
481
  inlineData: {
460
- mimeType: "image/png",
482
+ mimeType: screenshot.mediaType,
461
483
  data: base64Data,
462
484
  },
463
485
  },
@@ -494,8 +516,14 @@ export class GoogleCUAClient extends AgentClient {
494
516
  message: result.message,
495
517
  completed: result.completed,
496
518
  usage: {
519
+ // promptTokenCount is the TOTAL input and already includes the
520
+ // cached portion; cachedContentTokenCount is the cache-hit subset
521
+ // (tracked separately for visibility, not additive). thoughtsTokenCount
522
+ // is Gemini's thinking/reasoning output.
497
523
  input_tokens: usageMetadata?.promptTokenCount || 0,
498
524
  output_tokens: usageMetadata?.candidatesTokenCount || 0,
525
+ reasoning_tokens: usageMetadata?.thoughtsTokenCount || 0,
526
+ cached_input_tokens: usageMetadata?.cachedContentTokenCount || 0,
499
527
  inference_time_ms: elapsedMs,
500
528
  },
501
529
  };
@@ -550,23 +578,26 @@ export class GoogleCUAClient extends AgentClient {
550
578
  level: 2,
551
579
  });
552
580
  // Convert function call to action(s)
553
- const action = this.convertFunctionCallToAction(part.functionCall);
581
+ const action = this.convertFunctionCallToAction(part.functionCall, logger);
554
582
  if (action) {
555
- // Special handling for type_text_at - we need to click first
556
- if (part.functionCall.name === "type_text_at" &&
557
- action.type === "type") {
583
+ // Special handling for type actions. gemini-2.5 type_text_at carries
584
+ // coordinates (click the field first); gemini-3.x `type` has none and
585
+ // types into the element the model already focused.
586
+ if (action.type === "type") {
558
587
  logger({
559
588
  category: "agent",
560
589
  message: `Adding action: ${JSON.stringify(action)}`,
561
590
  level: 2,
562
591
  });
563
- // First add a click action at the same coordinates
564
- actions.push({
565
- type: "click",
566
- x: action.x,
567
- y: action.y,
568
- button: "left",
569
- });
592
+ // Click the target first only when coordinates are provided.
593
+ if (typeof action.x === "number" && typeof action.y === "number") {
594
+ actions.push({
595
+ type: "click",
596
+ x: action.x,
597
+ y: action.y,
598
+ button: "left",
599
+ });
600
+ }
570
601
  // If clear_before_typing is true (default), add a select all
571
602
  if (action.clearBeforeTyping) {
572
603
  // Select all text in the field
@@ -620,18 +651,80 @@ export class GoogleCUAClient extends AgentClient {
620
651
  /**
621
652
  * Convert Google function call to Stagehand action
622
653
  */
623
- convertFunctionCallToAction(functionCall) {
624
- const { name, args } = functionCall;
625
- if (!name || !args) {
654
+ convertFunctionCallToAction(functionCall, logger) {
655
+ const { name: rawName } = functionCall;
656
+ // Default args to an empty object so no-argument predefined functions
657
+ // (e.g. take_screenshot, go_back) are not rejected by the guard below.
658
+ const args = functionCall.args ?? {};
659
+ if (!rawName) {
626
660
  return null;
627
661
  }
662
+ // The gemini-3.x computer-use tool renamed several of the predefined
663
+ // functions that gemini-2.5-computer-use-preview used, and adds a
664
+ // descriptive `intent` arg to every call. The argument fields are otherwise
665
+ // unchanged (confirmed for click/navigate). Normalize the 3.x names to the
666
+ // canonical 2.5 names so a single set of handlers serves both generations;
667
+ // `intent` is ignored since handlers only read the args they need.
668
+ // NOTE: click and take_screenshot are confirmed from live gemini-3.5-flash
669
+ // traffic; the rest are inferred from the same drop-the-qualifier pattern
670
+ // and are safe aliases (any unmapped name still hits the warning below).
671
+ // gemini-3.x renamed several predefined functions vs gemini-2.5. Alias the
672
+ // 3.x names whose behavior maps cleanly onto a 2.5 canonical handler. Click
673
+ // variants that carry distinct semantics (double/triple/right/middle click,
674
+ // move) are NOT aliased here — they have dedicated cases below so the click
675
+ // count and button are preserved. 2.5 never emits any of these names, so
676
+ // the 2.5 handlers are unaffected.
677
+ const NAME_ALIASES = {
678
+ click: "click_at",
679
+ left_click: "click_at",
680
+ type: "type_text_at",
681
+ type_text: "type_text_at",
682
+ hover: "hover_at",
683
+ scroll: "scroll_at",
684
+ drag: "drag_and_drop",
685
+ key: "key_combination",
686
+ keys: "key_combination",
687
+ key_press: "key_combination",
688
+ press_key: "key_combination",
689
+ press_keys: "key_combination",
690
+ hotkey: "key_combination",
691
+ screenshot: "take_screenshot",
692
+ wait: "wait_5_seconds",
693
+ };
694
+ const name = NAME_ALIASES[rawName] ?? rawName;
695
+ // Predefined computer-use tools take precedence over custom tools. If a
696
+ // custom tool was registered under a reserved (aliased) name, note that the
697
+ // predefined tool wins rather than silently dropping the custom one.
698
+ if (rawName in NAME_ALIASES && isCustomTool(functionCall, this.tools)) {
699
+ logger?.({
700
+ category: "agent",
701
+ message: `Custom tool "${rawName}" collides with a predefined Google CUA function; using the predefined tool. Rename the custom tool to avoid the conflict.`,
702
+ level: 2,
703
+ });
704
+ }
628
705
  switch (name) {
629
706
  case "open_web_browser":
630
707
  return {
631
708
  type: "open_web_browser",
632
709
  timestamp: Date.now(),
633
710
  };
711
+ case "take_screenshot":
712
+ // No UI interaction. The step loop captures a fresh screenshot and
713
+ // returns it to the model as this call's function response; marked as a
714
+ // recognized action (not null) so it isn't dropped, and skipped in the
715
+ // executor like open_web_browser.
716
+ return {
717
+ type: "screenshot",
718
+ timestamp: Date.now(),
719
+ };
634
720
  case "click_at": {
721
+ // x/y are required; reject a malformed call rather than normalizing
722
+ // undefined/NaN/Infinity into bad coordinates. (gemini-3.x `click`
723
+ // aliases here.)
724
+ if (!GoogleCUAClient.isFiniteCoord(args.x) ||
725
+ !GoogleCUAClient.isFiniteCoord(args.y)) {
726
+ return null;
727
+ }
635
728
  const { x, y } = this.normalizeCoordinates(args.x, args.y);
636
729
  return {
637
730
  type: "click",
@@ -640,28 +733,74 @@ export class GoogleCUAClient extends AgentClient {
640
733
  button: args.button || "left",
641
734
  };
642
735
  }
643
- case "type_text_at": {
736
+ // gemini-3.x click family. The executor natively supports double/triple
737
+ // click and right/middle button, so preserve those semantics rather than
738
+ // collapsing to a single left click. All require integer coordinates;
739
+ // drop the call (return null) on a malformed payload so the executor is
740
+ // never handed NaN.
741
+ case "double_click":
742
+ case "triple_click":
743
+ case "right_click":
744
+ case "middle_click":
745
+ case "move": {
746
+ if (!GoogleCUAClient.isFiniteCoord(args.x) ||
747
+ !GoogleCUAClient.isFiniteCoord(args.y)) {
748
+ return null;
749
+ }
644
750
  const { x, y } = this.normalizeCoordinates(args.x, args.y);
645
- // Google's type_text_at includes press_enter and clear_before_typing parameters
751
+ if (name === "move") {
752
+ return { type: "move", x, y };
753
+ }
754
+ if (name === "double_click" || name === "triple_click") {
755
+ return { type: name, x, y };
756
+ }
757
+ return {
758
+ type: "click",
759
+ x,
760
+ y,
761
+ button: name === "right_click" ? "right" : "middle",
762
+ };
763
+ }
764
+ case "type_text_at": {
765
+ // text is required; reject a malformed call rather than typing
766
+ // "undefined". An empty string is valid (e.g. clear the field).
767
+ if (typeof args.text !== "string") {
768
+ return null;
769
+ }
770
+ // press_enter and clear_before_typing are shared across generations.
646
771
  const pressEnter = args.press_enter ?? false;
647
772
  const clearBeforeTyping = args.clear_before_typing ?? true;
648
- // For type_text_at, we need to click first then type
649
- // This matches the behavior expected by Google's CUA
650
- // We'll handle this in the executeStep method by converting to two actions
651
- return {
773
+ const base = {
652
774
  type: "type",
653
775
  text: args.text,
654
- x,
655
- y,
656
776
  pressEnter,
657
777
  clearBeforeTyping,
658
778
  };
779
+ // gemini-2.5 type_text_at carries x/y (click the field, then type).
780
+ // gemini-3.x `type` has no coordinates and types into the element the
781
+ // model already focused with a preceding click. Only attach coords when
782
+ // present so the executor doesn't click at NaN.
783
+ if (typeof args.x === "number" && typeof args.y === "number") {
784
+ const { x, y } = this.normalizeCoordinates(args.x, args.y);
785
+ return { ...base, x, y };
786
+ }
787
+ return base;
659
788
  }
660
789
  case "key_combination": {
661
- const keys = args.keys
662
- .split("+")
663
- .map((key) => key.trim())
790
+ // gemini-2.5 key_combination sends `keys` as a "+"-joined string;
791
+ // gemini-3.x `hotkey` sends a `keys` array, and `press_key` sends a
792
+ // single `key`. Accept all three.
793
+ const raw = args.keys !== undefined ? args.keys : args.key;
794
+ const parts = Array.isArray(raw)
795
+ ? raw
796
+ : String(raw ?? "").split("+");
797
+ const keys = parts
798
+ .map((key) => String(key).trim())
799
+ .filter(Boolean)
664
800
  .map((key) => mapKeyToPlaywright(key));
801
+ if (keys.length === 0) {
802
+ return null;
803
+ }
665
804
  return {
666
805
  type: "keypress",
667
806
  keys,
@@ -675,9 +814,24 @@ export class GoogleCUAClient extends AgentClient {
675
814
  };
676
815
  }
677
816
  case "scroll_at": {
817
+ // A coordinate-less (or malformed) `scroll` alias (gemini-3.x) scrolls
818
+ // the document via PageUp/PageDown.
819
+ if (!GoogleCUAClient.isFiniteCoord(args.x) ||
820
+ !GoogleCUAClient.isFiniteCoord(args.y)) {
821
+ const dir = (args.direction || "down").toLowerCase();
822
+ return {
823
+ type: "keypress",
824
+ keys: [dir === "up" ? "PageUp" : "PageDown"],
825
+ };
826
+ }
678
827
  const { x, y } = this.normalizeCoordinates(args.x, args.y);
679
828
  const direction = (args.direction || "down").toLowerCase();
680
- const magnitude = typeof args.magnitude === "number" ? args.magnitude : 800;
829
+ // 2.5 uses `magnitude`; gemini-3.x `scroll` uses `magnitude_in_pixels`.
830
+ const magnitude = GoogleCUAClient.isFiniteCoord(args.magnitude)
831
+ ? args.magnitude
832
+ : GoogleCUAClient.isFiniteCoord(args.magnitude_in_pixels)
833
+ ? args.magnitude_in_pixels
834
+ : 800;
681
835
  let scroll_x = 0;
682
836
  let scroll_y = 0;
683
837
  if (direction === "up") {
@@ -705,6 +859,11 @@ export class GoogleCUAClient extends AgentClient {
705
859
  };
706
860
  }
707
861
  case "navigate":
862
+ // url is required; reject a malformed call rather than navigating to
863
+ // "undefined".
864
+ if (typeof args.url !== "string" || args.url.length === 0) {
865
+ return null;
866
+ }
708
867
  return {
709
868
  type: "goto",
710
869
  url: args.url,
@@ -736,8 +895,20 @@ export class GoogleCUAClient extends AgentClient {
736
895
  url: "https://www.google.com",
737
896
  };
738
897
  case "drag_and_drop": {
739
- const startPoint = this.normalizeCoordinates(args.x, args.y);
740
- const endPoint = this.normalizeCoordinates(args.destination_x, args.destination_y);
898
+ // 2.5 uses x/y + destination_x/destination_y; gemini-3.x `drag_and_drop`
899
+ // uses start_x/start_y + end_x/end_y. Accept either.
900
+ const sx = args.x ?? args.start_x;
901
+ const sy = args.y ?? args.start_y;
902
+ const ex = args.destination_x ?? args.end_x;
903
+ const ey = args.destination_y ?? args.end_y;
904
+ if (!GoogleCUAClient.isFiniteCoord(sx) ||
905
+ !GoogleCUAClient.isFiniteCoord(sy) ||
906
+ !GoogleCUAClient.isFiniteCoord(ex) ||
907
+ !GoogleCUAClient.isFiniteCoord(ey)) {
908
+ return null;
909
+ }
910
+ const startPoint = this.normalizeCoordinates(sx, sy);
911
+ const endPoint = this.normalizeCoordinates(ex, ey);
741
912
  return {
742
913
  type: "drag",
743
914
  path: [
@@ -760,6 +931,14 @@ export class GoogleCUAClient extends AgentClient {
760
931
  return null;
761
932
  }
762
933
  }
934
+ /**
935
+ * True only for a usable coordinate/number: rejects undefined, non-numbers,
936
+ * and the numeric edge cases NaN and Infinity (both `typeof "number"`), so
937
+ * malformed function calls are dropped instead of normalizing into NaN.
938
+ */
939
+ static isFiniteCoord(value) {
940
+ return typeof value === "number" && Number.isFinite(value);
941
+ }
763
942
  /**
764
943
  * Normalize coordinates from Google's 0-1000 range to viewport dimensions
765
944
  */
@@ -778,13 +957,15 @@ export class GoogleCUAClient extends AgentClient {
778
957
  }
779
958
  // Use provided options if available
780
959
  if (options?.base64Image) {
781
- return `data:image/png;base64,${options.base64Image}`;
960
+ return {
961
+ base64: options.base64Image,
962
+ mediaType: options.mediaType ?? "image/png",
963
+ };
782
964
  }
783
965
  // Use the screenshot provider if available
784
966
  if (this.screenshotProvider) {
785
967
  try {
786
- const base64Image = await this.screenshotProvider();
787
- return `data:image/png;base64,${base64Image}`;
968
+ return await this.screenshotProvider();
788
969
  }
789
970
  catch (error) {
790
971
  console.error("Error capturing screenshot:", error);
@@ -792,7 +973,7 @@ export class GoogleCUAClient extends AgentClient {
792
973
  }
793
974
  }
794
975
  throw new AgentScreenshotProviderError("`screenshotProvider` has not been set. " +
795
- "Please call `setScreenshotProvider()` with a valid function that returns a base64-encoded image");
976
+ "Please call `setScreenshotProvider()` with a valid function that returns a base64-encoded image and media type");
796
977
  }
797
978
  }
798
979
  //# sourceMappingURL=GoogleCUAClient.js.map