@browserbasehq/orca 3.2.0-preview.5 → 3.2.1-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 (176) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/lib/inference.js +29 -22
  3. package/dist/cjs/lib/inference.js.map +1 -1
  4. package/dist/cjs/lib/prompt.js +18 -21
  5. package/dist/cjs/lib/prompt.js.map +1 -1
  6. package/dist/cjs/lib/v3/agent/AgentProvider.js +1 -0
  7. package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
  8. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.d.ts +3 -1
  9. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js +60 -9
  10. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
  11. package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.js +15 -0
  12. package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.js.map +1 -1
  13. package/dist/cjs/lib/v3/agent/OpenAICUAClient.d.ts +8 -2
  14. package/dist/cjs/lib/v3/agent/OpenAICUAClient.js +103 -49
  15. package/dist/cjs/lib/v3/agent/OpenAICUAClient.js.map +1 -1
  16. package/dist/cjs/lib/v3/agent/tools/index.js +1 -1
  17. package/dist/cjs/lib/v3/agent/tools/index.js.map +1 -1
  18. package/dist/cjs/lib/v3/agent/tools/keys.d.ts +2 -1
  19. package/dist/cjs/lib/v3/agent/tools/keys.js +57 -49
  20. package/dist/cjs/lib/v3/agent/tools/keys.js.map +1 -1
  21. package/dist/cjs/lib/v3/agent/utils/coordinateNormalization.js +3 -5
  22. package/dist/cjs/lib/v3/agent/utils/coordinateNormalization.js.map +1 -1
  23. package/dist/cjs/lib/v3/api.d.ts +5 -3
  24. package/dist/cjs/lib/v3/api.js +3 -6
  25. package/dist/cjs/lib/v3/api.js.map +1 -1
  26. package/dist/cjs/lib/v3/cache/AgentCache.js +5 -3
  27. package/dist/cjs/lib/v3/cache/AgentCache.js.map +1 -1
  28. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js +6 -15
  29. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  30. package/dist/cjs/lib/v3/index.d.ts +1 -1
  31. package/dist/cjs/lib/v3/llm/LLMProvider.d.ts +5 -2
  32. package/dist/cjs/lib/v3/llm/LLMProvider.js +14 -6
  33. package/dist/cjs/lib/v3/llm/LLMProvider.js.map +1 -1
  34. package/dist/cjs/lib/v3/llm/OpenAIClient.js +1 -0
  35. package/dist/cjs/lib/v3/llm/OpenAIClient.js.map +1 -1
  36. package/dist/cjs/lib/v3/llm/aisdk.d.ts +3 -1
  37. package/dist/cjs/lib/v3/llm/aisdk.js +67 -17
  38. package/dist/cjs/lib/v3/llm/aisdk.js.map +1 -1
  39. package/dist/cjs/lib/v3/types/public/agent.d.ts +8 -3
  40. package/dist/cjs/lib/v3/types/public/agent.js +1 -0
  41. package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
  42. package/dist/cjs/lib/v3/types/public/api.d.ts +30 -0
  43. package/dist/cjs/lib/v3/types/public/api.js +6 -2
  44. package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
  45. package/dist/cjs/lib/v3/types/public/model.d.ts +32 -2
  46. package/dist/cjs/lib/v3/types/public/model.js.map +1 -1
  47. package/dist/cjs/lib/v3/understudy/context.js +11 -3
  48. package/dist/cjs/lib/v3/understudy/context.js.map +1 -1
  49. package/dist/cjs/lib/v3/understudy/page.js +1 -1
  50. package/dist/cjs/lib/v3/understudy/page.js.map +1 -1
  51. package/dist/cjs/lib/v3/v3.d.ts +18 -2
  52. package/dist/cjs/lib/v3/v3.js +92 -9
  53. package/dist/cjs/lib/v3/v3.js.map +1 -1
  54. package/dist/cjs/tests/integration/chrome-newtab-page-tracking.spec.d.ts +1 -0
  55. package/dist/cjs/tests/integration/chrome-newtab-page-tracking.spec.js +56 -0
  56. package/dist/cjs/tests/integration/chrome-newtab-page-tracking.spec.js.map +1 -0
  57. package/dist/cjs/tests/integration/flowLogger.spec.js +12 -8
  58. package/dist/cjs/tests/integration/flowLogger.spec.js.map +1 -1
  59. package/dist/cjs/tests/integration/testUtils.js +1 -1
  60. package/dist/cjs/tests/integration/testUtils.js.map +1 -1
  61. package/dist/cjs/tests/integration/timeouts.spec.js +6 -4
  62. package/dist/cjs/tests/integration/timeouts.spec.js.map +1 -1
  63. package/dist/cjs/tests/unit/agent-captcha-hooks.test.js +56 -0
  64. package/dist/cjs/tests/unit/agent-captcha-hooks.test.js.map +1 -1
  65. package/dist/cjs/tests/unit/agent-metrics.test.d.ts +1 -0
  66. package/dist/cjs/tests/unit/agent-metrics.test.js +112 -0
  67. package/dist/cjs/tests/unit/agent-metrics.test.js.map +1 -0
  68. package/dist/cjs/tests/unit/aisdk-clients.test.d.ts +1 -0
  69. package/dist/cjs/tests/unit/aisdk-clients.test.js +90 -0
  70. package/dist/cjs/tests/unit/aisdk-clients.test.js.map +1 -0
  71. package/dist/cjs/tests/unit/anthropic-cua-adaptive-thinking.test.d.ts +1 -0
  72. package/dist/cjs/tests/unit/anthropic-cua-adaptive-thinking.test.js +250 -0
  73. package/dist/cjs/tests/unit/anthropic-cua-adaptive-thinking.test.js.map +1 -0
  74. package/dist/cjs/tests/unit/api-optional-model-api-key.test.d.ts +1 -0
  75. package/dist/cjs/tests/unit/api-optional-model-api-key.test.js +95 -0
  76. package/dist/cjs/tests/unit/api-optional-model-api-key.test.js.map +1 -0
  77. package/dist/cjs/tests/unit/browserbase-session-accessors.test.js +20 -0
  78. package/dist/cjs/tests/unit/browserbase-session-accessors.test.js.map +1 -1
  79. package/dist/cjs/tests/unit/llm-middleware.test.d.ts +1 -0
  80. package/dist/cjs/tests/unit/llm-middleware.test.js +495 -0
  81. package/dist/cjs/tests/unit/llm-middleware.test.js.map +1 -0
  82. package/dist/cjs/tests/unit/microsoft-cua-client.test.d.ts +1 -0
  83. package/dist/cjs/tests/unit/microsoft-cua-client.test.js +86 -0
  84. package/dist/cjs/tests/unit/microsoft-cua-client.test.js.map +1 -0
  85. package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js +1 -0
  86. package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
  87. package/dist/esm/lib/inference.js +29 -22
  88. package/dist/esm/lib/inference.js.map +1 -1
  89. package/dist/esm/lib/prompt.js +18 -21
  90. package/dist/esm/lib/prompt.js.map +1 -1
  91. package/dist/esm/lib/v3/agent/AgentProvider.js +1 -0
  92. package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
  93. package/dist/esm/lib/v3/agent/AnthropicCUAClient.d.ts +3 -1
  94. package/dist/esm/lib/v3/agent/AnthropicCUAClient.js +60 -9
  95. package/dist/esm/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
  96. package/dist/esm/lib/v3/agent/MicrosoftCUAClient.js +15 -0
  97. package/dist/esm/lib/v3/agent/MicrosoftCUAClient.js.map +1 -1
  98. package/dist/esm/lib/v3/agent/OpenAICUAClient.d.ts +8 -2
  99. package/dist/esm/lib/v3/agent/OpenAICUAClient.js +103 -49
  100. package/dist/esm/lib/v3/agent/OpenAICUAClient.js.map +1 -1
  101. package/dist/esm/lib/v3/agent/tools/index.js +1 -1
  102. package/dist/esm/lib/v3/agent/tools/index.js.map +1 -1
  103. package/dist/esm/lib/v3/agent/tools/keys.d.ts +2 -1
  104. package/dist/esm/lib/v3/agent/tools/keys.js +57 -49
  105. package/dist/esm/lib/v3/agent/tools/keys.js.map +1 -1
  106. package/dist/esm/lib/v3/agent/utils/coordinateNormalization.js +3 -5
  107. package/dist/esm/lib/v3/agent/utils/coordinateNormalization.js.map +1 -1
  108. package/dist/esm/lib/v3/api.d.ts +5 -3
  109. package/dist/esm/lib/v3/api.js +3 -6
  110. package/dist/esm/lib/v3/api.js.map +1 -1
  111. package/dist/esm/lib/v3/cache/AgentCache.js +5 -3
  112. package/dist/esm/lib/v3/cache/AgentCache.js.map +1 -1
  113. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js +6 -15
  114. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  115. package/dist/esm/lib/v3/index.d.ts +1 -1
  116. package/dist/esm/lib/v3/llm/LLMProvider.d.ts +5 -2
  117. package/dist/esm/lib/v3/llm/LLMProvider.js +15 -7
  118. package/dist/esm/lib/v3/llm/LLMProvider.js.map +1 -1
  119. package/dist/esm/lib/v3/llm/OpenAIClient.js +1 -0
  120. package/dist/esm/lib/v3/llm/OpenAIClient.js.map +1 -1
  121. package/dist/esm/lib/v3/llm/aisdk.d.ts +3 -1
  122. package/dist/esm/lib/v3/llm/aisdk.js +67 -17
  123. package/dist/esm/lib/v3/llm/aisdk.js.map +1 -1
  124. package/dist/esm/lib/v3/types/public/agent.d.ts +8 -3
  125. package/dist/esm/lib/v3/types/public/agent.js +1 -0
  126. package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
  127. package/dist/esm/lib/v3/types/public/api.d.ts +30 -0
  128. package/dist/esm/lib/v3/types/public/api.js +6 -2
  129. package/dist/esm/lib/v3/types/public/api.js.map +1 -1
  130. package/dist/esm/lib/v3/types/public/model.d.ts +32 -2
  131. package/dist/esm/lib/v3/types/public/model.js.map +1 -1
  132. package/dist/esm/lib/v3/understudy/context.js +11 -3
  133. package/dist/esm/lib/v3/understudy/context.js.map +1 -1
  134. package/dist/esm/lib/v3/understudy/page.js +1 -1
  135. package/dist/esm/lib/v3/understudy/page.js.map +1 -1
  136. package/dist/esm/lib/v3/v3.d.ts +18 -2
  137. package/dist/esm/lib/v3/v3.js +92 -10
  138. package/dist/esm/lib/v3/v3.js.map +1 -1
  139. package/dist/esm/tests/integration/chrome-newtab-page-tracking.spec.d.ts +1 -0
  140. package/dist/esm/tests/integration/chrome-newtab-page-tracking.spec.js +54 -0
  141. package/dist/esm/tests/integration/chrome-newtab-page-tracking.spec.js.map +1 -0
  142. package/dist/esm/tests/integration/flowLogger.spec.js +12 -8
  143. package/dist/esm/tests/integration/flowLogger.spec.js.map +1 -1
  144. package/dist/esm/tests/integration/testUtils.js +1 -1
  145. package/dist/esm/tests/integration/testUtils.js.map +1 -1
  146. package/dist/esm/tests/integration/timeouts.spec.js +6 -4
  147. package/dist/esm/tests/integration/timeouts.spec.js.map +1 -1
  148. package/dist/esm/tests/unit/agent-captcha-hooks.test.js +56 -0
  149. package/dist/esm/tests/unit/agent-captcha-hooks.test.js.map +1 -1
  150. package/dist/esm/tests/unit/agent-metrics.test.d.ts +1 -0
  151. package/dist/esm/tests/unit/agent-metrics.test.js +110 -0
  152. package/dist/esm/tests/unit/agent-metrics.test.js.map +1 -0
  153. package/dist/esm/tests/unit/aisdk-clients.test.d.ts +1 -0
  154. package/dist/esm/tests/unit/aisdk-clients.test.js +88 -0
  155. package/dist/esm/tests/unit/aisdk-clients.test.js.map +1 -0
  156. package/dist/esm/tests/unit/anthropic-cua-adaptive-thinking.test.d.ts +1 -0
  157. package/dist/esm/tests/unit/anthropic-cua-adaptive-thinking.test.js +245 -0
  158. package/dist/esm/tests/unit/anthropic-cua-adaptive-thinking.test.js.map +1 -0
  159. package/dist/esm/tests/unit/api-optional-model-api-key.test.d.ts +1 -0
  160. package/dist/esm/tests/unit/api-optional-model-api-key.test.js +93 -0
  161. package/dist/esm/tests/unit/api-optional-model-api-key.test.js.map +1 -0
  162. package/dist/esm/tests/unit/browserbase-session-accessors.test.js +20 -0
  163. package/dist/esm/tests/unit/browserbase-session-accessors.test.js.map +1 -1
  164. package/dist/esm/tests/unit/llm-middleware.test.d.ts +1 -0
  165. package/dist/esm/tests/unit/llm-middleware.test.js +460 -0
  166. package/dist/esm/tests/unit/llm-middleware.test.js.map +1 -0
  167. package/dist/esm/tests/unit/microsoft-cua-client.test.d.ts +1 -0
  168. package/dist/esm/tests/unit/microsoft-cua-client.test.js +84 -0
  169. package/dist/esm/tests/unit/microsoft-cua-client.test.js.map +1 -0
  170. package/dist/esm/tests/unit/public-api/llm-and-agents.test.js +1 -0
  171. package/dist/esm/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
  172. package/package.json +4 -8
  173. package/dist/cjs/lib/v3/dom/build/rerender-index.js +0 -1
  174. package/dist/cjs/lib/v3/dom/build/v3-index.js +0 -1
  175. package/dist/esm/lib/v3/dom/build/rerender-index.js +0 -1
  176. package/dist/esm/lib/v3/dom/build/v3-index.js +0 -1
