@browserbasehq/orca 3.2.1-preview.2 → 3.4.0-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 (209) hide show
  1. package/dist/cjs/lib/inference.js +2 -9
  2. package/dist/cjs/lib/inference.js.map +1 -1
  3. package/dist/cjs/lib/prompt.js +3 -1
  4. package/dist/cjs/lib/prompt.js.map +1 -1
  5. package/dist/cjs/lib/v3/agent/AgentProvider.js +3 -0
  6. package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
  7. package/dist/cjs/lib/v3/agent/tools/fillFormVision.js +16 -12
  8. package/dist/cjs/lib/v3/agent/tools/fillFormVision.js.map +1 -1
  9. package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
  10. package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
  11. package/dist/cjs/lib/v3/api.d.ts +1 -0
  12. package/dist/cjs/lib/v3/api.js +15 -3
  13. package/dist/cjs/lib/v3/api.js.map +1 -1
  14. package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js +1 -1
  15. package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
  16. package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js +1 -1
  17. package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
  18. package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
  19. package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js +1 -1
  20. package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
  21. package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js +1 -1
  22. package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
  23. package/dist/cjs/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
  24. package/dist/cjs/lib/v3/dom/build/scriptV3Content.js +1 -1
  25. package/dist/cjs/lib/v3/dom/build/scriptV3Content.js.map +1 -1
  26. package/dist/cjs/lib/v3/handlers/extractHandler.js +3 -1
  27. package/dist/cjs/lib/v3/handlers/extractHandler.js.map +1 -1
  28. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +3 -5
  29. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  30. package/dist/cjs/lib/v3/index.d.ts +1 -1
  31. package/dist/cjs/lib/v3/llm/CerebrasClient.js +1 -1
  32. package/dist/cjs/lib/v3/llm/CerebrasClient.js.map +1 -1
  33. package/dist/cjs/lib/v3/llm/GroqClient.js +1 -1
  34. package/dist/cjs/lib/v3/llm/GroqClient.js.map +1 -1
  35. package/dist/cjs/lib/v3/types/private/agent.d.ts +5 -0
  36. package/dist/cjs/lib/v3/types/private/agent.js +11 -0
  37. package/dist/cjs/lib/v3/types/private/agent.js.map +1 -1
  38. package/dist/cjs/lib/v3/types/private/handlers.d.ts +1 -0
  39. package/dist/cjs/lib/v3/types/private/handlers.js.map +1 -1
  40. package/dist/cjs/lib/v3/types/private/snapshot.d.ts +8 -0
  41. package/dist/cjs/lib/v3/types/private/snapshot.js.map +1 -1
  42. package/dist/cjs/lib/v3/types/public/agent.d.ts +2 -3
  43. package/dist/cjs/lib/v3/types/public/agent.js +3 -0
  44. package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
  45. package/dist/cjs/lib/v3/types/public/api.d.ts +5 -1
  46. package/dist/cjs/lib/v3/types/public/api.js +15 -2
  47. package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
  48. package/dist/cjs/lib/v3/types/public/methods.d.ts +1 -0
  49. package/dist/cjs/lib/v3/types/public/methods.js.map +1 -1
  50. package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
  51. package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
  52. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
  53. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js +268 -21
  54. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
  55. package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
  56. package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
  57. package/dist/cjs/lib/v3/understudy/frameRegistry.js +16 -5
  58. package/dist/cjs/lib/v3/understudy/frameRegistry.js.map +1 -1
  59. package/dist/cjs/lib/v3/v3.d.ts +1 -0
  60. package/dist/cjs/lib/v3/v3.js +15 -14
  61. package/dist/cjs/lib/v3/v3.js.map +1 -1
  62. package/dist/cjs/lib/version.d.ts +1 -1
  63. package/dist/cjs/lib/version.js +1 -1
  64. package/dist/cjs/lib/version.js.map +1 -1
  65. package/dist/cjs/tests/integration/observe-element-id-format.spec.js +130 -0
  66. package/dist/cjs/tests/integration/observe-element-id-format.spec.js.map +1 -0
  67. package/dist/cjs/tests/unit/agent-mode-routing.test.js +88 -0
  68. package/dist/cjs/tests/unit/agent-mode-routing.test.js.map +1 -0
  69. package/dist/cjs/tests/unit/agent-temperature.test.d.ts +1 -0
  70. package/dist/cjs/tests/unit/agent-temperature.test.js +191 -0
  71. package/dist/cjs/tests/unit/agent-temperature.test.js.map +1 -0
  72. package/dist/cjs/tests/unit/agent-variables-validation.test.d.ts +1 -0
  73. package/dist/cjs/tests/unit/agent-variables-validation.test.js +43 -0
  74. package/dist/cjs/tests/unit/agent-variables-validation.test.js.map +1 -0
  75. package/dist/cjs/tests/unit/api-client-observe-variables.test.js +47 -0
  76. package/dist/cjs/tests/unit/api-client-observe-variables.test.js.map +1 -1
  77. package/dist/cjs/tests/unit/api-optional-model-api-key.test.js +60 -0
  78. package/dist/cjs/tests/unit/api-optional-model-api-key.test.js.map +1 -1
  79. package/dist/cjs/tests/unit/api-variables-schema.test.js +25 -0
  80. package/dist/cjs/tests/unit/api-variables-schema.test.js.map +1 -1
  81. package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
  82. package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js +60 -0
  83. package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
  84. package/dist/cjs/tests/unit/inference-temperature.test.d.ts +1 -0
  85. package/dist/cjs/tests/unit/inference-temperature.test.js +65 -0
  86. package/dist/cjs/tests/unit/inference-temperature.test.js.map +1 -0
  87. package/dist/cjs/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
  88. package/dist/cjs/tests/unit/openai-compatible-temperature.test.js +84 -0
  89. package/dist/cjs/tests/unit/openai-compatible-temperature.test.js.map +1 -0
  90. package/dist/cjs/tests/unit/prompt-observe-variables.test.js +6 -0
  91. package/dist/cjs/tests/unit/prompt-observe-variables.test.js.map +1 -1
  92. package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js +3 -0
  93. package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
  94. package/dist/cjs/tests/unit/public-api/public-types.test.js.map +1 -1
  95. package/dist/cjs/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
  96. package/dist/cjs/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
  97. package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
  98. package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
  99. package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js +119 -9
  100. package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
  101. package/dist/esm/lib/inference.js +2 -9
  102. package/dist/esm/lib/inference.js.map +1 -1
  103. package/dist/esm/lib/prompt.js +3 -1
  104. package/dist/esm/lib/prompt.js.map +1 -1
  105. package/dist/esm/lib/v3/agent/AgentProvider.js +3 -0
  106. package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
  107. package/dist/esm/lib/v3/agent/tools/fillFormVision.js +16 -12
  108. package/dist/esm/lib/v3/agent/tools/fillFormVision.js.map +1 -1
  109. package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
  110. package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
  111. package/dist/esm/lib/v3/api.d.ts +1 -0
  112. package/dist/esm/lib/v3/api.js +15 -3
  113. package/dist/esm/lib/v3/api.js.map +1 -1
  114. package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js +1 -1
  115. package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
  116. package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js +1 -1
  117. package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
  118. package/dist/esm/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
  119. package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js +1 -1
  120. package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
  121. package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js +1 -1
  122. package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
  123. package/dist/esm/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
  124. package/dist/esm/lib/v3/dom/build/scriptV3Content.js +1 -1
  125. package/dist/esm/lib/v3/dom/build/scriptV3Content.js.map +1 -1
  126. package/dist/esm/lib/v3/handlers/extractHandler.js +3 -1
  127. package/dist/esm/lib/v3/handlers/extractHandler.js.map +1 -1
  128. package/dist/esm/lib/v3/handlers/v3AgentHandler.js +3 -5
  129. package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  130. package/dist/esm/lib/v3/index.d.ts +1 -1
  131. package/dist/esm/lib/v3/llm/CerebrasClient.js +1 -1
  132. package/dist/esm/lib/v3/llm/CerebrasClient.js.map +1 -1
  133. package/dist/esm/lib/v3/llm/GroqClient.js +1 -1
  134. package/dist/esm/lib/v3/llm/GroqClient.js.map +1 -1
  135. package/dist/esm/lib/v3/types/private/agent.d.ts +5 -0
  136. package/dist/esm/lib/v3/types/private/agent.js +10 -1
  137. package/dist/esm/lib/v3/types/private/agent.js.map +1 -1
  138. package/dist/esm/lib/v3/types/private/handlers.d.ts +1 -0
  139. package/dist/esm/lib/v3/types/private/handlers.js.map +1 -1
  140. package/dist/esm/lib/v3/types/private/snapshot.d.ts +8 -0
  141. package/dist/esm/lib/v3/types/private/snapshot.js.map +1 -1
  142. package/dist/esm/lib/v3/types/public/agent.d.ts +2 -3
  143. package/dist/esm/lib/v3/types/public/agent.js +3 -0
  144. package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
  145. package/dist/esm/lib/v3/types/public/api.d.ts +5 -1
  146. package/dist/esm/lib/v3/types/public/api.js +15 -2
  147. package/dist/esm/lib/v3/types/public/api.js.map +1 -1
  148. package/dist/esm/lib/v3/types/public/methods.d.ts +1 -0
  149. package/dist/esm/lib/v3/types/public/methods.js.map +1 -1
  150. package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
  151. package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
  152. package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
  153. package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js +267 -22
  154. package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
  155. package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
  156. package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
  157. package/dist/esm/lib/v3/understudy/frameRegistry.js +16 -5
  158. package/dist/esm/lib/v3/understudy/frameRegistry.js.map +1 -1
  159. package/dist/esm/lib/v3/v3.d.ts +1 -0
  160. package/dist/esm/lib/v3/v3.js +15 -14
  161. package/dist/esm/lib/v3/v3.js.map +1 -1
  162. package/dist/esm/lib/version.d.ts +1 -1
  163. package/dist/esm/lib/version.js +1 -1
  164. package/dist/esm/lib/version.js.map +1 -1
  165. package/dist/esm/tests/integration/observe-element-id-format.spec.d.ts +1 -0
  166. package/dist/esm/tests/integration/observe-element-id-format.spec.js +128 -0
  167. package/dist/esm/tests/integration/observe-element-id-format.spec.js.map +1 -0
  168. package/dist/esm/tests/unit/agent-mode-routing.test.d.ts +1 -0
  169. package/dist/esm/tests/unit/agent-mode-routing.test.js +86 -0
  170. package/dist/esm/tests/unit/agent-mode-routing.test.js.map +1 -0
  171. package/dist/esm/tests/unit/agent-temperature.test.d.ts +1 -0
  172. package/dist/esm/tests/unit/agent-temperature.test.js +189 -0
  173. package/dist/esm/tests/unit/agent-temperature.test.js.map +1 -0
  174. package/dist/esm/tests/unit/agent-variables-validation.test.d.ts +1 -0
  175. package/dist/esm/tests/unit/agent-variables-validation.test.js +41 -0
  176. package/dist/esm/tests/unit/agent-variables-validation.test.js.map +1 -0
  177. package/dist/esm/tests/unit/api-client-observe-variables.test.js +47 -0
  178. package/dist/esm/tests/unit/api-client-observe-variables.test.js.map +1 -1
  179. package/dist/esm/tests/unit/api-optional-model-api-key.test.js +60 -0
  180. package/dist/esm/tests/unit/api-optional-model-api-key.test.js.map +1 -1
  181. package/dist/esm/tests/unit/api-variables-schema.test.js +25 -0
  182. package/dist/esm/tests/unit/api-variables-schema.test.js.map +1 -1
  183. package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
  184. package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js +58 -0
  185. package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
  186. package/dist/esm/tests/unit/inference-temperature.test.d.ts +1 -0
  187. package/dist/esm/tests/unit/inference-temperature.test.js +63 -0
  188. package/dist/esm/tests/unit/inference-temperature.test.js.map +1 -0
  189. package/dist/esm/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
  190. package/dist/esm/tests/unit/openai-compatible-temperature.test.js +82 -0
  191. package/dist/esm/tests/unit/openai-compatible-temperature.test.js.map +1 -0
  192. package/dist/esm/tests/unit/prompt-observe-variables.test.js +6 -0
  193. package/dist/esm/tests/unit/prompt-observe-variables.test.js.map +1 -1
  194. package/dist/esm/tests/unit/public-api/llm-and-agents.test.js +3 -0
  195. package/dist/esm/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
  196. package/dist/esm/tests/unit/public-api/public-types.test.js.map +1 -1
  197. package/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
  198. package/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
  199. package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
  200. package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
  201. package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js +119 -9
  202. package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
  203. package/package.json +1 -1
  204. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js +0 -56
  205. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
  206. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js +0 -54
  207. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
  208. /package/dist/cjs/tests/integration/{agent-captcha-autosolve.spec.d.ts → observe-element-id-format.spec.d.ts} +0 -0
  209. /package/dist/{esm/tests/integration/agent-captcha-autosolve.spec.d.ts → cjs/tests/unit/agent-mode-routing.test.d.ts} +0 -0
