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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/cjs/lib/modelUtils.d.ts +10 -0
  2. package/dist/cjs/lib/modelUtils.js +11 -0
  3. package/dist/cjs/lib/modelUtils.js.map +1 -1
  4. package/dist/cjs/lib/v3/agent/AgentProvider.js +3 -0
  5. package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
  6. package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.js +3 -1
  7. package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.js.map +1 -1
  8. package/dist/cjs/lib/v3/api.js +9 -0
  9. package/dist/cjs/lib/v3/api.js.map +1 -1
  10. package/dist/cjs/lib/v3/cache/AgentCache.js +6 -1
  11. package/dist/cjs/lib/v3/cache/AgentCache.js.map +1 -1
  12. package/dist/cjs/lib/v3/external_clients/aisdk.js +2 -0
  13. package/dist/cjs/lib/v3/external_clients/aisdk.js.map +1 -1
  14. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +5 -4
  15. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  16. package/dist/cjs/lib/v3/index.d.ts +1 -1
  17. package/dist/cjs/lib/v3/llm/LLMProvider.js +9 -2
  18. package/dist/cjs/lib/v3/llm/LLMProvider.js.map +1 -1
  19. package/dist/cjs/lib/v3/llm/aisdk.js +2 -0
  20. package/dist/cjs/lib/v3/llm/aisdk.js.map +1 -1
  21. package/dist/cjs/lib/v3/llm/providerOptions.d.ts +7 -0
  22. package/dist/cjs/lib/v3/llm/providerOptions.js +9 -0
  23. package/dist/cjs/lib/v3/llm/providerOptions.js.map +1 -0
  24. package/dist/cjs/lib/v3/types/private/agent.d.ts +1 -1
  25. package/dist/cjs/lib/v3/types/private/agent.js +1 -0
  26. package/dist/cjs/lib/v3/types/private/agent.js.map +1 -1
  27. package/dist/cjs/lib/v3/types/public/agent.d.ts +1 -1
  28. package/dist/cjs/lib/v3/types/public/agent.js +3 -0
  29. package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
  30. package/dist/cjs/lib/v3/types/public/model.d.ts +7 -0
  31. package/dist/cjs/lib/v3/types/public/model.js.map +1 -1
  32. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js +4 -3
  33. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
  34. package/dist/cjs/lib/v3/v3.js +39 -3
  35. package/dist/cjs/lib/v3/v3.js.map +1 -1
  36. package/dist/cjs/lib/v3/verifier/types.d.ts +3 -2
  37. package/dist/cjs/lib/v3/verifier/types.js.map +1 -1
  38. package/dist/cjs/lib/version.d.ts +1 -1
  39. package/dist/cjs/lib/version.js +1 -1
  40. package/dist/cjs/lib/version.js.map +1 -1
  41. package/dist/esm/lib/modelUtils.d.ts +10 -0
  42. package/dist/esm/lib/modelUtils.js +9 -0
  43. package/dist/esm/lib/modelUtils.js.map +1 -1
  44. package/dist/esm/lib/v3/agent/AgentProvider.js +3 -0
  45. package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
  46. package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.js +3 -1
  47. package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.js.map +1 -1
  48. package/dist/esm/lib/v3/api.js +9 -0
  49. package/dist/esm/lib/v3/api.js.map +1 -1
  50. package/dist/esm/lib/v3/cache/AgentCache.js +6 -1
  51. package/dist/esm/lib/v3/cache/AgentCache.js.map +1 -1
  52. package/dist/esm/lib/v3/external_clients/aisdk.js +2 -0
  53. package/dist/esm/lib/v3/external_clients/aisdk.js.map +1 -1
  54. package/dist/esm/lib/v3/handlers/v3AgentHandler.js +5 -4
  55. package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  56. package/dist/esm/lib/v3/index.d.ts +1 -1
  57. package/dist/esm/lib/v3/llm/LLMProvider.js +9 -2
  58. package/dist/esm/lib/v3/llm/LLMProvider.js.map +1 -1
  59. package/dist/esm/lib/v3/llm/aisdk.js +2 -0
  60. package/dist/esm/lib/v3/llm/aisdk.js.map +1 -1
  61. package/dist/esm/lib/v3/llm/providerOptions.d.ts +7 -0
  62. package/dist/esm/lib/v3/llm/providerOptions.js +6 -0
  63. package/dist/esm/lib/v3/llm/providerOptions.js.map +1 -0
  64. package/dist/esm/lib/v3/types/private/agent.d.ts +1 -1
  65. package/dist/esm/lib/v3/types/private/agent.js +1 -0
  66. package/dist/esm/lib/v3/types/private/agent.js.map +1 -1
  67. package/dist/esm/lib/v3/types/public/agent.d.ts +1 -1
  68. package/dist/esm/lib/v3/types/public/agent.js +3 -0
  69. package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
  70. package/dist/esm/lib/v3/types/public/model.d.ts +7 -0
  71. package/dist/esm/lib/v3/types/public/model.js.map +1 -1
  72. package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js +4 -3
  73. package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
  74. package/dist/esm/lib/v3/v3.js +40 -4
  75. package/dist/esm/lib/v3/v3.js.map +1 -1
  76. package/dist/esm/lib/v3/verifier/types.d.ts +3 -2
  77. package/dist/esm/lib/v3/verifier/types.js.map +1 -1
  78. package/dist/esm/lib/version.d.ts +1 -1
  79. package/dist/esm/lib/version.js +1 -1
  80. package/dist/esm/lib/version.js.map +1 -1
  81. package/package.json +1 -1
@@ -411,7 +411,7 @@ export interface AgentStreamExecuteOptions extends AgentExecuteOptionsBase {
411
411
  callbacks?: AgentStreamCallbacks;
412
412
  }
413
413
  export type AgentType = "openai" | "anthropic" | "google" | "microsoft" | "bedrock" | "vertex" | "azure";
414
- export declare const AVAILABLE_CUA_MODELS: readonly ["openai/gpt-5.4", "openai/gpt-5.4-mini", "openai/gpt-5.5", "openai/computer-use-preview", "openai/computer-use-preview-2025-03-11", "anthropic/claude-opus-4-5-20251101", "anthropic/claude-opus-4-6", "anthropic/claude-opus-4-8", "anthropic/claude-sonnet-4-6", "anthropic/claude-haiku-4-5", "anthropic/claude-haiku-4-5-20251001", "anthropic/claude-sonnet-4-20250514", "anthropic/claude-sonnet-4-5-20250929", "anthropic/claude-fable-5", "google/gemini-2.5-computer-use-preview-10-2025", "google/gemini-3-flash-preview", "google/gemini-3.5-flash", "google/gemini-3-pro-preview", "microsoft/fara-7b"];
414
+ export declare const AVAILABLE_CUA_MODELS: readonly ["openai/gpt-5.4", "openai/gpt-5.4-mini", "openai/gpt-5.5", "openai/gpt-5.6-terra", "openai/gpt-5.6-luna", "openai/gpt-5.6-sol", "openai/computer-use-preview", "openai/computer-use-preview-2025-03-11", "anthropic/claude-opus-4-5-20251101", "anthropic/claude-opus-4-6", "anthropic/claude-opus-4-8", "anthropic/claude-sonnet-4-6", "anthropic/claude-haiku-4-5", "anthropic/claude-haiku-4-5-20251001", "anthropic/claude-sonnet-4-20250514", "anthropic/claude-sonnet-4-5-20250929", "anthropic/claude-fable-5", "google/gemini-2.5-computer-use-preview-10-2025", "google/gemini-3-flash-preview", "google/gemini-3.5-flash", "google/gemini-3-pro-preview", "microsoft/fara-7b"];
415
415
  export type AvailableCuaModel = (typeof AVAILABLE_CUA_MODELS)[number];
