@browserbasehq/orca 3.5.0-preview.0 → 3.5.0-preview.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/dist/cjs/lib/v3/agent/utils/captureAriaTreeProbe.d.ts +35 -0
  2. package/dist/cjs/lib/v3/agent/utils/captureAriaTreeProbe.js +38 -0
  3. package/dist/cjs/lib/v3/agent/utils/captureAriaTreeProbe.js.map +1 -0
  4. package/dist/cjs/lib/v3/agent/utils/postStepProbeEvidence.d.ts +19 -0
  5. package/dist/cjs/lib/v3/agent/utils/postStepProbeEvidence.js +54 -0
  6. package/dist/cjs/lib/v3/agent/utils/postStepProbeEvidence.js.map +1 -0
  7. package/dist/cjs/lib/v3/agent/utils/toolOutputEvidence.d.ts +2 -0
  8. package/dist/cjs/lib/v3/agent/utils/toolOutputEvidence.js +62 -0
  9. package/dist/cjs/lib/v3/agent/utils/toolOutputEvidence.js.map +1 -0
  10. package/dist/cjs/lib/v3/agent/utils/wrapEvidenceCallback.d.ts +3 -0
  11. package/dist/cjs/lib/v3/agent/utils/wrapEvidenceCallback.js +25 -0
  12. package/dist/cjs/lib/v3/agent/utils/wrapEvidenceCallback.js.map +1 -0
  13. package/dist/cjs/lib/v3/api.d.ts +7 -1
  14. package/dist/cjs/lib/v3/api.js +100 -29
  15. package/dist/cjs/lib/v3/api.js.map +1 -1
  16. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.d.ts +24 -0
  17. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js +31 -0
  18. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js.map +1 -0
  19. package/dist/cjs/lib/v3/handlers/v3AgentHandler.d.ts +1 -0
  20. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +83 -7
  21. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  22. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.d.ts +11 -0
  23. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js +119 -5
  24. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  25. package/dist/cjs/lib/v3/index.d.ts +11 -0
  26. package/dist/cjs/lib/v3/index.js +19 -1
  27. package/dist/cjs/lib/v3/index.js.map +1 -1
  28. package/dist/cjs/lib/v3/llm/LLMProvider.d.ts +3 -0
  29. package/dist/cjs/lib/v3/llm/LLMProvider.js +28 -8
  30. package/dist/cjs/lib/v3/llm/LLMProvider.js.map +1 -1
  31. package/dist/cjs/lib/v3/types/public/agent.d.ts +6 -0
  32. package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
  33. package/dist/cjs/lib/v3/types/public/agentEvidenceEvents.d.ts +85 -0
  34. package/dist/cjs/lib/v3/types/public/agentEvidenceEvents.js +15 -0
  35. package/dist/cjs/lib/v3/types/public/agentEvidenceEvents.js.map +1 -0
  36. package/dist/cjs/lib/v3/types/public/api.d.ts +414 -182
  37. package/dist/cjs/lib/v3/types/public/api.js +62 -20
  38. package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
  39. package/dist/cjs/lib/v3/types/public/index.d.ts +1 -0
  40. package/dist/cjs/lib/v3/types/public/index.js +1 -0
  41. package/dist/cjs/lib/v3/types/public/index.js.map +1 -1
  42. package/dist/cjs/lib/v3/types/public/model.d.ts +16 -7
  43. package/dist/cjs/lib/v3/types/public/model.js.map +1 -1
  44. package/dist/cjs/lib/v3/v3.d.ts +1 -0
  45. package/dist/cjs/lib/v3/v3.js +14 -0
  46. package/dist/cjs/lib/v3/v3.js.map +1 -1
  47. package/dist/cjs/lib/v3/verifier/evidenceNormalization.d.ts +7 -0
  48. package/dist/cjs/lib/v3/verifier/evidenceNormalization.js +100 -0
  49. package/dist/cjs/lib/v3/verifier/evidenceNormalization.js.map +1 -0
  50. package/dist/cjs/lib/v3/verifier/index.d.ts +6 -0
  51. package/dist/cjs/lib/v3/verifier/index.js +16 -0
  52. package/dist/cjs/lib/v3/verifier/index.js.map +1 -0
  53. package/dist/cjs/lib/v3/verifier/trajectory.d.ts +50 -0
  54. package/dist/cjs/lib/v3/verifier/trajectory.js +316 -0
  55. package/dist/cjs/lib/v3/verifier/trajectory.js.map +1 -0
  56. package/dist/cjs/lib/v3/verifier/types.d.ts +281 -0
  57. package/dist/cjs/lib/v3/verifier/types.js +10 -0
  58. package/dist/cjs/lib/v3/verifier/types.js.map +1 -0
  59. package/dist/cjs/lib/v3Evaluator.d.ts +9 -4
  60. package/dist/cjs/lib/v3Evaluator.js +148 -0
  61. package/dist/cjs/lib/v3Evaluator.js.map +1 -1
  62. package/dist/cjs/lib/v3LegacyEvaluator.js +5 -1
  63. package/dist/cjs/lib/v3LegacyEvaluator.js.map +1 -1
  64. package/dist/esm/lib/v3/agent/utils/captureAriaTreeProbe.d.ts +35 -0
  65. package/dist/esm/lib/v3/agent/utils/captureAriaTreeProbe.js +35 -0
  66. package/dist/esm/lib/v3/agent/utils/captureAriaTreeProbe.js.map +1 -0
  67. package/dist/esm/lib/v3/agent/utils/postStepProbeEvidence.d.ts +19 -0
  68. package/dist/esm/lib/v3/agent/utils/postStepProbeEvidence.js +50 -0
  69. package/dist/esm/lib/v3/agent/utils/postStepProbeEvidence.js.map +1 -0
  70. package/dist/esm/lib/v3/agent/utils/toolOutputEvidence.d.ts +2 -0
  71. package/dist/esm/lib/v3/agent/utils/toolOutputEvidence.js +59 -0
  72. package/dist/esm/lib/v3/agent/utils/toolOutputEvidence.js.map +1 -0
  73. package/dist/esm/lib/v3/agent/utils/wrapEvidenceCallback.d.ts +3 -0
  74. package/dist/esm/lib/v3/agent/utils/wrapEvidenceCallback.js +22 -0
  75. package/dist/esm/lib/v3/agent/utils/wrapEvidenceCallback.js.map +1 -0
  76. package/dist/esm/lib/v3/api.d.ts +7 -1
  77. package/dist/esm/lib/v3/api.js +100 -29
  78. package/dist/esm/lib/v3/api.js.map +1 -1
  79. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.d.ts +24 -0
  80. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js +28 -0
  81. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js.map +1 -0
  82. package/dist/esm/lib/v3/handlers/v3AgentHandler.d.ts +1 -0
  83. package/dist/esm/lib/v3/handlers/v3AgentHandler.js +83 -7
  84. package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  85. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.d.ts +11 -0
  86. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js +119 -5
  87. package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
  88. package/dist/esm/lib/v3/index.d.ts +11 -0
  89. package/dist/esm/lib/v3/index.js +10 -0
  90. package/dist/esm/lib/v3/index.js.map +1 -1
  91. package/dist/esm/lib/v3/llm/LLMProvider.d.ts +3 -0
  92. package/dist/esm/lib/v3/llm/LLMProvider.js +28 -9
  93. package/dist/esm/lib/v3/llm/LLMProvider.js.map +1 -1
  94. package/dist/esm/lib/v3/types/public/agent.d.ts +6 -0
  95. package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
  96. package/dist/esm/lib/v3/types/public/agentEvidenceEvents.d.ts +85 -0
  97. package/dist/esm/lib/v3/types/public/agentEvidenceEvents.js +14 -0
  98. package/dist/esm/lib/v3/types/public/agentEvidenceEvents.js.map +1 -0
  99. package/dist/esm/lib/v3/types/public/api.d.ts +414 -182
  100. package/dist/esm/lib/v3/types/public/api.js +60 -18
  101. package/dist/esm/lib/v3/types/public/api.js.map +1 -1
  102. package/dist/esm/lib/v3/types/public/index.d.ts +1 -0
  103. package/dist/esm/lib/v3/types/public/index.js +1 -0
  104. package/dist/esm/lib/v3/types/public/index.js.map +1 -1
  105. package/dist/esm/lib/v3/types/public/model.d.ts +16 -7
  106. package/dist/esm/lib/v3/types/public/model.js.map +1 -1
  107. package/dist/esm/lib/v3/v3.d.ts +1 -0
  108. package/dist/esm/lib/v3/v3.js +14 -0
  109. package/dist/esm/lib/v3/v3.js.map +1 -1
  110. package/dist/esm/lib/v3/verifier/evidenceNormalization.d.ts +7 -0
  111. package/dist/esm/lib/v3/verifier/evidenceNormalization.js +93 -0
  112. package/dist/esm/lib/v3/verifier/evidenceNormalization.js.map +1 -0
  113. package/dist/esm/lib/v3/verifier/index.d.ts +6 -0
  114. package/dist/esm/lib/v3/verifier/index.js +3 -0
  115. package/dist/esm/lib/v3/verifier/index.js.map +1 -0
  116. package/dist/esm/lib/v3/verifier/trajectory.d.ts +50 -0
  117. package/dist/esm/lib/v3/verifier/trajectory.js +273 -0
  118. package/dist/esm/lib/v3/verifier/trajectory.js.map +1 -0
  119. package/dist/esm/lib/v3/verifier/types.d.ts +281 -0
  120. package/dist/esm/lib/v3/verifier/types.js +9 -0
  121. package/dist/esm/lib/v3/verifier/types.js.map +1 -0
  122. package/dist/esm/lib/v3Evaluator.d.ts +9 -4
  123. package/dist/esm/lib/v3Evaluator.js +148 -0
  124. package/dist/esm/lib/v3Evaluator.js.map +1 -1
  125. package/dist/esm/lib/v3LegacyEvaluator.js +5 -1
  126. package/dist/esm/lib/v3LegacyEvaluator.js.map +1 -1
  127. package/package.json +4 -4