@@ -27,9 +27,12 @@ const api_1 = require("../../lib/v3/api");
27
27
  }
28
28
  (0, vitest_1.beforeEach)(() => {
29
29
  originalFetch = globalThis.fetch;
30
+ logger.mockClear();
30
31
  });
31
32
  (0, vitest_1.afterEach)(() => {
32
33
  globalThis.fetch = originalFetch;
34
+ delete process.env.STAGEHAND_BASE_URL;
35
+ delete process.env.STAGEHAND_API_URL;
33
36
  vitest_1.vi.restoreAllMocks();
34
37
  });
35
38
  (0, vitest_1.it)("should NOT throw when modelApiKey is omitted", async () => {
@@ -91,5 +94,62 @@ const api_1 = require("../../lib/v3/api");
91
94
  const [, requestInit] = fetchSpy.mock.calls[0];
92
95
  (0, vitest_1.expect)(requestInit.headers["x-model-api-key"]).toBeUndefined();
93
96
  });
97
+ (0, vitest_1.it)("should use STAGEHAND_API_URL for the API base URL", async () => {
98
+ process.env.STAGEHAND_API_URL = "http://localhost:5000";
99
+ const fetchSpy = vitest_1.vi
100
+ .fn()
101
+ .mockResolvedValue(createSessionStartResponse("sess-api-url"));
102
+ globalThis.fetch = fetchSpy;
103
+ const client = new api_1.StagehandAPIClient({
104
+ apiKey: "test-api-key",
105
+ logger,
106
+ });
107
+ await client.init({
108
+ modelName: "openai/gpt-4.1-mini",
109
+ });
110
+ const [url] = fetchSpy.mock.calls[0];
111
+ (0, vitest_1.expect)(url.toString()).toBe("http://localhost:5000/v1/sessions/start");
112
+ });
113
+ (0, vitest_1.it)("should use STAGEHAND_BASE_URL as a legacy fallback", async () => {
114
+ process.env.STAGEHAND_BASE_URL = "http://localhost:5001";
115
+ const fetchSpy = vitest_1.vi
116
+ .fn()
117
+ .mockResolvedValue(createSessionStartResponse("sess-base-url"));
118
+ globalThis.fetch = fetchSpy;
119
+ const client = new api_1.StagehandAPIClient({
120
+ apiKey: "test-api-key",
121
+ logger,
122
+ });
123
+ await client.init({
124
+ modelName: "openai/gpt-4.1-mini",
125
+ });
126
+ const [url] = fetchSpy.mock.calls[0];
127
+ (0, vitest_1.expect)(url.toString()).toBe("http://localhost:5001/v1/sessions/start");
128
+ (0, vitest_1.expect)(logger).toHaveBeenCalledWith(vitest_1.expect.objectContaining({
129
+ category: "config",
130
+ message: "STAGEHAND_BASE_URL is deprecated. Use STAGEHAND_API_URL instead.",
131
+ level: 0,
132
+ }));
133
+ });
134
+ (0, vitest_1.it)("should prefer STAGEHAND_API_URL over STAGEHAND_BASE_URL", async () => {
135
+ process.env.STAGEHAND_BASE_URL = "http://localhost:5002";
136
+ process.env.STAGEHAND_API_URL = "http://localhost:5003";
137
+ const fetchSpy = vitest_1.vi
138
+ .fn()
139
+ .mockResolvedValue(createSessionStartResponse("sess-base-precedence"));
140
+ globalThis.fetch = fetchSpy;
141
+ const client = new api_1.StagehandAPIClient({
142
+ apiKey: "test-api-key",
143
+ logger,
144
+ });
145
+ await client.init({
146
+ modelName: "openai/gpt-4.1-mini",
147
+ });
148
+ const [url] = fetchSpy.mock.calls[0];
149
+ (0, vitest_1.expect)(url.toString()).toBe("http://localhost:5003/v1/sessions/start");
150
+ (0, vitest_1.expect)(logger).not.toHaveBeenCalledWith(vitest_1.expect.objectContaining({
151
+ message: "STAGEHAND_BASE_URL is deprecated. Use STAGEHAND_API_URL instead.",
152
+ }));
153
+ });
94
154
  });
95
155
  //# sourceMappingURL=api-optional-model-api-key.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-optional-model-api-key.test.js","sourceRoot":"","sources":["../../../../tests/unit/api-optional-model-api-key.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi, beforeEach, afterEach } from \"vitest\";\nimport { StagehandAPIClient } from \"../../lib/v3/api\";\n\n/**\n * Tests that modelApiKey is optional when calling StagehandAPIClient.init().\n *\n * Previously, init() would throw \"modelApiKey is required\" if the key was not\n * provided. After the fix, sessions can be started without a model API key\n * (the server may provide its own key or the user may not need one).\n * When provided, the key should still be sent via the x-model-api-key header.\n */\ndescribe(\"StagehandAPIClient - optional modelApiKey\", () => {\n const logger = vi.fn();\n\n // We mock fetch to avoid real network calls; we just need to verify\n // that init() doesn't throw when modelApiKey is omitted and that\n // the header is conditionally included.\n let originalFetch: typeof globalThis.fetch;\n\n function createSessionStartResponse(sessionId: string) {\n return new Response(\n JSON.stringify({\n success: true,\n data: { sessionId, available: true },\n }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n }\n\n beforeEach(() => {\n originalFetch = globalThis.fetch;\n });\n\n afterEach(() => {\n globalThis.fetch = originalFetch;\n vi.restoreAllMocks();\n });\n\n it(\"should NOT throw when modelApiKey is omitted\", async () => {\n globalThis.fetch = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-123\"));\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n // Should not throw \"modelApiKey is required\"\n await expect(\n client.init({\n modelName: \"openai/gpt-4.1-mini\",\n }),\n ).resolves.toBeDefined();\n });\n\n it(\"should NOT throw when modelApiKey is undefined\", async () => {\n globalThis.fetch = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-456\"));\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await expect(\n client.init({\n modelName: \"openai/gpt-4.1-mini\",\n modelApiKey: undefined,\n }),\n ).resolves.toBeDefined();\n });\n\n it(\"should send x-model-api-key header when modelApiKey IS provided\", async () => {\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-789\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n modelApiKey: \"my-model-key\",\n });\n\n // Verify the fetch was called with x-model-api-key header\n const [, requestInit] = fetchSpy.mock.calls[0];\n expect(requestInit.headers[\"x-model-api-key\"]).toBe(\"my-model-key\");\n });\n\n it(\"should NOT send x-model-api-key header when modelApiKey is omitted\", async () => {\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-012\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n });\n\n // Verify x-model-api-key header is NOT present\n const [, requestInit] = fetchSpy.mock.calls[0];\n expect(requestInit.headers[\"x-model-api-key\"]).toBeUndefined();\n });\n});\n"]}