416
416
  export interface AgentExecutionOptions<TOptions extends AgentExecuteOptions = AgentExecuteOptions> {
417
417
  options: TOptions;
@@ -2,6 +2,9 @@ export const AVAILABLE_CUA_MODELS = [
2
2
  "openai/gpt-5.4",
3
3
  "openai/gpt-5.4-mini",
4
4
  "openai/gpt-5.5",
5
+ "openai/gpt-5.6-terra",
6
+ "openai/gpt-5.6-luna",
7
+ "openai/gpt-5.6-sol",
5
8
  "openai/computer-use-preview",
6
9
  "openai/computer-use-preview-2025-03-11",
7
10
  "anthropic/claude-opus-4-5-20251101",
@@ -1 +1 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../../../../lib/v3/types/public/agent.ts"],"names":[],"mappings":"AAmdA,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,gBAAgB;IAChB,qBAAqB;IACrB,gBAAgB;IAChB,6BAA6B;IAC7B,wCAAwC;IACxC,oCAAoC;IACpC,2BAA2B;IAC3B,2BAA2B;IAC3B,6BAA6B;IAC7B,4BAA4B;IAC5B,qCAAqC;IACrC,oCAAoC;IACpC,sCAAsC;IACtC,0BAA0B;IAC1B,gDAAgD;IAChD,+BAA+B;IAC/B,yBAAyB;IACzB,6BAA6B;IAC7B,mBAAmB;CACX,CAAC","sourcesContent":["import type { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport {\n ToolSet,\n ModelMessage,\n wrapLanguageModel,\n StreamTextResult,\n StepResult,\n PrepareStepFunction,\n GenerateTextOnStepFinishCallback,\n StreamTextOnStepFinishCallback,\n StreamTextOnErrorCallback,\n StreamTextOnChunkCallback,\n StreamTextOnFinishCallback,\n} from \"ai\";\nimport { LogLine } from \"./logs.js\";\nimport { ClientOptions } from \"./model.js\";\nimport { StagehandZodObject } from \"../../zodCompat.js\";\nimport type { AgentEvidenceCallback } from \"./agentEvidenceEvents.js\";\n\n// Re-export ModelMessage for consumers who want to use it for conversation continuation\nexport type { ModelMessage } from \"ai\";\n\n// Re-export Tool type for consumers who want to define custom tools\nexport type { Tool } from \"ai\";\nimport { Page as PlaywrightPage } from \"playwright-core\";\nimport { Page as PuppeteerPage } from \"puppeteer-core\";\nimport { Page as PatchrightPage } from \"patchright-core\";\nimport { Page } from \"../../understudy/page.js\";\n\n/**\n * Result of a screenshot provider: the base64-encoded image bytes plus an\n * explicit media type. Declaring the media type at the capture boundary lets\n * every CUA client pass it through instead of hardcoding or inferring it.\n */\nexport interface ScreenshotProviderResult {\n base64: string;\n mediaType: \"image/png\" | \"image/jpeg\";\n}\n\n// =============================================================================\n// Variable Types\n// =============================================================================\n\n/**\n * A variable value can be a simple primitive or a rich object with an optional description.\n * This unified type is shared across `act`, `agent.execute`, and other methods.\n *\n * @example Simple (backward-compatible):\n * ```typescript\n * variables: { username: \"john@example.com\" }\n * ```\n *\n * @example Rich with description (useful for agents):\n * ```typescript\n * variables: {\n * username: { value: \"john@example.com\", description: \"The login email\" }\n * }\n * ```\n */\nexport type VariableValue =\n | string\n | number\n | boolean\n | { value: string | number | boolean; description?: string };\n\n/**\n * A collection of named variables for use in act, agent, and other methods.\n */\nexport type Variables = Record<string, VariableValue>;\n\nexport interface AgentContext {\n options: AgentExecuteOptionsBase;\n maxSteps: number;\n systemPrompt: string;\n allTools: ToolSet;\n messages: ModelMessage[];\n wrappedModel: ReturnType<typeof wrapLanguageModel>;\n initialPageUrl: string;\n}\n\nexport interface AgentState {\n collectedReasoning: string[];\n actions: AgentAction[];\n finalMessage: string;\n completed: boolean;\n currentPageUrl: string;\n}\n\nexport interface AgentAction {\n type: string;\n reasoning?: string;\n taskCompleted?: boolean;\n action?: string;\n // Tool-specific fields\n timeMs?: number; // wait tool\n pageText?: string; // ariaTree tool\n pageUrl?: string; // ariaTree tool\n instruction?: string; // various tools\n [key: string]: unknown;\n}\n\nexport interface AgentResult {\n success: boolean;\n message: string;\n actions: AgentAction[];\n completed: boolean;\n metadata?: Record<string, unknown>;\n usage?: {\n input_tokens: number;\n output_tokens: number;\n reasoning_tokens?: number;\n cached_input_tokens?: number;\n inference_time_ms: number;\n };\n /**\n * The conversation messages from this execution.\n * Pass these to a subsequent execute() call via the `messages` option to continue the conversation.\n * @experimental\n */\n messages?: ModelMessage[];\n /**\n * Custom output data extracted based on the `output` schema provided in execute options.\n * Only populated if an `output` schema was provided.\n * @experimental\n */\n output?: Record<string, unknown>;\n}\n\nexport type AgentStreamResult = StreamTextResult<ToolSet, never> & {\n result: Promise<AgentResult>;\n};\n\n/**\n * Base callbacks shared between execute (non-streaming) and streaming modes.\n */\nexport interface AgentCallbacks {\n /**\n * Optional function called before each step to modify settings.\n * You can change the model, tool choices, active tools, system prompt,\n * and input messages for each step.\n */\n prepareStep?: PrepareStepFunction<ToolSet>;\n /**\n * Callback called when each step (LLM call) is finished.\n * This is called for intermediate steps as well as the final step.\n */\n onStepFinish?:\n | GenerateTextOnStepFinishCallback<ToolSet>\n | StreamTextOnStepFinishCallback<ToolSet>;\n /**\n * Callback called when Stagehand captures agent-run evidence such as\n * screenshots, completed tool/action steps, or post-action observations.\n */\n onEvidence?: AgentEvidenceCallback;\n}\n\n/**\n * Error message type for streaming-only callbacks used in non-streaming mode.\n * This provides a clear error message when users try to use streaming callbacks without stream: true.\n */\ntype StreamingCallbackNotAvailable =\n \"This callback requires 'stream: true' in AgentConfig. Set stream: true to use streaming callbacks like onChunk, onFinish, onError, and onAbort.\";\n\n/**\n * Error message for safety confirmation callback misuse.\n * Safety confirmations are only available for non-streaming CUA agent executions.\n */\ntype SafetyConfirmationCallbackNotAvailable =\n \"Safety confirmation callbacks are only available via non-streaming AgentExecuteOptions.callbacks when using mode: 'cua'.\";\n\n/**\n * Callbacks specific to the non-streaming execute method.\n */\nexport interface AgentExecuteCallbacks extends AgentCallbacks {\n /**\n * Callback called when each step (LLM call) is finished.\n */\n onStepFinish?: GenerateTextOnStepFinishCallback<ToolSet>;\n /**\n * Callback for handling safety confirmation requests from CUA providers.\n * Only available when running an agent configured with mode: \"cua\".\n */\n onSafetyConfirmation?: SafetyConfirmationHandler;\n\n /**\n * NOT AVAILABLE in non-streaming mode.\n * This callback requires `stream: true` in AgentConfig.\n *\n * @example\n * ```typescript\n * // Enable streaming to use onChunk:\n * const agent = stagehand.agent({ stream: true });\n * await agent.execute({\n * instruction: \"...\",\n * callbacks: { onChunk: async (chunk) => console.log(chunk) }\n * });\n * ```\n */\n onChunk?: StreamingCallbackNotAvailable;\n\n /**\n * NOT AVAILABLE in non-streaming mode.\n * This callback requires `stream: true` in AgentConfig.\n *\n * @example\n * ```typescript\n * // Enable streaming to use onFinish:\n * const agent = stagehand.agent({ stream: true });\n * await agent.execute({\n * instruction: \"...\",\n * callbacks: { onFinish: (event) => console.log(\"Done!\", event) }\n * });\n * ```\n */\n onFinish?: StreamingCallbackNotAvailable;\n\n /**\n * NOT AVAILABLE in non-streaming mode.\n * This callback requires `stream: true` in AgentConfig.\n *\n * @example\n * ```typescript\n * // Enable streaming to use onError:\n * const agent = stagehand.agent({ stream: true });\n * await agent.execute({\n * instruction: \"...\",\n * callbacks: { onError: ({ error }) => console.error(error) }\n * });\n * ```\n */\n onError?: StreamingCallbackNotAvailable;\n\n /**\n * NOT AVAILABLE in non-streaming mode.\n * This callback requires `stream: true` in AgentConfig.\n *\n * @example\n * ```typescript\n * // Enable streaming to use onAbort:\n * const agent = stagehand.agent({ stream: true });\n * await agent.execute({\n * instruction: \"...\",\n * callbacks: { onAbort: (event) => console.log(\"Aborted\", event.steps) }\n * });\n * ```\n */\n onAbort?: StreamingCallbackNotAvailable;\n}\n\n/**\n * Callbacks specific to the streaming mode.\n */\nexport interface AgentStreamCallbacks extends AgentCallbacks {\n /**\n * Callback called when each step (LLM call) is finished during streaming.\n */\n onStepFinish?: StreamTextOnStepFinishCallback<ToolSet>;\n /**\n * Callback called when an error occurs during streaming.\n * Use this to log errors or handle error states.\n */\n onError?: StreamTextOnErrorCallback;\n /**\n * Callback called for each chunk of the stream.\n * Stream processing will pause until the callback promise resolves.\n */\n onChunk?: StreamTextOnChunkCallback<ToolSet>;\n /**\n * Callback called when the stream finishes.\n */\n onFinish?: StreamTextOnFinishCallback<ToolSet>;\n /**\n * Callback called when the stream is aborted.\n */\n onAbort?: (event: {\n steps: Array<StepResult<ToolSet>>;\n }) => PromiseLike<void> | void;\n /**\n * NOT AVAILABLE in streaming mode.\n * Safety confirmations currently require non-streaming execute() on CUA agents.\n */\n onSafetyConfirmation?: SafetyConfirmationCallbackNotAvailable;\n}\n\n/**\n * Base options for agent execution (without callbacks).\n */\nexport interface AgentExecuteOptionsBase {\n instruction: string;\n maxSteps?: number;\n page?: PlaywrightPage | PuppeteerPage | PatchrightPage | Page;\n highlightCursor?: boolean;\n /**\n * Previous conversation messages to continue from.\n * Pass the `messages` from a previous AgentResult to continue that conversation.\n * @experimental\n */\n messages?: ModelMessage[];\n /**\n * An AbortSignal that can be used to cancel the agent execution.\n * When aborted, the agent will stop and return a partial result.\n * @experimental\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 30000); // 30 second timeout\n *\n * const result = await agent.execute({\n * instruction: \"...\",\n * signal: controller.signal\n * });\n * ```\n */\n signal?: AbortSignal;\n /**\n * Tools to exclude from this execution.\n * Pass an array of tool names to prevent the agent from using those tools.\n *\n * **Note:** Not supported in CUA mode (`mode: \"cua\"`).\n *\n * **Available tools by mode:**\n *\n * **DOM mode (default):**\n * - `act` - Perform semantic actions (click, type, etc.)\n * - `fillForm` - Fill form fields using DOM selectors\n * - `ariaTree` - Get accessibility tree of the page\n * - `extract` - Extract structured data from page\n * - `goto` - Navigate to a URL\n * - `scroll` - Scroll using semantic directions (up/down/left/right)\n * - `keys` - Press keyboard keys\n * - `navback` - Navigate back in history\n * - `screenshot` - Take a screenshot\n * - `think` - Agent reasoning/planning step\n * - `wait` - Wait for time or condition\n * - `done` - Mark task as complete\n * - `search` - Web search (requires useSearch: true and BROWSERBASE_API_KEY)\n *\n * **Hybrid mode:**\n * - `click` - Click at specific coordinates\n * - `type` - Type text at coordinates\n * - `dragAndDrop` - Drag from one point to another\n * - `clickAndHold` - Click and hold at coordinates\n * - `fillFormVision` - Fill forms using vision/coordinates\n * - `act` - Perform semantic actions\n * - `ariaTree` - Get accessibility tree\n * - `extract` - Extract data from page\n * - `goto` - Navigate to URL\n * - `scroll` - Scroll using coordinates\n * - `keys` - Press keyboard keys\n * - `navback` - Navigate back\n * - `screenshot` - Take screenshot\n * - `think` - Agent reasoning step\n * - `wait` - Wait for time/condition\n * - `done` - Mark task complete\n * - `search` - Web search (requires useSearch: true and BROWSERBASE_API_KEY)\n *\n * @experimental\n * @example\n * ```typescript\n * // Exclude screenshot and extract tools\n * const result = await agent.execute({\n * instruction: \"Click the submit button\",\n * excludeTools: [\"screenshot\", \"extract\"]\n * });\n * ```\n */\n excludeTools?: string[];\n /**\n * A Zod schema defining custom output data to return when the task completes.\n * The agent will populate this data in the final done tool call.\n *\n * @experimental\n * @example\n * ```typescript\n * const result = await agent.execute({\n * instruction: \"Find the cheapest flight from NYC to LA\",\n * output: z.object({\n * price: z.string().describe(\"The price of the flight\"),\n * airline: z.string().describe(\"The airline name\"),\n * departureTime: z.string().describe(\"Departure time\"),\n * }),\n * });\n *\n * console.log(result.output); // { price: \"$199\", airline: \"Delta\", departureTime: \"8:00 AM\" }\n * ```\n */\n output?: StagehandZodObject;\n /**\n * Variables that the agent can use when filling forms or typing text.\n * The agent will see variable names and descriptions in the system prompt,\n * and can use them via `%variableName%` syntax in act/type/fillForm tool calls.\n *\n * Accepts both simple values and rich objects with descriptions (same type as `act`).\n *\n * **Note:** Not supported in CUA mode (`mode: \"cua\"`).\n *\n * @example\n * ```typescript\n * // Simple values\n * variables: { username: \"john@example.com\", password: \"secret123\" }\n *\n * // Rich values with descriptions (helps the agent understand context)\n * variables: {\n * username: { value: \"john@example.com\", description: \"The login email\" },\n * password: { value: \"secret123\", description: \"The login password\" },\n * }\n * ```\n */\n variables?: Variables;\n /**\n * Timeout in milliseconds for each agent tool call.\n * If a tool call exceeds this duration, it will be aborted and\n * reported back to the LLM as a timeout error so it can retry or adjust.\n * For tools that call v3 methods (act, extract, fillForm, ariaTree), the\n * timeout is also forwarded to the underlying v3 call for true cancellation.\n * @default 45000 (45 seconds)\n */\n toolTimeout?: number;\n /**\n * Enable the web search tool powered by Browserbase Search API.\n * Requires a valid Browserbase API key (BROWSERBASE_API_KEY).\n * When set to true, the agent gains access to a `search` tool for web searches.\n *\n * @example\n * ```typescript\n * const result = await agent.execute({\n * instruction: \"Find the latest news about AI\",\n * useSearch: true,\n * });\n * ```\n */\n useSearch?: boolean;\n}\n\n/**\n * Options for non-streaming agent execution.\n * Only accepts AgentExecuteCallbacks (no streaming-specific callbacks like onChunk, onFinish).\n */\nexport interface AgentExecuteOptions extends AgentExecuteOptionsBase {\n /**\n * Callbacks for non-streaming agent execution.\n * For streaming callbacks (onChunk, onFinish, onError, onAbort), use stream: true in AgentConfig.\n */\n callbacks?: AgentExecuteCallbacks;\n}\n\n/**\n * Options for streaming agent execution.\n * Accepts AgentStreamCallbacks including onChunk, onFinish, onError, and onAbort.\n */\nexport interface AgentStreamExecuteOptions extends AgentExecuteOptionsBase {\n /**\n * Callbacks for streaming agent execution.\n * Includes streaming-specific callbacks: onChunk, onFinish, onError, onAbort.\n */\n callbacks?: AgentStreamCallbacks;\n}\nexport type AgentType =\n | \"openai\"\n | \"anthropic\"\n | \"google\"\n | \"microsoft\"\n | \"bedrock\"\n | \"vertex\"\n | \"azure\";\n\nexport const AVAILABLE_CUA_MODELS = [\n \"openai/gpt-5.4\",\n \"openai/gpt-5.4-mini\",\n \"openai/gpt-5.5\",\n \"openai/computer-use-preview\",\n \"openai/computer-use-preview-2025-03-11\",\n \"anthropic/claude-opus-4-5-20251101\",\n \"anthropic/claude-opus-4-6\",\n \"anthropic/claude-opus-4-8\",\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 \"anthropic/claude-fable-5\",\n \"google/gemini-2.5-computer-use-preview-10-2025\",\n \"google/gemini-3-flash-preview\",\n \"google/gemini-3.5-flash\",\n \"google/gemini-3-pro-preview\",\n \"microsoft/fara-7b\",\n] as const;\nexport type AvailableCuaModel = (typeof AVAILABLE_CUA_MODELS)[number];\n\nexport interface AgentExecutionOptions<\n TOptions extends AgentExecuteOptions = AgentExecuteOptions,\n> {\n options: TOptions;\n logger: (message: LogLine) => void;\n retries?: number;\n}\n\nexport interface AgentHandlerOptions {\n modelName: string;\n clientOptions?: ClientOptions;\n userProvidedInstructions?: string;\n experimental?: boolean;\n}\n\nexport interface ActionExecutionResult {\n success: boolean;\n error?: string;\n data?: unknown;\n}\n\n/**\n * Represents a safety check that requires user confirmation before proceeding.\n * These are issued by CUA providers (OpenAI, Google) when the agent attempts\n * potentially risky actions.\n */\nexport interface SafetyCheck {\n /** Unique identifier for this safety check */\n id: string;\n /** Code identifying the type of safety concern */\n code: string;\n /** Human-readable description of the safety concern */\n message: string;\n}\n\n/**\n * Response from the user for a safety confirmation request.\n */\nexport interface SafetyConfirmationResponse {\n /** Whether the user acknowledged/approved the safety checks */\n acknowledged: boolean;\n}\n\n/**\n * Callback for handling safety confirmation requests.\n * Called when the CUA provider issues safety checks that require user confirmation.\n * The callback should return a promise that resolves when the user has made a decision.\n *\n * @param safetyChecks - Array of safety checks requiring confirmation\n * @returns Promise resolving to the user's response\n *\n * @example\n * ```typescript\n * const agent = stagehand.agent({\n * mode: \"cua\",\n * });\n * await agent.execute({\n * instruction: \"...\",\n * callbacks: {\n * onSafetyConfirmation: async (checks) => {\n * console.log(\"Safety checks:\", checks);\n * const userApproved = await showConfirmationDialog(checks);\n * return { acknowledged: userApproved };\n * },\n * },\n * });\n * ```\n */\nexport type SafetyConfirmationHandler = (\n safetyChecks: SafetyCheck[],\n) => Promise<SafetyConfirmationResponse>;\n\n// Anthropic types:\n\nexport interface ToolUseItem extends ResponseItem {\n type: \"tool_use\";\n id: string; // This is the correct property name from Anthropic's API\n name: string; // Name of the tool being used\n input: Record<string, unknown>;\n}\n\nexport interface AnthropicMessage {\n role: string;\n content: string | Array<AnthropicContentBlock>;\n}\n\nexport interface AnthropicContentBlock {\n type: string;\n [key: string]: unknown;\n}\n\nexport interface AnthropicTextBlock extends AnthropicContentBlock {\n type: \"text\";\n text: string;\n}\n\nexport interface AnthropicToolResult {\n type: \"tool_result\";\n tool_use_id: string;\n content: string | Array<AnthropicContentBlock>;\n}\n\n// OpenAI types:\n\nexport interface ResponseItem {\n type: string;\n id: string;\n [key: string]: unknown;\n}\n\nexport interface ComputerCallItem extends ResponseItem {\n type: \"computer_call\";\n call_id: string;\n action?: {\n type: string;\n [key: string]: unknown;\n };\n actions?: Array<{\n type: string;\n [key: string]: unknown;\n }>;\n pending_safety_checks?: Array<{\n id: string;\n code: string;\n message: string;\n }>;\n}\n\nexport interface FunctionCallItem extends ResponseItem {\n type: \"function_call\";\n call_id: string;\n name: string;\n arguments: string;\n}\n\nexport type ResponseInputItem =\n | { role: string; content: string }\n | {\n type: \"computer_call_output\";\n call_id: string;\n output:\n | {\n type: \"input_image\" | \"computer_screenshot\";\n image_url: string;\n detail?: \"original\" | \"high\" | \"low\";\n current_url?: string;\n error?: string;\n [key: string]: unknown;\n }\n | string;\n acknowledged_safety_checks?: Array<{\n id: string;\n code: string;\n message: string;\n }>;\n }\n | {\n type: \"function_call_output\";\n call_id: string;\n output: string;\n };\n\nexport interface AgentInstance {\n execute: (\n instructionOrOptions: string | AgentExecuteOptions,\n ) => Promise<AgentResult>;\n}\n\nexport type AgentProviderType = AgentType;\n\nexport type AgentModelConfig<TModelName extends string = string> = {\n modelName: TModelName;\n} & Record<string, unknown>;\n\n/**\n * Agent tool mode determines which set of tools are available to the agent.\n * - 'dom': Uses DOM-based tools (act, fillForm) - better for structured page interactions\n * - 'hybrid': Uses coordinate-based tools (click, type, dragAndDrop, etc.) - better for visual/screenshot-based interactions\n * - 'cua': Uses Computer Use Agent (CUA) providers like Anthropic Claude or Google Gemini for screenshot-based automation\n */\nexport type AgentToolMode = \"dom\" | \"hybrid\" | \"cua\";\n\nexport type AgentConfig = {\n /**\n * Custom system prompt to provide to the agent. Overrides the default system prompt.\n */\n systemPrompt?: string;\n /**\n * MCP integrations - Array of Client objects\n */\n integrations?: (Client | string)[];\n /**\n * Tools passed to the agent client\n */\n tools?: ToolSet;\n /**\n * @deprecated Use `mode: \"cua\"` instead. This option will be removed in a future version.\n * Enables Computer Use Agent (CUA) mode.\n */\n cua?: boolean;\n /**\n * The model to use for agent functionality\n */\n model?: string | AgentModelConfig<string>;\n /**\n * The model to use for tool execution (observe/act calls within agent tools).\n * If not specified, inherits from the main model configuration.\n * Format: \"provider/model\" (e.g., \"openai/gpt-4o-mini\", \"google/gemini-2.0-flash-exp\")\n */\n executionModel?: string | AgentModelConfig<string>;\n /**\n * Enable streaming mode for the agent.\n * When true, execute() returns AgentStreamResult with textStream for incremental output.\n * When false (default), execute() returns AgentResult after completion.\n */\n stream?: boolean;\n /**\n * Tool mode for the agent. Determines which set of tools are available.\n * - 'dom' (default): Uses DOM-based tools (act, fillForm) for structured interactions\n * - 'hybrid': Uses coordinate-based tools (click, type, dragAndDrop, clickAndHold, fillFormVision)\n * for visual/screenshot-based interactions\n * - 'cua': Uses Computer Use Agent (CUA) providers for screenshot-based automation\n */\n mode?: AgentToolMode;\n};\n\n/**\n * Agent instance returned when stream: true is set in AgentConfig.\n * execute() returns a streaming result that can be consumed incrementally.\n * Accepts AgentStreamExecuteOptions with streaming-specific callbacks.\n */\nexport interface StreamingAgentInstance {\n execute: (\n instructionOrOptions: string | AgentStreamExecuteOptions,\n ) => Promise<AgentStreamResult>;\n}\n\n/**\n * Agent instance returned when stream is false or not set in AgentConfig.\n * execute() returns a result after the agent completes.\n * Accepts AgentExecuteOptions with non-streaming callbacks only.\n */\nexport interface NonStreamingAgentInstance {\n execute: (\n instructionOrOptions: string | AgentExecuteOptions,\n ) => Promise<AgentResult>;\n}\n\n// =============================================================================\n// Vision Action Tool Result Types\n// =============================================================================\n\n/**\n * Content item type for toModelOutput return values.\n * Used in tool definitions to return text and/or media to the model.\n */\nexport type ModelOutputContentItem =\n | { type: \"text\"; text: string }\n | { type: \"media\"; mediaType: string; data: string };\n\nexport interface ClickToolResult {\n success: boolean;\n describe?: string;\n coordinates?: number[];\n error?: string;\n screenshotBase64?: string;\n}\n\nexport interface TypeToolResult {\n success: boolean;\n describe?: string;\n text?: string;\n error?: string;\n screenshotBase64?: string;\n}\n\nexport interface DragAndDropToolResult {\n success: boolean;\n describe?: string;\n error?: string;\n screenshotBase64?: string;\n}\n\nexport interface FillFormField {\n action: string;\n value: string;\n coordinates: { x: number; y: number };\n}\n\nexport interface FillFormVisionToolResult {\n success: boolean;\n playwrightArguments?: FillFormField[];\n error?: string;\n screenshotBase64?: string;\n}\n\nexport interface ScrollToolResult {\n success: boolean;\n message: string;\n scrolledPixels: number;\n error?: string;\n}\n\nexport interface ScrollVisionToolResult extends ScrollToolResult {\n screenshotBase64?: string;\n}\n\nexport interface WaitToolResult {\n success: boolean;\n waited: number;\n screenshotBase64?: string;\n error?: string;\n}\n"]}
1
+ {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../../../../lib/v3/types/public/agent.ts"],"names":[],"mappings":"AAmdA,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,gBAAgB;IAChB,qBAAqB;IACrB,gBAAgB;IAChB,sBAAsB;IACtB,qBAAqB;IACrB,oBAAoB;IACpB,6BAA6B;IAC7B,wCAAwC;IACxC,oCAAoC;IACpC,2BAA2B;IAC3B,2BAA2B;IAC3B,6BAA6B;IAC7B,4BAA4B;IAC5B,qCAAqC;IACrC,oCAAoC;IACpC,sCAAsC;IACtC,0BAA0B;IAC1B,gDAAgD;IAChD,+BAA+B;IAC/B,yBAAyB;IACzB,6BAA6B;IAC7B,mBAAmB;CACX,CAAC","sourcesContent":["import type { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport {\n ToolSet,\n ModelMessage,\n wrapLanguageModel,\n StreamTextResult,\n StepResult,\n PrepareStepFunction,\n GenerateTextOnStepFinishCallback,\n StreamTextOnStepFinishCallback,\n StreamTextOnErrorCallback,\n StreamTextOnChunkCallback,\n StreamTextOnFinishCallback,\n} from \"ai\";\nimport { LogLine } from \"./logs.js\";\nimport { ClientOptions } from \"./model.js\";\nimport { StagehandZodObject } from \"../../zodCompat.js\";\nimport type { AgentEvidenceCallback } from \"./agentEvidenceEvents.js\";\n\n// Re-export ModelMessage for consumers who want to use it for conversation continuation\nexport type { ModelMessage } from \"ai\";\n\n// Re-export Tool type for consumers who want to define custom tools\nexport type { Tool } from \"ai\";\nimport { Page as PlaywrightPage } from \"playwright-core\";\nimport { Page as PuppeteerPage } from \"puppeteer-core\";\nimport { Page as PatchrightPage } from \"patchright-core\";\nimport { Page } from \"../../understudy/page.js\";\n\n/**\n * Result of a screenshot provider: the base64-encoded image bytes plus an\n * explicit media type. Declaring the media type at the capture boundary lets\n * every CUA client pass it through instead of hardcoding or inferring it.\n */\nexport interface ScreenshotProviderResult {\n base64: string;\n mediaType: \"image/png\" | \"image/jpeg\";\n}\n\n// =============================================================================\n// Variable Types\n// =============================================================================\n\n/**\n * A variable value can be a simple primitive or a rich object with an optional description.\n * This unified type is shared across `act`, `agent.execute`, and other methods.\n *\n * @example Simple (backward-compatible):\n * ```typescript\n * variables: { username: \"john@example.com\" }\n * ```\n *\n * @example Rich with description (useful for agents):\n * ```typescript\n * variables: {\n * username: { value: \"john@example.com\", description: \"The login email\" }\n * }\n * ```\n */\nexport type VariableValue =\n | string\n | number\n | boolean\n | { value: string | number | boolean; description?: string };\n\n/**\n * A collection of named variables for use in act, agent, and other methods.\n */\nexport type Variables = Record<string, VariableValue>;\n\nexport interface AgentContext {\n options: AgentExecuteOptionsBase;\n maxSteps: number;\n systemPrompt: string;\n allTools: ToolSet;\n messages: ModelMessage[];\n wrappedModel: ReturnType<typeof wrapLanguageModel>;\n initialPageUrl: string;\n}\n\nexport interface AgentState {\n collectedReasoning: string[];\n actions: AgentAction[];\n finalMessage: string;\n completed: boolean;\n currentPageUrl: string;\n}\n\nexport interface AgentAction {\n type: string;\n reasoning?: string;\n taskCompleted?: boolean;\n action?: string;\n // Tool-specific fields\n timeMs?: number; // wait tool\n pageText?: string; // ariaTree tool\n pageUrl?: string; // ariaTree tool\n instruction?: string; // various tools\n [key: string]: unknown;\n}\n\nexport interface AgentResult {\n success: boolean;\n message: string;\n actions: AgentAction[];\n completed: boolean;\n metadata?: Record<string, unknown>;\n usage?: {\n input_tokens: number;\n output_tokens: number;\n reasoning_tokens?: number;\n cached_input_tokens?: number;\n inference_time_ms: number;\n };\n /**\n * The conversation messages from this execution.\n * Pass these to a subsequent execute() call via the `messages` option to continue the conversation.\n * @experimental\n */\n messages?: ModelMessage[];\n /**\n * Custom output data extracted based on the `output` schema provided in execute options.\n * Only populated if an `output` schema was provided.\n * @experimental\n */\n output?: Record<string, unknown>;\n}\n\nexport type AgentStreamResult = StreamTextResult<ToolSet, never> & {\n result: Promise<AgentResult>;\n};\n\n/**\n * Base callbacks shared between execute (non-streaming) and streaming modes.\n */\nexport interface AgentCallbacks {\n /**\n * Optional function called before each step to modify settings.\n * You can change the model, tool choices, active tools, system prompt,\n * and input messages for each step.\n */\n prepareStep?: PrepareStepFunction<ToolSet>;\n /**\n * Callback called when each step (LLM call) is finished.\n * This is called for intermediate steps as well as the final step.\n */\n onStepFinish?:\n | GenerateTextOnStepFinishCallback<ToolSet>\n | StreamTextOnStepFinishCallback<ToolSet>;\n /**\n * Callback called when Stagehand captures agent-run evidence such as\n * screenshots, completed tool/action steps, or post-action observations.\n */\n onEvidence?: AgentEvidenceCallback;\n}\n\n/**\n * Error message type for streaming-only callbacks used in non-streaming mode.\n * This provides a clear error message when users try to use streaming callbacks without stream: true.\n */\ntype StreamingCallbackNotAvailable =\n \"This callback requires 'stream: true' in AgentConfig. Set stream: true to use streaming callbacks like onChunk, onFinish, onError, and onAbort.\";\n\n/**\n * Error message for safety confirmation callback misuse.\n * Safety confirmations are only available for non-streaming CUA agent executions.\n */\ntype SafetyConfirmationCallbackNotAvailable =\n \"Safety confirmation callbacks are only available via non-streaming AgentExecuteOptions.callbacks when using mode: 'cua'.\";\n\n/**\n * Callbacks specific to the non-streaming execute method.\n */\nexport interface AgentExecuteCallbacks extends AgentCallbacks {\n /**\n * Callback called when each step (LLM call) is finished.\n */\n onStepFinish?: GenerateTextOnStepFinishCallback<ToolSet>;\n /**\n * Callback for handling safety confirmation requests from CUA providers.\n * Only available when running an agent configured with mode: \"cua\".\n */\n onSafetyConfirmation?: SafetyConfirmationHandler;\n\n /**\n * NOT AVAILABLE in non-streaming mode.\n * This callback requires `stream: true` in AgentConfig.\n *\n * @example\n * ```typescript\n * // Enable streaming to use onChunk:\n * const agent = stagehand.agent({ stream: true });\n * await agent.execute({\n * instruction: \"...\",\n * callbacks: { onChunk: async (chunk) => console.log(chunk) }\n * });\n * ```\n */\n onChunk?: StreamingCallbackNotAvailable;\n\n /**\n * NOT AVAILABLE in non-streaming mode.\n * This callback requires `stream: true` in AgentConfig.\n *\n * @example\n * ```typescript\n * // Enable streaming to use onFinish:\n * const agent = stagehand.agent({ stream: true });\n * await agent.execute({\n * instruction: \"...\",\n * callbacks: { onFinish: (event) => console.log(\"Done!\", event) }\n * });\n * ```\n */\n onFinish?: StreamingCallbackNotAvailable;\n\n /**\n * NOT AVAILABLE in non-streaming mode.\n * This callback requires `stream: true` in AgentConfig.\n *\n * @example\n * ```typescript\n * // Enable streaming to use onError:\n * const agent = stagehand.agent({ stream: true });\n * await agent.execute({\n * instruction: \"...\",\n * callbacks: { onError: ({ error }) => console.error(error) }\n * });\n * ```\n */\n onError?: StreamingCallbackNotAvailable;\n\n /**\n * NOT AVAILABLE in non-streaming mode.\n * This callback requires `stream: true` in AgentConfig.\n *\n * @example\n * ```typescript\n * // Enable streaming to use onAbort:\n * const agent = stagehand.agent({ stream: true });\n * await agent.execute({\n * instruction: \"...\",\n * callbacks: { onAbort: (event) => console.log(\"Aborted\", event.steps) }\n * });\n * ```\n */\n onAbort?: StreamingCallbackNotAvailable;\n}\n\n/**\n * Callbacks specific to the streaming mode.\n */\nexport interface AgentStreamCallbacks extends AgentCallbacks {\n /**\n * Callback called when each step (LLM call) is finished during streaming.\n */\n onStepFinish?: StreamTextOnStepFinishCallback<ToolSet>;\n /**\n * Callback called when an error occurs during streaming.\n * Use this to log errors or handle error states.\n */\n onError?: StreamTextOnErrorCallback;\n /**\n * Callback called for each chunk of the stream.\n * Stream processing will pause until the callback promise resolves.\n */\n onChunk?: StreamTextOnChunkCallback<ToolSet>;\n /**\n * Callback called when the stream finishes.\n */\n onFinish?: StreamTextOnFinishCallback<ToolSet>;\n /**\n * Callback called when the stream is aborted.\n */\n onAbort?: (event: {\n steps: Array<StepResult<ToolSet>>;\n }) => PromiseLike<void> | void;\n /**\n * NOT AVAILABLE in streaming mode.\n * Safety confirmations currently require non-streaming execute() on CUA agents.\n */\n onSafetyConfirmation?: SafetyConfirmationCallbackNotAvailable;\n}\n\n/**\n * Base options for agent execution (without callbacks).\n */\nexport interface AgentExecuteOptionsBase {\n instruction: string;\n maxSteps?: number;\n page?: PlaywrightPage | PuppeteerPage | PatchrightPage | Page;\n highlightCursor?: boolean;\n /**\n * Previous conversation messages to continue from.\n * Pass the `messages` from a previous AgentResult to continue that conversation.\n * @experimental\n */\n messages?: ModelMessage[];\n /**\n * An AbortSignal that can be used to cancel the agent execution.\n * When aborted, the agent will stop and return a partial result.\n * @experimental\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 30000); // 30 second timeout\n *\n * const result = await agent.execute({\n * instruction: \"...\",\n * signal: controller.signal\n * });\n * ```\n */\n signal?: AbortSignal;\n /**\n * Tools to exclude from this execution.\n * Pass an array of tool names to prevent the agent from using those tools.\n *\n * **Note:** Not supported in CUA mode (`mode: \"cua\"`).\n *\n * **Available tools by mode:**\n *\n * **DOM mode (default):**\n * - `act` - Perform semantic actions (click, type, etc.)\n * - `fillForm` - Fill form fields using DOM selectors\n * - `ariaTree` - Get accessibility tree of the page\n * - `extract` - Extract structured data from page\n * - `goto` - Navigate to a URL\n * - `scroll` - Scroll using semantic directions (up/down/left/right)\n * - `keys` - Press keyboard keys\n * - `navback` - Navigate back in history\n * - `screenshot` - Take a screenshot\n * - `think` - Agent reasoning/planning step\n * - `wait` - Wait for time or condition\n * - `done` - Mark task as complete\n * - `search` - Web search (requires useSearch: true and BROWSERBASE_API_KEY)\n *\n * **Hybrid mode:**\n * - `click` - Click at specific coordinates\n * - `type` - Type text at coordinates\n * - `dragAndDrop` - Drag from one point to another\n * - `clickAndHold` - Click and hold at coordinates\n * - `fillFormVision` - Fill forms using vision/coordinates\n * - `act` - Perform semantic actions\n * - `ariaTree` - Get accessibility tree\n * - `extract` - Extract data from page\n * - `goto` - Navigate to URL\n * - `scroll` - Scroll using coordinates\n * - `keys` - Press keyboard keys\n * - `navback` - Navigate back\n * - `screenshot` - Take screenshot\n * - `think` - Agent reasoning step\n * - `wait` - Wait for time/condition\n * - `done` - Mark task complete\n * - `search` - Web search (requires useSearch: true and BROWSERBASE_API_KEY)\n *\n * @experimental\n * @example\n * ```typescript\n * // Exclude screenshot and extract tools\n * const result = await agent.execute({\n * instruction: \"Click the submit button\",\n * excludeTools: [\"screenshot\", \"extract\"]\n * });\n * ```\n */\n excludeTools?: string[];\n /**\n * A Zod schema defining custom output data to return when the task completes.\n * The agent will populate this data in the final done tool call.\n *\n * @experimental\n * @example\n * ```typescript\n * const result = await agent.execute({\n * instruction: \"Find the cheapest flight from NYC to LA\",\n * output: z.object({\n * price: z.string().describe(\"The price of the flight\"),\n * airline: z.string().describe(\"The airline name\"),\n * departureTime: z.string().describe(\"Departure time\"),\n * }),\n * });\n *\n * console.log(result.output); // { price: \"$199\", airline: \"Delta\", departureTime: \"8:00 AM\" }\n * ```\n */\n output?: StagehandZodObject;\n /**\n * Variables that the agent can use when filling forms or typing text.\n * The agent will see variable names and descriptions in the system prompt,\n * and can use them via `%variableName%` syntax in act/type/fillForm tool calls.\n *\n * Accepts both simple values and rich objects with descriptions (same type as `act`).\n *\n * **Note:** Not supported in CUA mode (`mode: \"cua\"`).\n *\n * @example\n * ```typescript\n * // Simple values\n * variables: { username: \"john@example.com\", password: \"secret123\" }\n *\n * // Rich values with descriptions (helps the agent understand context)\n * variables: {\n * username: { value: \"john@example.com\", description: \"The login email\" },\n * password: { value: \"secret123\", description: \"The login password\" },\n * }\n * ```\n */\n variables?: Variables;\n /**\n * Timeout in milliseconds for each agent tool call.\n * If a tool call exceeds this duration, it will be aborted and\n * reported back to the LLM as a timeout error so it can retry or adjust.\n * For tools that call v3 methods (act, extract, fillForm, ariaTree), the\n * timeout is also forwarded to the underlying v3 call for true cancellation.\n * @default 45000 (45 seconds)\n */\n toolTimeout?: number;\n /**\n * Enable the web search tool powered by Browserbase Search API.\n * Requires a valid Browserbase API key (BROWSERBASE_API_KEY).\n * When set to true, the agent gains access to a `search` tool for web searches.\n *\n * @example\n * ```typescript\n * const result = await agent.execute({\n * instruction: \"Find the latest news about AI\",\n * useSearch: true,\n * });\n * ```\n */\n useSearch?: boolean;\n}\n\n/**\n * Options for non-streaming agent execution.\n * Only accepts AgentExecuteCallbacks (no streaming-specific callbacks like onChunk, onFinish).\n */\nexport interface AgentExecuteOptions extends AgentExecuteOptionsBase {\n /**\n * Callbacks for non-streaming agent execution.\n * For streaming callbacks (onChunk, onFinish, onError, onAbort), use stream: true in AgentConfig.\n */\n callbacks?: AgentExecuteCallbacks;\n}\n\n/**\n * Options for streaming agent execution.\n * Accepts AgentStreamCallbacks including onChunk, onFinish, onError, and onAbort.\n */\nexport interface AgentStreamExecuteOptions extends AgentExecuteOptionsBase {\n /**\n * Callbacks for streaming agent execution.\n * Includes streaming-specific callbacks: onChunk, onFinish, onError, onAbort.\n */\n callbacks?: AgentStreamCallbacks;\n}\nexport type AgentType =\n | \"openai\"\n | \"anthropic\"\n | \"google\"\n | \"microsoft\"\n | \"bedrock\"\n | \"vertex\"\n | \"azure\";\n\nexport const AVAILABLE_CUA_MODELS = [\n \"openai/gpt-5.4\",\n \"openai/gpt-5.4-mini\",\n \"openai/gpt-5.5\",\n \"openai/gpt-5.6-terra\",\n \"openai/gpt-5.6-luna\",\n \"openai/gpt-5.6-sol\",\n \"openai/computer-use-preview\",\n \"openai/computer-use-preview-2025-03-11\",\n \"anthropic/claude-opus-4-5-20251101\",\n \"anthropic/claude-opus-4-6\",\n \"anthropic/claude-opus-4-8\",\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 \"anthropic/claude-fable-5\",\n \"google/gemini-2.5-computer-use-preview-10-2025\",\n \"google/gemini-3-flash-preview\",\n \"google/gemini-3.5-flash\",\n \"google/gemini-3-pro-preview\",\n \"microsoft/fara-7b\",\n] as const;\nexport type AvailableCuaModel = (typeof AVAILABLE_CUA_MODELS)[number];\n\nexport interface AgentExecutionOptions<\n TOptions extends AgentExecuteOptions = AgentExecuteOptions,\n> {\n options: TOptions;\n logger: (message: LogLine) => void;\n retries?: number;\n}\n\nexport interface AgentHandlerOptions {\n modelName: string;\n clientOptions?: ClientOptions;\n userProvidedInstructions?: string;\n experimental?: boolean;\n}\n\nexport interface ActionExecutionResult {\n success: boolean;\n error?: string;\n data?: unknown;\n}\n\n/**\n * Represents a safety check that requires user confirmation before proceeding.\n * These are issued by CUA providers (OpenAI, Google) when the agent attempts\n * potentially risky actions.\n */\nexport interface SafetyCheck {\n /** Unique identifier for this safety check */\n id: string;\n /** Code identifying the type of safety concern */\n code: string;\n /** Human-readable description of the safety concern */\n message: string;\n}\n\n/**\n * Response from the user for a safety confirmation request.\n */\nexport interface SafetyConfirmationResponse {\n /** Whether the user acknowledged/approved the safety checks */\n acknowledged: boolean;\n}\n\n/**\n * Callback for handling safety confirmation requests.\n * Called when the CUA provider issues safety checks that require user confirmation.\n * The callback should return a promise that resolves when the user has made a decision.\n *\n * @param safetyChecks - Array of safety checks requiring confirmation\n * @returns Promise resolving to the user's response\n *\n * @example\n * ```typescript\n * const agent = stagehand.agent({\n * mode: \"cua\",\n * });\n * await agent.execute({\n * instruction: \"...\",\n * callbacks: {\n * onSafetyConfirmation: async (checks) => {\n * console.log(\"Safety checks:\", checks);\n * const userApproved = await showConfirmationDialog(checks);\n * return { acknowledged: userApproved };\n * },\n * },\n * });\n * ```\n */\nexport type SafetyConfirmationHandler = (\n safetyChecks: SafetyCheck[],\n) => Promise<SafetyConfirmationResponse>;\n\n// Anthropic types:\n\nexport interface ToolUseItem extends ResponseItem {\n type: \"tool_use\";\n id: string; // This is the correct property name from Anthropic's API\n name: string; // Name of the tool being used\n input: Record<string, unknown>;\n}\n\nexport interface AnthropicMessage {\n role: string;\n content: string | Array<AnthropicContentBlock>;\n}\n\nexport interface AnthropicContentBlock {\n type: string;\n [key: string]: unknown;\n}\n\nexport interface AnthropicTextBlock extends AnthropicContentBlock {\n type: \"text\";\n text: string;\n}\n\nexport interface AnthropicToolResult {\n type: \"tool_result\";\n tool_use_id: string;\n content: string | Array<AnthropicContentBlock>;\n}\n\n// OpenAI types:\n\nexport interface ResponseItem {\n type: string;\n id: string;\n [key: string]: unknown;\n}\n\nexport interface ComputerCallItem extends ResponseItem {\n type: \"computer_call\";\n call_id: string;\n action?: {\n type: string;\n [key: string]: unknown;\n };\n actions?: Array<{\n type: string;\n [key: string]: unknown;\n }>;\n pending_safety_checks?: Array<{\n id: string;\n code: string;\n message: string;\n }>;\n}\n\nexport interface FunctionCallItem extends ResponseItem {\n type: \"function_call\";\n call_id: string;\n name: string;\n arguments: string;\n}\n\nexport type ResponseInputItem =\n | { role: string; content: string }\n | {\n type: \"computer_call_output\";\n call_id: string;\n output:\n | {\n type: \"input_image\" | \"computer_screenshot\";\n image_url: string;\n detail?: \"original\" | \"high\" | \"low\";\n current_url?: string;\n error?: string;\n [key: string]: unknown;\n }\n | string;\n acknowledged_safety_checks?: Array<{\n id: string;\n code: string;\n message: string;\n }>;\n }\n | {\n type: \"function_call_output\";\n call_id: string;\n output: string;\n };\n\nexport interface AgentInstance {\n execute: (\n instructionOrOptions: string | AgentExecuteOptions,\n ) => Promise<AgentResult>;\n}\n\nexport type AgentProviderType = AgentType;\n\nexport type AgentModelConfig<TModelName extends string = string> = {\n modelName: TModelName;\n} & Record<string, unknown>;\n\n/**\n * Agent tool mode determines which set of tools are available to the agent.\n * - 'dom': Uses DOM-based tools (act, fillForm) - better for structured page interactions\n * - 'hybrid': Uses coordinate-based tools (click, type, dragAndDrop, etc.) - better for visual/screenshot-based interactions\n * - 'cua': Uses Computer Use Agent (CUA) providers like Anthropic Claude or Google Gemini for screenshot-based automation\n */\nexport type AgentToolMode = \"dom\" | \"hybrid\" | \"cua\";\n\nexport type AgentConfig = {\n /**\n * Custom system prompt to provide to the agent. Overrides the default system prompt.\n */\n systemPrompt?: string;\n /**\n * MCP integrations - Array of Client objects\n */\n integrations?: (Client | string)[];\n /**\n * Tools passed to the agent client\n */\n tools?: ToolSet;\n /**\n * @deprecated Use `mode: \"cua\"` instead. This option will be removed in a future version.\n * Enables Computer Use Agent (CUA) mode.\n */\n cua?: boolean;\n /**\n * The model to use for agent functionality\n */\n model?: string | AgentModelConfig<string>;\n /**\n * The model to use for tool execution (observe/act calls within agent tools).\n * If not specified, inherits from the main model configuration.\n * Format: \"provider/model\" (e.g., \"openai/gpt-4o-mini\", \"google/gemini-2.0-flash-exp\")\n */\n executionModel?: string | AgentModelConfig<string>;\n /**\n * Enable streaming mode for the agent.\n * When true, execute() returns AgentStreamResult with textStream for incremental output.\n * When false (default), execute() returns AgentResult after completion.\n */\n stream?: boolean;\n /**\n * Tool mode for the agent. Determines which set of tools are available.\n * - 'dom' (default): Uses DOM-based tools (act, fillForm) for structured interactions\n * - 'hybrid': Uses coordinate-based tools (click, type, dragAndDrop, clickAndHold, fillFormVision)\n * for visual/screenshot-based interactions\n * - 'cua': Uses Computer Use Agent (CUA) providers for screenshot-based automation\n */\n mode?: AgentToolMode;\n};\n\n/**\n * Agent instance returned when stream: true is set in AgentConfig.\n * execute() returns a streaming result that can be consumed incrementally.\n * Accepts AgentStreamExecuteOptions with streaming-specific callbacks.\n */\nexport interface StreamingAgentInstance {\n execute: (\n instructionOrOptions: string | AgentStreamExecuteOptions,\n ) => Promise<AgentStreamResult>;\n}\n\n/**\n * Agent instance returned when stream is false or not set in AgentConfig.\n * execute() returns a result after the agent completes.\n * Accepts AgentExecuteOptions with non-streaming callbacks only.\n */\nexport interface NonStreamingAgentInstance {\n execute: (\n instructionOrOptions: string | AgentExecuteOptions,\n ) => Promise<AgentResult>;\n}\n\n// =============================================================================\n// Vision Action Tool Result Types\n// =============================================================================\n\n/**\n * Content item type for toModelOutput return values.\n * Used in tool definitions to return text and/or media to the model.\n */\nexport type ModelOutputContentItem =\n | { type: \"text\"; text: string }\n | { type: \"media\"; mediaType: string; data: string };\n\nexport interface ClickToolResult {\n success: boolean;\n describe?: string;\n coordinates?: number[];\n error?: string;\n screenshotBase64?: string;\n}\n\nexport interface TypeToolResult {\n success: boolean;\n describe?: string;\n text?: string;\n error?: string;\n screenshotBase64?: string;\n}\n\nexport interface DragAndDropToolResult {\n success: boolean;\n describe?: string;\n error?: string;\n screenshotBase64?: string;\n}\n\nexport interface FillFormField {\n action: string;\n value: string;\n coordinates: { x: number; y: number };\n}\n\nexport interface FillFormVisionToolResult {\n success: boolean;\n playwrightArguments?: FillFormField[];\n error?: string;\n screenshotBase64?: string;\n}\n\nexport interface ScrollToolResult {\n success: boolean;\n message: string;\n scrolledPixels: number;\n error?: string;\n}\n\nexport interface ScrollVisionToolResult extends ScrollToolResult {\n screenshotBase64?: string;\n}\n\nexport interface WaitToolResult {\n success: boolean;\n waited: number;\n screenshotBase64?: string;\n error?: string;\n}\n"]}
@@ -80,6 +80,7 @@ export type ModelProvider = "openai" | "anthropic" | "cerebras" | "groq" | "goog
80
80
  * - "max": Claude always thinks with no constraints
81
81
  */
82
82
  export type ThinkingEffort = "none" | "low" | "medium" | "high" | "xhigh" | "max";
83
+ export type OpenAIEndpointFormat = "responses" | "chat";
83
84
  export type ClientOptions = (OpenAIClientOptions | AnthropicClientOptions) & {
84
85
  apiKey?: string;
85
86
  provider?: AgentProviderType;
@@ -113,6 +114,12 @@ export type ClientOptions = (OpenAIClientOptions | AnthropicClientOptions) & {
113
114
  headers?: Record<string, string>;
114
115
  /** Reasoning effort for reasoning-capable models (e.g., "none", "low", "medium", "high") */
115
116
  reasoningEffort?: string;
117
+ /**
118
+ * Wire format used against the OpenAI-compatible endpoint at `baseURL`.
119
+ * Defaults to the Responses API. Use `chat` for providers that expose only
120
+ * an OpenAI-compatible Chat Completions endpoint (e.g. Databricks).
121
+ */
122
+ openaiEndpointFormat?: OpenAIEndpointFormat;
116
123
  };
117
124
  export type ModelConfiguration = AvailableModel | (ClientOptions & {
118
125
  modelName: AvailableModel;
@@ -1 +1 @@
1
- {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../../../lib/v3/types/public/model.ts"],"names":[],"mappings":"","sourcesContent":["import type { ClientOptions as AnthropicClientOptionsBase } from \"@anthropic-ai/sdk\";\nimport type {\n LanguageModelV2,\n LanguageModelV2Middleware,\n} from \"@ai-sdk/provider\";\nimport type { ClientOptions as OpenAIClientOptionsBase } from \"openai\";\nimport type { AgentProviderType } from \"./agent.js\";\n\nexport type OpenAIClientOptions = Pick<\n OpenAIClientOptionsBase,\n \"baseURL\" | \"apiKey\"\n>;\n\nexport type AnthropicClientOptions = Pick<\n AnthropicClientOptionsBase,\n \"baseURL\" | \"apiKey\"\n>;\n\nexport interface GoogleServiceAccountCredentials {\n type?: \"service_account\";\n project_id?: string;\n private_key_id?: string;\n private_key: string;\n client_email: string;\n client_id?: string;\n auth_uri?: string;\n token_uri?: string;\n auth_provider_x509_cert_url?: string;\n client_x509_cert_url?: string;\n universe_domain?: string;\n}\n\nexport interface GoogleServiceAccountAuth {\n type: \"googleServiceAccount\";\n credentials: GoogleServiceAccountCredentials;\n scopes?: string | string[];\n projectId?: string;\n universeDomain?: string;\n}\n\nexport interface AzureEntraIdAuth {\n type: \"azureEntraId\";\n token: string;\n}\n\nexport type ModelAuth = GoogleServiceAccountAuth | AzureEntraIdAuth;\n\nexport interface VertexProviderOptions {\n project: string;\n location: string;\n baseURL?: string;\n headers?: Record<string, string>;\n}\n\nexport interface AzureProviderOptions {\n resourceName?: string;\n baseURL?: string;\n apiVersion?: string;\n useDeploymentBasedUrls?: boolean;\n headers?: Record<string, string>;\n}\n\nexport type ModelProviderOptions =\n | { vertex: VertexProviderOptions; azure?: never }\n | { azure: AzureProviderOptions; vertex?: never };\n\nexport type AnthropicJsonSchemaObject = {\n definitions?: {\n MySchema?: {\n properties?: Record<string, unknown>;\n required?: string[];\n };\n };\n properties?: Record<string, unknown>;\n required?: string[];\n} & Record<string, unknown>;\n\nexport interface LLMTool {\n type: \"function\";\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n}\n\nexport type AISDKProvider = (modelName: string) => LanguageModelV2;\n// Represents a function that takes options (like apiKey) and returns an AISDKProvider\nexport type AISDKCustomProvider = (options: ClientOptions) => AISDKProvider;\n\nexport type AvailableModel =\n | \"gpt-4.1\"\n | \"gpt-4.1-mini\"\n | \"gpt-4.1-nano\"\n | \"o4-mini\"\n | \"o3\"\n | \"o3-mini\"\n | \"o1\"\n | \"o1-mini\"\n | \"gpt-4o\"\n | \"gpt-4o-mini\"\n | \"gpt-4o-2024-08-06\"\n | \"gpt-4.5-preview\"\n | \"o1-preview\"\n | \"cerebras-llama-3.3-70b\"\n | \"cerebras-llama-3.1-8b\"\n | \"groq-llama-3.3-70b-versatile\"\n | \"groq-llama-3.3-70b-specdec\"\n | \"gemini-1.5-flash\"\n | \"gemini-1.5-pro\"\n | \"gemini-1.5-flash-8b\"\n | \"gemini-2.0-flash-lite\"\n | \"gemini-2.0-flash\"\n | \"gemini-2.5-flash-preview-04-17\"\n | \"gemini-2.5-pro-preview-03-25\"\n | string;\n\nexport type ModelProvider =\n | \"openai\"\n | \"anthropic\"\n | \"cerebras\"\n | \"groq\"\n | \"google\"\n | \"aisdk\";\n\n/**\n * Effort levels for Claude adaptive thinking.\n * Used with Claude 4.6+ models (claude-opus-4-6, claude-sonnet-4-6).\n * - \"none\": Disable adaptive thinking entirely\n * - \"low\": Claude minimizes thinking, skips for simple tasks\n * - \"medium\": Claude uses moderate thinking, may skip for simple queries (default)\n * - \"high\": Claude always thinks with deep reasoning\n * - \"xhigh\": Deeper reasoning than \"high\" (Opus 4.7/4.8 and Fable 5 only)\n * - \"max\": Claude always thinks with no constraints\n */\nexport type ThinkingEffort =\n | \"none\"\n | \"low\"\n | \"medium\"\n | \"high\"\n | \"xhigh\"\n | \"max\";\n\nexport type ClientOptions = (OpenAIClientOptions | AnthropicClientOptions) & {\n apiKey?: string;\n provider?: AgentProviderType;\n auth?: ModelAuth;\n providerOptions?: ModelProviderOptions;\n baseURL?: string;\n /** OpenAI organization ID */\n organization?: string;\n /** Delay between agent actions in ms */\n waitBetweenActions?: number;\n /**\n * @deprecated For Claude 4.6+ models, use `thinkingEffort` instead.\n * Anthropic thinking budget for extended thinking (used with older Claude models like 4.5).\n * Sets `thinking.type: \"enabled\"` with the specified `budget_tokens`.\n */\n thinkingBudget?: number;\n /**\n * Effort level for Claude adaptive thinking (Claude 4.6+ models only).\n * Uses `thinking.type: \"adaptive\"` with `output_config.effort`.\n * This is the recommended approach for Claude Opus 4.6 and Sonnet 4.6.\n * @see https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking\n */\n thinkingEffort?: ThinkingEffort;\n /** Environment type for CUA agents (browser, mac, windows, ubuntu) */\n environment?: string;\n /** Max images for Microsoft FARA agent */\n maxImages?: number;\n /** Temperature for model inference */\n temperature?: number;\n /** Custom headers sent with every request to the provider */\n headers?: Record<string, string>;\n /** Reasoning effort for reasoning-capable models (e.g., \"none\", \"low\", \"medium\", \"high\") */\n reasoningEffort?: string;\n};\n\nexport type ModelConfiguration =\n | AvailableModel\n | (ClientOptions & {\n modelName: AvailableModel;\n /**\n * Optional AI SDK middleware applied to every LanguageModelV2 created for this model.\n * Use this to intercept LLM calls for usage tracking, logging, request transforms, etc.\n *\n * Only effective when running locally (direct mode). Cannot be serialized over HTTP,\n */\n middleware?: LanguageModelV2Middleware;\n });\n"]}
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../../../lib/v3/types/public/model.ts"],"names":[],"mappings":"","sourcesContent":["import type { ClientOptions as AnthropicClientOptionsBase } from \"@anthropic-ai/sdk\";\nimport type {\n LanguageModelV2,\n LanguageModelV2Middleware,\n} from \"@ai-sdk/provider\";\nimport type { ClientOptions as OpenAIClientOptionsBase } from \"openai\";\nimport type { AgentProviderType } from \"./agent.js\";\n\nexport type OpenAIClientOptions = Pick<\n OpenAIClientOptionsBase,\n \"baseURL\" | \"apiKey\"\n>;\n\nexport type AnthropicClientOptions = Pick<\n AnthropicClientOptionsBase,\n \"baseURL\" | \"apiKey\"\n>;\n\nexport interface GoogleServiceAccountCredentials {\n type?: \"service_account\";\n project_id?: string;\n private_key_id?: string;\n private_key: string;\n client_email: string;\n client_id?: string;\n auth_uri?: string;\n token_uri?: string;\n auth_provider_x509_cert_url?: string;\n client_x509_cert_url?: string;\n universe_domain?: string;\n}\n\nexport interface GoogleServiceAccountAuth {\n type: \"googleServiceAccount\";\n credentials: GoogleServiceAccountCredentials;\n scopes?: string | string[];\n projectId?: string;\n universeDomain?: string;\n}\n\nexport interface AzureEntraIdAuth {\n type: \"azureEntraId\";\n token: string;\n}\n\nexport type ModelAuth = GoogleServiceAccountAuth | AzureEntraIdAuth;\n\nexport interface VertexProviderOptions {\n project: string;\n location: string;\n baseURL?: string;\n headers?: Record<string, string>;\n}\n\nexport interface AzureProviderOptions {\n resourceName?: string;\n baseURL?: string;\n apiVersion?: string;\n useDeploymentBasedUrls?: boolean;\n headers?: Record<string, string>;\n}\n\nexport type ModelProviderOptions =\n | { vertex: VertexProviderOptions; azure?: never }\n | { azure: AzureProviderOptions; vertex?: never };\n\nexport type AnthropicJsonSchemaObject = {\n definitions?: {\n MySchema?: {\n properties?: Record<string, unknown>;\n required?: string[];\n };\n };\n properties?: Record<string, unknown>;\n required?: string[];\n} & Record<string, unknown>;\n\nexport interface LLMTool {\n type: \"function\";\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n}\n\nexport type AISDKProvider = (modelName: string) => LanguageModelV2;\n// Represents a function that takes options (like apiKey) and returns an AISDKProvider\nexport type AISDKCustomProvider = (options: ClientOptions) => AISDKProvider;\n\nexport type AvailableModel =\n | \"gpt-4.1\"\n | \"gpt-4.1-mini\"\n | \"gpt-4.1-nano\"\n | \"o4-mini\"\n | \"o3\"\n | \"o3-mini\"\n | \"o1\"\n | \"o1-mini\"\n | \"gpt-4o\"\n | \"gpt-4o-mini\"\n | \"gpt-4o-2024-08-06\"\n | \"gpt-4.5-preview\"\n | \"o1-preview\"\n | \"cerebras-llama-3.3-70b\"\n | \"cerebras-llama-3.1-8b\"\n | \"groq-llama-3.3-70b-versatile\"\n | \"groq-llama-3.3-70b-specdec\"\n | \"gemini-1.5-flash\"\n | \"gemini-1.5-pro\"\n | \"gemini-1.5-flash-8b\"\n | \"gemini-2.0-flash-lite\"\n | \"gemini-2.0-flash\"\n | \"gemini-2.5-flash-preview-04-17\"\n | \"gemini-2.5-pro-preview-03-25\"\n | string;\n\nexport type ModelProvider =\n | \"openai\"\n | \"anthropic\"\n | \"cerebras\"\n | \"groq\"\n | \"google\"\n | \"aisdk\";\n\n/**\n * Effort levels for Claude adaptive thinking.\n * Used with Claude 4.6+ models (claude-opus-4-6, claude-sonnet-4-6).\n * - \"none\": Disable adaptive thinking entirely\n * - \"low\": Claude minimizes thinking, skips for simple tasks\n * - \"medium\": Claude uses moderate thinking, may skip for simple queries (default)\n * - \"high\": Claude always thinks with deep reasoning\n * - \"xhigh\": Deeper reasoning than \"high\" (Opus 4.7/4.8 and Fable 5 only)\n * - \"max\": Claude always thinks with no constraints\n */\nexport type ThinkingEffort =\n | \"none\"\n | \"low\"\n | \"medium\"\n | \"high\"\n | \"xhigh\"\n | \"max\";\n\nexport type OpenAIEndpointFormat = \"responses\" | \"chat\";\n\nexport type ClientOptions = (OpenAIClientOptions | AnthropicClientOptions) & {\n apiKey?: string;\n provider?: AgentProviderType;\n auth?: ModelAuth;\n providerOptions?: ModelProviderOptions;\n baseURL?: string;\n /** OpenAI organization ID */\n organization?: string;\n /** Delay between agent actions in ms */\n waitBetweenActions?: number;\n /**\n * @deprecated For Claude 4.6+ models, use `thinkingEffort` instead.\n * Anthropic thinking budget for extended thinking (used with older Claude models like 4.5).\n * Sets `thinking.type: \"enabled\"` with the specified `budget_tokens`.\n */\n thinkingBudget?: number;\n /**\n * Effort level for Claude adaptive thinking (Claude 4.6+ models only).\n * Uses `thinking.type: \"adaptive\"` with `output_config.effort`.\n * This is the recommended approach for Claude Opus 4.6 and Sonnet 4.6.\n * @see https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking\n */\n thinkingEffort?: ThinkingEffort;\n /** Environment type for CUA agents (browser, mac, windows, ubuntu) */\n environment?: string;\n /** Max images for Microsoft FARA agent */\n maxImages?: number;\n /** Temperature for model inference */\n temperature?: number;\n /** Custom headers sent with every request to the provider */\n headers?: Record<string, string>;\n /** Reasoning effort for reasoning-capable models (e.g., \"none\", \"low\", \"medium\", \"high\") */\n reasoningEffort?: string;\n /**\n * Wire format used against the OpenAI-compatible endpoint at `baseURL`.\n * Defaults to the Responses API. Use `chat` for providers that expose only\n * an OpenAI-compatible Chat Completions endpoint (e.g. Databricks).\n */\n openaiEndpointFormat?: OpenAIEndpointFormat;\n};\n\nexport type ModelConfiguration =\n | AvailableModel\n | (ClientOptions & {\n modelName: AvailableModel;\n /**\n * Optional AI SDK middleware applied to every LanguageModelV2 created for this model.\n * Use this to intercept LLM calls for usage tracking, logging, request transforms, etc.\n *\n * Only effective when running locally (direct mode). Cannot be serialized over HTTP,\n */\n middleware?: LanguageModelV2Middleware;\n });\n"]}
@@ -150,14 +150,15 @@ export async function tryScopedSnapshot(page, options, context, pierce, sessionT
150
150
  }
151
151
  }