@@ -0,0 +1,245 @@
1
+ import { describe, expect, it, vi, beforeEach } from "vitest";
2
+ import { AnthropicCUAClient } from "../../lib/v3/agent/AnthropicCUAClient.js";
3
+ import Anthropic from "@anthropic-ai/sdk";
4
+ // Mock the Anthropic SDK's beta.messages.create method
5
+ vi.mock("@anthropic-ai/sdk", () => {
6
+ const mockCreate = vi.fn().mockResolvedValue({
7
+ id: "test-id",
8
+ content: [{ type: "text", text: "test response" }],
9
+ usage: { input_tokens: 10, output_tokens: 20 },
10
+ });
11
+ return {
12
+ default: class MockAnthropic {
13
+ beta = {
14
+ messages: {
15
+ create: mockCreate,
16
+ },
17
+ };
18
+ },
19
+ };
20
+ });
21
+ describe("AnthropicCUAClient adaptive thinking", () => {
22
+ let mockCreate;
23
+ beforeEach(() => {
24
+ vi.clearAllMocks();
25
+ // Get the mock create function from a new instance
26
+ const anthropic = new Anthropic({ apiKey: "test" });
27
+ mockCreate = anthropic.beta.messages.create;
28
+ mockCreate.mockResolvedValue({
29
+ id: "test-id",
30
+ content: [{ type: "text", text: "test response" }],
31
+ usage: { input_tokens: 10, output_tokens: 20 },
32
+ });
33
+ });
34
+ describe("Claude 4.6 models (adaptive thinking)", () => {
35
+ it("should use thinking.type: 'adaptive' for claude-opus-4-6 when thinkingEffort is set", async () => {
36
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
37
+ apiKey: "test-key",
38
+ thinkingEffort: "high",
39
+ });
40
+ client.setViewport(1280, 720);
41
+ await client.getAction([{ role: "user", content: "test" }]);
42
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
43
+ thinking: { type: "adaptive" },
44
+ output_config: { effort: "high" },
45
+ temperature: 1,
46
+ }));
47
+ // Should NOT have budget_tokens
48
+ const callArgs = mockCreate.mock.calls[0][0];
49
+ expect(callArgs.thinking).not.toHaveProperty("budget_tokens");
50
+ });
51
+ it("should use thinking.type: 'adaptive' for claude-sonnet-4-6 when thinkingEffort is set", async () => {
52
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-6", undefined, {
53
+ apiKey: "test-key",
54
+ thinkingEffort: "medium",
55
+ });
56
+ client.setViewport(1280, 720);
57
+ await client.getAction([{ role: "user", content: "test" }]);
58
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
59
+ thinking: { type: "adaptive" },
60
+ output_config: { effort: "medium" },
61
+ temperature: 1,
62
+ }));
63
+ });
64
+ it("should support 'max' effort level for claude-opus-4-6", async () => {
65
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
66
+ apiKey: "test-key",
67
+ thinkingEffort: "max",
68
+ });
69
+ client.setViewport(1280, 720);
70
+ await client.getAction([{ role: "user", content: "test" }]);
71
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
72
+ thinking: { type: "adaptive" },
73
+ output_config: { effort: "max" },
74
+ temperature: 1,
75
+ }));
76
+ });
77
+ it("should support 'low' effort level", async () => {
78
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-6", undefined, {
79
+ apiKey: "test-key",
80
+ thinkingEffort: "low",
81
+ });
82
+ client.setViewport(1280, 720);
83
+ await client.getAction([{ role: "user", content: "test" }]);
84
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
85
+ thinking: { type: "adaptive" },
86
+ output_config: { effort: "low" },
87
+ temperature: 1,
88
+ }));
89
+ });
90
+ it("should default to adaptive thinking with 'medium' effort when thinkingEffort is not set for 4.6 models", async () => {
91
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
92
+ apiKey: "test-key",
93
+ });
94
+ client.setViewport(1280, 720);
95
+ await client.getAction([{ role: "user", content: "test" }]);
96
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
97
+ thinking: { type: "adaptive" },
98
+ output_config: { effort: "medium" },
99
+ temperature: 1,
100
+ }));
101
+ });
102
+ it("should set temperature to 1 when adaptive thinking is enabled", async () => {
103
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
104
+ apiKey: "test-key",
105
+ thinkingEffort: "high",
106
+ });
107
+ client.setViewport(1280, 720);
108
+ await client.getAction([{ role: "user", content: "test" }]);
109
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
110
+ temperature: 1,
111
+ }));
112
+ });
113
+ it("should set temperature to 1 for claude-sonnet-4-6 with adaptive thinking", async () => {
114
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-6", undefined, {
115
+ apiKey: "test-key",
116
+ thinkingEffort: "low",
117
+ });
118
+ client.setViewport(1280, 720);
119
+ await client.getAction([{ role: "user", content: "test" }]);
120
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
121
+ thinking: { type: "adaptive" },
122
+ output_config: { effort: "low" },
123
+ temperature: 1,
124
+ }));
125
+ });
126
+ it("should disable adaptive thinking when thinkingEffort is 'none'", async () => {
127
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
128
+ apiKey: "test-key",
129
+ thinkingEffort: "none",
130
+ });
131
+ client.setViewport(1280, 720);
132
+ await client.getAction([{ role: "user", content: "test" }]);
133
+ const callArgs = mockCreate.mock.calls[0][0];
134
+ expect(callArgs.thinking).toBeUndefined();
135
+ expect(callArgs.output_config).toBeUndefined();
136
+ expect(callArgs.temperature).toBeUndefined();
137
+ });
138
+ it("should log a debug warning when thinkingBudget is set on a 4.6 model", async () => {
139
+ const logger = vi.fn();
140
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
141
+ apiKey: "test-key",
142
+ thinkingBudget: 10000,
143
+ });
144
+ client.setViewport(1280, 720);
145
+ await client.getAction([{ role: "user", content: "test" }], logger);
146
+ expect(logger).toHaveBeenCalledWith(expect.objectContaining({
147
+ category: "agent",
148
+ message: expect.stringContaining("thinkingBudget is ignored"),
149
+ level: 2,
150
+ }));
151
+ // Should still use adaptive thinking, not budget_tokens
152
+ const callArgs = mockCreate.mock.calls[0][0];
153
+ expect(callArgs.thinking).toEqual({ type: "adaptive" });
154
+ });
155
+ it("should log a debug warning when user-specified temperature is overridden", async () => {
156
+ const logger = vi.fn();
157
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
158
+ apiKey: "test-key",
159
+ thinkingEffort: "high",
160
+ temperature: 0.5,
161
+ });
162
+ client.setViewport(1280, 720);
163
+ await client.getAction([{ role: "user", content: "test" }], logger);
164
+ expect(logger).toHaveBeenCalledWith(expect.objectContaining({
165
+ category: "agent",
166
+ message: expect.stringContaining("overriding user-specified temperature=0.5"),
167
+ level: 2,
168
+ }));
169
+ // Temperature should still be forced to 1
170
+ const callArgs = mockCreate.mock.calls[0][0];
171
+ expect(callArgs.temperature).toBe(1);
172
+ });
173
+ });
174
+ describe("older Claude models (budget_tokens - deprecated)", () => {
175
+ it("should use thinking.type: 'enabled' with budget_tokens for claude-sonnet-4-5 when thinkingBudget is set", async () => {
176
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-5-20250929", undefined, {
177
+ apiKey: "test-key",
178
+ thinkingBudget: 8000,
179
+ });
180
+ client.setViewport(1280, 720);
181
+ await client.getAction([{ role: "user", content: "test" }]);
182
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
183
+ thinking: { type: "enabled", budget_tokens: 8000 },
184
+ }));
185
+ // Should NOT have output_config for older models
186
+ const callArgs = mockCreate.mock.calls[0][0];
187
+ expect(callArgs.output_config).toBeUndefined();
188
+ });
189
+ it("should use thinking.type: 'enabled' with budget_tokens for claude-opus-4-5 when thinkingBudget is set", async () => {
190
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-5-20251101", undefined, {
191
+ apiKey: "test-key",
192
+ thinkingBudget: 10000,
193
+ });
194
+ client.setViewport(1280, 720);
195
+ await client.getAction([{ role: "user", content: "test" }]);
196
+ expect(mockCreate).toHaveBeenCalledWith(expect.objectContaining({
197
+ thinking: { type: "enabled", budget_tokens: 10000 },
198
+ }));
199
+ });
200
+ it("should NOT force temperature to 1 for older models with budget_tokens", async () => {
201
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-5-20250929", undefined, {
202
+ apiKey: "test-key",
203
+ thinkingBudget: 8000,
204
+ });
205
+ client.setViewport(1280, 720);
206
+ await client.getAction([{ role: "user", content: "test" }]);
207
+ const callArgs = mockCreate.mock.calls[0][0];
208
+ // Temperature should not be explicitly set to 1 for older models
209
+ expect(callArgs.temperature).toBeUndefined();
210
+ });
211
+ });
212
+ describe("model detection", () => {
213
+ it("should detect claude-opus-4-6 as a 4.6 model", async () => {
214
+ const client = new AnthropicCUAClient("anthropic", "claude-opus-4-6", undefined, {
215
+ apiKey: "test-key",
216
+ thinkingEffort: "high",
217
+ });
218
+ client.setViewport(1280, 720);
219
+ await client.getAction([{ role: "user", content: "test" }]);
220
+ const callArgs = mockCreate.mock.calls[0][0];
221
+ expect(callArgs.thinking.type).toBe("adaptive");
222
+ });
223
+ it("should detect claude-sonnet-4-6 as a 4.6 model", async () => {
224
+ const client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-6", undefined, {
225
+ apiKey: "test-key",
226
+ thinkingEffort: "high",
227
+ });
228
+ client.setViewport(1280, 720);
229
+ await client.getAction([{ role: "user", content: "test" }]);
230
+ const callArgs = mockCreate.mock.calls[0][0];
231
+ expect(callArgs.thinking.type).toBe("adaptive");
232
+ });
233
+ it("should handle provider-prefixed model names (anthropic/claude-opus-4-6)", async () => {
234
+ const client = new AnthropicCUAClient("anthropic", "anthropic/claude-opus-4-6", undefined, {
235
+ apiKey: "test-key",
236
+ thinkingEffort: "high",
237
+ });
238
+ client.setViewport(1280, 720);
239
+ await client.getAction([{ role: "user", content: "test" }]);
240
+ const callArgs = mockCreate.mock.calls[0][0];
241
+ expect(callArgs.thinking.type).toBe("adaptive");
242
+ });
243
+ });
244
+ });
245
+ //# sourceMappingURL=anthropic-cua-adaptive-thinking.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic-cua-adaptive-thinking.test.js","sourceRoot":"","sources":["../../../../tests/unit/anthropic-cua-adaptive-thinking.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi, beforeEach } from \"vitest\";\nimport { AnthropicCUAClient } from \"../../lib/v3/agent/AnthropicCUAClient.js\";\nimport Anthropic from \"@anthropic-ai/sdk\";\n\n// Mock the Anthropic SDK's beta.messages.create method\nvi.mock(\"@anthropic-ai/sdk\", () => {\n const mockCreate = vi.fn().mockResolvedValue({\n id: \"test-id\",\n content: [{ type: \"text\", text: \"test response\" }],\n usage: { input_tokens: 10, output_tokens: 20 },\n });\n\n return {\n default: class MockAnthropic {\n beta = {\n messages: {\n create: mockCreate,\n },\n };\n },\n };\n});\n\ndescribe(\"AnthropicCUAClient adaptive thinking\", () => {\n let mockCreate: ReturnType<typeof vi.fn>;\n\n beforeEach(() => {\n vi.clearAllMocks();\n // Get the mock create function from a new instance\n const anthropic = new Anthropic({ apiKey: \"test\" });\n mockCreate = anthropic.beta.messages.create as ReturnType<typeof vi.fn>;\n mockCreate.mockResolvedValue({\n id: \"test-id\",\n content: [{ type: \"text\", text: \"test response\" }],\n usage: { input_tokens: 10, output_tokens: 20 },\n });\n });\n\n describe(\"Claude 4.6 models (adaptive thinking)\", () => {\n it(\"should use thinking.type: 'adaptive' for claude-opus-4-6 when thinkingEffort is set\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"high\" },\n temperature: 1,\n }),\n );\n\n // Should NOT have budget_tokens\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking).not.toHaveProperty(\"budget_tokens\");\n });\n\n it(\"should use thinking.type: 'adaptive' for claude-sonnet-4-6 when thinkingEffort is set\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"medium\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"medium\" },\n temperature: 1,\n }),\n );\n });\n\n it(\"should support 'max' effort level for claude-opus-4-6\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"max\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"max\" },\n temperature: 1,\n }),\n );\n });\n\n it(\"should support 'low' effort level\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"low\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"low\" },\n temperature: 1,\n }),\n );\n });\n\n it(\"should default to adaptive thinking with 'medium' effort when thinkingEffort is not set for 4.6 models\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"medium\" },\n temperature: 1,\n }),\n );\n });\n\n it(\"should set temperature to 1 when adaptive thinking is enabled\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n temperature: 1,\n }),\n );\n });\n\n it(\"should set temperature to 1 for claude-sonnet-4-6 with adaptive thinking\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"low\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"adaptive\" },\n output_config: { effort: \"low\" },\n temperature: 1,\n }),\n );\n });\n\n it(\"should disable adaptive thinking when thinkingEffort is 'none'\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"none\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking).toBeUndefined();\n expect(callArgs.output_config).toBeUndefined();\n expect(callArgs.temperature).toBeUndefined();\n });\n\n it(\"should log a debug warning when thinkingBudget is set on a 4.6 model\", async () => {\n const logger = vi.fn();\n\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingBudget: 10000,\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }], logger);\n\n expect(logger).toHaveBeenCalledWith(\n expect.objectContaining({\n category: \"agent\",\n message: expect.stringContaining(\"thinkingBudget is ignored\"),\n level: 2,\n }),\n );\n\n // Should still use adaptive thinking, not budget_tokens\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking).toEqual({ type: \"adaptive\" });\n });\n\n it(\"should log a debug warning when user-specified temperature is overridden\", async () => {\n const logger = vi.fn();\n\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n temperature: 0.5,\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }], logger);\n\n expect(logger).toHaveBeenCalledWith(\n expect.objectContaining({\n category: \"agent\",\n message: expect.stringContaining(\n \"overriding user-specified temperature=0.5\",\n ),\n level: 2,\n }),\n );\n\n // Temperature should still be forced to 1\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.temperature).toBe(1);\n });\n });\n\n describe(\"older Claude models (budget_tokens - deprecated)\", () => {\n it(\"should use thinking.type: 'enabled' with budget_tokens for claude-sonnet-4-5 when thinkingBudget is set\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-5-20250929\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingBudget: 8000,\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"enabled\", budget_tokens: 8000 },\n }),\n );\n\n // Should NOT have output_config for older models\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.output_config).toBeUndefined();\n });\n\n it(\"should use thinking.type: 'enabled' with budget_tokens for claude-opus-4-5 when thinkingBudget is set\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-5-20251101\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingBudget: 10000,\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n expect(mockCreate).toHaveBeenCalledWith(\n expect.objectContaining({\n thinking: { type: \"enabled\", budget_tokens: 10000 },\n }),\n );\n });\n\n it(\"should NOT force temperature to 1 for older models with budget_tokens\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-5-20250929\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingBudget: 8000,\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n const callArgs = mockCreate.mock.calls[0][0];\n // Temperature should not be explicitly set to 1 for older models\n expect(callArgs.temperature).toBeUndefined();\n });\n });\n\n describe(\"model detection\", () => {\n it(\"should detect claude-opus-4-6 as a 4.6 model\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking.type).toBe(\"adaptive\");\n });\n\n it(\"should detect claude-sonnet-4-6 as a 4.6 model\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking.type).toBe(\"adaptive\");\n });\n\n it(\"should handle provider-prefixed model names (anthropic/claude-opus-4-6)\", async () => {\n const client = new AnthropicCUAClient(\n \"anthropic\",\n \"anthropic/claude-opus-4-6\",\n undefined,\n {\n apiKey: \"test-key\",\n thinkingEffort: \"high\",\n },\n );\n client.setViewport(1280, 720);\n\n await client.getAction([{ role: \"user\", content: \"test\" }]);\n\n const callArgs = mockCreate.mock.calls[0][0];\n expect(callArgs.thinking.type).toBe(\"adaptive\");\n });\n });\n});\n"]}
@@ -0,0 +1,93 @@
1
+ import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
2
+ import { StagehandAPIClient } from "../../lib/v3/api";
3
+ /**
4
+ * Tests that modelApiKey is optional when calling StagehandAPIClient.init().
5
+ *
6
+ * Previously, init() would throw "modelApiKey is required" if the key was not
7
+ * provided. After the fix, sessions can be started without a model API key
8
+ * (the server may provide its own key or the user may not need one).
9
+ * When provided, the key should still be sent via the x-model-api-key header.
10
+ */
11
+ describe("StagehandAPIClient - optional modelApiKey", () => {
12
+ const logger = vi.fn();
13
+ // We mock fetch to avoid real network calls; we just need to verify
14
+ // that init() doesn't throw when modelApiKey is omitted and that
15
+ // the header is conditionally included.
16
+ let originalFetch;
17
+ function createSessionStartResponse(sessionId) {
18
+ return new Response(JSON.stringify({
19
+ success: true,
20
+ data: { sessionId, available: true },
21
+ }), {
22
+ status: 200,
23
+ headers: { "Content-Type": "application/json" },
24
+ });
25
+ }
26
+ beforeEach(() => {
27
+ originalFetch = globalThis.fetch;
28
+ });
29
+ afterEach(() => {
30
+ globalThis.fetch = originalFetch;
31
+ vi.restoreAllMocks();
32
+ });
33
+ it("should NOT throw when modelApiKey is omitted", async () => {
34
+ globalThis.fetch = vi
35
+ .fn()
36
+ .mockResolvedValue(createSessionStartResponse("sess-123"));
37
+ const client = new StagehandAPIClient({
38
+ apiKey: "test-api-key",
39
+ logger,
40
+ });
41
+ // Should not throw "modelApiKey is required"
42
+ await expect(client.init({
43
+ modelName: "openai/gpt-4.1-mini",
44
+ })).resolves.toBeDefined();
45
+ });
46
+ it("should NOT throw when modelApiKey is undefined", async () => {
47
+ globalThis.fetch = vi
48
+ .fn()
49
+ .mockResolvedValue(createSessionStartResponse("sess-456"));
50
+ const client = new StagehandAPIClient({
51
+ apiKey: "test-api-key",
52
+ logger,
53
+ });
54
+ await expect(client.init({
55
+ modelName: "openai/gpt-4.1-mini",
56
+ modelApiKey: undefined,
57
+ })).resolves.toBeDefined();
58
+ });
59
+ it("should send x-model-api-key header when modelApiKey IS provided", async () => {
60
+ const fetchSpy = vi
61
+ .fn()
62
+ .mockResolvedValue(createSessionStartResponse("sess-789"));
63
+ globalThis.fetch = fetchSpy;
64
+ const client = new StagehandAPIClient({
65
+ apiKey: "test-api-key",
66
+ logger,
67
+ });
68
+ await client.init({
69
+ modelName: "openai/gpt-4.1-mini",
70
+ modelApiKey: "my-model-key",
71
+ });
72
+ // Verify the fetch was called with x-model-api-key header
73
+ const [, requestInit] = fetchSpy.mock.calls[0];
74
+ expect(requestInit.headers["x-model-api-key"]).toBe("my-model-key");
75
+ });
76
+ it("should NOT send x-model-api-key header when modelApiKey is omitted", async () => {
77
+ const fetchSpy = vi
78
+ .fn()
79
+ .mockResolvedValue(createSessionStartResponse("sess-012"));
80
+ globalThis.fetch = fetchSpy;
81
+ const client = new StagehandAPIClient({
82
+ apiKey: "test-api-key",
83
+ logger,
84
+ });
85
+ await client.init({
86
+ modelName: "openai/gpt-4.1-mini",
87
+ });
88
+ // Verify x-model-api-key header is NOT present
89
+ const [, requestInit] = fetchSpy.mock.calls[0];
90
+ expect(requestInit.headers["x-model-api-key"]).toBeUndefined();
91
+ });
92
+ });
93
+ //# sourceMappingURL=api-optional-model-api-key.test.js.map
@@ -0,0 +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"]}
@@ -96,6 +96,26 @@ describe("browserbase accessors", () => {
96
96
  await v3.close().catch(() => { });
97
97
  }
98
98
  });