1
+ {"version":3,"file":"api-optional-model-api-key.test.js","sourceRoot":"","sources":["../../../../tests/unit/api-optional-model-api-key.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi, beforeEach, afterEach } from \"vitest\";\nimport { StagehandAPIClient } from \"../../lib/v3/api\";\n\n/**\n * Tests that modelApiKey is optional when calling StagehandAPIClient.init().\n *\n * Previously, init() would throw \"modelApiKey is required\" if the key was not\n * provided. After the fix, sessions can be started without a model API key\n * (the server may provide its own key or the user may not need one).\n * When provided, the key should still be sent via the x-model-api-key header.\n */\ndescribe(\"StagehandAPIClient - optional modelApiKey\", () => {\n const logger = vi.fn();\n\n // We mock fetch to avoid real network calls; we just need to verify\n // that init() doesn't throw when modelApiKey is omitted and that\n // the header is conditionally included.\n let originalFetch: typeof globalThis.fetch;\n\n function createSessionStartResponse(sessionId: string) {\n return new Response(\n JSON.stringify({\n success: true,\n data: { sessionId, available: true },\n }),\n {\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n },\n );\n }\n\n beforeEach(() => {\n originalFetch = globalThis.fetch;\n logger.mockClear();\n });\n\n afterEach(() => {\n globalThis.fetch = originalFetch;\n delete process.env.STAGEHAND_BASE_URL;\n delete process.env.STAGEHAND_API_URL;\n vi.restoreAllMocks();\n });\n\n it(\"should NOT throw when modelApiKey is omitted\", async () => {\n globalThis.fetch = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-123\"));\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n // Should not throw \"modelApiKey is required\"\n await expect(\n client.init({\n modelName: \"openai/gpt-4.1-mini\",\n }),\n ).resolves.toBeDefined();\n });\n\n it(\"should NOT throw when modelApiKey is undefined\", async () => {\n globalThis.fetch = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-456\"));\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await expect(\n client.init({\n modelName: \"openai/gpt-4.1-mini\",\n modelApiKey: undefined,\n }),\n ).resolves.toBeDefined();\n });\n\n it(\"should send x-model-api-key header when modelApiKey IS provided\", async () => {\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-789\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n modelApiKey: \"my-model-key\",\n });\n\n // Verify the fetch was called with x-model-api-key header\n const [, requestInit] = fetchSpy.mock.calls[0];\n expect(requestInit.headers[\"x-model-api-key\"]).toBe(\"my-model-key\");\n });\n\n it(\"should NOT send x-model-api-key header when modelApiKey is omitted\", async () => {\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-012\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n });\n\n // Verify x-model-api-key header is NOT present\n const [, requestInit] = fetchSpy.mock.calls[0];\n expect(requestInit.headers[\"x-model-api-key\"]).toBeUndefined();\n });\n\n it(\"should use STAGEHAND_API_URL for the API base URL\", async () => {\n process.env.STAGEHAND_API_URL = \"http://localhost:5000\";\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-api-url\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n });\n\n const [url] = fetchSpy.mock.calls[0];\n expect(url.toString()).toBe(\"http://localhost:5000/v1/sessions/start\");\n });\n\n it(\"should use STAGEHAND_BASE_URL as a legacy fallback\", async () => {\n process.env.STAGEHAND_BASE_URL = \"http://localhost:5001\";\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-base-url\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n });\n\n const [url] = fetchSpy.mock.calls[0];\n expect(url.toString()).toBe(\"http://localhost:5001/v1/sessions/start\");\n expect(logger).toHaveBeenCalledWith(\n expect.objectContaining({\n category: \"config\",\n message:\n \"STAGEHAND_BASE_URL is deprecated. Use STAGEHAND_API_URL instead.\",\n level: 0,\n }),\n );\n });\n\n it(\"should prefer STAGEHAND_API_URL over STAGEHAND_BASE_URL\", async () => {\n process.env.STAGEHAND_BASE_URL = \"http://localhost:5002\";\n process.env.STAGEHAND_API_URL = \"http://localhost:5003\";\n const fetchSpy = vi\n .fn()\n .mockResolvedValue(createSessionStartResponse(\"sess-base-precedence\"));\n globalThis.fetch = fetchSpy;\n\n const client = new StagehandAPIClient({\n apiKey: \"test-api-key\",\n logger,\n });\n\n await client.init({\n modelName: \"openai/gpt-4.1-mini\",\n });\n\n const [url] = fetchSpy.mock.calls[0];\n expect(url.toString()).toBe(\"http://localhost:5003/v1/sessions/start\");\n expect(logger).not.toHaveBeenCalledWith(\n expect.objectContaining({\n message:\n \"STAGEHAND_BASE_URL is deprecated. Use STAGEHAND_API_URL instead.\",\n }),\n );\n });\n});\n"]}
@@ -33,5 +33,30 @@ const index_js_1 = require("../../lib/v3/types/public/index.js");
33
33
  });
34
34
  (0, vitest_1.expect)(result.success).toBe(true);
35
35
  });
36
+ (0, vitest_1.it)("preserves variables for agent execute requests", () => {
37
+ const result = index_js_1.Api.AgentExecuteRequestSchema.safeParse({
38
+ agentConfig: { mode: "dom" },
39
+ executeOptions: {
40
+ instruction: "fill the form with %username% and %password%",
41
+ variables: {
42
+ username: "john@example.com",
43
+ password: {
44
+ value: "secret-password",
45
+ description: "The login password",
46
+ },
47
+ },
48
+ },
49
+ });
50
+ (0, vitest_1.expect)(result.success).toBe(true);
51
+ if (!result.success)
52
+ throw result.error;
53
+ (0, vitest_1.expect)(result.data.executeOptions.variables).toEqual({
54
+ username: "john@example.com",
55
+ password: {
56
+ value: "secret-password",
57
+ description: "The login password",
58
+ },
59
+ });
60
+ });
36
61
  });
37
62
  //# sourceMappingURL=api-variables-schema.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-variables-schema.test.js","sourceRoot":"","sources":["../../../../tests/unit/api-variables-schema.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,iEAAyD;AAEzD,IAAA,iBAAQ,EAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAA,WAAE,EAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,MAAM,GAAG,cAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC;YAC5C,KAAK,EAAE,sCAAsC;YAC7C,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,UAAU,EAAE,IAAI;iBACjB;aACF;SACF,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,cAAG,CAAC,oBAAoB,CAAC,SAAS,CAAC;YAChD,WAAW,EAAE,mDAAmD;YAChE,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,UAAU,EAAE,IAAI;iBACjB;aACF;SACF,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { Api } from \"../../lib/v3/types/public/index.js\";\n\ndescribe(\"API variable schemas\", () => {\n it(\"accepts rich variables for act requests\", () => {\n const result = Api.ActRequestSchema.safeParse({\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 rememberMe: true,\n },\n },\n });\n\n expect(result.success).toBe(true);\n });\n\n it(\"accepts rich variables for observe requests\", () => {\n const result = Api.ObserveRequestSchema.safeParse({\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 rememberMe: true,\n },\n },\n });\n\n expect(result.success).toBe(true);\n });\n});\n"]}