152
152
  const scopedUrlMap = { ...urlMap };
153
+ const wellFormedOutline = outline.toWellFormed();
153
154
  const snapshot = {
154
- combinedTree: outline,
155
+ combinedTree: wellFormedOutline,
155
156
  combinedXpathMap: scopedXpathMap,
156
157
  combinedUrlMap: scopedUrlMap,
157
158
  perFrame: [
158
159
  {
159
160
  frameId: targetFrameId,
160
- outline,
161
+ outline: wellFormedOutline,
161
162
  xpathMap,
162
163
  urlMap,
163
164
  },
@@ -562,7 +563,7 @@ export function mergeFramesIntoSnapshot(context, perFrameMaps, perFrameOutlines,
562
563
  const rootOutline = perFrameOutlines.find((o) => o.frameId === context.rootId)?.outline ??
563
564
  perFrameOutlines[0]?.outline ??
564
565
  "";
565
- const combinedTree = injectSubtrees(rootOutline, idToTree);
566
+ const combinedTree = injectSubtrees(rootOutline, idToTree).toWellFormed();
566
567
  return {
567
568
  combinedTree,
568
569
  combinedXpathMap,
@@ -1 +1 @@
1
- {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/capture.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport type { CDPSessionLike } from \"../../cdp.js\";\nimport { Page } from \"../../page.js\";\nimport { Frame } from \"../../frame.js\";\nimport {\n FrameSelectorResolver,\n type ResolvedNode,\n type SelectorQuery,\n} from \"../../selectorResolver.js\";\nimport { v3Logger } from \"../../../logger.js\";\nimport type {\n FrameContext,\n FrameDomMaps,\n FrameParentIndex,\n HybridSnapshot,\n SnapshotOptions,\n SessionDomIndex,\n} from \"../../../types/private/index.js\";\nimport { a11yForFrame } from \"./a11yTree.js\";\nimport {\n resolveCssFocusFrameAndTail,\n resolveFocusFrameAndTail,\n listChildrenOf,\n} from \"./focusSelectors.js\";\nimport {\n buildSessionDomIndex,\n domMapsForSession,\n relativizeXPath,\n} from \"./domTree.js\";\nimport { injectSubtrees } from \"./treeFormatUtils.js\";\nimport { ownerSession, parentSession } from \"./sessions.js\";\nimport { normalizeXPath, prefixXPath } from \"./xpathUtils.js\";\n\ntype IgnoredNodeMap = Map<string, Set<number>>;\ntype Interval = { start: number; end: number };\ntype ExclusionIntervalsByFrame = Map<string, Interval[]>;\ntype ChildFrameHost = { childFrameId: string; hostBackendNodeId: number };\ntype ChildFramesByParent = Map<string, ChildFrameHost[]>;\n\n/**\n * Capture a hybrid DOM + Accessibility snapshot for the provided page.\n *\n * Flow overview:\n * 1. (Optional) Scope directly to a requested selector. We walk iframe hops to\n * find the owning frame, build just that frame’s DOM + AX tree, and bail out\n * early when the subtree satisfies the caller.\n * 2. Build DOM indexes for every unique CDP session. DOM.getDocument is called\n * once per session and hydrated so per-frame slices can share the result.\n * 3. Slice each frame’s DOM data from its session index and fetch its AX tree.\n * This yields relative XPath/tag/url maps for the document rooted at that frame.\n * 4. Walk the frame tree to compute absolute iframe prefixes. Every child frame\n * needs the XPath of the iframe element that hosts it so we can prefix maps.\n * 5. Merge all per-frame results into global combined maps and stitch the text\n * outline. The final payload mirrors the legacy shape but is built in layers.\n *\n * Each numbered block below references the step above for easier debugging.\n */\nexport async function captureHybridSnapshot(\n page: Page,\n options?: SnapshotOptions,\n): Promise<HybridSnapshot> {\n const pierce = options?.pierceShadow ?? true;\n const includeIframes = options?.includeIframes !== false;\n const hasIgnoreSelectors = (options?.ignoreSelectors?.length ?? 0) > 0;\n\n const context = buildFrameContext(page);\n const framesInScope = includeIframes ? [...context.frames] : [context.rootId];\n if (!framesInScope.includes(context.rootId)) {\n framesInScope.unshift(context.rootId);\n }\n\n if (!hasIgnoreSelectors) {\n const scopedSnapshot = await tryScopedSnapshot(\n page,\n options,\n context,\n pierce,\n new Map<string, SessionDomIndex>(),\n new Map(),\n );\n if (scopedSnapshot) return scopedSnapshot;\n }\n\n const sessionToIndex = await buildSessionIndexes(page, framesInScope, pierce);\n const ignoredNodesByFrame = await resolveIgnoredNodes(\n page,\n options?.ignoreSelectors,\n context,\n sessionToIndex,\n );\n const exclusionIntervalsByFrame = await buildFrameExclusionIntervals(\n page,\n context,\n sessionToIndex,\n ignoredNodesByFrame,\n );\n if (hasIgnoreSelectors) {\n const scopedSnapshot = await tryScopedSnapshot(\n page,\n options,\n context,\n pierce,\n sessionToIndex,\n exclusionIntervalsByFrame,\n );\n if (scopedSnapshot) return scopedSnapshot;\n }\n\n const { perFrameMaps, perFrameOutlines } = await collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n options,\n pierce,\n framesInScope,\n exclusionIntervalsByFrame,\n );\n const { absPrefix, iframeHostEncByChild } = await computeFramePrefixes(\n page,\n context,\n perFrameMaps,\n framesInScope,\n );\n\n return mergeFramesIntoSnapshot(\n context,\n perFrameMaps,\n perFrameOutlines,\n absPrefix,\n iframeHostEncByChild,\n framesInScope,\n );\n}\n\n/**\n * Snapshot the current frame tree so downstream helpers have consistent topology\n * without re-querying CDP. The map is intentionally shallow (frameId → parentId)\n * so it is serializable/testable without holding on to CDP handles.\n */\nexport function buildFrameContext(page: Page): FrameContext {\n const rootId = page.mainFrameId();\n const frameTree = page.asProtocolFrameTree(rootId);\n const parentByFrame: FrameParentIndex = new Map();\n (function index(n: Protocol.Page.FrameTree, parent: string | null) {\n parentByFrame.set(n.frame.id, parent);\n for (const c of n.childFrames ?? []) index(c, n.frame.id);\n })(frameTree, null);\n const frames = page.listAllFrameIds();\n return { rootId, parentByFrame, frames };\n}\n\n/**\n * Step 1 – scoped snapshot fast-path. If a selector is provided we try to:\n * 1) Resolve the selector (XPath or CSS) across iframes.\n * 2) Build DOM + AX data only for the owning frame.\n * 3) Bail out early when the selector's subtree satisfies the request.\n *\n * Returns `null` when scoping fails (e.g., selector miss) so the caller can\n * fall back to the full multi-frame snapshot.\n */\nexport async function tryScopedSnapshot(\n page: Page,\n options: SnapshotOptions | undefined,\n context: FrameContext,\n pierce: boolean,\n sessionToIndex: Map<string, SessionDomIndex>,\n exclusionIntervalsByFrame: ExclusionIntervalsByFrame,\n): Promise<HybridSnapshot | null> {\n const requestedFocus = options?.focusSelector?.trim();\n if (!requestedFocus) return null;\n\n const logScopeFallback = () => {\n v3Logger({\n message: `Unable to narrow scope with selector. Falling back to using full DOM`,\n level: 1,\n auxiliary: {\n arguments: {\n value: `selector: ${options?.focusSelector?.trim()}`,\n type: \"string\",\n },\n },\n });\n };\n\n try {\n let targetFrameId: string;\n let tailSelector: string | undefined;\n let absPrefix: string | undefined;\n\n const looksLikeXPath =\n /^xpath=/i.test(requestedFocus) || requestedFocus.startsWith(\"/\");\n if (looksLikeXPath) {\n const focus = normalizeXPath(requestedFocus);\n const hit = await resolveFocusFrameAndTail(\n page,\n focus,\n context.parentByFrame,\n context.rootId,\n );\n targetFrameId = hit.targetFrameId;\n tailSelector = hit.tailXPath || undefined;\n absPrefix = hit.absPrefix;\n } else {\n const cssHit = await resolveCssFocusFrameAndTail(\n page,\n requestedFocus,\n context.parentByFrame,\n context.rootId,\n );\n targetFrameId = cssHit.targetFrameId;\n tailSelector = cssHit.tailSelector || undefined;\n absPrefix = cssHit.absPrefix;\n }\n\n const owningSess = ownerSession(page, targetFrameId);\n const parentId = context.parentByFrame.get(targetFrameId);\n const sameSessionAsParent =\n !!parentId &&\n ownerSession(page, parentId) === ownerSession(page, targetFrameId);\n const { tagNameMap, xpathMap, scrollableMap } = await domMapsForSession(\n owningSess,\n targetFrameId,\n pierce,\n (fid, be) => `${page.getOrdinal(fid)}-${be}`,\n sameSessionAsParent,\n );\n\n const { outline, urlMap, scopeApplied } = await a11yForFrame(\n owningSess,\n targetFrameId,\n {\n focusSelector: tailSelector || undefined,\n isIgnoredBackendNode: makeIsIgnoredBackendNode(\n targetFrameId,\n ownerSessionIndexForFrame(page, targetFrameId, sessionToIndex),\n exclusionIntervalsByFrame,\n ),\n tagNameMap,\n experimental: options?.experimental ?? false,\n scrollableMap,\n encode: (backendNodeId) =>\n `${page.getOrdinal(targetFrameId)}-${backendNodeId}`,\n },\n );\n\n const scopedXpathMap: Record<string, string> = {};\n const isIgnoredBackendNode = makeIsIgnoredBackendNode(\n targetFrameId,\n ownerSessionIndexForFrame(page, targetFrameId, sessionToIndex),\n exclusionIntervalsByFrame,\n );\n const abs = absPrefix ?? \"\";\n const isRoot = !abs || abs === \"/\";\n if (isRoot) {\n for (const [encId, xp] of Object.entries(xpathMap)) {\n const backendNodeId = parseEncodedBackendNodeId(encId);\n if (\n typeof backendNodeId === \"number\" &&\n isIgnoredBackendNode?.(backendNodeId)\n ) {\n continue;\n }\n scopedXpathMap[encId] = xp;\n }\n } else {\n // Prefix relative XPaths so the scoped result matches the global encoding.\n for (const [encId, xp] of Object.entries(xpathMap)) {\n const backendNodeId = parseEncodedBackendNodeId(encId);\n if (\n typeof backendNodeId === \"number\" &&\n isIgnoredBackendNode?.(backendNodeId)\n ) {\n continue;\n }\n scopedXpathMap[encId] = prefixXPath(abs, xp);\n }\n }\n\n const scopedUrlMap: Record<string, string> = { ...urlMap };\n\n const snapshot: HybridSnapshot = {\n combinedTree: outline,\n combinedXpathMap: scopedXpathMap,\n combinedUrlMap: scopedUrlMap,\n perFrame: [\n {\n frameId: targetFrameId,\n outline,\n xpathMap,\n urlMap,\n },\n ],\n };\n\n if (scopeApplied) {\n return snapshot;\n }\n\n logScopeFallback();\n } catch {\n logScopeFallback();\n }\n return null;\n}\n\n/**\n * Step 2 – call DOM.getDocument once per unique CDP session and hydrate the\n * result so per-frame slices can share the structure. We key by session id\n * because same process iframes live inside the same session.\n */\nexport async function buildSessionIndexes(\n page: Page,\n frames: string[],\n pierce: boolean,\n): Promise<Map<string, SessionDomIndex>> {\n const sessionToIndex = new Map<string, SessionDomIndex>();\n const sessionById = new Map<string, CDPSessionLike>();\n for (const frameId of frames) {\n const sess = ownerSession(page, frameId);\n const sid = sess.id ?? \"root\";\n if (!sessionById.has(sid)) sessionById.set(sid, sess);\n }\n for (const [sid, sess] of sessionById.entries()) {\n const idx = await buildSessionDomIndex(sess, pierce);\n sessionToIndex.set(sid, idx);\n }\n return sessionToIndex;\n}\n\n/**\n * Step 3 – derive per-frame DOM maps and accessibility outlines.\n * Each frame:\n * - slices the shared session index down to its document root\n * - builds frame-aware encoded ids (ordinal-backendNodeId)\n * - collects tag/xpath/scrollability maps for DOM-based lookups\n * - fetches its AX tree to produce outlines and URL maps\n */\nexport async function collectPerFrameMaps(\n page: Page,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n options: SnapshotOptions | undefined,\n pierce: boolean,\n frameIds: string[],\n exclusionIntervalsByFrame: ExclusionIntervalsByFrame,\n): Promise<{\n perFrameMaps: Map<string, FrameDomMaps>;\n perFrameOutlines: Array<{ frameId: string; outline: string }>;\n}> {\n const perFrameMaps = new Map<string, FrameDomMaps>();\n const perFrameOutlines: Array<{ frameId: string; outline: string }> = [];\n\n for (const frameId of frameIds) {\n const sess = ownerSession(page, frameId);\n const sid = sess.id ?? \"root\";\n let idx = sessionToIndex.get(sid);\n if (!idx) {\n idx = await buildSessionDomIndex(sess, pierce);\n sessionToIndex.set(sid, idx);\n }\n\n const parentId = context.parentByFrame.get(frameId);\n const sameSessionAsParent =\n !!parentId && ownerSession(page, parentId) === sess;\n\n const docRootBe = await resolveFrameDocRootBackendId(\n page,\n frameId,\n idx,\n sameSessionAsParent,\n );\n\n const tagNameMap: Record<string, string> = {};\n const xpathMap: Record<string, string> = {};\n const scrollableMap: Record<string, boolean> = {};\n const isIgnoredBackendNode = makeIsIgnoredBackendNode(\n frameId,\n idx,\n exclusionIntervalsByFrame,\n );\n const enc = (be: number) => `${page.getOrdinal(frameId)}-${be}`;\n const baseAbs = idx.absByBe.get(docRootBe) ?? \"/\";\n\n for (const [be, nodeAbs] of idx.absByBe.entries()) {\n const nodeDocRoot = idx.docRootOf.get(be);\n if (nodeDocRoot !== docRootBe) continue;\n if (isIgnoredBackendNode?.(be)) continue;\n\n // Translate absolute XPaths into document-relative ones for this frame.\n const rel = relativizeXPath(baseAbs, nodeAbs);\n const key = enc(be);\n xpathMap[key] = rel;\n const tag = idx.tagByBe.get(be);\n if (tag) tagNameMap[key] = tag;\n if (idx.scrollByBe.get(be)) scrollableMap[key] = true;\n }\n\n const { outline, urlMap } = await a11yForFrame(sess, frameId, {\n isIgnoredBackendNode,\n experimental: options?.experimental ?? false,\n tagNameMap,\n scrollableMap,\n encode: (backendNodeId) => `${page.getOrdinal(frameId)}-${backendNodeId}`,\n });\n\n perFrameOutlines.push({ frameId, outline });\n perFrameMaps.set(frameId, { tagNameMap, xpathMap, scrollableMap, urlMap });\n }\n\n return { perFrameMaps, perFrameOutlines };\n}\n\nexport async function resolveIgnoredNodes(\n page: Page,\n ignoreSelectors: string[] | undefined,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n): Promise<IgnoredNodeMap> {\n const ignoredNodesByFrame: IgnoredNodeMap = new Map();\n\n for (const rawSelector of ignoreSelectors ?? []) {\n const selector = rawSelector.trim();\n if (!selector) continue;\n\n try {\n const resolved = await resolveIgnoredNodesForSelector(\n page,\n selector,\n context,\n sessionToIndex,\n );\n for (const match of resolved) {\n const nodes =\n ignoredNodesByFrame.get(match.frameId) ?? new Set<number>();\n nodes.add(match.backendNodeId);\n ignoredNodesByFrame.set(match.frameId, nodes);\n }\n } catch {\n continue;\n }\n }\n\n return ignoredNodesByFrame;\n}\n\nasync function resolveIgnoredNodesForSelector(\n page: Page,\n selector: string,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n): Promise<Array<{ frameId: string; backendNodeId: number }>> {\n const looksLikeXPath = /^xpath=/i.test(selector) || selector.startsWith(\"/\");\n\n if (looksLikeXPath) {\n const hit = await resolveFocusFrameAndTail(\n page,\n normalizeXPath(selector),\n context.parentByFrame,\n context.rootId,\n );\n const targetFrameId = hit.targetFrameId;\n const tailXPath = hit.tailXPath || \"/\";\n if (tailXPath === \"/\") {\n const idx = ownerSessionIndexForFrame(\n page,\n targetFrameId,\n sessionToIndex,\n );\n if (!idx) return [];\n const parentId = context.parentByFrame.get(targetFrameId);\n const sameSessionAsParent =\n !!parentId &&\n ownerSession(page, parentId) === ownerSession(page, targetFrameId);\n const backendNodeId = await resolveFrameDocRootBackendId(\n page,\n targetFrameId,\n idx,\n sameSessionAsParent,\n );\n return [{ frameId: targetFrameId, backendNodeId }];\n }\n return resolveIgnoredNodesInFrame(page, targetFrameId, {\n kind: \"xpath\",\n value: tailXPath,\n });\n }\n\n const hit = await resolveCssFocusFrameAndTail(\n page,\n selector,\n context.parentByFrame,\n context.rootId,\n );\n const targetFrameId = hit.targetFrameId;\n return resolveIgnoredNodesInFrame(page, targetFrameId, {\n kind: \"css\",\n value: hit.tailSelector || selector,\n });\n}\n\nasync function resolveIgnoredNodesInFrame(\n page: Page,\n frameId: string,\n query: SelectorQuery,\n): Promise<Array<{ frameId: string; backendNodeId: number }>> {\n const session = ownerSession(page, frameId);\n const frame = new Frame(session, frameId, \"\", false);\n const resolver = new FrameSelectorResolver(frame);\n const resolvedNodes = await resolver.resolveAll(query);\n if (!resolvedNodes.length) return [];\n\n const backendNodeIds = await describeResolvedNodes(session, resolvedNodes);\n return backendNodeIds.map((backendNodeId) => ({ frameId, backendNodeId }));\n}\n\nasync function describeResolvedNodes(\n session: CDPSessionLike,\n resolvedNodes: ResolvedNode[],\n): Promise<number[]> {\n const backendNodeIds = new Set<number>();\n\n try {\n for (const resolvedNode of resolvedNodes) {\n const desc = await session.send<Protocol.DOM.DescribeNodeResponse>(\n \"DOM.describeNode\",\n { objectId: resolvedNode.objectId },\n );\n const backendNodeId = desc.node.backendNodeId;\n if (typeof backendNodeId === \"number\") {\n backendNodeIds.add(backendNodeId);\n }\n }\n } finally {\n await Promise.all(\n resolvedNodes.map((resolvedNode) =>\n session\n .send(\"Runtime.releaseObject\", { objectId: resolvedNode.objectId })\n .catch(() => {}),\n ),\n );\n }\n\n return [...backendNodeIds];\n}\n\nexport async function buildFrameExclusionIntervals(\n page: Page,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n ignoredNodesByFrame: IgnoredNodeMap,\n): Promise<ExclusionIntervalsByFrame> {\n const intervalsByFrame: ExclusionIntervalsByFrame = new Map();\n if (!ignoredNodesByFrame.size) return intervalsByFrame;\n const childFramesByParent = await resolveChildFramesByParent(page, context);\n const excludedFrames = new Set<string>();\n\n const pushInterval = (frameId: string, start: number, end: number) => {\n const intervals = intervalsByFrame.get(frameId) ?? [];\n intervals.push({ start, end });\n intervalsByFrame.set(frameId, intervals);\n };\n\n const excludeFrameSubtree = async (frameId: string): Promise<void> => {\n if (excludedFrames.has(frameId)) return;\n excludedFrames.add(frameId);\n\n const idx = ownerSessionIndexForFrame(page, frameId, sessionToIndex);\n if (!idx) return;\n const parentId = context.parentByFrame.get(frameId);\n const sameSessionAsParent =\n !!parentId &&\n ownerSession(page, parentId) === ownerSession(page, frameId);\n const docRootBe = await resolveFrameDocRootBackendId(\n page,\n frameId,\n idx,\n sameSessionAsParent,\n );\n const start = idx.enterByBe.get(docRootBe);\n const end = idx.exitByBe.get(docRootBe);\n if (typeof start === \"number\" && typeof end === \"number\") {\n pushInterval(frameId, start, end);\n }\n\n for (const childFrameId of listChildrenOf(context.parentByFrame, frameId)) {\n await excludeFrameSubtree(childFrameId);\n }\n };\n\n const excludeIgnoredNode = async (\n frameId: string,\n backendNodeId: number,\n ): Promise<void> => {\n const idx = ownerSessionIndexForFrame(page, frameId, sessionToIndex);\n if (!idx) return;\n const start = idx.enterByBe.get(backendNodeId);\n const end = idx.exitByBe.get(backendNodeId);\n if (typeof start !== \"number\" || typeof end !== \"number\") return;\n\n pushInterval(frameId, start, end);\n for (const childFrame of childFramesByParent.get(frameId) ?? []) {\n const hostEnter = idx.enterByBe.get(childFrame.hostBackendNodeId);\n if (typeof hostEnter !== \"number\") continue;\n if (hostEnter < start || hostEnter > end) continue;\n await excludeFrameSubtree(childFrame.childFrameId);\n }\n };\n\n for (const [frameId, backendNodeIds] of ignoredNodesByFrame.entries()) {\n for (const backendNodeId of backendNodeIds) {\n await excludeIgnoredNode(frameId, backendNodeId);\n }\n }\n\n for (const [frameId, intervals] of intervalsByFrame.entries()) {\n intervals.sort((a, b) => a.start - b.start || a.end - b.end);\n const merged: Interval[] = [];\n for (const interval of intervals) {\n const prev = merged[merged.length - 1];\n if (!prev || interval.start > prev.end) {\n merged.push({ ...interval });\n continue;\n }\n if (interval.end > prev.end) prev.end = interval.end;\n }\n intervalsByFrame.set(frameId, merged);\n }\n\n return intervalsByFrame;\n}\n\nasync function resolveChildFramesByParent(\n page: Page,\n context: FrameContext,\n): Promise<ChildFramesByParent> {\n const childFramesByParent: ChildFramesByParent = new Map();\n\n for (const frameId of context.frames) {\n const parentId = context.parentByFrame.get(frameId);\n if (!parentId) continue;\n\n const session = parentSession(page, context.parentByFrame, frameId);\n if (!session) continue;\n\n try {\n const { backendNodeId } = await session.send<{ backendNodeId?: number }>(\n \"DOM.getFrameOwner\",\n { frameId },\n );\n if (typeof backendNodeId !== \"number\") continue;\n const childFrames = childFramesByParent.get(parentId) ?? [];\n childFrames.push({\n childFrameId: frameId,\n hostBackendNodeId: backendNodeId,\n });\n childFramesByParent.set(parentId, childFrames);\n } catch {\n continue;\n }\n }\n\n return childFramesByParent;\n}\n\nfunction makeIsIgnoredBackendNode(\n frameId: string,\n idx: SessionDomIndex | undefined,\n exclusionIntervalsByFrame: ExclusionIntervalsByFrame,\n): ((backendNodeId: number) => boolean) | undefined {\n if (!idx) return undefined;\n const intervals = exclusionIntervalsByFrame.get(frameId);\n if (!intervals?.length) return undefined;\n\n return (backendNodeId: number): boolean => {\n const enter = idx.enterByBe.get(backendNodeId);\n if (typeof enter !== \"number\") return false;\n\n let lo = 0;\n let hi = intervals.length - 1;\n while (lo <= hi) {\n const mid = (lo + hi) >> 1;\n const interval = intervals[mid]!;\n if (enter < interval.start) {\n hi = mid - 1;\n } else if (enter > interval.end) {\n lo = mid + 1;\n } else {\n return true;\n }\n }\n return false;\n };\n}\n\nfunction parseEncodedBackendNodeId(encodedId: string): number | undefined {\n const parts = encodedId.split(\"-\");\n if (parts.length !== 2) return undefined;\n const backendNodeId = Number(parts[1]);\n return Number.isFinite(backendNodeId) ? backendNodeId : undefined;\n}\n\nfunction ownerSessionIndexForFrame(\n page: Page,\n frameId: string,\n sessionToIndex: Map<string, SessionDomIndex>,\n): SessionDomIndex | undefined {\n const session = ownerSession(page, frameId);\n return sessionToIndex.get(session.id ?? \"root\");\n}\n\nasync function resolveFrameDocRootBackendId(\n page: Page,\n frameId: string,\n idx: SessionDomIndex,\n sameSessionAsParent: boolean,\n): Promise<number> {\n if (!sameSessionAsParent) return idx.rootBackend;\n const session = ownerSession(page, frameId);\n try {\n const { backendNodeId } = await session.send<{ backendNodeId?: number }>(\n \"DOM.getFrameOwner\",\n { frameId },\n );\n if (typeof backendNodeId === \"number\") {\n const docRootBe = idx.contentDocRootByIframe.get(backendNodeId);\n if (typeof docRootBe === \"number\") return docRootBe;\n }\n } catch {\n //\n }\n return idx.rootBackend;\n}\n\n/**\n * Step 4 – walk the frame tree (parent-first) to compute absolute prefixes for\n * every frame. The prefix is the absolute XPath of the iframe element hosting\n * the frame, so we can later convert relative XPaths into cross-frame ones.\n */\nexport async function computeFramePrefixes(\n page: Page,\n context: FrameContext,\n perFrameMaps: Map<string, FrameDomMaps>,\n frameIds: string[],\n): Promise<{\n absPrefix: Map<string, string>;\n iframeHostEncByChild: Map<string, string>;\n}> {\n const absPrefix = new Map<string, string>();\n const iframeHostEncByChild = new Map<string, string>();\n absPrefix.set(context.rootId, \"\");\n const included = new Set(frameIds);\n\n const queue: string[] = [];\n if (included.has(context.rootId)) {\n queue.push(context.rootId);\n }\n\n while (queue.length) {\n const parent = queue.shift()!;\n const parentAbs = absPrefix.get(parent)!;\n\n for (const child of context.frames) {\n if (!included.has(child)) continue;\n if (context.parentByFrame.get(child) !== parent) continue;\n queue.push(child);\n\n const parentSess = parentSession(page, context.parentByFrame, child);\n\n const ownerBackendNodeId = await (async () => {\n try {\n const { backendNodeId } = await parentSess.send<{\n backendNodeId?: number;\n }>(\"DOM.getFrameOwner\", { frameId: child });\n return backendNodeId;\n } catch {\n return undefined;\n }\n })();\n\n if (!ownerBackendNodeId) {\n // OOPIFs resolved via a different session inherit the parent prefix.\n absPrefix.set(child, parentAbs);\n continue;\n }\n\n const parentDom = perFrameMaps.get(parent);\n const iframeEnc = `${page.getOrdinal(parent)}-${ownerBackendNodeId}`;\n const iframeXPath = parentDom?.xpathMap[iframeEnc];\n\n const childAbs = iframeXPath\n ? prefixXPath(parentAbs || \"/\", iframeXPath)\n : parentAbs;\n\n absPrefix.set(child, childAbs);\n iframeHostEncByChild.set(child, iframeEnc);\n }\n }\n\n return { absPrefix, iframeHostEncByChild };\n}\n\n/**\n * Step 5 – merge per-frame maps into the combined snapshot payload. We prefix\n * each frame's relative XPaths with the absolute path collected in step 4,\n * merge URL maps, and stitch text outlines by nesting child trees under the\n * encoded id of their parent iframe host.\n */\nexport function mergeFramesIntoSnapshot(\n context: FrameContext,\n perFrameMaps: Map<string, FrameDomMaps>,\n perFrameOutlines: Array<{ frameId: string; outline: string }>,\n absPrefix: Map<string, string>,\n iframeHostEncByChild: Map<string, string>,\n frameIds: string[],\n): HybridSnapshot {\n const combinedXpathMap: Record<string, string> = {};\n const combinedUrlMap: Record<string, string> = {};\n\n for (const frameId of frameIds) {\n const maps = perFrameMaps.get(frameId);\n if (!maps) continue;\n\n const abs = absPrefix.get(frameId) ?? \"\";\n const isRoot = abs === \"\" || abs === \"/\";\n\n if (isRoot) {\n Object.assign(combinedXpathMap, maps.xpathMap);\n Object.assign(combinedUrlMap, maps.urlMap);\n continue;\n }\n\n for (const [encId, xp] of Object.entries(maps.xpathMap)) {\n combinedXpathMap[encId] = prefixXPath(abs, xp);\n }\n Object.assign(combinedUrlMap, maps.urlMap);\n }\n\n const idToTree = new Map<string, string>();\n for (const { frameId, outline } of perFrameOutlines) {\n const parentEnc = iframeHostEncByChild.get(frameId);\n // The key is the parent iframe's encoded id so injectSubtrees can nest lines.\n if (parentEnc) idToTree.set(parentEnc, outline);\n }\n\n const rootOutline =\n perFrameOutlines.find((o) => o.frameId === context.rootId)?.outline ??\n perFrameOutlines[0]?.outline ??\n \"\";\n const combinedTree = injectSubtrees(rootOutline, idToTree);\n\n return {\n combinedTree,\n combinedXpathMap,\n combinedUrlMap,\n perFrame: perFrameOutlines.map(({ frameId, outline }) => {\n const maps = perFrameMaps.get(frameId);\n return {\n frameId,\n outline,\n xpathMap: maps?.xpathMap ?? {},\n urlMap: maps?.urlMap ?? {},\n };\n }),\n };\n}\n"]}
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/capture.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport type { CDPSessionLike } from \"../../cdp.js\";\nimport { Page } from \"../../page.js\";\nimport { Frame } from \"../../frame.js\";\nimport {\n FrameSelectorResolver,\n type ResolvedNode,\n type SelectorQuery,\n} from \"../../selectorResolver.js\";\nimport { v3Logger } from \"../../../logger.js\";\nimport type {\n FrameContext,\n FrameDomMaps,\n FrameParentIndex,\n HybridSnapshot,\n SnapshotOptions,\n SessionDomIndex,\n} from \"../../../types/private/index.js\";\nimport { a11yForFrame } from \"./a11yTree.js\";\nimport {\n resolveCssFocusFrameAndTail,\n resolveFocusFrameAndTail,\n listChildrenOf,\n} from \"./focusSelectors.js\";\nimport {\n buildSessionDomIndex,\n domMapsForSession,\n relativizeXPath,\n} from \"./domTree.js\";\nimport { injectSubtrees } from \"./treeFormatUtils.js\";\nimport { ownerSession, parentSession } from \"./sessions.js\";\nimport { normalizeXPath, prefixXPath } from \"./xpathUtils.js\";\n\ntype IgnoredNodeMap = Map<string, Set<number>>;\ntype Interval = { start: number; end: number };\ntype ExclusionIntervalsByFrame = Map<string, Interval[]>;\ntype ChildFrameHost = { childFrameId: string; hostBackendNodeId: number };\ntype ChildFramesByParent = Map<string, ChildFrameHost[]>;\ntype WellFormedString = string & { toWellFormed(): string };\n\n/**\n * Capture a hybrid DOM + Accessibility snapshot for the provided page.\n *\n * Flow overview:\n * 1. (Optional) Scope directly to a requested selector. We walk iframe hops to\n * find the owning frame, build just that frame’s DOM + AX tree, and bail out\n * early when the subtree satisfies the caller.\n * 2. Build DOM indexes for every unique CDP session. DOM.getDocument is called\n * once per session and hydrated so per-frame slices can share the result.\n * 3. Slice each frame’s DOM data from its session index and fetch its AX tree.\n * This yields relative XPath/tag/url maps for the document rooted at that frame.\n * 4. Walk the frame tree to compute absolute iframe prefixes. Every child frame\n * needs the XPath of the iframe element that hosts it so we can prefix maps.\n * 5. Merge all per-frame results into global combined maps and stitch the text\n * outline. The final payload mirrors the legacy shape but is built in layers.\n *\n * Each numbered block below references the step above for easier debugging.\n */\nexport async function captureHybridSnapshot(\n page: Page,\n options?: SnapshotOptions,\n): Promise<HybridSnapshot> {\n const pierce = options?.pierceShadow ?? true;\n const includeIframes = options?.includeIframes !== false;\n const hasIgnoreSelectors = (options?.ignoreSelectors?.length ?? 0) > 0;\n\n const context = buildFrameContext(page);\n const framesInScope = includeIframes ? [...context.frames] : [context.rootId];\n if (!framesInScope.includes(context.rootId)) {\n framesInScope.unshift(context.rootId);\n }\n\n if (!hasIgnoreSelectors) {\n const scopedSnapshot = await tryScopedSnapshot(\n page,\n options,\n context,\n pierce,\n new Map<string, SessionDomIndex>(),\n new Map(),\n );\n if (scopedSnapshot) return scopedSnapshot;\n }\n\n const sessionToIndex = await buildSessionIndexes(page, framesInScope, pierce);\n const ignoredNodesByFrame = await resolveIgnoredNodes(\n page,\n options?.ignoreSelectors,\n context,\n sessionToIndex,\n );\n const exclusionIntervalsByFrame = await buildFrameExclusionIntervals(\n page,\n context,\n sessionToIndex,\n ignoredNodesByFrame,\n );\n if (hasIgnoreSelectors) {\n const scopedSnapshot = await tryScopedSnapshot(\n page,\n options,\n context,\n pierce,\n sessionToIndex,\n exclusionIntervalsByFrame,\n );\n if (scopedSnapshot) return scopedSnapshot;\n }\n\n const { perFrameMaps, perFrameOutlines } = await collectPerFrameMaps(\n page,\n context,\n sessionToIndex,\n options,\n pierce,\n framesInScope,\n exclusionIntervalsByFrame,\n );\n const { absPrefix, iframeHostEncByChild } = await computeFramePrefixes(\n page,\n context,\n perFrameMaps,\n framesInScope,\n );\n\n return mergeFramesIntoSnapshot(\n context,\n perFrameMaps,\n perFrameOutlines,\n absPrefix,\n iframeHostEncByChild,\n framesInScope,\n );\n}\n\n/**\n * Snapshot the current frame tree so downstream helpers have consistent topology\n * without re-querying CDP. The map is intentionally shallow (frameId → parentId)\n * so it is serializable/testable without holding on to CDP handles.\n */\nexport function buildFrameContext(page: Page): FrameContext {\n const rootId = page.mainFrameId();\n const frameTree = page.asProtocolFrameTree(rootId);\n const parentByFrame: FrameParentIndex = new Map();\n (function index(n: Protocol.Page.FrameTree, parent: string | null) {\n parentByFrame.set(n.frame.id, parent);\n for (const c of n.childFrames ?? []) index(c, n.frame.id);\n })(frameTree, null);\n const frames = page.listAllFrameIds();\n return { rootId, parentByFrame, frames };\n}\n\n/**\n * Step 1 – scoped snapshot fast-path. If a selector is provided we try to:\n * 1) Resolve the selector (XPath or CSS) across iframes.\n * 2) Build DOM + AX data only for the owning frame.\n * 3) Bail out early when the selector's subtree satisfies the request.\n *\n * Returns `null` when scoping fails (e.g., selector miss) so the caller can\n * fall back to the full multi-frame snapshot.\n */\nexport async function tryScopedSnapshot(\n page: Page,\n options: SnapshotOptions | undefined,\n context: FrameContext,\n pierce: boolean,\n sessionToIndex: Map<string, SessionDomIndex>,\n exclusionIntervalsByFrame: ExclusionIntervalsByFrame,\n): Promise<HybridSnapshot | null> {\n const requestedFocus = options?.focusSelector?.trim();\n if (!requestedFocus) return null;\n\n const logScopeFallback = () => {\n v3Logger({\n message: `Unable to narrow scope with selector. Falling back to using full DOM`,\n level: 1,\n auxiliary: {\n arguments: {\n value: `selector: ${options?.focusSelector?.trim()}`,\n type: \"string\",\n },\n },\n });\n };\n\n try {\n let targetFrameId: string;\n let tailSelector: string | undefined;\n let absPrefix: string | undefined;\n\n const looksLikeXPath =\n /^xpath=/i.test(requestedFocus) || requestedFocus.startsWith(\"/\");\n if (looksLikeXPath) {\n const focus = normalizeXPath(requestedFocus);\n const hit = await resolveFocusFrameAndTail(\n page,\n focus,\n context.parentByFrame,\n context.rootId,\n );\n targetFrameId = hit.targetFrameId;\n tailSelector = hit.tailXPath || undefined;\n absPrefix = hit.absPrefix;\n } else {\n const cssHit = await resolveCssFocusFrameAndTail(\n page,\n requestedFocus,\n context.parentByFrame,\n context.rootId,\n );\n targetFrameId = cssHit.targetFrameId;\n tailSelector = cssHit.tailSelector || undefined;\n absPrefix = cssHit.absPrefix;\n }\n\n const owningSess = ownerSession(page, targetFrameId);\n const parentId = context.parentByFrame.get(targetFrameId);\n const sameSessionAsParent =\n !!parentId &&\n ownerSession(page, parentId) === ownerSession(page, targetFrameId);\n const { tagNameMap, xpathMap, scrollableMap } = await domMapsForSession(\n owningSess,\n targetFrameId,\n pierce,\n (fid, be) => `${page.getOrdinal(fid)}-${be}`,\n sameSessionAsParent,\n );\n\n const { outline, urlMap, scopeApplied } = await a11yForFrame(\n owningSess,\n targetFrameId,\n {\n focusSelector: tailSelector || undefined,\n isIgnoredBackendNode: makeIsIgnoredBackendNode(\n targetFrameId,\n ownerSessionIndexForFrame(page, targetFrameId, sessionToIndex),\n exclusionIntervalsByFrame,\n ),\n tagNameMap,\n experimental: options?.experimental ?? false,\n scrollableMap,\n encode: (backendNodeId) =>\n `${page.getOrdinal(targetFrameId)}-${backendNodeId}`,\n },\n );\n\n const scopedXpathMap: Record<string, string> = {};\n const isIgnoredBackendNode = makeIsIgnoredBackendNode(\n targetFrameId,\n ownerSessionIndexForFrame(page, targetFrameId, sessionToIndex),\n exclusionIntervalsByFrame,\n );\n const abs = absPrefix ?? \"\";\n const isRoot = !abs || abs === \"/\";\n if (isRoot) {\n for (const [encId, xp] of Object.entries(xpathMap)) {\n const backendNodeId = parseEncodedBackendNodeId(encId);\n if (\n typeof backendNodeId === \"number\" &&\n isIgnoredBackendNode?.(backendNodeId)\n ) {\n continue;\n }\n scopedXpathMap[encId] = xp;\n }\n } else {\n // Prefix relative XPaths so the scoped result matches the global encoding.\n for (const [encId, xp] of Object.entries(xpathMap)) {\n const backendNodeId = parseEncodedBackendNodeId(encId);\n if (\n typeof backendNodeId === \"number\" &&\n isIgnoredBackendNode?.(backendNodeId)\n ) {\n continue;\n }\n scopedXpathMap[encId] = prefixXPath(abs, xp);\n }\n }\n\n const scopedUrlMap: Record<string, string> = { ...urlMap };\n\n const wellFormedOutline = (outline as WellFormedString).toWellFormed();\n\n const snapshot: HybridSnapshot = {\n combinedTree: wellFormedOutline,\n combinedXpathMap: scopedXpathMap,\n combinedUrlMap: scopedUrlMap,\n perFrame: [\n {\n frameId: targetFrameId,\n outline: wellFormedOutline,\n xpathMap,\n urlMap,\n },\n ],\n };\n\n if (scopeApplied) {\n return snapshot;\n }\n\n logScopeFallback();\n } catch {\n logScopeFallback();\n }\n return null;\n}\n\n/**\n * Step 2 – call DOM.getDocument once per unique CDP session and hydrate the\n * result so per-frame slices can share the structure. We key by session id\n * because same process iframes live inside the same session.\n */\nexport async function buildSessionIndexes(\n page: Page,\n frames: string[],\n pierce: boolean,\n): Promise<Map<string, SessionDomIndex>> {\n const sessionToIndex = new Map<string, SessionDomIndex>();\n const sessionById = new Map<string, CDPSessionLike>();\n for (const frameId of frames) {\n const sess = ownerSession(page, frameId);\n const sid = sess.id ?? \"root\";\n if (!sessionById.has(sid)) sessionById.set(sid, sess);\n }\n for (const [sid, sess] of sessionById.entries()) {\n const idx = await buildSessionDomIndex(sess, pierce);\n sessionToIndex.set(sid, idx);\n }\n return sessionToIndex;\n}\n\n/**\n * Step 3 – derive per-frame DOM maps and accessibility outlines.\n * Each frame:\n * - slices the shared session index down to its document root\n * - builds frame-aware encoded ids (ordinal-backendNodeId)\n * - collects tag/xpath/scrollability maps for DOM-based lookups\n * - fetches its AX tree to produce outlines and URL maps\n */\nexport async function collectPerFrameMaps(\n page: Page,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n options: SnapshotOptions | undefined,\n pierce: boolean,\n frameIds: string[],\n exclusionIntervalsByFrame: ExclusionIntervalsByFrame,\n): Promise<{\n perFrameMaps: Map<string, FrameDomMaps>;\n perFrameOutlines: Array<{ frameId: string; outline: string }>;\n}> {\n const perFrameMaps = new Map<string, FrameDomMaps>();\n const perFrameOutlines: Array<{ frameId: string; outline: string }> = [];\n\n for (const frameId of frameIds) {\n const sess = ownerSession(page, frameId);\n const sid = sess.id ?? \"root\";\n let idx = sessionToIndex.get(sid);\n if (!idx) {\n idx = await buildSessionDomIndex(sess, pierce);\n sessionToIndex.set(sid, idx);\n }\n\n const parentId = context.parentByFrame.get(frameId);\n const sameSessionAsParent =\n !!parentId && ownerSession(page, parentId) === sess;\n\n const docRootBe = await resolveFrameDocRootBackendId(\n page,\n frameId,\n idx,\n sameSessionAsParent,\n );\n\n const tagNameMap: Record<string, string> = {};\n const xpathMap: Record<string, string> = {};\n const scrollableMap: Record<string, boolean> = {};\n const isIgnoredBackendNode = makeIsIgnoredBackendNode(\n frameId,\n idx,\n exclusionIntervalsByFrame,\n );\n const enc = (be: number) => `${page.getOrdinal(frameId)}-${be}`;\n const baseAbs = idx.absByBe.get(docRootBe) ?? \"/\";\n\n for (const [be, nodeAbs] of idx.absByBe.entries()) {\n const nodeDocRoot = idx.docRootOf.get(be);\n if (nodeDocRoot !== docRootBe) continue;\n if (isIgnoredBackendNode?.(be)) continue;\n\n // Translate absolute XPaths into document-relative ones for this frame.\n const rel = relativizeXPath(baseAbs, nodeAbs);\n const key = enc(be);\n xpathMap[key] = rel;\n const tag = idx.tagByBe.get(be);\n if (tag) tagNameMap[key] = tag;\n if (idx.scrollByBe.get(be)) scrollableMap[key] = true;\n }\n\n const { outline, urlMap } = await a11yForFrame(sess, frameId, {\n isIgnoredBackendNode,\n experimental: options?.experimental ?? false,\n tagNameMap,\n scrollableMap,\n encode: (backendNodeId) => `${page.getOrdinal(frameId)}-${backendNodeId}`,\n });\n\n perFrameOutlines.push({ frameId, outline });\n perFrameMaps.set(frameId, { tagNameMap, xpathMap, scrollableMap, urlMap });\n }\n\n return { perFrameMaps, perFrameOutlines };\n}\n\nexport async function resolveIgnoredNodes(\n page: Page,\n ignoreSelectors: string[] | undefined,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n): Promise<IgnoredNodeMap> {\n const ignoredNodesByFrame: IgnoredNodeMap = new Map();\n\n for (const rawSelector of ignoreSelectors ?? []) {\n const selector = rawSelector.trim();\n if (!selector) continue;\n\n try {\n const resolved = await resolveIgnoredNodesForSelector(\n page,\n selector,\n context,\n sessionToIndex,\n );\n for (const match of resolved) {\n const nodes =\n ignoredNodesByFrame.get(match.frameId) ?? new Set<number>();\n nodes.add(match.backendNodeId);\n ignoredNodesByFrame.set(match.frameId, nodes);\n }\n } catch {\n continue;\n }\n }\n\n return ignoredNodesByFrame;\n}\n\nasync function resolveIgnoredNodesForSelector(\n page: Page,\n selector: string,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n): Promise<Array<{ frameId: string; backendNodeId: number }>> {\n const looksLikeXPath = /^xpath=/i.test(selector) || selector.startsWith(\"/\");\n\n if (looksLikeXPath) {\n const hit = await resolveFocusFrameAndTail(\n page,\n normalizeXPath(selector),\n context.parentByFrame,\n context.rootId,\n );\n const targetFrameId = hit.targetFrameId;\n const tailXPath = hit.tailXPath || \"/\";\n if (tailXPath === \"/\") {\n const idx = ownerSessionIndexForFrame(\n page,\n targetFrameId,\n sessionToIndex,\n );\n if (!idx) return [];\n const parentId = context.parentByFrame.get(targetFrameId);\n const sameSessionAsParent =\n !!parentId &&\n ownerSession(page, parentId) === ownerSession(page, targetFrameId);\n const backendNodeId = await resolveFrameDocRootBackendId(\n page,\n targetFrameId,\n idx,\n sameSessionAsParent,\n );\n return [{ frameId: targetFrameId, backendNodeId }];\n }\n return resolveIgnoredNodesInFrame(page, targetFrameId, {\n kind: \"xpath\",\n value: tailXPath,\n });\n }\n\n const hit = await resolveCssFocusFrameAndTail(\n page,\n selector,\n context.parentByFrame,\n context.rootId,\n );\n const targetFrameId = hit.targetFrameId;\n return resolveIgnoredNodesInFrame(page, targetFrameId, {\n kind: \"css\",\n value: hit.tailSelector || selector,\n });\n}\n\nasync function resolveIgnoredNodesInFrame(\n page: Page,\n frameId: string,\n query: SelectorQuery,\n): Promise<Array<{ frameId: string; backendNodeId: number }>> {\n const session = ownerSession(page, frameId);\n const frame = new Frame(session, frameId, \"\", false);\n const resolver = new FrameSelectorResolver(frame);\n const resolvedNodes = await resolver.resolveAll(query);\n if (!resolvedNodes.length) return [];\n\n const backendNodeIds = await describeResolvedNodes(session, resolvedNodes);\n return backendNodeIds.map((backendNodeId) => ({ frameId, backendNodeId }));\n}\n\nasync function describeResolvedNodes(\n session: CDPSessionLike,\n resolvedNodes: ResolvedNode[],\n): Promise<number[]> {\n const backendNodeIds = new Set<number>();\n\n try {\n for (const resolvedNode of resolvedNodes) {\n const desc = await session.send<Protocol.DOM.DescribeNodeResponse>(\n \"DOM.describeNode\",\n { objectId: resolvedNode.objectId },\n );\n const backendNodeId = desc.node.backendNodeId;\n if (typeof backendNodeId === \"number\") {\n backendNodeIds.add(backendNodeId);\n }\n }\n } finally {\n await Promise.all(\n resolvedNodes.map((resolvedNode) =>\n session\n .send(\"Runtime.releaseObject\", { objectId: resolvedNode.objectId })\n .catch(() => {}),\n ),\n );\n }\n\n return [...backendNodeIds];\n}\n\nexport async function buildFrameExclusionIntervals(\n page: Page,\n context: FrameContext,\n sessionToIndex: Map<string, SessionDomIndex>,\n ignoredNodesByFrame: IgnoredNodeMap,\n): Promise<ExclusionIntervalsByFrame> {\n const intervalsByFrame: ExclusionIntervalsByFrame = new Map();\n if (!ignoredNodesByFrame.size) return intervalsByFrame;\n const childFramesByParent = await resolveChildFramesByParent(page, context);\n const excludedFrames = new Set<string>();\n\n const pushInterval = (frameId: string, start: number, end: number) => {\n const intervals = intervalsByFrame.get(frameId) ?? [];\n intervals.push({ start, end });\n intervalsByFrame.set(frameId, intervals);\n };\n\n const excludeFrameSubtree = async (frameId: string): Promise<void> => {\n if (excludedFrames.has(frameId)) return;\n excludedFrames.add(frameId);\n\n const idx = ownerSessionIndexForFrame(page, frameId, sessionToIndex);\n if (!idx) return;\n const parentId = context.parentByFrame.get(frameId);\n const sameSessionAsParent =\n !!parentId &&\n ownerSession(page, parentId) === ownerSession(page, frameId);\n const docRootBe = await resolveFrameDocRootBackendId(\n page,\n frameId,\n idx,\n sameSessionAsParent,\n );\n const start = idx.enterByBe.get(docRootBe);\n const end = idx.exitByBe.get(docRootBe);\n if (typeof start === \"number\" && typeof end === \"number\") {\n pushInterval(frameId, start, end);\n }\n\n for (const childFrameId of listChildrenOf(context.parentByFrame, frameId)) {\n await excludeFrameSubtree(childFrameId);\n }\n };\n\n const excludeIgnoredNode = async (\n frameId: string,\n backendNodeId: number,\n ): Promise<void> => {\n const idx = ownerSessionIndexForFrame(page, frameId, sessionToIndex);\n if (!idx) return;\n const start = idx.enterByBe.get(backendNodeId);\n const end = idx.exitByBe.get(backendNodeId);\n if (typeof start !== \"number\" || typeof end !== \"number\") return;\n\n pushInterval(frameId, start, end);\n for (const childFrame of childFramesByParent.get(frameId) ?? []) {\n const hostEnter = idx.enterByBe.get(childFrame.hostBackendNodeId);\n if (typeof hostEnter !== \"number\") continue;\n if (hostEnter < start || hostEnter > end) continue;\n await excludeFrameSubtree(childFrame.childFrameId);\n }\n };\n\n for (const [frameId, backendNodeIds] of ignoredNodesByFrame.entries()) {\n for (const backendNodeId of backendNodeIds) {\n await excludeIgnoredNode(frameId, backendNodeId);\n }\n }\n\n for (const [frameId, intervals] of intervalsByFrame.entries()) {\n intervals.sort((a, b) => a.start - b.start || a.end - b.end);\n const merged: Interval[] = [];\n for (const interval of intervals) {\n const prev = merged[merged.length - 1];\n if (!prev || interval.start > prev.end) {\n merged.push({ ...interval });\n continue;\n }\n if (interval.end > prev.end) prev.end = interval.end;\n }\n intervalsByFrame.set(frameId, merged);\n }\n\n return intervalsByFrame;\n}\n\nasync function resolveChildFramesByParent(\n page: Page,\n context: FrameContext,\n): Promise<ChildFramesByParent> {\n const childFramesByParent: ChildFramesByParent = new Map();\n\n for (const frameId of context.frames) {\n const parentId = context.parentByFrame.get(frameId);\n if (!parentId) continue;\n\n const session = parentSession(page, context.parentByFrame, frameId);\n if (!session) continue;\n\n try {\n const { backendNodeId } = await session.send<{ backendNodeId?: number }>(\n \"DOM.getFrameOwner\",\n { frameId },\n );\n if (typeof backendNodeId !== \"number\") continue;\n const childFrames = childFramesByParent.get(parentId) ?? [];\n childFrames.push({\n childFrameId: frameId,\n hostBackendNodeId: backendNodeId,\n });\n childFramesByParent.set(parentId, childFrames);\n } catch {\n continue;\n }\n }\n\n return childFramesByParent;\n}\n\nfunction makeIsIgnoredBackendNode(\n frameId: string,\n idx: SessionDomIndex | undefined,\n exclusionIntervalsByFrame: ExclusionIntervalsByFrame,\n): ((backendNodeId: number) => boolean) | undefined {\n if (!idx) return undefined;\n const intervals = exclusionIntervalsByFrame.get(frameId);\n if (!intervals?.length) return undefined;\n\n return (backendNodeId: number): boolean => {\n const enter = idx.enterByBe.get(backendNodeId);\n if (typeof enter !== \"number\") return false;\n\n let lo = 0;\n let hi = intervals.length - 1;\n while (lo <= hi) {\n const mid = (lo + hi) >> 1;\n const interval = intervals[mid]!;\n if (enter < interval.start) {\n hi = mid - 1;\n } else if (enter > interval.end) {\n lo = mid + 1;\n } else {\n return true;\n }\n }\n return false;\n };\n}\n\nfunction parseEncodedBackendNodeId(encodedId: string): number | undefined {\n const parts = encodedId.split(\"-\");\n if (parts.length !== 2) return undefined;\n const backendNodeId = Number(parts[1]);\n return Number.isFinite(backendNodeId) ? backendNodeId : undefined;\n}\n\nfunction ownerSessionIndexForFrame(\n page: Page,\n frameId: string,\n sessionToIndex: Map<string, SessionDomIndex>,\n): SessionDomIndex | undefined {\n const session = ownerSession(page, frameId);\n return sessionToIndex.get(session.id ?? \"root\");\n}\n\nasync function resolveFrameDocRootBackendId(\n page: Page,\n frameId: string,\n idx: SessionDomIndex,\n sameSessionAsParent: boolean,\n): Promise<number> {\n if (!sameSessionAsParent) return idx.rootBackend;\n const session = ownerSession(page, frameId);\n try {\n const { backendNodeId } = await session.send<{ backendNodeId?: number }>(\n \"DOM.getFrameOwner\",\n { frameId },\n );\n if (typeof backendNodeId === \"number\") {\n const docRootBe = idx.contentDocRootByIframe.get(backendNodeId);\n if (typeof docRootBe === \"number\") return docRootBe;\n }\n } catch {\n //\n }\n return idx.rootBackend;\n}\n\n/**\n * Step 4 – walk the frame tree (parent-first) to compute absolute prefixes for\n * every frame. The prefix is the absolute XPath of the iframe element hosting\n * the frame, so we can later convert relative XPaths into cross-frame ones.\n */\nexport async function computeFramePrefixes(\n page: Page,\n context: FrameContext,\n perFrameMaps: Map<string, FrameDomMaps>,\n frameIds: string[],\n): Promise<{\n absPrefix: Map<string, string>;\n iframeHostEncByChild: Map<string, string>;\n}> {\n const absPrefix = new Map<string, string>();\n const iframeHostEncByChild = new Map<string, string>();\n absPrefix.set(context.rootId, \"\");\n const included = new Set(frameIds);\n\n const queue: string[] = [];\n if (included.has(context.rootId)) {\n queue.push(context.rootId);\n }\n\n while (queue.length) {\n const parent = queue.shift()!;\n const parentAbs = absPrefix.get(parent)!;\n\n for (const child of context.frames) {\n if (!included.has(child)) continue;\n if (context.parentByFrame.get(child) !== parent) continue;\n queue.push(child);\n\n const parentSess = parentSession(page, context.parentByFrame, child);\n\n const ownerBackendNodeId = await (async () => {\n try {\n const { backendNodeId } = await parentSess.send<{\n backendNodeId?: number;\n }>(\"DOM.getFrameOwner\", { frameId: child });\n return backendNodeId;\n } catch {\n return undefined;\n }\n })();\n\n if (!ownerBackendNodeId) {\n // OOPIFs resolved via a different session inherit the parent prefix.\n absPrefix.set(child, parentAbs);\n continue;\n }\n\n const parentDom = perFrameMaps.get(parent);\n const iframeEnc = `${page.getOrdinal(parent)}-${ownerBackendNodeId}`;\n const iframeXPath = parentDom?.xpathMap[iframeEnc];\n\n const childAbs = iframeXPath\n ? prefixXPath(parentAbs || \"/\", iframeXPath)\n : parentAbs;\n\n absPrefix.set(child, childAbs);\n iframeHostEncByChild.set(child, iframeEnc);\n }\n }\n\n return { absPrefix, iframeHostEncByChild };\n}\n\n/**\n * Step 5 – merge per-frame maps into the combined snapshot payload. We prefix\n * each frame's relative XPaths with the absolute path collected in step 4,\n * merge URL maps, and stitch text outlines by nesting child trees under the\n * encoded id of their parent iframe host.\n */\nexport function mergeFramesIntoSnapshot(\n context: FrameContext,\n perFrameMaps: Map<string, FrameDomMaps>,\n perFrameOutlines: Array<{ frameId: string; outline: string }>,\n absPrefix: Map<string, string>,\n iframeHostEncByChild: Map<string, string>,\n frameIds: string[],\n): HybridSnapshot {\n const combinedXpathMap: Record<string, string> = {};\n const combinedUrlMap: Record<string, string> = {};\n\n for (const frameId of frameIds) {\n const maps = perFrameMaps.get(frameId);\n if (!maps) continue;\n\n const abs = absPrefix.get(frameId) ?? \"\";\n const isRoot = abs === \"\" || abs === \"/\";\n\n if (isRoot) {\n Object.assign(combinedXpathMap, maps.xpathMap);\n Object.assign(combinedUrlMap, maps.urlMap);\n continue;\n }\n\n for (const [encId, xp] of Object.entries(maps.xpathMap)) {\n combinedXpathMap[encId] = prefixXPath(abs, xp);\n }\n Object.assign(combinedUrlMap, maps.urlMap);\n }\n\n const idToTree = new Map<string, string>();\n for (const { frameId, outline } of perFrameOutlines) {\n const parentEnc = iframeHostEncByChild.get(frameId);\n // The key is the parent iframe's encoded id so injectSubtrees can nest lines.\n if (parentEnc) idToTree.set(parentEnc, outline);\n }\n\n const rootOutline =\n perFrameOutlines.find((o) => o.frameId === context.rootId)?.outline ??\n perFrameOutlines[0]?.outline ??\n \"\";\n const combinedTree = (\n injectSubtrees(rootOutline, idToTree) as WellFormedString\n ).toWellFormed();\n\n return {\n combinedTree,\n combinedXpathMap,\n combinedUrlMap,\n perFrame: perFrameOutlines.map(({ frameId, outline }) => {\n const maps = perFrameMaps.get(frameId);\n return {\n frameId,\n outline,\n xpathMap: maps?.xpathMap ?? {},\n urlMap: maps?.urlMap ?? {},\n };\n }),\n };\n}\n"]}
@@ -60,7 +60,7 @@ import { resolveTools } from "./mcp/utils.js";
60
60
  import { HYBRID_CAPABLE_MODEL_PATTERNS } from "./types/private/agent.js";
61
61
  import { AVAILABLE_CUA_MODELS, defaultExtractSchema, V3FunctionName, CuaModelRequiredError, StagehandInvalidArgumentError, StagehandNotInitializedError, MissingEnvironmentVariableError, StagehandInitError, } from "./types/public/index.js";
62
62
  import { V3Context } from "./understudy/context.js";
63
- import { resolveModel } from "../modelUtils.js";
63
+ import { AUTO_MODEL_NAME, isAutoModel, resolveModel } from "../modelUtils.js";
64
64
  import { StagehandAPIClient } from "./api.js";
65
65
  import { validateExperimentalFeatures } from "./agent/utils/validateExperimentalFeatures.js";
66
66
  import { flattenVariables } from "./agent/utils/variables.js";
@@ -69,6 +69,7 @@ import { EventEmitterWithWildcardSupport } from "./flowlogger/EventEmitter.js";
69
69
  import { EventStore } from "./flowlogger/EventStore.js";
70
70
  import { createTimeoutGuard } from "./handlers/handlerUtils/timeoutGuard.js";
71
71
  import { ActTimeoutError } from "./types/public/sdkErrors.js";
72
+ const AUTO_MODEL_API_ONLY_MESSAGE = `model: "${AUTO_MODEL_NAME}" is only supported when running through the Stagehand API (env: "BROWSERBASE" with disableAPI: false and experimental: false). Specify a concrete model (e.g. "openai/gpt-5") instead.`;
72
73
  const DEFAULT_MODEL_NAME = "openai/gpt-4.1-mini";
73
74
  const DEFAULT_VIEWPORT = { width: 1288, height: 711 };
74
75
  const DEFAULT_AGENT_TOOL_TIMEOUT_MS = 45000;
@@ -310,7 +311,18 @@ let V3 = (() => {
310
311
  const baseClientOptions = clientOptions
311
312
  ? { ...clientOptions }
312
313
  : {};
313
- if (opts.llmClient) {
314
+ if (isAutoModel(this.modelName)) {
315
+ if (opts.llmClient ||
316
+ opts.env !== "BROWSERBASE" ||
317
+ this.disableAPI ||
318
+ this.experimental) {
319
+ throw new StagehandInvalidArgumentError(AUTO_MODEL_API_ONLY_MESSAGE);
320
+ }
321
+ // "auto" delegates model selection to the Stagehand API, so no local
322
+ // LLM client is created and no provider API key is required.
323
+ this.modelClientOptions = baseClientOptions;
324
+ }
325
+ else if (opts.llmClient) {
314
326
  this.llmClient = opts.llmClient;
315
327
  this.modelClientOptions = baseClientOptions;
316
328
  this.disableAPI = true;
@@ -486,6 +498,15 @@ let V3 = (() => {
486
498
  clientOptions = rest;
487
499
  perCallMiddleware = middleware;
488
500
  }
501
+ if (isAutoModel(modelName)) {
502
+ if (!this.apiClient) {
503
+ throw new StagehandInvalidArgumentError(AUTO_MODEL_API_ONLY_MESSAGE);
504
+ }
505
+ // The Stagehand API resolves "auto" server-side and intercepts every
506
+ // act/extract/observe, so the local client is never dereferenced here.
507
+ // Note it is undefined when the session's base model is also "auto".
508
+ return this.llmClient;
509
+ }
489
510
  if (modelName === this.modelName &&
490
511
  !perCallMiddleware &&
491
512
  (!clientOptions || Object.keys(clientOptions).length === 0)) {
@@ -842,6 +863,16 @@ let V3 = (() => {
842
863
  browserbaseSessionID: this.opts.browserbaseSessionID,
843
864
  });
844
865
  if (!available) {
866
+ if (isAutoModel(this.modelName)) {
867
+ // "auto" has no local fallback; end the just-created session
868
+ // best-effort before surfacing the error. Never end a
869
+ // caller-supplied (resumed) session we didn't create.
870
+ if (!this.opts.browserbaseSessionID) {
871
+ await this.apiClient.end().catch(() => { });
872
+ }
873
+ this.apiClient = null;
874
+ throw new StagehandInitError(`model: "${AUTO_MODEL_NAME}" requires the Stagehand API, but it is unavailable for this session (sessionId: ${sessionId}). Specify a concrete model (e.g. "openai/gpt-5") instead.`);
875
+ }
845
876
  this.apiClient = null;
846
877
  }
847
878
  this.opts.browserbaseSessionID = sessionId;
@@ -994,7 +1025,10 @@ let V3 = (() => {
994
1025
  let actCacheContext = null;
995
1026
  const canUseCache = typeof input === "string" &&
996
1027
  !this.isAgentReplayRecording() &&
997
- this.actCache.enabled;
1028
+ this.actCache.enabled &&
1029
+ // "auto" sessions have no local LLM client for replay self-heal;
1030
+ // rely on the API (and its server-side cache) instead.
1031
+ !isAutoModel(this.modelName);
998
1032
  if (canUseCache) {
999
1033
  actCacheContext = await this.actCache.prepareContext(input, page, flattenVariables(options?.variables));
1000
1034
  if (actCacheContext) {
@@ -1478,7 +1512,9 @@ let V3 = (() => {
1478
1512
  cua: { value: isCuaMode ? "true" : "false", type: "boolean" },
1479
1513
  mode: { value: loggedMode, type: "string" },
1480
1514
  model: {
1481
- value: extractModelName(options?.model) ?? this.llmClient.modelName,
1515
+ value: extractModelName(options?.model) ??
1516
+ this.llmClient?.modelName ??
1517
+ this.modelName,
1482
1518
  type: "string",
1483
1519
  },
1484
1520
  systemPrompt: { value: options?.systemPrompt ?? "", type: "string" },