99
+ it("treats verified Browserbase sessions as managed fingerprinting mode", async () => {
100
+ const v3 = new V3({
101
+ env: "BROWSERBASE",
102
+ disableAPI: true,
103
+ verbose: 0,
104
+ browserbaseSessionCreateParams: {
105
+ browserSettings: {
106
+ verified: true,
107
+ },
108
+ },
109
+ });
110
+ try {
111
+ await v3.init();
112
+ expect(v3.isVerified).toBe(true);
113
+ expect(v3.isAdvancedStealth).toBe(true);
114
+ }
115
+ finally {
116
+ await v3.close().catch(() => { });
117
+ }
118
+ });
99
119
  });
100
120
  describe("local accessors", () => {
101
121
  it("stay empty for LOCAL environments", async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"browserbase-session-accessors.test.js","sourceRoot":"","sources":["../../../../tests/unit/browserbase-session-accessors.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi, beforeEach, afterEach } from \"vitest\";\nimport { V3 } from \"../../lib/v3/v3.js\";\n\nconst MOCK_SESSION_ID = \"session-123\";\nconst MOCK_SESSION_URL = `https://www.browserbase.com/sessions/${MOCK_SESSION_ID}`;\nconst MOCK_DEBUG_URL = `https://debug.browserbase.com/${MOCK_SESSION_ID}`;\n\nvi.mock(\"../../lib/v3/understudy/context\", () => {\n class MockConnection {\n onTransportClosed = vi.fn();\n offTransportClosed = vi.fn();\n send = vi.fn(async () => {});\n }\n\n class MockV3Context {\n static async create(): Promise<MockV3Context> {\n return new MockV3Context();\n }\n\n conn = new MockConnection();\n\n pages(): never[] {\n return [];\n }\n\n async close(): Promise<void> {\n // noop\n }\n }\n\n return { V3Context: MockV3Context };\n});\n\nvi.mock(\"../../lib/v3/launch/browserbase\", () => ({\n createBrowserbaseSession: vi.fn(async () => ({\n ws: \"wss://mock-browserbase\",\n sessionId: MOCK_SESSION_ID,\n bb: {\n sessions: {\n debug: vi.fn(async () => ({ debuggerUrl: MOCK_DEBUG_URL })),\n },\n },\n })),\n}));\n\nvi.mock(\"../../lib/v3/launch/local\", () => ({\n launchLocalChrome: vi.fn(async () => ({\n ws: \"ws://local-cdp\",\n chrome: { kill: vi.fn(async () => {}) },\n })),\n}));\n\ndescribe(\"browserbase accessors\", () => {\n beforeEach(() => {\n process.env.BROWSERBASE_API_KEY = \"fake-key\";\n process.env.BROWSERBASE_PROJECT_ID = \"fake-project\";\n });\n\n afterEach(() => {\n delete process.env.BROWSERBASE_API_KEY;\n delete process.env.BROWSERBASE_PROJECT_ID;\n vi.clearAllMocks();\n });\n\n it(\"exposes Browserbase session and debug URLs after init\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n });\n\n try {\n await v3.init();\n\n expect(v3.browserbaseSessionURL).toBe(MOCK_SESSION_URL);\n expect(v3.browserbaseDebugURL).toBe(MOCK_DEBUG_URL);\n expect(v3.isCaptchaAutoSolveEnabled).toBe(true);\n } finally {\n await v3.close().catch(() => {});\n }\n });\n\n it(\"clears stored URLs after close\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n });\n\n await v3.init();\n await v3.close();\n\n expect(v3.browserbaseSessionURL).toBeUndefined();\n expect(v3.browserbaseDebugURL).toBeUndefined();\n });\n\n it(\"disables captcha solving when solveCaptchas is explicitly false\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n browserbaseSessionCreateParams: {\n browserSettings: {\n solveCaptchas: false,\n },\n },\n });\n\n try {\n await v3.init();\n expect(v3.isCaptchaAutoSolveEnabled).toBe(false);\n } finally {\n await v3.close().catch(() => {});\n }\n });\n});\n\ndescribe(\"local accessors\", () => {\n it(\"stay empty for LOCAL environments\", async () => {\n const v3 = new V3({\n env: \"LOCAL\",\n disableAPI: true,\n verbose: 0,\n localBrowserLaunchOptions: {\n cdpUrl: \"ws://local-existing-session\",\n },\n });\n\n try {\n await v3.init();\n expect(v3.browserbaseSessionURL).toBeUndefined();\n expect(v3.browserbaseDebugURL).toBeUndefined();\n } finally {\n await v3.close().catch(() => {});\n }\n });\n});\n"]}
1
+ {"version":3,"file":"browserbase-session-accessors.test.js","sourceRoot":"","sources":["../../../../tests/unit/browserbase-session-accessors.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi, beforeEach, afterEach } from \"vitest\";\nimport { V3 } from \"../../lib/v3/v3.js\";\n\nconst MOCK_SESSION_ID = \"session-123\";\nconst MOCK_SESSION_URL = `https://www.browserbase.com/sessions/${MOCK_SESSION_ID}`;\nconst MOCK_DEBUG_URL = `https://debug.browserbase.com/${MOCK_SESSION_ID}`;\n\nvi.mock(\"../../lib/v3/understudy/context\", () => {\n class MockConnection {\n onTransportClosed = vi.fn();\n offTransportClosed = vi.fn();\n send = vi.fn(async () => {});\n }\n\n class MockV3Context {\n static async create(): Promise<MockV3Context> {\n return new MockV3Context();\n }\n\n conn = new MockConnection();\n\n pages(): never[] {\n return [];\n }\n\n async close(): Promise<void> {\n // noop\n }\n }\n\n return { V3Context: MockV3Context };\n});\n\nvi.mock(\"../../lib/v3/launch/browserbase\", () => ({\n createBrowserbaseSession: vi.fn(async () => ({\n ws: \"wss://mock-browserbase\",\n sessionId: MOCK_SESSION_ID,\n bb: {\n sessions: {\n debug: vi.fn(async () => ({ debuggerUrl: MOCK_DEBUG_URL })),\n },\n },\n })),\n}));\n\nvi.mock(\"../../lib/v3/launch/local\", () => ({\n launchLocalChrome: vi.fn(async () => ({\n ws: \"ws://local-cdp\",\n chrome: { kill: vi.fn(async () => {}) },\n })),\n}));\n\ndescribe(\"browserbase accessors\", () => {\n beforeEach(() => {\n process.env.BROWSERBASE_API_KEY = \"fake-key\";\n process.env.BROWSERBASE_PROJECT_ID = \"fake-project\";\n });\n\n afterEach(() => {\n delete process.env.BROWSERBASE_API_KEY;\n delete process.env.BROWSERBASE_PROJECT_ID;\n vi.clearAllMocks();\n });\n\n it(\"exposes Browserbase session and debug URLs after init\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n });\n\n try {\n await v3.init();\n\n expect(v3.browserbaseSessionURL).toBe(MOCK_SESSION_URL);\n expect(v3.browserbaseDebugURL).toBe(MOCK_DEBUG_URL);\n expect(v3.isCaptchaAutoSolveEnabled).toBe(true);\n } finally {\n await v3.close().catch(() => {});\n }\n });\n\n it(\"clears stored URLs after close\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n });\n\n await v3.init();\n await v3.close();\n\n expect(v3.browserbaseSessionURL).toBeUndefined();\n expect(v3.browserbaseDebugURL).toBeUndefined();\n });\n\n it(\"disables captcha solving when solveCaptchas is explicitly false\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n browserbaseSessionCreateParams: {\n browserSettings: {\n solveCaptchas: false,\n },\n },\n });\n\n try {\n await v3.init();\n expect(v3.isCaptchaAutoSolveEnabled).toBe(false);\n } finally {\n await v3.close().catch(() => {});\n }\n });\n\n it(\"treats verified Browserbase sessions as managed fingerprinting mode\", async () => {\n const v3 = new V3({\n env: \"BROWSERBASE\",\n disableAPI: true,\n verbose: 0,\n browserbaseSessionCreateParams: {\n browserSettings: {\n verified: true,\n },\n },\n });\n\n try {\n await v3.init();\n expect(v3.isVerified).toBe(true);\n expect(v3.isAdvancedStealth).toBe(true);\n } finally {\n await v3.close().catch(() => {});\n }\n });\n});\n\ndescribe(\"local accessors\", () => {\n it(\"stay empty for LOCAL environments\", async () => {\n const v3 = new V3({\n env: \"LOCAL\",\n disableAPI: true,\n verbose: 0,\n localBrowserLaunchOptions: {\n cdpUrl: \"ws://local-existing-session\",\n },\n });\n\n try {\n await v3.init();\n expect(v3.browserbaseSessionURL).toBeUndefined();\n expect(v3.browserbaseDebugURL).toBeUndefined();\n } finally {\n await v3.close().catch(() => {});\n }\n });\n});\n"]}
@@ -0,0 +1 @@
1
+ export {};