1
+ {"version":3,"file":"api-variables-schema.test.js","sourceRoot":"","sources":["../../../../tests/unit/api-variables-schema.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,iEAAyD;AAEzD,IAAA,iBAAQ,EAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,IAAA,WAAE,EAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,MAAM,GAAG,cAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC;YAC5C,KAAK,EAAE,sCAAsC;YAC7C,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,UAAU,EAAE,IAAI;iBACjB;aACF;SACF,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,cAAG,CAAC,oBAAoB,CAAC,SAAS,CAAC;YAChD,WAAW,EAAE,mDAAmD;YAChE,OAAO,EAAE;gBACP,SAAS,EAAE;oBACT,QAAQ,EAAE;wBACR,KAAK,EAAE,kBAAkB;wBACzB,WAAW,EAAE,iBAAiB;qBAC/B;oBACD,UAAU,EAAE,IAAI;iBACjB;aACF;SACF,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,MAAM,GAAG,cAAG,CAAC,yBAAyB,CAAC,SAAS,CAAC;YACrD,WAAW,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;YAC5B,cAAc,EAAE;gBACd,WAAW,EAAE,8CAA8C;gBAC3D,SAAS,EAAE;oBACT,QAAQ,EAAE,kBAAkB;oBAC5B,QAAQ,EAAE;wBACR,KAAK,EAAE,iBAAiB;wBACxB,WAAW,EAAE,oBAAoB;qBAClC;iBACF;aACF;SACF,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,MAAM,CAAC,KAAK,CAAC;QACxC,IAAA,eAAM,EAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC;YACnD,QAAQ,EAAE,kBAAkB;YAC5B,QAAQ,EAAE;gBACR,KAAK,EAAE,iBAAiB;gBACxB,WAAW,EAAE,oBAAoB;aAClC;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { Api } from \"../../lib/v3/types/public/index.js\";\n\ndescribe(\"API variable schemas\", () => {\n it(\"accepts rich variables for act requests\", () => {\n const result = Api.ActRequestSchema.safeParse({\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 rememberMe: true,\n },\n },\n });\n\n expect(result.success).toBe(true);\n });\n\n it(\"accepts rich variables for observe requests\", () => {\n const result = Api.ObserveRequestSchema.safeParse({\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 rememberMe: true,\n },\n },\n });\n\n expect(result.success).toBe(true);\n });\n\n it(\"preserves variables for agent execute requests\", () => {\n const result = Api.AgentExecuteRequestSchema.safeParse({\n agentConfig: { mode: \"dom\" },\n executeOptions: {\n instruction: \"fill the form with %username% and %password%\",\n variables: {\n username: \"john@example.com\",\n password: {\n value: \"secret-password\",\n description: \"The login password\",\n },\n },\n },\n });\n\n expect(result.success).toBe(true);\n if (!result.success) throw result.error;\n expect(result.data.executeOptions.variables).toEqual({\n username: \"john@example.com\",\n password: {\n value: \"secret-password\",\n description: \"The login password\",\n },\n });\n });\n});\n"]}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const frameRegistry_js_1 = require("../../lib/v3/understudy/frameRegistry.js");
5
+ (0, vitest_1.describe)("FrameRegistry OOPIF adoption ordering", () => {
6
+ (0, vitest_1.it)("keeps child-session ownership when parent frameAttached arrives before child target adoption", () => {
7
+ const registry = new frameRegistry_js_1.FrameRegistry("target-1", "root-frame");
8
+ registry.onFrameAttached("child-frame", "root-frame", "parent-session");
9
+ registry.adoptChildSession("child-session", "child-frame");
10
+ (0, vitest_1.expect)(registry.listAllFrames()).toEqual(["root-frame", "child-frame"]);
11
+ (0, vitest_1.expect)(registry.getParent("child-frame")).toBe("root-frame");
12
+ (0, vitest_1.expect)(registry.getOwnerSessionId("child-frame")).toBe("child-session");
13
+ (0, vitest_1.expect)(registry.framesForSession("parent-session")).toEqual([]);
14
+ (0, vitest_1.expect)(registry.framesForSession("child-session")).toEqual(["child-frame"]);
15
+ });
16
+ (0, vitest_1.it)("keeps child-session ownership when child target adoption is staged before parent frameAttached", () => {
17
+ const registry = new frameRegistry_js_1.FrameRegistry("target-1", "root-frame");
18
+ registry.adoptChildSession("child-session", "child-frame");
19
+ registry.onFrameAttached("child-frame", "root-frame", "parent-session");
20
+ registry.adoptChildSession("child-session", "child-frame");
21
+ (0, vitest_1.expect)(registry.listAllFrames()).toEqual(["root-frame", "child-frame"]);
22
+ (0, vitest_1.expect)(registry.getParent("child-frame")).toBe("root-frame");
23
+ (0, vitest_1.expect)(registry.getOwnerSessionId("child-frame")).toBe("child-session");
24
+ (0, vitest_1.expect)(registry.framesForSession("parent-session")).toEqual([]);
25
+ (0, vitest_1.expect)(registry.framesForSession("child-session")).toEqual(["child-frame"]);
26
+ });
27
+ (0, vitest_1.it)("preserves the known parent edge when seeding an adopted OOPIF child frame tree", () => {
28
+ const registry = new frameRegistry_js_1.FrameRegistry("target-1", "root-frame");
29
+ registry.onFrameAttached("child-frame", "root-frame", "parent-session");
30
+ registry.adoptChildSession("child-session", "child-frame");
31
+ registry.seedFromFrameTree("child-session", {
32
+ frame: {
33
+ id: "child-frame",
34
+ loaderId: "loader-1",
35
+ name: "payment-frame",
36
+ url: "https://js.stripe.com/v3/elements-inner-payment.html",
37
+ domainAndRegistry: "stripe.com",
38
+ securityOrigin: "https://js.stripe.com",
39
+ mimeType: "text/html",
40
+ secureContextType: "Secure",
41
+ crossOriginIsolatedContextType: "NotIsolated",
42
+ gatedAPIFeatures: [],
43
+ },
44
+ });
45
+ (0, vitest_1.expect)(registry.getParent("child-frame")).toBe("root-frame");
46
+ (0, vitest_1.expect)(registry.asProtocolFrameTree("root-frame")).toMatchObject({
47
+ frame: { id: "root-frame" },
48
+ childFrames: [
49
+ {
50
+ frame: {
51
+ id: "child-frame",
52
+ parentId: "root-frame",
53
+ url: "https://js.stripe.com/v3/elements-inner-payment.html",
54
+ },
55
+ },
56
+ ],
57
+ });
58
+ });
59
+ });
60
+ //# sourceMappingURL=frame-registry-oopif-adoption.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-registry-oopif-adoption.test.js","sourceRoot":"","sources":["../../../../tests/unit/frame-registry-oopif-adoption.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport type { Protocol } from \"devtools-protocol\";\n\nimport { FrameRegistry } from \"../../lib/v3/understudy/frameRegistry.js\";\n\ndescribe(\"FrameRegistry OOPIF adoption ordering\", () => {\n it(\"keeps child-session ownership when parent frameAttached arrives before child target adoption\", () => {\n const registry = new FrameRegistry(\"target-1\", \"root-frame\");\n\n registry.onFrameAttached(\"child-frame\", \"root-frame\", \"parent-session\");\n registry.adoptChildSession(\"child-session\", \"child-frame\");\n\n expect(registry.listAllFrames()).toEqual([\"root-frame\", \"child-frame\"]);\n expect(registry.getParent(\"child-frame\")).toBe(\"root-frame\");\n expect(registry.getOwnerSessionId(\"child-frame\")).toBe(\"child-session\");\n expect(registry.framesForSession(\"parent-session\")).toEqual([]);\n expect(registry.framesForSession(\"child-session\")).toEqual([\"child-frame\"]);\n });\n\n it(\"keeps child-session ownership when child target adoption is staged before parent frameAttached\", () => {\n const registry = new FrameRegistry(\"target-1\", \"root-frame\");\n\n registry.adoptChildSession(\"child-session\", \"child-frame\");\n registry.onFrameAttached(\"child-frame\", \"root-frame\", \"parent-session\");\n registry.adoptChildSession(\"child-session\", \"child-frame\");\n\n expect(registry.listAllFrames()).toEqual([\"root-frame\", \"child-frame\"]);\n expect(registry.getParent(\"child-frame\")).toBe(\"root-frame\");\n expect(registry.getOwnerSessionId(\"child-frame\")).toBe(\"child-session\");\n expect(registry.framesForSession(\"parent-session\")).toEqual([]);\n expect(registry.framesForSession(\"child-session\")).toEqual([\"child-frame\"]);\n });\n\n it(\"preserves the known parent edge when seeding an adopted OOPIF child frame tree\", () => {\n const registry = new FrameRegistry(\"target-1\", \"root-frame\");\n\n registry.onFrameAttached(\"child-frame\", \"root-frame\", \"parent-session\");\n registry.adoptChildSession(\"child-session\", \"child-frame\");\n registry.seedFromFrameTree(\"child-session\", {\n frame: {\n id: \"child-frame\",\n loaderId: \"loader-1\",\n name: \"payment-frame\",\n url: \"https://js.stripe.com/v3/elements-inner-payment.html\",\n domainAndRegistry: \"stripe.com\",\n securityOrigin: \"https://js.stripe.com\",\n mimeType: \"text/html\",\n secureContextType: \"Secure\",\n crossOriginIsolatedContextType: \"NotIsolated\",\n gatedAPIFeatures: [],\n },\n } satisfies Protocol.Page.FrameTree);\n\n expect(registry.getParent(\"child-frame\")).toBe(\"root-frame\");\n expect(registry.asProtocolFrameTree(\"root-frame\")).toMatchObject({\n frame: { id: \"root-frame\" },\n childFrames: [\n {\n frame: {\n id: \"child-frame\",\n parentId: \"root-frame\",\n url: \"https://js.stripe.com/v3/elements-inner-payment.html\",\n },\n },\n ],\n });\n });\n});\n"]}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const zod_1 = require("zod");
4
+ const vitest_1 = require("vitest");
5
+ const inference_js_1 = require("../../lib/inference.js");
6
+ function createLlmClient(responses) {
7
+ const calls = [];
8
+ const createChatCompletion = vitest_1.vi.fn(async (request) => {
9
+ calls.push(request);
10
+ const response = responses.shift();
11
+ if (!response) {
12
+ throw new Error("Unexpected LLM call");
13
+ }
14
+ return response;
15
+ });
16
+ const llmClient = {
17
+ type: "openai",
18
+ modelName: "openai/gpt-5",
19
+ createChatCompletion,
20
+ };
21
+ return { llmClient, calls };
22
+ }
23
+ (0, vitest_1.describe)("shared act/extract/observe inference temperature", () => {
24
+ (0, vitest_1.it)("does not pass temperature for either extract call", async () => {
25
+ const { llmClient, calls } = createLlmClient([
26
+ { data: { answer: "42" } },
27
+ { data: { completed: true, progress: "complete" } },
28
+ ]);
29
+ await (0, inference_js_1.extract)({
30
+ instruction: "extract the answer",
31
+ domElements: "body",
32
+ schema: zod_1.z.object({ answer: zod_1.z.string() }),
33
+ llmClient,
34
+ logger: vitest_1.vi.fn(),
35
+ });
36
+ (0, vitest_1.expect)(calls).toHaveLength(2);
37
+ (0, vitest_1.expect)(calls[0].options).not.toHaveProperty("temperature");
38
+ (0, vitest_1.expect)(calls[1].options).not.toHaveProperty("temperature");
39
+ });
40
+ (0, vitest_1.it)("does not pass temperature for observe", async () => {
41
+ const { llmClient, calls } = createLlmClient([{ data: { elements: [] } }]);
42
+ await (0, inference_js_1.observe)({
43
+ instruction: "find buttons",
44
+ domElements: "body",
45
+ llmClient,
46
+ logger: vitest_1.vi.fn(),
47
+ });
48
+ (0, vitest_1.expect)(calls).toHaveLength(1);
49
+ (0, vitest_1.expect)(calls[0].options).not.toHaveProperty("temperature");
50
+ });
51
+ (0, vitest_1.it)("does not pass temperature for act", async () => {
52
+ const { llmClient, calls } = createLlmClient([
53
+ { data: { action: null, twoStep: false } },
54
+ ]);
55
+ await (0, inference_js_1.act)({
56
+ instruction: "click the button",
57
+ domElements: "body",
58
+ llmClient,
59
+ logger: vitest_1.vi.fn(),
60
+ });
61
+ (0, vitest_1.expect)(calls).toHaveLength(1);
62
+ (0, vitest_1.expect)(calls[0].options).not.toHaveProperty("temperature");
63
+ });
64
+ });
65
+ //# sourceMappingURL=inference-temperature.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inference-temperature.test.js","sourceRoot":"","sources":["../../../../tests/unit/inference-temperature.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport { describe, expect, it, vi } from \"vitest\";\nimport { act, extract, observe } from \"../../lib/inference.js\";\nimport type {\n CreateChatCompletionOptions,\n LLMClient,\n} from \"../../lib/v3/llm/LLMClient.js\";\n\ntype QueuedResponse = {\n data: unknown;\n usage?: Record<string, number>;\n};\n\nfunction createLlmClient(responses: QueuedResponse[]) {\n const calls: CreateChatCompletionOptions[] = [];\n const createChatCompletion = vi.fn(\n async (request: CreateChatCompletionOptions) => {\n calls.push(request);\n const response = responses.shift();\n if (!response) {\n throw new Error(\"Unexpected LLM call\");\n }\n return response;\n },\n );\n\n const llmClient = {\n type: \"openai\",\n modelName: \"openai/gpt-5\",\n createChatCompletion,\n } as unknown as LLMClient;\n\n return { llmClient, calls };\n}\n\ndescribe(\"shared act/extract/observe inference temperature\", () => {\n it(\"does not pass temperature for either extract call\", async () => {\n const { llmClient, calls } = createLlmClient([\n { data: { answer: \"42\" } },\n { data: { completed: true, progress: \"complete\" } },\n ]);\n\n await extract({\n instruction: \"extract the answer\",\n domElements: \"body\",\n schema: z.object({ answer: z.string() }),\n llmClient,\n logger: vi.fn(),\n });\n\n expect(calls).toHaveLength(2);\n expect(calls[0].options).not.toHaveProperty(\"temperature\");\n expect(calls[1].options).not.toHaveProperty(\"temperature\");\n });\n\n it(\"does not pass temperature for observe\", async () => {\n const { llmClient, calls } = createLlmClient([{ data: { elements: [] } }]);\n\n await observe({\n instruction: \"find buttons\",\n domElements: \"body\",\n llmClient,\n logger: vi.fn(),\n });\n\n expect(calls).toHaveLength(1);\n expect(calls[0].options).not.toHaveProperty(\"temperature\");\n });\n\n it(\"does not pass temperature for act\", async () => {\n const { llmClient, calls } = createLlmClient([\n { data: { action: null, twoStep: false } },\n ]);\n\n await act({\n instruction: \"click the button\",\n domElements: \"body\",\n llmClient,\n logger: vi.fn(),\n });\n\n expect(calls).toHaveLength(1);\n expect(calls[0].options).not.toHaveProperty(\"temperature\");\n });\n});\n"]}
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const CerebrasClient_js_1 = require("../../lib/v3/llm/CerebrasClient.js");
5
+ const GroqClient_js_1 = require("../../lib/v3/llm/GroqClient.js");
6
+ function mockCompletionCreate() {
7
+ return vitest_1.vi.fn().mockResolvedValue({
8
+ id: "chatcmpl-test",
9
+ choices: [
10
+ {
11
+ message: {
12
+ role: "assistant",
13
+ content: "ok",
14
+ tool_calls: [],
15
+ },
16
+ finish_reason: "stop",
17
+ },
18
+ ],
19
+ usage: {
20
+ prompt_tokens: 1,
21
+ completion_tokens: 1,
22
+ total_tokens: 2,
23
+ },
24
+ });
25
+ }
26
+ function installMockClient(client) {
27
+ const create = mockCompletionCreate();
28
+ client.client = {
29
+ chat: {
30
+ completions: {
31
+ create,
32
+ },
33
+ },
34
+ };
35
+ return create;
36
+ }
37
+ const logger = vitest_1.vi.fn();
38
+ vitest_1.describe.each([
39
+ [
40
+ "GroqClient",
41
+ () => new GroqClient_js_1.GroqClient({
42
+ modelName: "groq-test-model",
43
+ clientOptions: { apiKey: "test-key" },
44
+ logger,
45
+ }),
46
+ ],
47
+ [
48
+ "CerebrasClient",
49
+ () => new CerebrasClient_js_1.CerebrasClient({
50
+ modelName: "cerebras-test-model",
51
+ clientOptions: { apiKey: "test-key" },
52
+ logger,
53
+ }),
54
+ ],
55
+ ])("%s temperature handling", (_name, createClient) => {
56
+ (0, vitest_1.it)("falls back to 0.7 when temperature is not provided", async () => {
57
+ const client = createClient();
58
+ const create = installMockClient(client);
59
+ await client.createChatCompletion({
60
+ options: {
61
+ messages: [{ role: "user", content: "hello" }],
62
+ },
63
+ logger,
64
+ });
65
+ (0, vitest_1.expect)(create).toHaveBeenCalledWith(vitest_1.expect.objectContaining({
66
+ temperature: 0.7,
67
+ }));
68
+ });
69
+ (0, vitest_1.it)("preserves explicit temperature zero", async () => {
70
+ const client = createClient();
71
+ const create = installMockClient(client);
72
+ await client.createChatCompletion({
73
+ options: {
74
+ messages: [{ role: "user", content: "hello" }],
75
+ temperature: 0,
76
+ },
77
+ logger,
78
+ });
79
+ (0, vitest_1.expect)(create).toHaveBeenCalledWith(vitest_1.expect.objectContaining({
80
+ temperature: 0,
81
+ }));
82
+ });
83
+ });
84
+ //# sourceMappingURL=openai-compatible-temperature.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-compatible-temperature.test.js","sourceRoot":"","sources":["../../../../tests/unit/openai-compatible-temperature.test.ts"],"names":[],"mappings":";;AAAA,mCAAkD;AAClD,0EAAoE;AACpE,kEAA4D;AAe5D,SAAS,oBAAoB;IAC3B,OAAO,WAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC;QAC/B,EAAE,EAAE,eAAe;QACnB,OAAO,EAAE;YACP;gBACE,OAAO,EAAE;oBACP,IAAI,EAAE,WAAW;oBACjB,OAAO,EAAE,IAAI;oBACb,UAAU,EAAE,EAAE;iBACf;gBACD,aAAa,EAAE,MAAM;aACtB;SACF;QACD,KAAK,EAAE;YACL,aAAa,EAAE,CAAC;YAChB,iBAAiB,EAAE,CAAC;YACpB,YAAY,EAAE,CAAC;SAChB;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAiB;IAC1C,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAC;IACrC,MAAiC,CAAC,MAAM,GAAG;QAC1C,IAAI,EAAE;YACJ,WAAW,EAAE;gBACX,MAAM;aACP;SACF;KACF,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,MAAM,GAAG,WAAE,CAAC,EAAE,EAA8B,CAAC;AAEnD,iBAAQ,CAAC,IAAI,CAAC;IACZ;QACE,YAAY;QACZ,GAAG,EAAE,CACH,IAAI,0BAAU,CAAC;YACb,SAAS,EAAE,iBAAmC;YAC9C,aAAa,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;YACrC,MAAM;SACP,CAAC;KACL;IACD;QACE,gBAAgB;QAChB,GAAG,EAAE,CACH,IAAI,kCAAc,CAAC;YACjB,SAAS,EAAE,qBAAuC;YAClD,aAAa,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;YACrC,MAAM;SACP,CAAC;KACL;CACF,CAAC,CAAC,yBAAyB,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE;IACpD,IAAA,WAAE,EAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAEzC,MAAM,MAAM,CAAC,oBAAoB,CAAC;YAChC,OAAO,EAAE;gBACP,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;aAC/C;YACD,MAAM;SACP,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,oBAAoB,CACjC,eAAM,CAAC,gBAAgB,CAAC;YACtB,WAAW,EAAE,GAAG;SACjB,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAEzC,MAAM,MAAM,CAAC,oBAAoB,CAAC;YAChC,OAAO,EAAE;gBACP,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;gBAC9C,WAAW,EAAE,CAAC;aACf;YACD,MAAM;SACP,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,CAAC,oBAAoB,CACjC,eAAM,CAAC,gBAAgB,CAAC;YACtB,WAAW,EAAE,CAAC;SACf,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it, vi } from \"vitest\";\nimport { CerebrasClient } from \"../../lib/v3/llm/CerebrasClient.js\";\nimport { GroqClient } from \"../../lib/v3/llm/GroqClient.js\";\nimport type { LLMClient } from \"../../lib/v3/llm/LLMClient.js\";\nimport type { LogLine } from \"../../lib/v3/types/public/logs.js\";\nimport type { AvailableModel } from \"../../lib/v3/types/public/model.js\";\n\ntype OpenAICompatibleClient = LLMClient & {\n client: {\n chat: {\n completions: {\n create: ReturnType<typeof vi.fn>;\n };\n };\n };\n};\n\nfunction mockCompletionCreate() {\n return vi.fn().mockResolvedValue({\n id: \"chatcmpl-test\",\n choices: [\n {\n message: {\n role: \"assistant\",\n content: \"ok\",\n tool_calls: [],\n },\n finish_reason: \"stop\",\n },\n ],\n usage: {\n prompt_tokens: 1,\n completion_tokens: 1,\n total_tokens: 2,\n },\n });\n}\n\nfunction installMockClient(client: LLMClient) {\n const create = mockCompletionCreate();\n (client as OpenAICompatibleClient).client = {\n chat: {\n completions: {\n create,\n },\n },\n };\n return create;\n}\n\nconst logger = vi.fn<(message: LogLine) => void>();\n\ndescribe.each([\n [\n \"GroqClient\",\n () =>\n new GroqClient({\n modelName: \"groq-test-model\" as AvailableModel,\n clientOptions: { apiKey: \"test-key\" },\n logger,\n }),\n ],\n [\n \"CerebrasClient\",\n () =>\n new CerebrasClient({\n modelName: \"cerebras-test-model\" as AvailableModel,\n clientOptions: { apiKey: \"test-key\" },\n logger,\n }),\n ],\n])(\"%s temperature handling\", (_name, createClient) => {\n it(\"falls back to 0.7 when temperature is not provided\", async () => {\n const client = createClient();\n const create = installMockClient(client);\n\n await client.createChatCompletion({\n options: {\n messages: [{ role: \"user\", content: \"hello\" }],\n },\n logger,\n });\n\n expect(create).toHaveBeenCalledWith(\n expect.objectContaining({\n temperature: 0.7,\n }),\n );\n });\n\n it(\"preserves explicit temperature zero\", async () => {\n const client = createClient();\n const create = installMockClient(client);\n\n await client.createChatCompletion({\n options: {\n messages: [{ role: \"user\", content: \"hello\" }],\n temperature: 0,\n },\n logger,\n });\n\n expect(create).toHaveBeenCalledWith(\n expect.objectContaining({\n temperature: 0,\n }),\n );\n });\n});\n"]}
@@ -15,5 +15,11 @@ const prompt_js_1 = require("../../lib/prompt.js");
15
15
  (0, vitest_1.expect)(prompt.content).toContain("Available variables: %username% (The login email), %password%");