@@ -0,0 +1,35 @@
1
+ /**
2
+ * captureAriaTreeProbe — capture a truncated accessibility tree of the active
3
+ * page for use as tier-2 evidence in the trajectory recorder.
4
+ *
5
+ * Shared by v3AgentHandler and v3CuaAgentHandler. Listener-gated by the
6
+ * callers so ordinary agent runs (no TrajectoryRecorder attached) don't pay
7
+ * the cost.
8
+ *
9
+ * The a11y tree is the same payload the agent's `ariaTree` tool sees, but
10
+ * captured by the harness (not the agent) so the verifier has independent
11
+ * textual ground truth for grounding non-visual claims — prices, names,
12
+ * dates, list contents — without OCR'ing screenshots.
13
+ *
14
+ * Budget: defaults to ~8000 tokens (32k chars). Per-step a11y captures
15
+ * across a ~30-step trajectory at that cap sum to ~240k tokens total,
16
+ * which the verifier handles via per-criterion top-K selection. The cap
17
+ * is configurable via VERIFIER_ARIATREE_TOKEN_BUDGET so consumers can
18
+ * trade RAM/disk for fidelity. Truncated content is marked explicitly so
19
+ * the verifier knows it was clipped.
20
+ */
21
+ import type { V3 } from "../../v3.js";
22
+ interface CaptureAriaTreeOptions {
23
+ /** Soft cap on token count (chars/4 approximation). Default 8000. */
24
+ tokenBudget?: number;
25
+ /** Hard timeout on the capture. Default 5s. */
26
+ timeoutMs?: number;
27
+ }
28
+ /**
29
+ * Returns the truncated a11y tree as a plain string, or undefined when
30
+ * capture fails. Never throws — a11y capture is best-effort tier-2 evidence,
31
+ * not a hard requirement, so failures are silently absorbed (the verifier
32
+ * surfaces this via evidence_insufficient).
33
+ */
34
+ export declare function captureAriaTreeProbe(v3: V3, opts?: CaptureAriaTreeOptions): Promise<string | undefined>;
35
+ export {};
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.captureAriaTreeProbe = captureAriaTreeProbe;
4
+ const APPROX_CHARS_PER_TOKEN = 4;
5
+ const DEFAULT_TOKEN_BUDGET = 8_000;
6
+ const DEFAULT_TIMEOUT_MS = 5_000;
7
+ /**
8
+ * Returns the truncated a11y tree as a plain string, or undefined when
9
+ * capture fails. Never throws — a11y capture is best-effort tier-2 evidence,
10
+ * not a hard requirement, so failures are silently absorbed (the verifier
11
+ * surfaces this via evidence_insufficient).
12
+ */
13
+ async function captureAriaTreeProbe(v3, opts = {}) {
14
+ const envBudget = parseInt(process.env.VERIFIER_ARIATREE_TOKEN_BUDGET ?? "", 10);
15
+ const tokenBudget = opts.tokenBudget ??
16
+ (Number.isFinite(envBudget) && envBudget > 0
17
+ ? envBudget
18
+ : DEFAULT_TOKEN_BUDGET);
19
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
20
+ const maxChars = tokenBudget * APPROX_CHARS_PER_TOKEN;
21
+ try {
22
+ // v3.extract() without a schema returns { pageText } where pageText is the
23
+ // rendered accessibility tree — same path the agent's ariaTree tool uses.
24
+ const result = await v3.extract({ timeout: timeoutMs });
25
+ const pageText = result?.pageText;
26
+ if (typeof pageText !== "string" || pageText.length === 0)
27
+ return undefined;
28
+ if (pageText.length > maxChars) {
29
+ return (pageText.slice(0, maxChars) +
30
+ `\n\n[CONTENT TRUNCATED at ~${tokenBudget} tokens — set VERIFIER_ARIATREE_TOKEN_BUDGET to raise]`);
31
+ }
32
+ return pageText;
33
+ }
34
+ catch {
35
+ return undefined;
36
+ }
37
+ }
38
+ //# sourceMappingURL=captureAriaTreeProbe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"captureAriaTreeProbe.js","sourceRoot":"","sources":["../../../../../../lib/v3/agent/utils/captureAriaTreeProbe.ts"],"names":[],"mappings":";;AAuCA,oDAiCC;AAlDD,MAAM,sBAAsB,GAAG,CAAC,CAAC;AACjC,MAAM,oBAAoB,GAAG,KAAK,CAAC;AACnC,MAAM,kBAAkB,GAAG,KAAK,CAAC;AASjC;;;;;GAKG;AACI,KAAK,UAAU,oBAAoB,CACxC,EAAM,EACN,OAA+B,EAAE;IAEjC,MAAM,SAAS,GAAG,QAAQ,CACxB,OAAO,CAAC,GAAG,CAAC,8BAA8B,IAAI,EAAE,EAChD,EAAE,CACH,CAAC;IACF,MAAM,WAAW,GACf,IAAI,CAAC,WAAW;QAChB,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC;YAC1C,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,kBAAkB,CAAC;IACvD,MAAM,QAAQ,GAAG,WAAW,GAAG,sBAAsB,CAAC;IAEtD,IAAI,CAAC;QACH,2EAA2E;QAC3E,0EAA0E;QAC1E,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,CAAC;QAClC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QAE5E,IAAI,QAAQ,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;YAC/B,OAAO,CACL,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC;gBAC3B,8BAA8B,WAAW,wDAAwD,CAClG,CAAC;QACJ,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC","sourcesContent":["/**\n * captureAriaTreeProbe — capture a truncated accessibility tree of the active\n * page for use as tier-2 evidence in the trajectory recorder.\n *\n * Shared by v3AgentHandler and v3CuaAgentHandler. Listener-gated by the\n * callers so ordinary agent runs (no TrajectoryRecorder attached) don't pay\n * the cost.\n *\n * The a11y tree is the same payload the agent's `ariaTree` tool sees, but\n * captured by the harness (not the agent) so the verifier has independent\n * textual ground truth for grounding non-visual claims — prices, names,\n * dates, list contents — without OCR'ing screenshots.\n *\n * Budget: defaults to ~8000 tokens (32k chars). Per-step a11y captures\n * across a ~30-step trajectory at that cap sum to ~240k tokens total,\n * which the verifier handles via per-criterion top-K selection. The cap\n * is configurable via VERIFIER_ARIATREE_TOKEN_BUDGET so consumers can\n * trade RAM/disk for fidelity. Truncated content is marked explicitly so\n * the verifier knows it was clipped.\n */\nimport type { V3 } from \"../../v3.js\";\n\nconst APPROX_CHARS_PER_TOKEN = 4;\nconst DEFAULT_TOKEN_BUDGET = 8_000;\nconst DEFAULT_TIMEOUT_MS = 5_000;\n\ninterface CaptureAriaTreeOptions {\n /** Soft cap on token count (chars/4 approximation). Default 8000. */\n tokenBudget?: number;\n /** Hard timeout on the capture. Default 5s. */\n timeoutMs?: number;\n}\n\n/**\n * Returns the truncated a11y tree as a plain string, or undefined when\n * capture fails. Never throws — a11y capture is best-effort tier-2 evidence,\n * not a hard requirement, so failures are silently absorbed (the verifier\n * surfaces this via evidence_insufficient).\n */\nexport async function captureAriaTreeProbe(\n v3: V3,\n opts: CaptureAriaTreeOptions = {},\n): Promise<string | undefined> {\n const envBudget = parseInt(\n process.env.VERIFIER_ARIATREE_TOKEN_BUDGET ?? \"\",\n 10,\n );\n const tokenBudget =\n opts.tokenBudget ??\n (Number.isFinite(envBudget) && envBudget > 0\n ? envBudget\n : DEFAULT_TOKEN_BUDGET);\n const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const maxChars = tokenBudget * APPROX_CHARS_PER_TOKEN;\n\n try {\n // v3.extract() without a schema returns { pageText } where pageText is the\n // rendered accessibility tree — same path the agent's ariaTree tool uses.\n const result = await v3.extract({ timeout: timeoutMs });\n const pageText = result?.pageText;\n if (typeof pageText !== \"string\" || pageText.length === 0) return undefined;\n\n if (pageText.length > maxChars) {\n return (\n pageText.slice(0, maxChars) +\n `\\n\\n[CONTENT TRUNCATED at ~${tokenBudget} tokens — set VERIFIER_ARIATREE_TOKEN_BUDGET to raise]`\n );\n }\n return pageText;\n } catch {\n return undefined;\n }\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import type { AgentEvidenceCallback } from "../../types/public/agentEvidenceEvents.js";
2
+ import type { LogLine } from "../../types/public/logs.js";
3
+ import type { V3 } from "../../v3.js";
4
+ interface CaptureProbeEvidenceOptions {
5
+ v3: V3;
6
+ url: string;
7
+ logger: (message: LogLine) => void;
8
+ warningMessage: string;
9
+ }
10
+ interface EmitPostStepProbeEvidenceOptions extends CaptureProbeEvidenceOptions {
11
+ evidenceCallback?: AgentEvidenceCallback;
12
+ }
13
+ export declare function captureProbeEvidence({ v3, url, logger, warningMessage, }: CaptureProbeEvidenceOptions): Promise<{
14
+ url: string;
15
+ screenshot?: Buffer;
16
+ ariaTree?: string;
17
+ }>;
18
+ export declare function emitPostStepProbeEvidence({ v3, url, evidenceCallback, logger, warningMessage, }: EmitPostStepProbeEvidenceOptions): Promise<void>;
19
+ export {};
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.captureProbeEvidence = captureProbeEvidence;
4
+ exports.emitPostStepProbeEvidence = emitPostStepProbeEvidence;
5
+ const captureAriaTreeProbe_js_1 = require("./captureAriaTreeProbe.js");
6
+ function errorMessage(error) {
7
+ return error instanceof Error ? error.message : String(error);
8
+ }
9
+ async function captureProbeEvidence({ v3, url, logger, warningMessage, }) {
10
+ let probeUrl = url;
11
+ let screenshot;
12
+ try {
13
+ const page = await v3.context.awaitActivePage();
14
+ probeUrl = page.url();
15
+ screenshot = await page.screenshot({ fullPage: false });
16
+ }
17
+ catch (e) {
18
+ logger({
19
+ category: "agent",
20
+ message: `${warningMessage}: ${errorMessage(e)}`,
21
+ level: 1,
22
+ });
23
+ }
24
+ const ariaTree = await (0, captureAriaTreeProbe_js_1.captureAriaTreeProbe)(v3);
25
+ return {
26
+ url: probeUrl,
27
+ ...(screenshot ? { screenshot } : {}),
28
+ ...(ariaTree !== undefined ? { ariaTree } : {}),
29
+ };
30
+ }
31
+ async function emitPostStepProbeEvidence({ v3, url, evidenceCallback, logger, warningMessage, }) {
32
+ if (!evidenceCallback)
33
+ return;
34
+ const probe = await captureProbeEvidence({
35
+ v3,
36
+ url,
37
+ logger,
38
+ warningMessage,
39
+ });
40
+ if (probe.screenshot) {
41
+ await evidenceCallback({
42
+ type: "screenshot",
43
+ screenshot: probe.screenshot,
44
+ url: probe.url,
45
+ evidenceRole: "probe",
46
+ });
47
+ }
48
+ await evidenceCallback({
49
+ type: "step_observed",
50
+ url: probe.url,
51
+ ariaTree: probe.ariaTree,
52
+ });
53
+ }
54
+ //# sourceMappingURL=postStepProbeEvidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postStepProbeEvidence.js","sourceRoot":"","sources":["../../../../../../lib/v3/agent/utils/postStepProbeEvidence.ts"],"names":[],"mappings":";;AAoBA,oDA8BC;AAED,8DA4BC;AA7ED,uEAAiE;AAajE,SAAS,YAAY,CAAC,KAAc;IAClC,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAEM,KAAK,UAAU,oBAAoB,CAAC,EACzC,EAAE,EACF,GAAG,EACH,MAAM,EACN,cAAc,GACc;IAK5B,IAAI,QAAQ,GAAG,GAAG,CAAC;IACnB,IAAI,UAA8B,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;QAChD,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACtB,UAAU,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,CAAC;YACL,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,GAAG,cAAc,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE;YAChD,KAAK,EAAE,CAAC;SACT,CAAC,CAAC;IACL,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,IAAA,8CAAoB,EAAC,EAAE,CAAC,CAAC;IAChD,OAAO;QACL,GAAG,EAAE,QAAQ;QACb,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrC,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChD,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,yBAAyB,CAAC,EAC9C,EAAE,EACF,GAAG,EACH,gBAAgB,EAChB,MAAM,EACN,cAAc,GACmB;IACjC,IAAI,CAAC,gBAAgB;QAAE,OAAO;IAE9B,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC;QACvC,EAAE;QACF,GAAG;QACH,MAAM;QACN,cAAc;KACf,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACrB,MAAM,gBAAgB,CAAC;YACrB,IAAI,EAAE,YAAY;YAClB,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,YAAY,EAAE,OAAO;SACtB,CAAC,CAAC;IACL,CAAC;IACD,MAAM,gBAAgB,CAAC;QACrB,IAAI,EAAE,eAAe;QACrB,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { AgentEvidenceCallback } from \"../../types/public/agentEvidenceEvents.js\";\nimport type { LogLine } from \"../../types/public/logs.js\";\nimport type { V3 } from \"../../v3.js\";\nimport { captureAriaTreeProbe } from \"./captureAriaTreeProbe.js\";\n\ninterface CaptureProbeEvidenceOptions {\n v3: V3;\n url: string;\n logger: (message: LogLine) => void;\n warningMessage: string;\n}\n\ninterface EmitPostStepProbeEvidenceOptions extends CaptureProbeEvidenceOptions {\n evidenceCallback?: AgentEvidenceCallback;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport async function captureProbeEvidence({\n v3,\n url,\n logger,\n warningMessage,\n}: CaptureProbeEvidenceOptions): Promise<{\n url: string;\n screenshot?: Buffer;\n ariaTree?: string;\n}> {\n let probeUrl = url;\n let screenshot: Buffer | undefined;\n try {\n const page = await v3.context.awaitActivePage();\n probeUrl = page.url();\n screenshot = await page.screenshot({ fullPage: false });\n } catch (e) {\n logger({\n category: \"agent\",\n message: `${warningMessage}: ${errorMessage(e)}`,\n level: 1,\n });\n }\n\n const ariaTree = await captureAriaTreeProbe(v3);\n return {\n url: probeUrl,\n ...(screenshot ? { screenshot } : {}),\n ...(ariaTree !== undefined ? { ariaTree } : {}),\n };\n}\n\nexport async function emitPostStepProbeEvidence({\n v3,\n url,\n evidenceCallback,\n logger,\n warningMessage,\n}: EmitPostStepProbeEvidenceOptions): Promise<void> {\n if (!evidenceCallback) return;\n\n const probe = await captureProbeEvidence({\n v3,\n url,\n logger,\n warningMessage,\n });\n if (probe.screenshot) {\n await evidenceCallback({\n type: \"screenshot\",\n screenshot: probe.screenshot,\n url: probe.url,\n evidenceRole: \"probe\",\n });\n }\n await evidenceCallback({\n type: \"step_observed\",\n url: probe.url,\n ariaTree: probe.ariaTree,\n });\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { AgentStepFinishedEvent } from "../../types/public/agentEvidenceEvents.js";
2
+ export declare function inferToolOutput(toolResult: unknown): AgentStepFinishedEvent["toolOutput"];
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.inferToolOutput = inferToolOutput;
4
+ const ERROR_STRING_LIMIT = 1000;
5
+ function isRecord(value) {
6
+ return value !== null && typeof value === "object" && !Array.isArray(value);
7
+ }
8
+ function hasOwn(value, key) {
9
+ return Object.prototype.hasOwnProperty.call(value, key);
10
+ }
11
+ function normalizeError(value) {
12
+ if (value === undefined || value === null || value === false) {
13
+ return undefined;
14
+ }
15
+ if (value instanceof Error) {
16
+ return value.message;
17
+ }
18
+ if (typeof value === "string") {
19
+ return value;
20
+ }
21
+ if (typeof value === "number" ||
22
+ typeof value === "boolean" ||
23
+ typeof value === "bigint") {
24
+ return String(value);
25
+ }
26
+ let serialized;
27
+ try {
28
+ serialized = JSON.stringify(value) ?? String(value);
29
+ }
30
+ catch {
31
+ serialized = String(value);
32
+ }
33
+ if (serialized.length <= ERROR_STRING_LIMIT) {
34
+ return serialized;
35
+ }
36
+ return `${serialized.slice(0, ERROR_STRING_LIMIT)}... [truncated]`;
37
+ }
38
+ function statusCandidates(toolResult) {
39
+ if (!isRecord(toolResult)) {
40
+ return [];
41
+ }
42
+ const candidates = [toolResult];
43
+ const output = toolResult.output;
44
+ if (isRecord(output)) {
45
+ candidates.push(output);
46
+ }
47
+ return candidates;
48
+ }
49
+ function inferToolOutput(toolResult) {
50
+ const candidates = statusCandidates(toolResult);
51
+ const error = candidates
52
+ .map((candidate) => hasOwn(candidate, "error") ? normalizeError(candidate.error) : undefined)
53
+ .find((message) => message !== undefined);
54
+ const successFalse = candidates.some((candidate) => candidate.success === false);
55
+ const isError = candidates.some((candidate) => Boolean(candidate.isError));
56
+ return {
57
+ ok: error === undefined && !isError && !successFalse,
58
+ result: toolResult,
59
+ error,
60
+ };
61
+ }
62
+ //# sourceMappingURL=toolOutputEvidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolOutputEvidence.js","sourceRoot":"","sources":["../../../../../../lib/v3/agent/utils/toolOutputEvidence.ts"],"names":[],"mappings":";;AAuDA,0CAoBC;AAzED,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,MAAM,CAAC,KAA8B,EAAE,GAAW;IACzD,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;QAC7D,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,OAAO,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IACE,OAAO,KAAK,KAAK,QAAQ;QACzB,OAAO,KAAK,KAAK,SAAS;QAC1B,OAAO,KAAK,KAAK,QAAQ,EACzB,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,IAAI,kBAAkB,EAAE,CAAC;QAC5C,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,iBAAiB,CAAC;AACrE,CAAC;AAED,SAAS,gBAAgB,CAAC,UAAmB;IAC3C,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,UAAU,GAAG,CAAC,UAAU,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IACjC,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAgB,eAAe,CAC7B,UAAmB;IAEnB,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,UAAU;SACrB,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CACjB,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CACzE;SACA,IAAI,CAAC,CAAC,OAAO,EAAqB,EAAE,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;IAE/D,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAClC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,KAAK,KAAK,CAC3C,CAAC;IACF,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAE3E,OAAO;QACL,EAAE,EAAE,KAAK,KAAK,SAAS,IAAI,CAAC,OAAO,IAAI,CAAC,YAAY;QACpD,MAAM,EAAE,UAAU;QAClB,KAAK;KACN,CAAC;AACJ,CAAC","sourcesContent":["import type { AgentStepFinishedEvent } from \"../../types/public/agentEvidenceEvents.js\";\n\nconst ERROR_STRING_LIMIT = 1000;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction hasOwn(value: Record<string, unknown>, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(value, key);\n}\n\nfunction normalizeError(value: unknown): string | undefined {\n if (value === undefined || value === null || value === false) {\n return undefined;\n }\n if (value instanceof Error) {\n return value.message;\n }\n if (typeof value === \"string\") {\n return value;\n }\n if (\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n typeof value === \"bigint\"\n ) {\n return String(value);\n }\n\n let serialized: string;\n try {\n serialized = JSON.stringify(value) ?? String(value);\n } catch {\n serialized = String(value);\n }\n if (serialized.length <= ERROR_STRING_LIMIT) {\n return serialized;\n }\n return `${serialized.slice(0, ERROR_STRING_LIMIT)}... [truncated]`;\n}\n\nfunction statusCandidates(toolResult: unknown): Record<string, unknown>[] {\n if (!isRecord(toolResult)) {\n return [];\n }\n\n const candidates = [toolResult];\n const output = toolResult.output;\n if (isRecord(output)) {\n candidates.push(output);\n }\n return candidates;\n}\n\nexport function inferToolOutput(\n toolResult: unknown,\n): AgentStepFinishedEvent[\"toolOutput\"] {\n const candidates = statusCandidates(toolResult);\n const error = candidates\n .map((candidate) =>\n hasOwn(candidate, \"error\") ? normalizeError(candidate.error) : undefined,\n )\n .find((message): message is string => message !== undefined);\n\n const successFalse = candidates.some(\n (candidate) => candidate.success === false,\n );\n const isError = candidates.some((candidate) => Boolean(candidate.isError));\n\n return {\n ok: error === undefined && !isError && !successFalse,\n result: toolResult,\n error,\n };\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import type { AgentEvidenceCallback } from "../../types/public/agentEvidenceEvents.js";
2
+ import type { LogLine } from "../../types/public/logs.js";
3
+ export declare function wrapEvidenceCallback(callback: AgentEvidenceCallback | undefined, logger: (message: LogLine) => void): AgentEvidenceCallback | undefined;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.wrapEvidenceCallback = wrapEvidenceCallback;
4
+ // onEvidence is a user-supplied observability hook (trajectory recording,
5
+ // verifier capture, etc.). Wrap it once at the boundary where the handler
6
+ // receives it so a throwing user callback can never abort the agent loop —
7
+ // internal emit sites can then call the wrapped callback directly without
8
+ // per-site try/catch.
9
+ function wrapEvidenceCallback(callback, logger) {
10
+ if (!callback)
11
+ return undefined;
12
+ return async (event) => {
13
+ try {
14
+ await callback(event);
15
+ }
16
+ catch (e) {
17
+ logger({
18
+ category: "agent",
19
+ message: `Warning: onEvidence callback failed for ${event.type}: ${e instanceof Error ? e.message : String(e)}`,
20
+ level: 1,
21
+ });
22
+ }
23
+ };
24
+ }
25
+ //# sourceMappingURL=wrapEvidenceCallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wrapEvidenceCallback.js","sourceRoot":"","sources":["../../../../../../lib/v3/agent/utils/wrapEvidenceCallback.ts"],"names":[],"mappings":";;AAQA,oDAkBC;AAvBD,0EAA0E;AAC1E,0EAA0E;AAC1E,2EAA2E;AAC3E,0EAA0E;AAC1E,sBAAsB;AACtB,SAAgB,oBAAoB,CAClC,QAA2C,EAC3C,MAAkC;IAElC,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChC,OAAO,KAAK,EAAE,KAAK,EAAE,EAAE;QACrB,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC;gBACL,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,2CAA2C,KAAK,CAAC,IAAI,KAC5D,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAC3C,EAAE;gBACF,KAAK,EAAE,CAAC;aACT,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import type { AgentEvidenceCallback } from \"../../types/public/agentEvidenceEvents.js\";\nimport type { LogLine } from \"../../types/public/logs.js\";\n\n// onEvidence is a user-supplied observability hook (trajectory recording,\n// verifier capture, etc.). Wrap it once at the boundary where the handler\n// receives it so a throwing user callback can never abort the agent loop —\n// internal emit sites can then call the wrapped callback directly without\n// per-site try/catch.\nexport function wrapEvidenceCallback(\n callback: AgentEvidenceCallback | undefined,\n logger: (message: LogLine) => void,\n): AgentEvidenceCallback | undefined {\n if (!callback) return undefined;\n return async (event) => {\n try {\n await callback(event);\n } catch (e) {\n logger({\n category: \"agent\",\n message: `Warning: onEvidence callback failed for ${event.type}: ${\n e instanceof Error ? e.message : String(e)\n }`,\n level: 1,\n });\n }\n };\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import type { ActResult, AgentConfig, AgentExecuteOptions, AgentResult, ExtractResult, ObserveResult, LogLine, StagehandMetrics, BrowserbaseRegion, ActOptions, ExtractOptions, ObserveOptions, Api } from "./types/public/index.js";
2
2
  import type { SerializableResponse, AgentCacheTransferPayload } from "./types/private/index.js";