16
16
  (0, vitest_1.expect)(prompt.content).toContain("return the matching %variableName% placeholder");
17
17
  });
18
+ (0, vitest_1.it)("instructs the model to copy complete bracketed element IDs", () => {
19
+ const prompt = (0, prompt_js_1.buildObserveSystemPrompt)(undefined, ["click"]);
20
+ (0, vitest_1.expect)(prompt.content).toContain("Always copy the complete ID exactly as shown inside the brackets into elementId");
21
+ (0, vitest_1.expect)(prompt.content).toContain('return elementId "0-18372"');
22
+ (0, vitest_1.expect)(prompt.content).toContain('never return only "18372"');
23
+ });
18
24
  });
19
25
  //# sourceMappingURL=prompt-observe-variables.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-observe-variables.test.js","sourceRoot":"","sources":["../../../../tests/unit/prompt-observe-variables.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,mDAA+D;AAE/D,IAAA,iBAAQ,EAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,IAAA,WAAE,EAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,IAAA,oCAAwB,EAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE;YACpE,QAAQ,EAAE;gBACR,KAAK,EAAE,kBAAkB;gBACzB,WAAW,EAAE,iBAAiB;aAC/B;YACD,QAAQ,EAAE,WAAW;SACtB,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;QACnE,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAC9B,+DAA+D,CAChE,CAAC;QACF,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAC9B,gDAAgD,CACjD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { buildObserveSystemPrompt } from \"../../lib/prompt.js\";\n\ndescribe(\"buildObserveSystemPrompt\", () => {\n it(\"includes variable descriptions when present\", () => {\n const prompt = buildObserveSystemPrompt(undefined, [\"click\", \"fill\"], {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret123\",\n });\n\n expect(prompt.content).toContain(\"Supported actions: click, fill\");\n expect(prompt.content).toContain(\n \"Available variables: %username% (The login email), %password%\",\n );\n expect(prompt.content).toContain(\n \"return the matching %variableName% placeholder\",\n );\n });\n});\n"]}