3
+ import type { ModelConfiguration } from "./types/public/model.js";
3
4
  import type { StagehandZodSchema } from "./zodCompat.js";
4
5
  /**
5
6
  * Mapping of Browserbase regions to their corresponding Stagehand API base URLs.
@@ -41,6 +42,8 @@ interface ClientSessionStartParams extends Api.SessionStartRequest {
41
42
  * Optional: when omitted, requests are sent without the x-model-api-key header
42
43
  * and the server is expected to handle model authentication on its own. */
43
44
  modelApiKey?: string;
45
+ /** Default model config for later action requests. Not sent to /sessions/start. */
46
+ defaultModelConfig?: ModelConfiguration;
44
47
  }
45
48
  /**
46
49
  * Client parameters for act() method.
@@ -79,6 +82,7 @@ export declare class StagehandAPIClient {
79
82
  private sessionId?;
80
83
  private modelApiKey?;
81
84
  private modelProvider?;
85
+ private defaultModelConfig?;
82
86
  private region?;
83
87
  private logger;
84
88
  private fetchWithCookies;
@@ -87,7 +91,7 @@ export declare class StagehandAPIClient {
87
91
  private latestAgentCacheEntry;
88
92
  private warnedStagehandBaseUrl;
89
93
  constructor({ apiKey, projectId, logger, serverCache, }: StagehandAPIConstructorParams);
90
- init({ modelName, modelApiKey, domSettleTimeoutMs, verbose, systemPrompt, selfHeal, browserbaseSessionCreateParams, browserbaseSessionID, }: ClientSessionStartParams): Promise<Api.SessionStartResult>;
94
+ init({ modelName, modelApiKey, defaultModelConfig, domSettleTimeoutMs, verbose, systemPrompt, selfHeal, browserbaseSessionCreateParams, browserbaseSessionID, }: ClientSessionStartParams): Promise<Api.SessionStartResult>;
91
95
  act({ input, options, frameId, }: ClientActParameters): Promise<ActResult>;
92
96
  extract<T extends StagehandZodSchema>({ instruction, schema: zodSchema, options, frameId, }: ClientExtractParameters): Promise<ExtractResult<T>>;
93
97
  observe({ instruction, options, frameId, }: ClientObserveParameters): Promise<ObserveResult>;
@@ -105,6 +109,8 @@ export declare class StagehandAPIClient {
105
109
  * model provider differs from the one used to init the session.
106
110
  */