1
+ {"version":3,"file":"prompt-observe-variables.test.js","sourceRoot":"","sources":["../../../../tests/unit/prompt-observe-variables.test.ts"],"names":[],"mappings":";;AAAA,mCAA8C;AAC9C,mDAA+D;AAE/D,IAAA,iBAAQ,EAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,IAAA,WAAE,EAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,MAAM,GAAG,IAAA,oCAAwB,EAAC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE;YACpE,QAAQ,EAAE;gBACR,KAAK,EAAE,kBAAkB;gBACzB,WAAW,EAAE,iBAAiB;aAC/B;YACD,QAAQ,EAAE,WAAW;SACtB,CAAC,CAAC;QAEH,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,gCAAgC,CAAC,CAAC;QACnE,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAC9B,+DAA+D,CAChE,CAAC;QACF,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAC9B,gDAAgD,CACjD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAA,WAAE,EAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,MAAM,GAAG,IAAA,oCAAwB,EAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAE9D,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAC9B,iFAAiF,CAClF,CAAC;QACF,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;QAC/D,IAAA,eAAM,EAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport { buildObserveSystemPrompt } from \"../../lib/prompt.js\";\n\ndescribe(\"buildObserveSystemPrompt\", () => {\n it(\"includes variable descriptions when present\", () => {\n const prompt = buildObserveSystemPrompt(undefined, [\"click\", \"fill\"], {\n username: {\n value: \"john@example.com\",\n description: \"The login email\",\n },\n password: \"secret123\",\n });\n\n expect(prompt.content).toContain(\"Supported actions: click, fill\");\n expect(prompt.content).toContain(\n \"Available variables: %username% (The login email), %password%\",\n );\n expect(prompt.content).toContain(\n \"return the matching %variableName% placeholder\",\n );\n });\n\n it(\"instructs the model to copy complete bracketed element IDs\", () => {\n const prompt = buildObserveSystemPrompt(undefined, [\"click\"]);\n\n expect(prompt.content).toContain(\n \"Always copy the complete ID exactly as shown inside the brackets into elementId\",\n );\n expect(prompt.content).toContain('return elementId \"0-18372\"');\n expect(prompt.content).toContain('never return only \"18372\"');\n });\n});\n"]}
@@ -65,9 +65,12 @@ const Stagehand = __importStar(require("@browserbasehq/stagehand"));
65
65
  "openai/computer-use-preview",
66
66
  "openai/computer-use-preview-2025-03-11",
67
67
  "openai/gpt-5.4",
68
+ "openai/gpt-5.4-mini",
69
+ "openai/gpt-5.5",
68
70
  "anthropic/claude-opus-4-5-20251101",
69
71
  "anthropic/claude-opus-4-6",
70
72
  "anthropic/claude-sonnet-4-6",
73
+ "anthropic/claude-haiku-4-5",
71
74
  "anthropic/claude-haiku-4-5-20251001",
72
75
  "anthropic/claude-sonnet-4-20250514",
73
76
  "anthropic/claude-sonnet-4-5-20250929",