107
111
  private prepareModelConfig;
112
+ private getDefaultModelConfig;
113
+ private getModelProvider;
108
114
  private consumeFinishedEventData;
109
115
  private execute;
110
116
  /**
@@ -42,6 +42,7 @@ class StagehandAPIClient {
42
42
  sessionId;
43
43
  modelApiKey;
44
44
  modelProvider;
45
+ defaultModelConfig;
45
46
  region;
46
47
  logger;
47
48
  fetchWithCookies;
@@ -57,7 +58,7 @@ class StagehandAPIClient {
57
58
  // Create a single cookie jar instance that will persist across all requests
58
59
  this.fetchWithCookies = (0, fetch_cookie_1.default)(fetch);
59
60
  }
60
- async init({ modelName, modelApiKey, domSettleTimeoutMs, verbose, systemPrompt, selfHeal, browserbaseSessionCreateParams, browserbaseSessionID,
61
+ async init({ modelName, modelApiKey, defaultModelConfig, domSettleTimeoutMs, verbose, systemPrompt, selfHeal, browserbaseSessionCreateParams, browserbaseSessionID,
61
62
  // browser, TODO for local browsers
62
63
  }) {
63
64
  this.modelApiKey = modelApiKey;
@@ -65,6 +66,9 @@ class StagehandAPIClient {
65
66
  this.modelProvider = modelName?.includes("/")
66
67
  ? modelName.split("/")[0]
67
68
  : undefined;
69
+ this.defaultModelConfig = defaultModelConfig
70
+ ? this.prepareModelConfig(defaultModelConfig)
71
+ : undefined;
68
72
  // Store the region for multi-region API URL resolution
69
73
  this.region = browserbaseSessionCreateParams?.region;
70
74
  this.logger({
@@ -118,13 +122,21 @@ class StagehandAPIClient {
118
122
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
119
123
  const { page: _, serverCache: enableCache, ...restOptions } = options;
120
124
  serverCache = enableCache;
125
+ if (restOptions.model) {
126
+ restOptions.model = this.prepareModelConfig(restOptions.model);
127
+ }
128
+ else if (this.defaultModelConfig) {
129
+ restOptions.model = this.getDefaultModelConfig();
130
+ }
121
131
  if (Object.keys(restOptions).length > 0) {
122
- if (restOptions.model) {
123
- restOptions.model = this.prepareModelConfig(restOptions.model);
124
- }
125
132
  wireOptions = restOptions;
126
133
  }
127
134
  }
135
+ else if (this.defaultModelConfig) {
136
+ wireOptions = {
137
+ model: this.getDefaultModelConfig(),
138
+ };
139
+ }
128
140
  // Build wire-format request body
129
141
  const requestBody = {
130
142
  input,
@@ -147,13 +159,21 @@ class StagehandAPIClient {
147
159
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
148
160
  const { page: _, serverCache: enableCache, ...restOptions } = options;
149
161
  serverCache = enableCache;
162
+ if (restOptions.model) {
163
+ restOptions.model = this.prepareModelConfig(restOptions.model);
164
+ }
165
+ else if (this.defaultModelConfig) {
166
+ restOptions.model = this.getDefaultModelConfig();
167
+ }
150
168
  if (Object.keys(restOptions).length > 0) {
151
- if (restOptions.model) {
152
- restOptions.model = this.prepareModelConfig(restOptions.model);
153
- }
154
169
  wireOptions = restOptions;
155
170
  }
156
171
  }
172
+ else if (this.defaultModelConfig) {
173
+ wireOptions = {
174
+ model: this.getDefaultModelConfig(),
175
+ };
176
+ }
157
177
  // Build wire-format request body
158
178
  const requestBody = {
159
179
  instruction,
@@ -175,13 +195,21 @@ class StagehandAPIClient {
175
195
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
176
196
  const { page: _, serverCache: enableCache, ...restOptions } = options;
177
197
  serverCache = enableCache;
198
+ if (restOptions.model) {
199
+ restOptions.model = this.prepareModelConfig(restOptions.model);
200
+ }
201
+ else if (this.defaultModelConfig) {
202
+ restOptions.model = this.getDefaultModelConfig();
203
+ }
178
204
  if (Object.keys(restOptions).length > 0) {
179
- if (restOptions.model) {
180
- restOptions.model = this.prepareModelConfig(restOptions.model);
181
- }
182
205
  wireOptions = restOptions;
183
206
  }
184
207
  }
208
+ else if (this.defaultModelConfig) {
209
+ wireOptions = {
210
+ model: this.getDefaultModelConfig(),
211
+ };
212
+ }
185
213
  // Build wire-format request body
186
214
  const requestBody = {
187
215
  instruction,
@@ -195,7 +223,19 @@ class StagehandAPIClient {
195
223
  });
196
224
  }
197
225
  async goto(url, options, frameId) {
198
- const requestBody = { url, options, frameId };
226
+ const publicOptions = { ...(options ?? {}) };
227
+ delete publicOptions.model;
228
+ const wireOptions = {
229
+ ...publicOptions,
230
+ ...(this.defaultModelConfig
231
+ ? { model: this.getDefaultModelConfig() }
232
+ : {}),
233
+ };
234
+ const requestBody = {
235
+ url,
236
+ options: Object.keys(wireOptions).length > 0 ? wireOptions : undefined,
237
+ frameId,
238
+ };
199
239
  return this.execute({
200
240
  method: "navigate",
201
241
  args: requestBody,
@@ -225,7 +265,7 @@ class StagehandAPIClient {
225
265
  cua: agentConfig.mode === undefined ? agentConfig.cua : undefined,
226
266
  model: agentConfig.model
227
267
  ? this.prepareModelConfig(agentConfig.model)
228
- : undefined,
268
+ : this.getDefaultModelConfig(),
229
269
  executionModel: agentConfig.executionModel
230
270
  ? this.prepareModelConfig(agentConfig.executionModel)
231
271
  : undefined,
@@ -381,28 +421,41 @@ class StagehandAPIClient {
381
421
  prepareModelConfig(model) {
382
422
  if (typeof model === "string") {
383
423
  // Extract provider from model string (e.g., "openai/gpt-5-nano" -> "openai")
384
- const provider = model.includes("/") ? model.split("/")[0] : undefined;
424
+ const provider = this.getModelProvider(model);
425
+ const inheritedDefault = provider && provider === this.modelProvider
426
+ ? this.getDefaultModelConfig()
427
+ : undefined;
385
428
  const apiKey = provider && provider !== this.modelProvider
386
429
  ? ((0, utils_js_1.loadApiKeyFromEnv)(provider, this.logger) ?? this.modelApiKey)
387
430
  : this.modelApiKey;
388
431
  return {
432
+ ...inheritedDefault,
389
433
  modelName: model,
390
434
  ...(apiKey ? { apiKey } : {}),
391
435
  };
392
436
  }
393
- if (!model.apiKey) {
394
- const provider = model.modelName?.includes("/")
395
- ? model.modelName.split("/")[0]
437
+ const provider = this.getModelProvider(model.modelName);
438
+ const inheritedDefault = provider && provider === this.modelProvider
439
+ ? this.getDefaultModelConfig()
440
+ : undefined;
441
+ const apiKey = !model.apiKey && provider && provider !== this.modelProvider
442
+ ? ((0, utils_js_1.loadApiKeyFromEnv)(provider, this.logger) ?? this.modelApiKey)
443
+ : !model.apiKey
444
+ ? this.modelApiKey
396
445
  : undefined;
397
- const apiKey = provider && provider !== this.modelProvider
398
- ? ((0, utils_js_1.loadApiKeyFromEnv)(provider, this.logger) ?? this.modelApiKey)
399
- : this.modelApiKey;
400
- return {
401
- ...model,
402
- ...(apiKey ? { apiKey } : {}),
403
- };
404
- }
405
- return model;
446
+ return {
447
+ ...inheritedDefault,
448
+ ...model,
449
+ ...(apiKey ? { apiKey } : {}),
450
+ };
451
+ }
452
+ getDefaultModelConfig() {
453
+ return this.defaultModelConfig
454
+ ? { ...this.defaultModelConfig }
455
+ : undefined;
456
+ }
457
+ getModelProvider(modelName) {
458
+ return modelName?.includes("/") ? modelName.split("/")[0] : undefined;
406
459
  }
407
460
  consumeFinishedEventData() {
408
461
  const data = this.lastFinishedEventData;
@@ -584,12 +637,30 @@ class StagehandAPIClient {
584
637
  else {
585
638
  baseUrl = getApiUrlForRegion(this.region);
586
639
  }
640
+ const headers = {
641
+ ...defaultHeaders,
642
+ ...options.headers,
643
+ };
644
+ if (path.endsWith("/navigate")) {
645
+ let body = options.body;
646
+ if (typeof options.body === "string") {
647
+ try {
648
+ body = JSON.parse(options.body);
649
+ }
650
+ catch {
651
+ body = options.body;
652
+ }
653
+ }
654
+ console.log("Stagehand goto request", JSON.stringify({
655
+ url: `${baseUrl}${path}`,
656
+ method: options.method,
657
+ headers,
658
+ body,
659
+ }, null, 2));
660
+ }
587
661
  const response = await this.fetchWithCookies(`${baseUrl}${path}`, {
588
662
  ...options,
589
- headers: {
590
- ...defaultHeaders,
591
- ...options.headers,
592
- },
663
+ headers,
593
664
  });
594
665
  return response;
595
666
  }