@@ -1 +1 @@
1
- {"version":3,"file":"llm-and-agents.test.js","sourceRoot":"","sources":["../../../../../tests/unit/public-api/llm-and-agents.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mCAA4D;AAC5D,oEAAsD;AAEtD,IAAA,iBAAQ,EAAC,iCAAiC,EAAE,GAAG,EAAE;IAC/C,IAAA,iBAAQ,EAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,IAAA,WAAE,EAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,YAAY,GAAG;gBACnB,SAAS,EAAE,+BAA+B;gBAC1C,OAAO,EAAE,cAAc;gBACvB,QAAQ,EAAE,QAAQ;gBAClB,OAAO,EAAE;oBACP,iBAAiB,EAAE,MAAM;iBAC1B;aACqC,CAAC;YAEzC,KAAK,YAAY,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,iBAAQ,EAAC,aAAa,EAAE,GAAG,EAAE;QAG3B,IAAA,WAAE,EAAC,aAAa,EAAE,GAAG,EAAE;YACrB,IAAA,eAAM,EAAC,SAAS,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,mBAAmB,EAAE,GAAG,EAAE;YAC3B,IAAA,qBAAY,GAAuB,CAAC,QAAQ,EAAuB,CAAC;QACtE,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,qCAAqC,EAAE,GAAG,EAAE;YAG7C,IAAA,qBAAY,GAAwB,CAAC,aAAa,EAAK,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,iBAAQ,EAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,MAAM,cAAc,GAAG;YACrB,6BAA6B;YAC7B,wCAAwC;YACxC,gBAAgB;YAChB,oCAAoC;YACpC,2BAA2B;YAC3B,6BAA6B;YAC7B,qCAAqC;YACrC,oCAAoC;YACpC,sCAAsC;YACtC,gDAAgD;YAChD,+BAA+B;YAC/B,6BAA6B;YAC7B,mBAAmB;SACX,CAAC;QAEX,IAAA,WAAE,EAAC,8CAA8C,EAAE,GAAG,EAAE;YACtD,IAAA,qBAAY,GAA+B,CAAC,aAAa,EAEtD,CAAC;YACJ,KAAK,cAAc,CAAC,CAAC,iCAAiC;QACxD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,iBAAQ,EAAC,eAAe,EAAE,GAAG,EAAE;QAG7B,IAAA,WAAE,EAAC,aAAa,EAAE,GAAG,EAAE;YACrB,IAAA,eAAM,EAAC,SAAS,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,sBAAsB,EAAE,GAAG,EAAE;YAC9B,IAAA,qBAAY,GAAsC,CAAC,gBAAgB,CACjE,YAAY,CACb,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,IAAA,qBAAY,GAET,CAAC,aAAa,EAA0C,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,iBAAQ,EAAC,yBAAyB,EAAE,GAAG,EAAE;QAGvC,IAAA,WAAE,EAAC,qBAAqB,EAAE,GAAG,EAAE;YAC7B,IAAA,qBAAY,GAET,CAAC,QAAQ,EAAmC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,iBAAQ,EAAC,gBAAgB,EAAE,GAAG,EAAE;QAkB9B,IAAA,WAAE,EAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,IAAA,qBAAY,GAA0B,CAAC,QAAQ,EAAiB,CAAC;QACnE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,iBAAQ,EAAC,aAAa,EAAE,GAAG,EAAE;QAI3B,IAAA,WAAE,EAAC,gDAAgD,EAAE,GAAG,EAAE;YAexD,IAAA,qBAAY,GAAmB,CAAC,QAAQ,EAAiB,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,iBAAQ,EAAC,WAAW,EAAE,GAAG,EAAE;QAiCzB,IAAA,WAAE,EAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,IAAA,qBAAY,GAAqB,CAAC,QAAQ,EAAiB,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,IAAA,qBAAY,GAET,CAAC,aAAa,EAAsB,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,IAAA,qBAAY,GAET,CAAC,gBAAgB,CAAC;gBACnB,OAAO,EAAE;oBACP,QAAQ,EAAE;wBACR;4BACE,IAAI,EAAE,MAAM;4BACZ,OAAO,EAAE,OAAO;yBACjB;qBACF;iBACF;gBACD,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;aACc,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,wDAAwD,EAAE,GAAG,EAAE;YAChE,MAAM,UAAU,GAAG,EAAkC,CAAC;YACtD,IAAA,qBAAY,GAET,CAAC,gBAAgB,CAAC;gBACnB,OAAO,EAAE;oBACP,QAAQ,EAAE;wBACR;4BACE,IAAI,EAAE,MAAM;4BACZ,OAAO,EAAE,cAAc;yBACxB;qBACF;oBACD,cAAc,EAAE;wBACd,IAAI,EAAE,WAAW;wBACjB,MAAM,EAAE,UAAU;qBACnB;iBACF;gBACD,MAAM,EAAE,GAAG,EAAE,GAAE,CAAC;aACmB,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,mDAAmD,EAAE,GAAG,EAAE;YAM3D,IAAA,qBAAY,GAET,CAAC,QAAQ,EAAqB,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,IAAA,WAAE,EAAC,wBAAwB,EAAE,GAAG,EAAE;YAChC,qFAAqF;YACrF,qDAAqD;YACrD,IAAA,qBAAY,GAAqC,CAAC,QAAQ,EAEvD,CAAC;YACJ,IAAA,qBAAY,GAAuC,CAAC,QAAQ,EAEzD,CAAC;YACJ,IAAA,qBAAY,GAAmC,CAAC,QAAQ,EAErD,CAAC;YACJ,IAAA,qBAAY,GAAqC,CAAC,QAAQ,EAEvD,CAAC;YACJ,IAAA,qBAAY,GAAsC,CAAC,QAAQ,EAExD,CAAC;YACJ,IAAA,qBAAY,GAA8B,CAAC,QAAQ,EAEhD,CAAC;YACJ,IAAA,qBAAY,GAAkC,CAAC,QAAQ,EAEpD,CAAC;YACJ,IAAA,qBAAY,GAAmC,CAAC,QAAQ,EAErD,CAAC;YACJ,IAAA,qBAAY,GAAuC,CAAC,QAAQ,EAEzD,CAAC;QACN,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,iBAAQ,EAAC,yBAAyB,EAAE,GAAG,EAAE;QAMvC,IAAA,WAAE,EAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,IAAA,qBAAY,GAET,CAAC,QAAQ,EAAmC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,IAAA,iBAAQ,EAAC,UAAU,EAAE,GAAG,EAAE;QAyBxB,IAAA,WAAE,EAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,IAAA,qBAAY,GAAoB,CAAC,QAAQ,EAAiB,CAAC;QAC7D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, expectTypeOf, it } from \"vitest\";\nimport * as Stagehand from \"@browserbasehq/stagehand\";\n\ndescribe(\"LLM and Agents public API types\", () => {\n describe(\"ModelConfiguration\", () => {\n it(\"accepts Vertex headers in model config\", () => {\n const googleConfig = {\n modelName: \"google/gemini-3-flash-preview\",\n project: \"test-project\",\n location: \"global\",\n headers: {\n \"X-Goog-Priority\": \"high\",\n },\n } satisfies Stagehand.ModelConfiguration;\n\n void googleConfig;\n });\n });\n\n describe(\"AISdkClient\", () => {\n type AISdkClientInstance = InstanceType<typeof Stagehand.AISdkClient>;\n\n it(\"is exported\", () => {\n expect(Stagehand.AISdkClient).toBeDefined();\n });\n\n it(\"extends LLMClient\", () => {\n expectTypeOf<AISdkClientInstance>().toExtend<Stagehand.LLMClient>();\n });\n\n it(\"constructor accepts model parameter\", () => {\n // AISdkClient constructor takes { model: LanguageModelV2 }\n type CtorParams = ConstructorParameters<typeof Stagehand.AISdkClient>;\n expectTypeOf<CtorParams[\"length\"]>().toEqualTypeOf<1>();\n });\n });\n\n describe(\"AVAILABLE_CUA_MODELS\", () => {\n const expectedModels = [\n \"openai/computer-use-preview\",\n \"openai/computer-use-preview-2025-03-11\",\n \"openai/gpt-5.4\",\n \"anthropic/claude-opus-4-5-20251101\",\n \"anthropic/claude-opus-4-6\",\n \"anthropic/claude-sonnet-4-6\",\n \"anthropic/claude-haiku-4-5-20251001\",\n \"anthropic/claude-sonnet-4-20250514\",\n \"anthropic/claude-sonnet-4-5-20250929\",\n \"google/gemini-2.5-computer-use-preview-10-2025\",\n \"google/gemini-3-flash-preview\",\n \"google/gemini-3-pro-preview\",\n \"microsoft/fara-7b\",\n ] as const;\n\n it(\"AvailableCuaModel matches the known literals\", () => {\n expectTypeOf<Stagehand.AvailableCuaModel>().toEqualTypeOf<\n (typeof expectedModels)[number]\n >();\n void expectedModels; // Mark as used to satisfy ESLint\n });\n });\n\n describe(\"AgentProvider\", () => {\n type AgentProviderInstance = InstanceType<typeof Stagehand.AgentProvider>;\n\n it(\"is exported\", () => {\n expect(Stagehand.AgentProvider).toBeDefined();\n });\n\n it(\"has getClient method\", () => {\n expectTypeOf<AgentProviderInstance[\"getClient\"]>().toBeCallableWith(\n \"test-model\",\n );\n });\n\n it(\"constructor accepts logger parameter\", () => {\n expectTypeOf<\n ConstructorParameters<typeof Stagehand.AgentProvider>\n >().toEqualTypeOf<[(message: Stagehand.LogLine) => void]>();\n });\n });\n\n describe(\"AnnotatedScreenshotText\", () => {\n type ExpectedAnnotatedScreenshotText = string;\n\n it(\"is a string literal\", () => {\n expectTypeOf<\n typeof Stagehand.AnnotatedScreenshotText\n >().toExtend<ExpectedAnnotatedScreenshotText>();\n });\n });\n\n describe(\"ConsoleMessage\", () => {\n type ExpectedShape = {\n type: () => string;\n text: () => string;\n args: () => unknown[];\n location: () => {\n url?: string;\n lineNumber?: number;\n columnNumber?: number;\n };\n page: () => unknown;\n timestamp: () => number | undefined;\n raw: () => unknown;\n toString: () => string;\n };\n\n type ConsoleMessageInstance = InstanceType<typeof Stagehand.ConsoleMessage>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<ConsoleMessageInstance>().toExtend<ExpectedShape>();\n });\n });\n\n describe(\"AgentClient\", () => {\n type AgentProviderInstance = InstanceType<typeof Stagehand.AgentProvider>;\n type GetClientReturn = ReturnType<AgentProviderInstance[\"getClient\"]>;\n\n it(\"getClient returns object with expected methods\", () => {\n type ExpectedShape = {\n execute: (\n options: Stagehand.AgentExecutionOptions,\n ) => Promise<Stagehand.AgentResult>;\n captureScreenshot: (\n options?: Record<string, unknown>,\n ) => Promise<unknown>;\n setViewport: (width: number, height: number) => void;\n setCurrentUrl: (url: string) => void;\n setScreenshotProvider: (provider: () => Promise<string>) => void;\n setActionHandler: (\n handler: (action: Stagehand.AgentAction) => Promise<void>,\n ) => void;\n };\n expectTypeOf<GetClientReturn>().toExtend<ExpectedShape>();\n });\n });\n\n describe(\"LLMClient\", () => {\n type ExpectedShape = {\n type: \"openai\" | \"anthropic\" | \"cerebras\" | \"groq\" | (string & {});\n modelName: Stagehand.AvailableModel | (string & {});\n hasVision: boolean;\n clientOptions: Stagehand.ClientOptions;\n userProvidedInstructions?: string;\n };\n\n type ExpectedCtorParams = [Stagehand.AvailableModel, string?];\n\n type ExpectedBasicOptions = {\n options: {\n messages: Array<{\n role: \"system\" | \"user\" | \"assistant\";\n content: string | Array<unknown>;\n }>;\n };\n logger: (message: unknown) => void;\n retries?: number;\n };\n\n type ExpectedWithResponseModel = ExpectedBasicOptions & {\n options: ExpectedBasicOptions[\"options\"] & {\n response_model: {\n name: string;\n schema: Stagehand.StagehandZodSchema;\n };\n };\n };\n\n type LLMClientInstance = InstanceType<typeof Stagehand.LLMClient>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<LLMClientInstance>().toExtend<ExpectedShape>();\n });\n\n it(\"constructor parameters match expected signature\", () => {\n expectTypeOf<\n ConstructorParameters<typeof Stagehand.LLMClient>\n >().toEqualTypeOf<ExpectedCtorParams>();\n });\n\n it(\"createChatCompletion can be called with basic options\", () => {\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toBeCallableWith({\n options: {\n messages: [\n {\n role: \"user\",\n content: \"Hello\",\n },\n ],\n },\n logger: () => {},\n } satisfies ExpectedBasicOptions);\n });\n\n it(\"createChatCompletion can be called with response_model\", () => {\n const mockSchema = {} as Stagehand.StagehandZodSchema;\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toBeCallableWith({\n options: {\n messages: [\n {\n role: \"user\",\n content: \"Extract data\",\n },\n ],\n response_model: {\n name: \"extracted\",\n schema: mockSchema,\n },\n },\n logger: () => {},\n } satisfies ExpectedWithResponseModel);\n });\n\n it(\"createChatCompletion supports generic return type\", () => {\n type Result = { custom: string };\n type ExpectedSignature = (\n options: Stagehand.CreateChatCompletionOptions,\n ) => Promise<Result>;\n\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toExtend<ExpectedSignature>();\n });\n\n it(\"has additional methods\", () => {\n // These methods exist on LLMClient but have complex signatures from the 'ai' library\n // We verify they exist by checking they're functions\n expectTypeOf<LLMClientInstance[\"generateText\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateObject\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"streamText\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"streamObject\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateImage\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"embed\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"embedMany\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"transcribe\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateSpeech\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n });\n });\n\n describe(\"modelToAgentProviderMap\", () => {\n type ExpectedModelToAgentProviderMap = Record<\n string,\n Stagehand.AgentProviderType\n >;\n\n it(\"only stores valid provider types\", () => {\n expectTypeOf<\n typeof Stagehand.modelToAgentProviderMap\n >().toExtend<ExpectedModelToAgentProviderMap>();\n });\n });\n\n describe(\"Response\", () => {\n type ExpectedShape = {\n url: () => string;\n status: () => number;\n statusText: () => string;\n ok: () => boolean;\n frame: () => unknown;\n fromServiceWorker: () => boolean;\n securityDetails: () => Promise<unknown>;\n serverAddr: () => Promise<unknown>;\n headers: () => Record<string, string>;\n allHeaders: () => Promise<Record<string, string>>;\n headerValue: (name: string) => Promise<string | null>;\n headerValues: (name: string) => Promise<string[]>;\n headersArray: () => Promise<Array<{ name: string; value: string }>>;\n body: () => Promise<Buffer>;\n text: () => Promise<string>;\n json: <T = unknown>() => Promise<T>;\n finished: () => Promise<null | Error>;\n markFinished: (error: Error | null) => void;\n applyExtraInfo: (info: unknown) => void;\n };\n\n type ResponseInstance = InstanceType<typeof Stagehand.Response>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<ResponseInstance>().toExtend<ExpectedShape>();\n });\n });\n});\n"]}
1
+ {"version":3,"file":"llm-and-agents.test.js","sourceRoot":"","sources":["../../../../../tests/unit/public-api/llm-and-agents.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, expectTypeOf, it } from \"vitest\";\nimport * as Stagehand from \"@browserbasehq/stagehand\";\n\ndescribe(\"LLM and Agents public API types\", () => {\n describe(\"ModelConfiguration\", () => {\n it(\"accepts Vertex headers in model config\", () => {\n const googleConfig = {\n modelName: \"google/gemini-3-flash-preview\",\n project: \"test-project\",\n location: \"global\",\n headers: {\n \"X-Goog-Priority\": \"high\",\n },\n } satisfies Stagehand.ModelConfiguration;\n\n void googleConfig;\n });\n });\n\n describe(\"AISdkClient\", () => {\n type AISdkClientInstance = InstanceType<typeof Stagehand.AISdkClient>;\n\n it(\"is exported\", () => {\n expect(Stagehand.AISdkClient).toBeDefined();\n });\n\n it(\"extends LLMClient\", () => {\n expectTypeOf<AISdkClientInstance>().toExtend<Stagehand.LLMClient>();\n });\n\n it(\"constructor accepts model parameter\", () => {\n // AISdkClient constructor takes { model: LanguageModelV2 }\n type CtorParams = ConstructorParameters<typeof Stagehand.AISdkClient>;\n expectTypeOf<CtorParams[\"length\"]>().toEqualTypeOf<1>();\n });\n });\n\n describe(\"AVAILABLE_CUA_MODELS\", () => {\n const expectedModels = [\n \"openai/computer-use-preview\",\n \"openai/computer-use-preview-2025-03-11\",\n \"openai/gpt-5.4\",\n \"openai/gpt-5.4-mini\",\n \"openai/gpt-5.5\",\n \"anthropic/claude-opus-4-5-20251101\",\n \"anthropic/claude-opus-4-6\",\n \"anthropic/claude-sonnet-4-6\",\n \"anthropic/claude-haiku-4-5\",\n \"anthropic/claude-haiku-4-5-20251001\",\n \"anthropic/claude-sonnet-4-20250514\",\n \"anthropic/claude-sonnet-4-5-20250929\",\n \"google/gemini-2.5-computer-use-preview-10-2025\",\n \"google/gemini-3-flash-preview\",\n \"google/gemini-3-pro-preview\",\n \"microsoft/fara-7b\",\n ] as const;\n\n it(\"AvailableCuaModel matches the known literals\", () => {\n expectTypeOf<Stagehand.AvailableCuaModel>().toEqualTypeOf<\n (typeof expectedModels)[number]\n >();\n void expectedModels; // Mark as used to satisfy ESLint\n });\n });\n\n describe(\"AgentProvider\", () => {\n type AgentProviderInstance = InstanceType<typeof Stagehand.AgentProvider>;\n\n it(\"is exported\", () => {\n expect(Stagehand.AgentProvider).toBeDefined();\n });\n\n it(\"has getClient method\", () => {\n expectTypeOf<AgentProviderInstance[\"getClient\"]>().toBeCallableWith(\n \"test-model\",\n );\n });\n\n it(\"constructor accepts logger parameter\", () => {\n expectTypeOf<\n ConstructorParameters<typeof Stagehand.AgentProvider>\n >().toEqualTypeOf<[(message: Stagehand.LogLine) => void]>();\n });\n });\n\n describe(\"AnnotatedScreenshotText\", () => {\n type ExpectedAnnotatedScreenshotText = string;\n\n it(\"is a string literal\", () => {\n expectTypeOf<\n typeof Stagehand.AnnotatedScreenshotText\n >().toExtend<ExpectedAnnotatedScreenshotText>();\n });\n });\n\n describe(\"ConsoleMessage\", () => {\n type ExpectedShape = {\n type: () => string;\n text: () => string;\n args: () => unknown[];\n location: () => {\n url?: string;\n lineNumber?: number;\n columnNumber?: number;\n };\n page: () => unknown;\n timestamp: () => number | undefined;\n raw: () => unknown;\n toString: () => string;\n };\n\n type ConsoleMessageInstance = InstanceType<typeof Stagehand.ConsoleMessage>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<ConsoleMessageInstance>().toExtend<ExpectedShape>();\n });\n });\n\n describe(\"AgentClient\", () => {\n type AgentProviderInstance = InstanceType<typeof Stagehand.AgentProvider>;\n type GetClientReturn = ReturnType<AgentProviderInstance[\"getClient\"]>;\n\n it(\"getClient returns object with expected methods\", () => {\n type ExpectedShape = {\n execute: (\n options: Stagehand.AgentExecutionOptions,\n ) => Promise<Stagehand.AgentResult>;\n captureScreenshot: (\n options?: Record<string, unknown>,\n ) => Promise<unknown>;\n setViewport: (width: number, height: number) => void;\n setCurrentUrl: (url: string) => void;\n setScreenshotProvider: (provider: () => Promise<string>) => void;\n setActionHandler: (\n handler: (action: Stagehand.AgentAction) => Promise<void>,\n ) => void;\n };\n expectTypeOf<GetClientReturn>().toExtend<ExpectedShape>();\n });\n });\n\n describe(\"LLMClient\", () => {\n type ExpectedShape = {\n type: \"openai\" | \"anthropic\" | \"cerebras\" | \"groq\" | (string & {});\n modelName: Stagehand.AvailableModel | (string & {});\n hasVision: boolean;\n clientOptions: Stagehand.ClientOptions;\n userProvidedInstructions?: string;\n };\n\n type ExpectedCtorParams = [Stagehand.AvailableModel, string?];\n\n type ExpectedBasicOptions = {\n options: {\n messages: Array<{\n role: \"system\" | \"user\" | \"assistant\";\n content: string | Array<unknown>;\n }>;\n };\n logger: (message: unknown) => void;\n retries?: number;\n };\n\n type ExpectedWithResponseModel = ExpectedBasicOptions & {\n options: ExpectedBasicOptions[\"options\"] & {\n response_model: {\n name: string;\n schema: Stagehand.StagehandZodSchema;\n };\n };\n };\n\n type LLMClientInstance = InstanceType<typeof Stagehand.LLMClient>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<LLMClientInstance>().toExtend<ExpectedShape>();\n });\n\n it(\"constructor parameters match expected signature\", () => {\n expectTypeOf<\n ConstructorParameters<typeof Stagehand.LLMClient>\n >().toEqualTypeOf<ExpectedCtorParams>();\n });\n\n it(\"createChatCompletion can be called with basic options\", () => {\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toBeCallableWith({\n options: {\n messages: [\n {\n role: \"user\",\n content: \"Hello\",\n },\n ],\n },\n logger: () => {},\n } satisfies ExpectedBasicOptions);\n });\n\n it(\"createChatCompletion can be called with response_model\", () => {\n const mockSchema = {} as Stagehand.StagehandZodSchema;\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toBeCallableWith({\n options: {\n messages: [\n {\n role: \"user\",\n content: \"Extract data\",\n },\n ],\n response_model: {\n name: \"extracted\",\n schema: mockSchema,\n },\n },\n logger: () => {},\n } satisfies ExpectedWithResponseModel);\n });\n\n it(\"createChatCompletion supports generic return type\", () => {\n type Result = { custom: string };\n type ExpectedSignature = (\n options: Stagehand.CreateChatCompletionOptions,\n ) => Promise<Result>;\n\n expectTypeOf<\n LLMClientInstance[\"createChatCompletion\"]\n >().toExtend<ExpectedSignature>();\n });\n\n it(\"has additional methods\", () => {\n // These methods exist on LLMClient but have complex signatures from the 'ai' library\n // We verify they exist by checking they're functions\n expectTypeOf<LLMClientInstance[\"generateText\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateObject\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"streamText\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"streamObject\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateImage\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"embed\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"embedMany\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"transcribe\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n expectTypeOf<LLMClientInstance[\"generateSpeech\"]>().toExtend<\n (...args: unknown[]) => unknown\n >();\n });\n });\n\n describe(\"modelToAgentProviderMap\", () => {\n type ExpectedModelToAgentProviderMap = Record<\n string,\n Stagehand.AgentProviderType\n >;\n\n it(\"only stores valid provider types\", () => {\n expectTypeOf<\n typeof Stagehand.modelToAgentProviderMap\n >().toExtend<ExpectedModelToAgentProviderMap>();\n });\n });\n\n describe(\"Response\", () => {\n type ExpectedShape = {\n url: () => string;\n status: () => number;\n statusText: () => string;\n ok: () => boolean;\n frame: () => unknown;\n fromServiceWorker: () => boolean;\n securityDetails: () => Promise<unknown>;\n serverAddr: () => Promise<unknown>;\n headers: () => Record<string, string>;\n allHeaders: () => Promise<Record<string, string>>;\n headerValue: (name: string) => Promise<string | null>;\n headerValues: (name: string) => Promise<string[]>;\n headersArray: () => Promise<Array<{ name: string; value: string }>>;\n body: () => Promise<Buffer>;\n text: () => Promise<string>;\n json: <T = unknown>() => Promise<T>;\n finished: () => Promise<null | Error>;\n markFinished: (error: Error | null) => void;\n applyExtraInfo: (info: unknown) => void;\n };\n\n type ResponseInstance = InstanceType<typeof Stagehand.Response>;\n\n it(\"has correct public interface shape\", () => {\n expectTypeOf<ResponseInstance>().toExtend<ExpectedShape>();\n });\n });\n});\n"]}