@omnivoice/page-agent 0.3.0 → 0.5.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.
- package/LICENSE +22 -0
- package/README.md +87 -15
- package/dist/esm/SimulatorMask-DIoKZt1z.js +379 -0
- package/dist/esm/SimulatorMask-DIoKZt1z.js.map +1 -0
- package/dist/esm/page-agent.d.ts +1076 -0
- package/dist/esm/page-agent.js +4783 -0
- package/dist/esm/page-agent.js.map +1 -0
- package/dist/iife/page-agent.demo.js +433 -0
- package/dist/voice/index.d.ts +533 -0
- package/dist/voice/index.js +1096 -0
- package/dist/voice/index.js.map +1 -0
- package/package.json +68 -28
- package/server/agent-gateway.mjs +215 -0
- package/src/voice/README.md +0 -48
- package/src/voice/bridge.ts +0 -230
- package/src/voice/config.ts +0 -200
- package/src/voice/engines.ts +0 -161
- package/src/voice/index.ts +0 -17
- package/src/voice/session.ts +0 -309
- package/src/voice/types.ts +0 -98
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-agent.js","sources":["../../vendor/page-agent/packages/llms/src/errors.ts","../../vendor/page-agent/packages/llms/src/utils.ts","../../vendor/page-agent/packages/llms/src/OpenAIClient.ts","../../vendor/page-agent/packages/llms/src/index.ts","../../vendor/page-agent/packages/core/src/prompts/system_prompt.md?raw","../../vendor/page-agent/packages/core/src/utils/autoFixer.ts","../../vendor/page-agent/packages/core/src/utils/index.ts","../../vendor/page-agent/packages/core/src/tools/index.ts","../../vendor/page-agent/packages/core/src/PageAgentCore.ts","../../vendor/page-agent/packages/page-controller/src/utils/index.ts","../../vendor/page-agent/packages/page-controller/src/actions.ts","../../vendor/page-agent/packages/page-controller/src/dom/dom_tree/index.js","../../vendor/page-agent/packages/page-controller/src/dom/index.ts","../../vendor/page-agent/packages/page-controller/src/dom/getPageInfo.ts","../../vendor/page-agent/packages/page-controller/src/patches/react.ts","../../vendor/page-agent/packages/page-controller/src/PageController.ts","../../vendor/page-agent/packages/ui/src/i18n/locales.ts","../../vendor/page-agent/packages/ui/src/i18n/index.ts","../../vendor/page-agent/packages/ui/src/utils.ts","../../vendor/page-agent/packages/ui/src/panel/cards.ts","../../vendor/page-agent/packages/ui/src/panel/icons.ts","../../vendor/page-agent/packages/ui/src/panel/Panel.ts","../../vendor/page-agent/packages/page-agent/src/PageAgent.ts","../../vendor/page-agent/packages/page-agent/src/voice.ts","../../vendor/page-agent/packages/page-agent/src/widget.ts"],"sourcesContent":["/**\n * Error types and error handling for LLM invocations.\n */\n\nexport const InvokeErrorTypes = {\n\t// Retryable\n\tNETWORK_ERROR: 'network_error', // Network error, retry\n\tRATE_LIMIT: 'rate_limit', // Rate limit, retry\n\tSERVER_ERROR: 'server_error', // 5xx, retry\n\tNO_TOOL_CALL: 'no_tool_call', // Model did not call tool\n\tINVALID_TOOL_ARGS: 'invalid_tool_args', // Tool args don't match schema\n\tTOOL_EXECUTION_ERROR: 'tool_execution_error', // Tool execution error\n\tINVALID_RESPONSE: 'invalid_response', // Response body is not valid JSON\n\tINVALID_SCHEMA: 'invalid_schema', // Response is valid JSON but doesn't match expected shape\n\n\tUNKNOWN: 'unknown',\n\n\t// Non-retryable\n\tCONFIG_ERROR: 'config_error', // Invalid local configuration or hook\n\tAUTH_ERROR: 'auth_error', // Authentication failed\n\tCONTEXT_LENGTH: 'context_length', // Prompt too long\n\tCONTENT_FILTER: 'content_filter', // Content filtered\n} as const\n\ntype InvokeErrorType = (typeof InvokeErrorTypes)[keyof typeof InvokeErrorTypes]\n\nconst RETRYABLE_TYPES: readonly InvokeErrorType[] = [\n\tInvokeErrorTypes.NETWORK_ERROR,\n\tInvokeErrorTypes.RATE_LIMIT,\n\tInvokeErrorTypes.SERVER_ERROR,\n\tInvokeErrorTypes.NO_TOOL_CALL,\n\tInvokeErrorTypes.INVALID_TOOL_ARGS,\n\tInvokeErrorTypes.TOOL_EXECUTION_ERROR,\n\tInvokeErrorTypes.INVALID_RESPONSE,\n\tInvokeErrorTypes.INVALID_SCHEMA,\n\tInvokeErrorTypes.UNKNOWN,\n]\n\nexport class InvokeError extends Error {\n\ttype: InvokeErrorType\n\tretryable: boolean\n\tstatusCode?: number\n\t/* raw error (provided if this error is caused by another error) */\n\trawError?: unknown\n\t/* raw response from the API (provided if this error is caused by an API calling) */\n\trawResponse?: unknown\n\n\tconstructor(type: InvokeErrorType, message: string, rawError?: unknown, rawResponse?: unknown) {\n\t\tsuper(message)\n\t\tthis.name = 'InvokeError'\n\t\tthis.type = type\n\t\tthis.retryable = RETRYABLE_TYPES.includes(type)\n\t\tthis.rawError = rawError\n\t\tthis.rawResponse = rawResponse\n\t}\n}\n","/**\n * Utility functions for LLM integration\n */\nimport chalk from 'chalk'\nimport * as z from 'zod/v4'\n\nimport type { Tool } from './types'\n\nfunction debug(...args: unknown[]) {\n\tconsole.debug(chalk.gray('[LLM]'), ...args)\n}\n\n/**\n * Convert Zod schema to OpenAI tool format\n * Uses Zod 4 native z.toJSONSchema()\n */\nexport function zodToOpenAITool(name: string, tool: Tool) {\n\treturn {\n\t\ttype: 'function' as const,\n\t\tfunction: {\n\t\t\tname,\n\t\t\tdescription: tool.description,\n\t\t\tparameters: z.toJSONSchema(tool.inputSchema, { target: 'openapi-3.0' }),\n\t\t},\n\t}\n}\n\n/**\n * Patch model specific parameters. Only patches known models.\n *\n * @purpose\n * - Reconcile the differences in the parameter schema each model accepts.\n * - Disable thinking/reasoning, or lower it to the minimum where a full disable is impossible.\n * - Minimize returned tokens.\n * - Raise temperature for known smaller models to improve auto-recovery odds.\n * @note Honor temperature if explicitly set by the user\n *\n * @todo Need vendor-specific patches.\n * Local and 3rd-party hosted models may have different schema.\n */\nexport function modelPatch(body: Record<string, any>, baseURL?: string) {\n\tconst model: string = body.model || ''\n\tif (!model) return body\n\n\tconst provider = getProvider(baseURL)\n\n\tconst modelName = normalizeModelName(model)\n\n\tif (modelName.startsWith('qwen')) {\n\t\tif (provider === 'openrouter' && modelName.startsWith('qwen38-max')) {\n\t\t\t// OpenRouter forces thinking on for this endpoint, and Qwen rejects tool_choice in thinking mode\n\t\t\tdebug('Patch Qwen3.8-max on OpenRouter: reasoning_effort=low, remove tool_choice')\n\t\t\tbody.reasoning_effort = 'low'\n\t\t\tdelete body.tool_choice\n\t\t} else {\n\t\t\tdebug('Patch Qwen: disable thinking')\n\t\t\tbody.enable_thinking = false\n\t\t}\n\t\tif (body.temperature === undefined && !/max|plus/.test(modelName)) {\n\t\t\tdebug('Patch Qwen: raise temperature to 1.0')\n\t\t\tbody.temperature = 1.0\n\t\t}\n\t}\n\n\tif (modelName.startsWith('deepseek')) {\n\t\tdebug('Patch DeepSeek: disable thinking, remove tool_choice')\n\t\tbody.thinking = { type: 'disabled' }\n\t\tdelete body.tool_choice\n\t}\n\n\tif (modelName.startsWith('gpt')) {\n\t\tif (modelName.startsWith('gpt-5')) {\n\t\t\tbody.verbosity = 'low'\n\t\t}\n\n\t\t// Since gpt-5.4, /chat/completions rejects any explicit reasoning_effort\n\t\t// when function tools are present. Newer models are expected to follow.\n\t\t// - gpt-5.1 / gpt-5.2 can fully disable reasoning\n\t\t// - gpt-5 / -mini / -nano bottom out at \"minimal\"\n\t\t// - everything else (gpt-4.x, chat-latest, gpt-5.4+) must not receive it\n\t\tif (modelName.includes('chat-latest')) {\n\t\t\tdebug('Patch chat-latest: omit reasoning_effort and temperature')\n\t\t\tdelete body.reasoning_effort\n\t\t\tdelete body.temperature\n\t\t} else if (/^gpt-5[12](-|$)/.test(modelName)) {\n\t\t\tdebug('Patch GPT-5.1/5.2: reasoning_effort=none')\n\t\t\tbody.reasoning_effort = 'none'\n\t\t} else if (/^gpt-5(-|$)/.test(modelName)) {\n\t\t\tdebug('Patch GPT-5: reasoning_effort=minimal')\n\t\t\tbody.reasoning_effort = 'minimal'\n\t\t} else {\n\t\t\tdebug('Patch GPT: omit reasoning_effort')\n\t\t\tdelete body.reasoning_effort\n\t\t}\n\t}\n\n\tif (modelName.startsWith('claude')) {\n\t\tif (/opus|sonnet|haiku/.test(modelName)) {\n\t\t\tdebug('Patch Claude: disable thinking')\n\t\t\tbody.thinking = { type: 'disabled' }\n\n\t\t\tif (provider !== 'openrouter') {\n\t\t\t\t// Convert tool_choice to Claude format\n\t\t\t\tif (body.tool_choice === 'required') {\n\t\t\t\t\t// 'required' -> { type: 'any' } (must call some tool)\n\t\t\t\t\tdebug('Applying Claude patch: convert tool_choice \"required\" to { type: \"any\" }')\n\t\t\t\t\tbody.tool_choice = { type: 'any' }\n\t\t\t\t} else if (body.tool_choice?.function?.name) {\n\t\t\t\t\t// { type: 'function', function: { name: '...' } } -> { type: 'tool', name: '...' }\n\t\t\t\t\tdebug('Applying Claude patch: convert tool_choice format')\n\t\t\t\t\tbody.tool_choice = { type: 'tool', name: body.tool_choice.function.name }\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tdebug('Patch Claude: reasoning_effort=low')\n\t\t\tbody.reasoning_effort = 'low'\n\n\t\t\t// Fable and mythos can not disable adaptive thinking.\n\t\t\t// Claude does not support tool_choice with extended thinking.\n\t\t\t// These 2 concepts are blurred. Basically no tool_choice with thinking.\n\t\t\tdelete body.tool_choice\n\t\t}\n\t}\n\n\tif (modelName.startsWith('gemini')) {\n\t\tdebug('Patch Gemini: reasoning_effort=low')\n\t\tbody.reasoning_effort = 'low'\n\t\tif (/^gemini-25(?!.*pro)/.test(modelName)) {\n\t\t\tdebug('Patch Gemini 2.5 non-Pro: reasoning_effort=none')\n\t\t\tbody.reasoning_effort = 'none'\n\t\t} else if (\n\t\t\tmodelName.startsWith('gemini-35-flash') ||\n\t\t\tmodelName.startsWith('gemini-31-flash-lite') ||\n\t\t\tmodelName.startsWith('gemini-3-flash')\n\t\t) {\n\t\t\tdebug('Patch Gemini 3.x Flash/Lite: reasoning_effort=minimal')\n\t\t\tbody.reasoning_effort = 'minimal'\n\t\t}\n\t}\n\n\tif (modelName.startsWith('glm')) {\n\t\tif (/^glm-5[3-9]/.test(modelName)) {\n\t\t\t// GLM 5.3+ cannot disable thinking\n\t\t\tdebug('Patch GLM 5.3+: reasoning_effort=low')\n\t\t\tbody.reasoning_effort = 'low'\n\t\t} else {\n\t\t\tdebug('Patch GLM: disable thinking')\n\t\t\tbody.thinking = { type: 'disabled' }\n\t\t}\n\t}\n\n\tif (modelName.startsWith('hy')) {\n\t\tdebug('Patch Hunyuan: disable thinking, reasoning_effort=low')\n\t\tbody.thinking = { type: 'disabled' }\n\t\tbody.reasoning_effort = 'low'\n\t}\n\n\tif (modelName.startsWith('grok')) {\n\t\tif (/^grok-4-?3/.test(modelName)) {\n\t\t\tdebug('Patch Grok 4.3: reasoning_effort=none')\n\t\t\tbody.reasoning_effort = 'none'\n\t\t} else if (modelName.startsWith('grok-3-mini') || modelName.startsWith('grok-code-fast')) {\n\t\t\tdebug('Patch Grok mini/code: reasoning_effort=low')\n\t\t\tbody.reasoning_effort = 'low'\n\t\t}\n\t}\n\n\tif (modelName.startsWith('kimi')) {\n\t\tif (modelName.startsWith('kimi-k3')) {\n\t\t\t// Kimi K3 always thinks and rejects named tool choice while thinking.\n\t\t\tdebug('Patch Kimi K3: use required tool choice, remove parallel tool calls')\n\t\t\tdelete body.parallel_tool_calls\n\t\t\tif (body.tool_choice?.function?.name) body.tool_choice = 'required'\n\t\t} else if (!modelName.includes('code')) {\n\t\t\t// kimi-k2.7-code cannot disable thinking\n\t\t\tdebug('Patch Kimi: disable thinking')\n\t\t\tbody.thinking = { type: 'disabled' }\n\t\t}\n\t}\n\n\tif (modelName.startsWith('minimax')) {\n\t\tdebug('Patch MiniMax: remove parallel_tool_calls')\n\t\tdelete body.parallel_tool_calls\n\n\t\tif (modelName.includes('m3')) {\n\t\t\t// Only M3 can disable thinking\n\t\t\tdebug('Patch MiniMax: disable thinking')\n\t\t\tbody.thinking = { type: 'disabled' }\n\t\t}\n\t}\n\n\t// provider patches\n\n\tif (provider === 'openrouter') {\n\t\t// openrouter use reasoning object instead of reasoning_effort\n\n\t\tconst reasoningEffort = body.reasoning_effort\n\t\tconst reasoningDisabled =\n\t\t\tbody.thinking?.type === 'disabled' ||\n\t\t\tbody.enable_thinking === false ||\n\t\t\treasoningEffort === 'none'\n\n\t\tif (reasoningDisabled) {\n\t\t\tbody.reasoning = { enabled: false }\n\t\t} else if (reasoningEffort) {\n\t\t\tbody.reasoning = { enabled: true, effort: reasoningEffort }\n\t\t}\n\t}\n\n\treturn body\n}\n\n/**\n * check if a given model ID fits a specific model name\n *\n * @note\n * Different model providers may use different model IDs for the same model.\n * For example, openai's `gpt-5.2` may called:\n *\n * - `gpt-5.2-version`\n * - `gpt-5_2-date`\n * - `GPT-52-version-date`\n * - `openai/gpt-5.2-chat`\n *\n * They should be treated as the same model.\n * Normalize them to `gpt-52`\n */\nexport function normalizeModelName(modelName: string): string {\n\tlet normalizedName = modelName.toLowerCase()\n\n\t// remove prefix before '/'\n\tif (normalizedName.includes('/')) {\n\t\tnormalizedName = normalizedName.split('/')[1]\n\t}\n\n\t// remove '_'\n\tnormalizedName = normalizedName.replace(/_/g, '')\n\n\t// remove '.'\n\tnormalizedName = normalizedName.replace(/\\./g, '')\n\n\treturn normalizedName\n}\n\nexport function getProvider(baseURL?: string): 'openrouter' | undefined {\n\tif (!baseURL) return undefined\n\ttry {\n\t\tconst url = new URL(baseURL)\n\t\tconst hostname = url.hostname\n\t\tif (hostname === 'openrouter.ai') return 'openrouter'\n\t\treturn undefined\n\t} catch (e) {\n\t\treturn undefined\n\t}\n}\n","/**\n * OpenAI Client implementation\n */\nimport * as z from 'zod/v4'\n\nimport { InvokeError, InvokeErrorTypes } from './errors'\nimport type {\n\tInvokeOptions,\n\tInvokeResult,\n\tLLMClient,\n\tMessage,\n\tResolvedLLMConfig,\n\tTool,\n} from './types'\nimport { modelPatch, zodToOpenAITool } from './utils'\n\n/**\n * Client for OpenAI compatible APIs\n */\nexport class OpenAIClient implements LLMClient {\n\tconfig: ResolvedLLMConfig\n\tprivate fetch: typeof globalThis.fetch\n\n\tconstructor(config: ResolvedLLMConfig) {\n\t\tthis.config = config\n\t\tthis.fetch = config.customFetch\n\t}\n\n\tasync invoke(\n\t\tmessages: Message[],\n\t\ttools: Record<string, Tool>,\n\t\tabortSignal?: AbortSignal,\n\t\toptions?: InvokeOptions\n\t): Promise<InvokeResult> {\n\t\tabortSignal?.throwIfAborted()\n\n\t\t// 1. Convert tools to OpenAI format\n\t\tconst openaiTools = Object.entries(tools).map(([name, t]) => zodToOpenAITool(name, t))\n\n\t\t// Build request body\n\n\t\tlet toolChoice: unknown = 'required'\n\t\tif (options?.toolChoiceName && !this.config.disableNamedToolChoice) {\n\t\t\ttoolChoice = { type: 'function', function: { name: options.toolChoiceName } }\n\t\t}\n\n\t\tconst requestBody: Record<string, unknown> = {\n\t\t\tmodel: this.config.model,\n\t\t\tmessages,\n\t\t\ttools: openaiTools,\n\t\t\tparallel_tool_calls: false,\n\t\t\ttool_choice: toolChoice,\n\t\t}\n\t\t// Only sent if the caller explicitly set it. Most new models throw if this is set.\n\t\tif (this.config.temperature !== undefined) {\n\t\t\trequestBody.temperature = this.config.temperature\n\t\t}\n\n\t\tmodelPatch(requestBody, this.config.baseURL)\n\n\t\tlet transformedBody: Record<string, unknown> | undefined\n\t\ttry {\n\t\t\ttransformedBody = this.config.transformRequestBody(requestBody)\n\t\t} catch (error) {\n\t\t\tthrow new InvokeError(\n\t\t\t\tInvokeErrorTypes.CONFIG_ERROR,\n\t\t\t\t`transformRequestBody failed: ${(error as Error).message}`,\n\t\t\t\terror\n\t\t\t)\n\t\t}\n\t\tconst finalRequestBody = transformedBody ?? requestBody\n\n\t\t// 2. Call API\n\t\tlet response: Response\n\t\ttry {\n\t\t\tresponse = await this.fetch(`${this.config.baseURL}/chat/completions`, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t\t...(this.config.apiKey && { Authorization: `Bearer ${this.config.apiKey}` }),\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(finalRequestBody),\n\t\t\t\tsignal: abortSignal,\n\t\t\t})\n\t\t} catch (error: unknown) {\n\t\t\tif ((error as any)?.name === 'AbortError') throw error\n\t\t\tconsole.error(error)\n\t\t\tthrow new InvokeError(InvokeErrorTypes.NETWORK_ERROR, 'Network request failed', error)\n\t\t}\n\n\t\t// 3. Handle HTTP errors\n\t\tif (!response.ok) {\n\t\t\tlet errorData: any\n\t\t\ttry {\n\t\t\t\terrorData = await response.json()\n\t\t\t} catch (error) {\n\t\t\t\tif ((error as any)?.name === 'AbortError') throw error\n\t\t\t}\n\t\t\tconst errorMessage = errorData?.error?.message || response.statusText\n\n\t\t\tif (response.status === 401 || response.status === 403) {\n\t\t\t\tthrow new InvokeError(\n\t\t\t\t\tInvokeErrorTypes.AUTH_ERROR,\n\t\t\t\t\t`Authentication failed: ${errorMessage}`,\n\t\t\t\t\terrorData\n\t\t\t\t)\n\t\t\t}\n\t\t\tif (response.status === 429) {\n\t\t\t\tthrow new InvokeError(\n\t\t\t\t\tInvokeErrorTypes.RATE_LIMIT,\n\t\t\t\t\t`Rate limit exceeded: ${errorMessage}`,\n\t\t\t\t\terrorData\n\t\t\t\t)\n\t\t\t}\n\t\t\tif (response.status >= 500) {\n\t\t\t\tthrow new InvokeError(\n\t\t\t\t\tInvokeErrorTypes.SERVER_ERROR,\n\t\t\t\t\t`Server error: ${errorMessage}`,\n\t\t\t\t\terrorData\n\t\t\t\t)\n\t\t\t}\n\t\t\tthrow new InvokeError(\n\t\t\t\tInvokeErrorTypes.UNKNOWN,\n\t\t\t\t`HTTP ${response.status}: ${errorMessage}`,\n\t\t\t\terrorData\n\t\t\t)\n\t\t}\n\n\t\t// 4. Parse and validate response\n\t\tlet data: any\n\t\ttry {\n\t\t\tdata = await response.json()\n\t\t} catch (error) {\n\t\t\tif ((error as any)?.name === 'AbortError') throw error\n\t\t\tthrow new InvokeError(\n\t\t\t\tInvokeErrorTypes.INVALID_RESPONSE,\n\t\t\t\t'Response body is not valid JSON',\n\t\t\t\terror\n\t\t\t)\n\t\t}\n\n\t\tconst choice = data.choices?.[0]\n\t\tif (!choice) {\n\t\t\tthrow new InvokeError(InvokeErrorTypes.INVALID_SCHEMA, 'No choices in response', data)\n\t\t}\n\n\t\t// Check finish_reason\n\t\tswitch (choice.finish_reason) {\n\t\t\tcase 'tool_calls':\n\t\t\tcase 'function_call': // gemini\n\t\t\tcase 'stop': // some models use this even with tool calls\n\t\t\t\tbreak\n\t\t\tcase 'length':\n\t\t\t\tthrow new InvokeError(\n\t\t\t\t\tInvokeErrorTypes.CONTEXT_LENGTH,\n\t\t\t\t\t'Response truncated: max tokens reached',\n\t\t\t\t\tundefined,\n\t\t\t\t\tdata\n\t\t\t\t)\n\t\t\tcase 'content_filter':\n\t\t\t\tthrow new InvokeError(\n\t\t\t\t\tInvokeErrorTypes.CONTENT_FILTER,\n\t\t\t\t\t'Content filtered by safety system',\n\t\t\t\t\tundefined,\n\t\t\t\t\tdata\n\t\t\t\t)\n\t\t\tdefault:\n\t\t\t\tthrow new InvokeError(\n\t\t\t\t\tInvokeErrorTypes.INVALID_SCHEMA,\n\t\t\t\t\t`Unexpected finish_reason: ${choice.finish_reason}`,\n\t\t\t\t\tundefined,\n\t\t\t\t\tdata\n\t\t\t\t)\n\t\t}\n\n\t\t// Apply normalizeResponse if provided (for fixing format issues automatically)\n\t\tconst normalizedData = options?.normalizeResponse ? options.normalizeResponse(data) : data\n\t\tconst normalizedChoice = (normalizedData as any).choices?.[0]\n\n\t\t// Get tool name from response\n\t\tconst toolCallName = normalizedChoice?.message?.tool_calls?.[0]?.function?.name\n\t\tif (!toolCallName) {\n\t\t\tthrow new InvokeError(\n\t\t\t\tInvokeErrorTypes.NO_TOOL_CALL,\n\t\t\t\t'No tool call found in response',\n\t\t\t\tundefined,\n\t\t\t\tdata\n\t\t\t)\n\t\t}\n\n\t\tconst tool = tools[toolCallName]\n\t\tif (!tool) {\n\t\t\tthrow new InvokeError(\n\t\t\t\tInvokeErrorTypes.UNKNOWN,\n\t\t\t\t`Tool \"${toolCallName}\" not found in tools`,\n\t\t\t\tundefined,\n\t\t\t\tdata\n\t\t\t)\n\t\t}\n\n\t\t// Extract and parse tool arguments\n\t\tconst argString = normalizedChoice.message?.tool_calls?.[0]?.function?.arguments\n\t\tif (!argString) {\n\t\t\tthrow new InvokeError(\n\t\t\t\tInvokeErrorTypes.INVALID_TOOL_ARGS,\n\t\t\t\t'No tool call arguments found',\n\t\t\t\tundefined,\n\t\t\t\tdata\n\t\t\t)\n\t\t}\n\n\t\tlet parsedArgs: unknown\n\t\ttry {\n\t\t\tparsedArgs = JSON.parse(argString)\n\t\t} catch (error) {\n\t\t\tthrow new InvokeError(\n\t\t\t\tInvokeErrorTypes.INVALID_TOOL_ARGS,\n\t\t\t\t'Failed to parse tool arguments as JSON',\n\t\t\t\terror,\n\t\t\t\tdata\n\t\t\t)\n\t\t}\n\n\t\t// Validate with schema\n\t\tconst validation = tool.inputSchema.safeParse(parsedArgs)\n\t\tif (!validation.success) {\n\t\t\tconsole.error(z.prettifyError(validation.error))\n\t\t\tthrow new InvokeError(\n\t\t\t\tInvokeErrorTypes.INVALID_TOOL_ARGS,\n\t\t\t\t'Tool arguments validation failed',\n\t\t\t\tvalidation.error,\n\t\t\t\tdata\n\t\t\t)\n\t\t}\n\t\tconst toolInput = validation.data\n\n\t\t// 5. Execute tool\n\t\tlet toolResult: unknown\n\t\ttry {\n\t\t\ttoolResult = await tool.execute(toolInput)\n\t\t} catch (error: unknown) {\n\t\t\tif ((error as any)?.name === 'AbortError') throw error\n\t\t\tthrow new InvokeError(\n\t\t\t\tInvokeErrorTypes.TOOL_EXECUTION_ERROR,\n\t\t\t\t`Tool execution failed: ${(error as Error)?.message}`,\n\t\t\t\terror,\n\t\t\t\tdata\n\t\t\t)\n\t\t}\n\n\t\t// Return result\n\t\treturn {\n\t\t\ttoolCall: {\n\t\t\t\tname: toolCallName,\n\t\t\t\targs: toolInput,\n\t\t\t},\n\t\t\ttoolResult,\n\t\t\tusage: {\n\t\t\t\tpromptTokens: data.usage?.prompt_tokens ?? 0,\n\t\t\t\tcompletionTokens: data.usage?.completion_tokens ?? 0,\n\t\t\t\ttotalTokens: data.usage?.total_tokens ?? 0,\n\t\t\t\tcachedTokens: data.usage?.prompt_tokens_details?.cached_tokens,\n\t\t\t\treasoningTokens: data.usage?.completion_tokens_details?.reasoning_tokens,\n\t\t\t},\n\t\t\trawResponse: data,\n\t\t\trawRequest: finalRequestBody,\n\t\t}\n\t}\n}\n","import { OpenAIClient } from './OpenAIClient'\nimport { InvokeError, InvokeErrorTypes } from './errors'\nimport type {\n\tInvokeOptions,\n\tInvokeResult,\n\tLLMClient,\n\tLLMConfig,\n\tMessage,\n\tResolvedLLMConfig,\n\tTool,\n} from './types'\n\nexport { InvokeError, InvokeErrorTypes }\nexport type { InvokeOptions, InvokeResult, LLMClient, LLMConfig, Message, Tool }\n\n/**\n * LLM module\n */\nexport class LLM extends EventTarget {\n\tconfig: ResolvedLLMConfig\n\tclient: LLMClient\n\n\tconstructor(config: LLMConfig) {\n\t\tsuper()\n\t\tthis.config = parseLLMConfig(config)\n\n\t\t// Default to OpenAI client\n\t\tthis.client = new OpenAIClient(this.config)\n\t}\n\n\t/**\n\t * - call llm api *once*\n\t * - invoke tool call *once*\n\t * - return the result of the tool\n\t */\n\tasync invoke(\n\t\tmessages: Message[],\n\t\ttools: Record<string, Tool>,\n\t\tabortSignal: AbortSignal,\n\t\toptions?: InvokeOptions\n\t): Promise<InvokeResult> {\n\t\treturn await withRetry(async () => this.client.invoke(messages, tools, abortSignal, options), {\n\t\t\tmaxRetries: this.config.maxRetries,\n\t\t\tonRetry: (attempt, lastError) => {\n\t\t\t\tthis.dispatchEvent(\n\t\t\t\t\tnew CustomEvent('retry', {\n\t\t\t\t\t\tdetail: { attempt, maxAttempts: this.config.maxRetries, lastError },\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t},\n\t\t})\n\t}\n}\n\n/**\n * Retry a function until it succeeds or reaches the maximum number of retries.\n */\nasync function withRetry<T>(\n\tfn: () => Promise<T>,\n\tsettings: {\n\t\tmaxRetries: number\n\t\tonRetry: (attempt: number, lastError: Error) => void\n\t}\n): Promise<T> {\n\tlet attempt = 0\n\twhile (true) {\n\t\ttry {\n\t\t\treturn await fn()\n\t\t} catch (error: unknown) {\n\t\t\tif ((error as any)?.name === 'AbortError') throw error\n\t\t\tif (error instanceof InvokeError && !error.retryable) throw error\n\t\t\tattempt++\n\t\t\tif (attempt > settings.maxRetries) throw error\n\n\t\t\tconsole.debug('[LLM] retryable failure, will retry:', error)\n\t\t\tsettings.onRetry(attempt, error as Error)\n\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, 100))\n\t\t}\n\t}\n}\n\nexport function parseLLMConfig(config: LLMConfig): ResolvedLLMConfig {\n\t// Runtime validation as defensive programming (types already guarantee these)\n\tif (!config.baseURL || !config.model) {\n\t\tthrow new Error(\n\t\t\t'[PageAgent] LLM configuration required. Please provide: baseURL, model. ' +\n\t\t\t\t'See: https://alibaba.github.io/page-agent/docs/features/models'\n\t\t)\n\t}\n\n\tif (config.temperature !== undefined) {\n\t\tconsole.warn(\n\t\t\t'[PageAgent] LLMConfig.temperature is deprecated and will be removed in a future version. ' +\n\t\t\t\t'Use transformRequestBody to set it only for models you have verified accept it.'\n\t\t)\n\t}\n\n\treturn {\n\t\tbaseURL: config.baseURL,\n\t\tmodel: config.model,\n\t\tapiKey: config.apiKey || '',\n\t\ttemperature: config.temperature,\n\t\tmaxRetries: config.maxRetries ?? 2,\n\t\ttransformRequestBody: config.transformRequestBody ?? ((requestBody) => requestBody),\n\t\tdisableNamedToolChoice: config.disableNamedToolChoice ?? false,\n\t\tcustomFetch: (config.customFetch ?? fetch).bind(globalThis), // fetch will be illegal unless bound\n\t}\n}\n","export default \"You are an AI agent designed to operate in an iterative loop to automate browser tasks. Your ultimate goal is accomplishing the task provided in <user_request>.\\n\\n<intro>\\nYou excel at following tasks:\\n1. Navigating complex websites and extracting precise information\\n2. Automating form submissions and interactive web actions\\n3. Gathering and saving information \\n4. Operate effectively in an agent loop\\n5. Efficiently performing diverse web tasks\\n</intro>\\n\\n<language_settings>\\n- Default working language: **English**\\n- Use the language that user is using. Return in user's language.\\n</language_settings>\\n\\n<input>\\nAt every step, your input will consist of: \\n1. <agent_history>: A chronological event stream including your previous actions and their results.\\n2. <agent_state>: Current <user_request> and <step_info>.\\n3. <browser_state>: Current URL, interactive elements indexed for actions, and visible page content.\\n</input>\\n\\n<agent_history>\\nAgent history will be given as a list of step information as follows:\\n\\n<step_{step_number}>:\\nEvaluation of Previous Step: Assessment of last action\\nMemory: Your memory of this step\\nNext Goal: Your goal for this step\\nAction Results: Your actions and their results\\n</step_{step_number}>\\n\\nand system messages wrapped in <sys> tag.\\n</agent_history>\\n\\n<user_request>\\nUSER REQUEST: This is your ultimate objective and always remains visible.\\n- This has the highest priority. Make the user happy.\\n- If the user request is very specific - then carefully follow each step and don't skip or hallucinate steps.\\n- If the task is open ended you can plan yourself how to get it done.\\n</user_request>\\n\\n<browser_state>\\n1. Browser State will be given as:\\n\\nCurrent URL: URL of the page you are currently viewing.\\nInteractive Elements: All interactive elements will be provided in format as [index]<type>text</type> where\\n- index: Numeric identifier for interaction\\n- type: HTML element type (button, input, etc.)\\n- text: Element description\\n\\nExamples:\\n[33]<div>User form</div>\\n\\\\t*[35]<button aria-label='Submit form'>Submit</button>\\n\\nNote that:\\n- Only elements with numeric indexes in [] are interactive\\n- (stacked) indentation (with \\\\t) is important and means that the element is a (html) child of the element above (with a lower index)\\n- Elements tagged with `*[` are the new clickable elements that appeared on the website since the last step - if url has not changed.\\n- Pure text elements without [] are not interactive.\\n</browser_state>\\n\\n<browser_rules>\\nStrictly follow these rules while using the browser and navigating the web:\\n- Only interact with elements that have a numeric [index] assigned.\\n- Only use indexes that are explicitly provided.\\n- If the page changes after, for example, an input text action, analyze if you need to interact with new elements, e.g. selecting the right option from the list.\\n- By default, only elements in the visible viewport are listed. Use scrolling actions if you suspect relevant content is offscreen which you need to interact with. Scroll ONLY if there are more pixels below or above the page.\\n- You can scroll by a specific number of pages using the num_pages parameter (e.g., 0.5 for half page, 2.0 for two pages).\\n- All the elements that are scrollable are marked with `data-scrollable` attribute. Including the scrollable distance in every directions. You can scroll *the element* in case some area are overflowed.\\n- If a captcha appears, tell user you can not solve captcha. Finish the task and ask user to solve it.\\n- If the page is not fully loaded, use the `wait` action.\\n- Do not repeat one action for more than 3 times unless some conditions changed.\\n- If you fill an input field and your action sequence is interrupted, most often something changed e.g. suggestions popped up under the field.\\n- If the <user_request> includes specific page information such as product type, rating, price, location, etc., try to apply filters to be more efficient.\\n- The <user_request> is the ultimate goal. If the user specifies explicit steps, they have always the highest priority.\\n- If you input_text into a field, you might need to press enter, click the search button, or select from dropdown for completion.\\n- Don't login into a page if you don't have to. Don't login if you don't have the credentials. \\n- There are 2 types of tasks always first think which type of request you are dealing with:\\n1. Very specific step by step instructions:\\n- Follow them as very precise and don't skip steps. Try to complete everything as requested.\\n2. Open ended tasks. Plan yourself, be creative in achieving them.\\n- If you get stuck e.g. with logins or captcha in open-ended tasks you can re-evaluate the task and try alternative ways, e.g. sometimes accidentally login pops up, even though there some part of the page is accessible or you get some information via web search.\\n</browser_rules>\\n\\n<capability>\\n- You can only handle single page app. Do not jump out of current page.\\n- Do not click on link if it will open in a new page (e.g., <a target=\\\"_blank\\\">)\\n- It is ok to fail the task.\\n\\t- User can be wrong. If the request of user is not achievable, inappropriate or you do not have enough information or tools to achieve it. Tell user to make a better request.\\n\\t- Webpage can be broken. All webpages or apps have bugs. Some bug will make it hard for your job. It's encouraged to tell user the problem of current page. Your feedbacks (including failing) are valuable for user.\\n\\t- Trying too hard can be harmful. Repeating some action back and forth or pushing for a complex procedure with little knowledge can cause unwanted results and harmful side-effects. User would rather you complete the task with a fail.\\n- If you do not have knowledge for the current webpage or task. You must require user to give specific instructions and detailed steps.\\n</capability>\\n\\n<task_completion_rules>\\nYou must call the `done` action in one of three cases:\\n- When you have fully completed the USER REQUEST.\\n- When you reach the final allowed step (`max_steps`), even if the task is incomplete.\\n- When you feel stuck or unable to solve user request. Or user request is not clear or contains inappropriate content.\\n- If it is ABSOLUTELY IMPOSSIBLE to continue.\\n\\nThe `done` action is your opportunity to terminate and share your findings with the user.\\n- Set `success` to `true` only if the full USER REQUEST has been completed with no missing components.\\n- If any part of the request is missing, incomplete, or uncertain, set `success` to `false`.\\n- You can use the `text` field of the `done` action to communicate your findings and to provide a coherent reply to the user and fulfill the USER REQUEST.\\n- You are ONLY ALLOWED to call `done` as a single action. Don't call it together with other actions.\\n- If the user asks for specified format, such as \\\"return JSON with following structure\\\", \\\"return a list of format...\\\", MAKE sure to use the right format in your answer.\\n- If the user asks for a structured output, your `done` action's schema may be modified. Take this schema into account when solving the task!\\n</task_completion_rules>\\n\\n<reasoning_rules>\\nExhibit the following reasoning patterns to successfully achieve the <user_request>:\\n\\n- Reason about <agent_history> to track progress and context toward <user_request>.\\n- Analyze the most recent \\\"Next Goal\\\" and \\\"Action Result\\\" in <agent_history> and clearly state what you previously tried to achieve.\\n- Analyze all relevant items in <agent_history> and <browser_state> to understand your state.\\n- Explicitly judge success/failure/uncertainty of the last action. Never assume an action succeeded just because it appears to be executed in your last step in <agent_history>. If the expected change is missing, mark the last action as failed (or uncertain) and plan a recovery.\\n- Analyze whether you are stuck, e.g. when you repeat the same actions multiple times without any progress. Then consider alternative approaches e.g. scrolling for more context or ask user for help.\\n- Ask user for help if you have any difficulty. Keep user in the loop.\\n- If you see information relevant to <user_request>, plan saving the information to memory.\\n- Always reason about the <user_request>. Make sure to carefully analyze the specific steps and information required. E.g. specific filters, specific form fields, specific information to search. Make sure to always compare the current trajectory with the user request and think carefully if thats how the user requested it.\\n</reasoning_rules>\\n\\n<examples>\\nHere are examples of good output patterns. Use them as reference but never copy them directly.\\n\\n<evaluation_examples>\\n\\\"evaluation_previous_goal\\\": \\\"Successfully navigated to the product page and found the target information. Verdict: Success\\\"\\n\\\"evaluation_previous_goal\\\": \\\"Clicked the login button and user authentication form appeared. Verdict: Success\\\"\\n</evaluation_examples>\\n\\n<memory_examples>\\n\\\"memory\\\": \\\"Found many pending reports that need to be analyzed in the main page. Successfully processed the first 2 reports on quarterly sales data and moving on to inventory analysis and customer feedback reports.\\\"\\n</memory_examples>\\n\\n<next_goal_examples>\\n\\\"next_goal\\\": \\\"Click on the 'Add to Cart' button to proceed with the purchase flow.\\\"\\n</next_goal_examples>\\n</examples>\\n\\n<output>\\n{\\n \\\"evaluation_previous_goal\\\": \\\"Concise one-sentence analysis of your last action. Clearly state success, failure, or uncertain.\\\",\\n \\\"memory\\\": \\\"1-3 concise sentences of specific memory of this step and overall progress. You should put here everything that will help you track progress in future steps. Like counting pages visited, items found, etc.\\\",\\n \\\"next_goal\\\": \\\"State the next immediate goal and action to achieve it, in one clear sentence.\\\",\\n \\\"action\\\":{\\n \\\"Action name\\\": {// Action parameters}\\n }\\n}\\n</output>\\n\"","import { InvokeError, InvokeErrorTypes } from '@page-agent/llms'\nimport chalk from 'chalk'\nimport * as z from 'zod/v4'\n\nimport type { PageAgentTool } from '../tools'\n\nconst log = console.log.bind(console, chalk.yellow('[autoFixer]'))\n\n/**\n * Normalize LLM response and fix common format issues.\n *\n * Handles:\n * - No tool_calls but JSON in message.content (fallback)\n * - Model returns action name as tool call instead of AgentOutput\n * - Arguments wrapped as double JSON string\n * - Nested function call format\n * - Missing action field (fallback to wait)\n * - Primitive action input for single-field tools (e.g. `{\"click_element_by_index\": 2}`)\n * - etc.\n */\nexport function normalizeResponse(response: any, tools?: Map<string, PageAgentTool>): any {\n\tlet resolvedArguments: any\n\n\tconst choice = (response as { choices?: Choice[] }).choices?.[0]\n\tif (!choice) throw new Error('No choices in response')\n\n\tconst message = choice.message\n\tif (!message) throw new Error('No message in choice')\n\n\tconst toolCall = message.tool_calls?.[0]\n\n\t// fix level and location of arguments\n\n\tif (toolCall?.function?.arguments) {\n\t\tresolvedArguments = safeJsonParse(toolCall.function.arguments)\n\n\t\t// case: sometimes the model only returns the action level\n\t\tif (toolCall.function.name && toolCall.function.name !== 'AgentOutput') {\n\t\t\tlog(`#1: fixing tool_call`)\n\t\t\tresolvedArguments = { action: safeJsonParse(resolvedArguments) }\n\t\t}\n\t} else {\n\t\t// case: sometimes the model returns json in content instead of tool_calls\n\t\tif (message.content) {\n\t\t\tconst content = message.content.trim()\n\t\t\tconst jsonInContent = retrieveJsonFromString(content)\n\t\t\tif (jsonInContent) {\n\t\t\t\tresolvedArguments = safeJsonParse(jsonInContent)\n\n\t\t\t\t// case: sometimes the content json includes upper level wrapper\n\t\t\t\tif (resolvedArguments?.name === 'AgentOutput') {\n\t\t\t\t\tlog(`#2: fixing tool_call`)\n\t\t\t\t\tresolvedArguments = safeJsonParse(resolvedArguments.arguments)\n\t\t\t\t}\n\n\t\t\t\t// case: sometimes even 2-levels of wrapping\n\t\t\t\tif (resolvedArguments?.type === 'function') {\n\t\t\t\t\tlog(`#3: fixing tool_call`)\n\t\t\t\t\tresolvedArguments = safeJsonParse(resolvedArguments.function.arguments)\n\t\t\t\t}\n\n\t\t\t\t// case: and sometimes action level only\n\t\t\t\t// todo: needs better detection logic\n\t\t\t\tif (\n\t\t\t\t\t!resolvedArguments?.action &&\n\t\t\t\t\t!resolvedArguments?.evaluation_previous_goal &&\n\t\t\t\t\t!resolvedArguments?.memory &&\n\t\t\t\t\t!resolvedArguments?.next_goal &&\n\t\t\t\t\t!resolvedArguments?.thinking\n\t\t\t\t) {\n\t\t\t\t\tlog(`#4: fixing tool_call`)\n\t\t\t\t\tresolvedArguments = { action: safeJsonParse(resolvedArguments) }\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error('No tool_call and the message content does not contain valid JSON')\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new Error('No tool_call nor message content is present')\n\t\t}\n\t}\n\n\t// fix double stringified arguments\n\tresolvedArguments = safeJsonParse(resolvedArguments)\n\tif (resolvedArguments.action) {\n\t\tresolvedArguments.action = safeJsonParse(resolvedArguments.action)\n\t}\n\n\t// validate and fix action input using tool schemas\n\tif (resolvedArguments.action && tools) {\n\t\tresolvedArguments.action = validateAction(resolvedArguments.action, tools)\n\t}\n\n\t// fix incomplete formats\n\tif (!resolvedArguments.action) {\n\t\tlog(`#5: fixing tool_call`)\n\t\tresolvedArguments.action = { wait: { seconds: 1 } }\n\t}\n\n\t// pack back to standard format\n\treturn {\n\t\t...response,\n\t\tchoices: [\n\t\t\t{\n\t\t\t\t...choice,\n\t\t\t\tmessage: {\n\t\t\t\t\t...message,\n\t\t\t\t\ttool_calls: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...(toolCall || {}),\n\t\t\t\t\t\t\tfunction: {\n\t\t\t\t\t\t\t\t...(toolCall?.function || {}),\n\t\t\t\t\t\t\t\tname: 'AgentOutput',\n\t\t\t\t\t\t\t\targuments: JSON.stringify(resolvedArguments),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t}\n}\n\n/**\n * Validate action against tool schemas. Provides clear error messages\n * instead of letting the union schema produce unreadable errors.\n *\n * Also coerces primitive inputs for single-field tools:\n * e.g. `{\"click_element_by_index\": 2}` → `{\"click_element_by_index\": {\"index\": 2}}`\n */\nfunction validateAction(action: any, tools: Map<string, PageAgentTool>): any {\n\tif (typeof action !== 'object' || action === null) return action\n\n\tconst toolName = Object.keys(action)[0]\n\tif (!toolName) return action\n\n\tconst tool = tools.get(toolName)\n\tif (!tool) {\n\t\tconst available = Array.from(tools.keys()).join(', ')\n\t\tthrow new InvokeError(\n\t\t\tInvokeErrorTypes.INVALID_TOOL_ARGS,\n\t\t\t`Unknown action \"${toolName}\". Available: ${available}`\n\t\t)\n\t}\n\n\tlet value = action[toolName]\n\tconst schema = tool.inputSchema\n\n\t// coerce primitive input for single-field tools\n\tif (schema instanceof z.ZodObject && value !== null && typeof value !== 'object') {\n\t\tconst requiredKey = Object.keys(schema.shape).find(\n\t\t\t(k) => !(schema.shape as Record<string, z.ZodType>)[k].safeParse(undefined).success\n\t\t)\n\t\tif (requiredKey) {\n\t\t\tlog(`coercing primitive action input for \"${toolName}\"`)\n\t\t\tvalue = { [requiredKey]: value }\n\t\t}\n\t}\n\n\tconst result = schema.safeParse(value)\n\tif (!result.success) {\n\t\tthrow new InvokeError(\n\t\t\tInvokeErrorTypes.INVALID_TOOL_ARGS,\n\t\t\t`Invalid input for action \"${toolName}\": ${z.prettifyError(result.error)}`\n\t\t)\n\t}\n\n\treturn { [toolName]: result.data }\n}\n\n/**\n * Safely parse JSON, return original input if not json.\n */\nfunction safeJsonParse(input: any): any {\n\tif (typeof input === 'string') {\n\t\ttry {\n\t\t\treturn JSON.parse(input.trim())\n\t\t} catch {\n\t\t\treturn input\n\t\t}\n\t}\n\treturn input\n}\n\n/**\n * Extract and parse JSON from a string.\n * - Treat content between the first `{` and the last `}` as JSON.\n * - Try to parse that content as JSON and return the parsed value (object/array/primitive) if successful, otherwise return null.\n */\nfunction retrieveJsonFromString(str: string): any {\n\ttry {\n\t\tconst json = /({[\\s\\S]*})/.exec(str) ?? []\n\t\tif (json.length === 0) {\n\t\t\treturn null\n\t\t}\n\t\treturn JSON.parse(json[0]!)\n\t} catch {\n\t\treturn null\n\t}\n}\n\ninterface Choice {\n\tmessage?: {\n\t\trole?: 'assistant'\n\t\tcontent?: string\n\t\ttool_calls?: {\n\t\t\tid?: string\n\t\t\ttype?: 'function'\n\t\t\tfunction?: {\n\t\t\t\tname?: string\n\t\t\t\targuments?: string\n\t\t\t}\n\t\t}[]\n\t}\n\tindex?: 0\n\tfinish_reason?: 'tool_calls'\n}\n","import chalk from 'chalk'\n\nexport * from './autoFixer'\n\n/**\n * Wait for `seconds`. If a `signal` is provided, the wait is cancellable:\n * aborting rejects with the signal's reason (an `AbortError`).\n */\nexport async function waitFor(seconds: number, signal?: AbortSignal): Promise<void> {\n\tif (!signal) {\n\t\tawait new Promise((resolve) => setTimeout(resolve, seconds * 1000))\n\t\treturn\n\t}\n\tsignal.throwIfAborted()\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst timer = setTimeout(() => {\n\t\t\tsignal.removeEventListener('abort', onAbort)\n\t\t\tresolve()\n\t\t}, seconds * 1000)\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timer)\n\t\t\t// reason is a DOMException AbortError.\n\t\t\treject(signal.reason as DOMException)\n\t\t}\n\t\tsignal.addEventListener('abort', onAbort, { once: true })\n\t})\n}\n\n//\n\nexport function truncate(text: string, maxLength: number): string {\n\tif (text.length > maxLength) {\n\t\treturn text.substring(0, maxLength) + '...'\n\t}\n\treturn text\n}\n\n//\n\nexport function randomID(existingIDs?: string[]): string {\n\tlet id = Math.random().toString(36).substring(2, 11)\n\n\tif (!existingIDs) {\n\t\treturn id\n\t}\n\n\tconst MAX_TRY = 1000\n\tlet tryCount = 0\n\n\twhile (existingIDs.includes(id)) {\n\t\tid = Math.random().toString(36).substring(2, 11)\n\t\ttryCount++\n\t\tif (tryCount > MAX_TRY) {\n\t\t\tthrow new Error('randomID: too many tries')\n\t\t}\n\t}\n\n\treturn id\n}\n\n//\nconst _global = globalThis as any\n\nif (!_global.__PAGE_AGENT_IDS__) {\n\t_global.__PAGE_AGENT_IDS__ = []\n}\n\nconst ids = _global.__PAGE_AGENT_IDS__\n\n/**\n * Generate a random ID.\n * @note Unique within this window.\n */\nexport function uid() {\n\tconst id = randomID(ids)\n\tids.push(id)\n\treturn id\n}\n\nconst llmsTxtCache = new Map<string, string | null>()\n\n/** Fetch /llms.txt for a URL's origin. Cached per origin, `null` = tried and not found. */\nexport async function fetchLlmsTxt(url: string): Promise<string | null> {\n\tlet origin: string\n\ttry {\n\t\torigin = new URL(url).origin\n\t} catch {\n\t\treturn null // Invalid URL\n\t}\n\t// about:blank, data:, file:\n\tif (origin === 'null') return null\n\n\tif (llmsTxtCache.has(origin)) return llmsTxtCache.get(origin)!\n\n\tconst endpoint = `${origin}/llms.txt`\n\tlet result: string | null = null\n\ttry {\n\t\tconsole.log(chalk.gray(`[llms.txt] Fetching ${endpoint}`))\n\t\tconst res = await fetch(endpoint, { signal: AbortSignal.timeout(3000) })\n\t\tif (res.ok) {\n\t\t\tresult = await res.text()\n\t\t\tconsole.log(chalk.green(`[llms.txt] Found (${result.length} chars)`))\n\t\t\tif (result.length > 1000) {\n\t\t\t\tconsole.log(chalk.yellow(`[llms.txt] Truncating to 1000 chars`))\n\t\t\t\tresult = truncate(result, 1000)\n\t\t\t}\n\t\t} else {\n\t\t\tconsole.debug(chalk.gray(`[llms.txt] ${res.status} for ${endpoint}`))\n\t\t}\n\t} catch (e) {\n\t\tconsole.debug(chalk.gray(`[llms.txt] not found for ${endpoint}`), e)\n\t}\n\tllmsTxtCache.set(origin, result)\n\treturn result\n}\n\n/**\n * Simple assertion function that throws an error if the condition is falsy\n * @param condition - The condition to assert\n * @param message - Optional error message\n * @throws Error if condition is falsy\n */\nexport function assert(condition: unknown, message?: string, silent?: boolean): asserts condition {\n\tif (!condition) {\n\t\tconst errorMessage = message ?? 'Assertion failed'\n\n\t\tif (!silent) console.error(chalk.red(`❌ assert: ${errorMessage}`))\n\n\t\tthrow new Error(errorMessage)\n\t}\n}\n\n/**\n * Suppress errors from a function.\n */\nexport async function suppress<T>(fn: () => T | Promise<T>): Promise<Awaited<T> | undefined> {\n\ttry {\n\t\treturn await fn()\n\t} catch (error) {\n\t\tconsole.error(error)\n\t\treturn undefined\n\t}\n}\n","/**\n * Internal tools for PageAgent.\n * @note Adapted from browser-use\n */\nimport * as z from 'zod/v4'\n\nimport type { PageAgentCore } from '../PageAgentCore'\nimport { waitFor } from '../utils'\n\n/**\n * Per-invocation context passed to every tool execution.\n * Tools MUST honor `signal` to support cooperative cancellation.\n */\nexport interface ToolContext {\n\tsignal: AbortSignal\n}\n\n/**\n * Internal tool definition that has access to PageAgent `this` context\n */\nexport interface PageAgentTool<TParams = any> {\n\t// name: string\n\tdescription: string\n\tinputSchema: z.ZodType<TParams>\n\texecute: (this: PageAgentCore, args: TParams, ctx: ToolContext) => Promise<string>\n}\n\nexport function tool<TParams>(options: PageAgentTool<TParams>): PageAgentTool<TParams> {\n\treturn options\n}\n\n/**\n * Internal tools for PageAgent.\n * Note: Using any to allow different parameter types for each tool\n */\nexport const tools = new Map<string, PageAgentTool>()\n\ntools.set(\n\t'done',\n\ttool({\n\t\tdescription:\n\t\t\t'Complete task. Text is your final response to the user — keep it concise unless the user explicitly asks for detail.',\n\t\tinputSchema: z.object({\n\t\t\ttext: z.string(),\n\t\t\tsuccess: z.boolean().default(true),\n\t\t}),\n\t\texecute: async function (this: PageAgentCore, input) {\n\t\t\t// @note main loop will handle this one\n\t\t\treturn Promise.resolve('Task completed')\n\t\t},\n\t})\n)\n\ntools.set(\n\t'wait',\n\ttool({\n\t\tdescription: 'Wait for x seconds. Can be used to wait until the page or data is fully loaded.',\n\t\tinputSchema: z.object({\n\t\t\tseconds: z.number().min(1).max(10).default(1),\n\t\t}),\n\t\texecute: async function (this: PageAgentCore, input, { signal }) {\n\t\t\t// try to subtract LLM calling time from the actual wait time\n\t\t\tconst lastTimeUpdate = await this.pageController.getLastUpdateTime()\n\t\t\tconst secondsSinceLastUpdate = (Date.now() - lastTimeUpdate) / 1000\n\t\t\tconst actualWaitTime = Math.max(0, input.seconds - secondsSinceLastUpdate)\n\t\t\tconsole.log(`actualWaitTime: ${actualWaitTime} seconds`)\n\t\t\tawait waitFor(actualWaitTime, signal)\n\n\t\t\tconst waitedSeconds = (secondsSinceLastUpdate + actualWaitTime).toFixed(2)\n\t\t\treturn `✅ Waited for ${waitedSeconds} seconds.`\n\t\t},\n\t})\n)\n\ntools.set(\n\t'ask_user',\n\ttool({\n\t\tdescription:\n\t\t\t'Ask the user a question and wait for their answer. Use this if you need more information or clarification.',\n\t\tinputSchema: z.object({\n\t\t\tquestion: z.string(),\n\t\t}),\n\t\texecute: async function (this: PageAgentCore, input, { signal }) {\n\t\t\tif (!this.onAskUser) {\n\t\t\t\tthrow new Error('ask_user tool requires onAskUser callback to be set')\n\t\t\t}\n\t\t\tconst answer = await this.onAskUser(input.question, { signal })\n\t\t\treturn `User answered: ${answer}`\n\t\t},\n\t})\n)\n\ntools.set(\n\t'click_element_by_index',\n\ttool({\n\t\tdescription: 'Click element by index',\n\t\tinputSchema: z.object({\n\t\t\tindex: z.int().min(0),\n\t\t}),\n\t\texecute: async function (this: PageAgentCore, input) {\n\t\t\tconst result = await this.pageController.clickElement(input.index)\n\t\t\treturn result.message\n\t\t},\n\t})\n)\n\ntools.set(\n\t'input_text',\n\ttool({\n\t\tdescription: 'Click and type text into an interactive input element',\n\t\tinputSchema: z.object({\n\t\t\tindex: z.int().min(0),\n\t\t\ttext: z.string(),\n\t\t}),\n\t\texecute: async function (this: PageAgentCore, input) {\n\t\t\tconst result = await this.pageController.inputText(input.index, input.text)\n\t\t\treturn result.message\n\t\t},\n\t})\n)\n\ntools.set(\n\t'select_dropdown_option',\n\ttool({\n\t\tdescription:\n\t\t\t'Select dropdown option for interactive element index by the text of the option you want to select',\n\t\tinputSchema: z.object({\n\t\t\tindex: z.int().min(0),\n\t\t\ttext: z.string(),\n\t\t}),\n\t\texecute: async function (this: PageAgentCore, input) {\n\t\t\tconst result = await this.pageController.selectOption(input.index, input.text)\n\t\t\treturn result.message\n\t\t},\n\t})\n)\n\n/**\n * @note Reference from browser-use\n */\ntools.set(\n\t'scroll',\n\ttool({\n\t\tdescription:\n\t\t\t'Scroll vertically. Without index: scrolls the document. With index: scrolls the container at that index (or its nearest scrollable ancestor). Use index of a data-scrollable element to scroll a specific area.',\n\t\tinputSchema: z.object({\n\t\t\tdown: z.boolean().default(true),\n\t\t\tnum_pages: z.number().min(0).max(10).optional().default(0.1),\n\t\t\tpixels: z.number().int().min(0).optional(),\n\t\t\tindex: z.number().int().min(0).optional(),\n\t\t}),\n\t\texecute: async function (this: PageAgentCore, input) {\n\t\t\tconst result = await this.pageController.scroll({\n\t\t\t\t...input,\n\t\t\t\tnumPages: input.num_pages,\n\t\t\t})\n\t\t\treturn result.message\n\t\t},\n\t})\n)\n\n/**\n * @todo Tables need a dedicated parser to extract structured data. This tool is useless.\n */\ntools.set(\n\t'scroll_horizontally',\n\ttool({\n\t\tdescription:\n\t\t\t'Scroll horizontally. Without index: scrolls the document. With index: scrolls the container at that index (or its nearest scrollable ancestor). Use index of a data-scrollable element to scroll a specific area.',\n\t\tinputSchema: z.object({\n\t\t\tright: z.boolean().default(true),\n\t\t\tpixels: z.number().int().min(0),\n\t\t\tindex: z.number().int().min(0).optional(),\n\t\t}),\n\t\texecute: async function (this: PageAgentCore, input) {\n\t\t\tconst result = await this.pageController.scrollHorizontally(input)\n\t\t\treturn result.message\n\t\t},\n\t})\n)\n\ntools.set(\n\t'execute_javascript',\n\ttool({\n\t\tdescription:\n\t\t\t'Execute JavaScript code on the current page. Supports async/await syntax. Use with caution! ' +\n\t\t\t'An `AbortSignal` named `signal` is available in scope: long-running async code MUST honor it ' +\n\t\t\t'(e.g. `await fetch(url, { signal })`, or `signal.throwIfAborted()` in loops)',\n\t\tinputSchema: z.object({\n\t\t\tscript: z.string(),\n\t\t}),\n\t\texecute: async function (this: PageAgentCore, input, { signal }) {\n\t\t\tconst result = await this.pageController.executeJavascript(input.script, signal)\n\t\t\tsignal.throwIfAborted()\n\t\t\treturn result.message\n\t\t},\n\t})\n)\n\n// @todo send_keys\n// @todo upload_file\n// @todo extract_structured_data\n","/**\n * Copyright (C) 2025 Alibaba Group Holding Limited\n * Copyright (C) 2026 SimonLuvRamen\n * All rights reserved.\n */\nimport { InvokeError, LLM, type Tool } from '@page-agent/llms'\nimport type { BrowserState, PageController } from '@page-agent/page-controller'\nimport chalk from 'chalk'\nimport * as z from 'zod/v4'\n\nimport SYSTEM_PROMPT from './prompts/system_prompt.md?raw'\nimport { tools } from './tools'\nimport type {\n\tAgentActivity,\n\tAgentConfig,\n\tAgentReflection,\n\tAgentStatus,\n\tAgentStepEvent,\n\tExecutionResult,\n\tHistoricalEvent,\n\tMacroToolInput,\n\tMacroToolResult,\n} from './types'\nimport { assert, fetchLlmsTxt, normalizeResponse, suppress, uid, waitFor } from './utils'\n\nexport { tool, type PageAgentTool, type ToolContext } from './tools'\nexport type * from './types'\n\nexport type PageAgentCoreConfig = AgentConfig & { pageController: PageController }\n\n/**\n * AI agent for browser automation.\n *\n * @remarks\n * ## Re-act Agent Loop\n * - step\n * - observe (gather information about current environment and context)\n * - think (LLM calling)\n * - reflection (evaluate history, generate memory, short-term planning)\n * - action (give the action to approach the next goal)\n * - act (execute the action)\n * - loop\n *\n * ## Event System\n * - `statuschange` - Agent status transitions (idle → running → completed/error/stopped)\n * - `historychange` - History events updated (persistent, part of agent memory)\n * - `activity` - Real-time activity feedback (transient, for UI only)\n * - `dispose` - Agent cleanup triggered\n *\n * ## Information Streams\n * 1. **History Events** (`history` array)\n * - Persistent event stream that forms agent's memory\n * - Included in LLM context across steps\n * - Types: steps, observations, user takeovers, llm errors\n *\n * 2. **Activity Events** (via `activity` event)\n * - Transient UI feedback during task execution\n * - NOT included in LLM context\n * - Types: thinking, executing, executed, retrying, error\n */\nexport class PageAgentCore extends EventTarget {\n\treadonly id = uid()\n\treadonly config: PageAgentCoreConfig & { maxSteps: number }\n\treadonly tools: typeof tools\n\t/** PageController for DOM operations */\n\treadonly pageController: PageController\n\n\ttask = ''\n\ttaskId = ''\n\t/** History events */\n\thistory: HistoricalEvent[] = []\n\t/** Whether this agent has been disposed */\n\tdisposed = false\n\n\t/**\n\t * Called when the agent needs to ask the user questions.\n\t * If unset, the `ask_user` tool will be disabled.\n\t * Implementations should reject the promise when `signal` aborts.\n\t * @example onAskUser: (q) => window.prompt(q) || ''\n\t */\n\tonAskUser?: (question: string, options?: { signal: AbortSignal }) => Promise<string>\n\n\t#status: AgentStatus = 'idle'\n\t#llm: LLM\n\t/**\n\t * Task cancellation primitive: its signal reaches the LLM fetch, tools\n\t * (via `ctx.signal`) and async callbacks. Aborted only by `stop`/`dispose`\n\t * (during a task) or task setup, always WITHOUT a reason so `signal.reason`\n\t * stays a standard `AbortError`.\n\t */\n\t#abortController = new AbortController()\n\t#observations: string[] = []\n\n\t/** Resolves when the current run has fully settled. Awaited by `stop()`. */\n\t#running: Promise<void> = Promise.resolve()\n\t#lastResult: ExecutionResult | null = null\n\n\t/** internal states during a single task execution */\n\t#states = {\n\t\t/** Accumulated wait time in seconds */\n\t\ttotalWaitTime: 0,\n\t\t/** For detecting navigation */\n\t\tlastURL: '',\n\t\t/** Browser state */\n\t\tbrowserState: null as BrowserState | null,\n\t}\n\n\tconstructor(config: PageAgentCoreConfig) {\n\t\tsuper()\n\n\t\tthis.config = { ...config, maxSteps: config.maxSteps ?? 40 }\n\n\t\tthis.#llm = new LLM(this.config)\n\t\tthis.tools = new Map(tools)\n\t\tthis.pageController = config.pageController\n\n\t\tthis.#llm.addEventListener('retry', (e) => {\n\t\t\tconst { attempt, maxAttempts, lastError } = (e as CustomEvent).detail\n\t\t\tthis.#emitActivity({ type: 'retrying', attempt, maxAttempts })\n\t\t\tthis.history.push({\n\t\t\t\ttype: 'error',\n\t\t\t\tmessage: String(lastError),\n\t\t\t\trawResponse: (lastError as InvokeError).rawResponse,\n\t\t\t})\n\t\t\tthis.history.push({\n\t\t\t\ttype: 'retry',\n\t\t\t\tmessage: `LLM retry attempt ${attempt} of ${maxAttempts}`,\n\t\t\t\tattempt,\n\t\t\t\tmaxAttempts,\n\t\t\t})\n\t\t\tthis.#emitHistoryChange()\n\t\t})\n\n\t\tif (this.config.customTools) {\n\t\t\tfor (const [name, tool] of Object.entries(this.config.customTools)) {\n\t\t\t\tif (tool === null) {\n\t\t\t\t\tthis.tools.delete(name)\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tthis.tools.set(name, tool)\n\t\t\t}\n\t\t}\n\n\t\tif (!this.config.experimentalScriptExecutionTool) {\n\t\t\tthis.tools.delete('execute_javascript')\n\t\t}\n\t}\n\n\t/** Get current agent status */\n\tget status(): AgentStatus {\n\t\treturn this.#status\n\t}\n\n\t/** Result of the most recent run, or `null` before the first run completes. */\n\tget lastResult(): ExecutionResult | null {\n\t\treturn this.#lastResult\n\t}\n\n\t/** Emit statuschange event */\n\t#emitStatusChange(): void {\n\t\tthis.dispatchEvent(new Event('statuschange'))\n\t}\n\n\t/** Emit historychange event */\n\t#emitHistoryChange(pushHistoricalEvent?: HistoricalEvent): void {\n\t\tif (pushHistoricalEvent) this.history.push(pushHistoricalEvent)\n\t\tthis.dispatchEvent(new Event('historychange'))\n\t}\n\n\t/**\n\t * Emit activity event - for transient UI feedback\n\t * @param activity - Current agent activity\n\t */\n\t#emitActivity(activity: AgentActivity): void {\n\t\tthis.dispatchEvent(new CustomEvent('activity', { detail: activity }))\n\t}\n\n\t/** Update status and emit event */\n\t#setStatus(status: AgentStatus): void {\n\t\tif (this.#status !== status) {\n\t\t\tthis.#status = status\n\t\t\tthis.#emitStatusChange()\n\t\t}\n\t}\n\n\t/**\n\t * Push an observation message to the history event stream.\n\t * This will be visible in <agent_history> and remain persistent in memory across steps.\n\t * @experimental @internal\n\t * @note history change will be emitted before next step starts\n\t */\n\tpushObservation(content: string): void {\n\t\tthis.#observations.push(content)\n\t}\n\n\t/**\n\t * Stop the current task and wait until the run has fully settled (including lifecycle hooks).\n\t * @note never await .stop() in a lifecycle hook.\n\t */\n\tasync stop(): Promise<void> {\n\t\tif (this.#status !== 'running') return\n\t\tthis.#abortController.abort()\n\t\tawait this.#running\n\t}\n\n\t/**\n\t * external errors (pre-checks/config/hooks) will threw;\n\t * agent errors will be caught and added to history, and return a failed result\n\t */\n\tasync execute(task: string): Promise<ExecutionResult> {\n\t\t// pre-checks\n\t\tif (this.disposed) throw new Error('PageAgent has been disposed. Create a new instance.')\n\t\tif (this.#status === 'running') throw new Error('A task is already running.')\n\t\tif (!task) throw new Error('Task is required')\n\n\t\tthis.task = task\n\t\tthis.taskId = uid()\n\n\t\tthis.history = []\n\t\tthis.#observations = []\n\t\tthis.#states = { totalWaitTime: 0, lastURL: '', browserState: null }\n\t\tthis.#abortController = new AbortController()\n\t\tconst signal = this.#abortController.signal\n\n\t\tlet resolveRunning!: () => void\n\t\tthis.#running = new Promise<void>((r) => (resolveRunning = r))\n\n\t\tthis.#setStatus('running')\n\t\tthis.#emitHistoryChange()\n\n\t\t// Disable ask_user tool if onAskUser is not set\n\t\tif (!this.onAskUser) this.tools.delete('ask_user')\n\n\t\tconst onBeforeStep = this.config.onBeforeStep\n\t\tconst onAfterStep = this.config.onAfterStep\n\t\tconst onBeforeTask = this.config.onBeforeTask\n\t\tconst onAfterTask = this.config.onAfterTask\n\t\tconst stepDelay = this.config.stepDelay ?? 0.4\n\t\tconst maxSteps = this.config.maxSteps\n\n\t\tlet step = 0\n\t\tlet taskResult: ExecutionResult\n\t\tlet finalStatus: AgentStatus = 'error'\n\n\t\tawait suppress(() => this.pageController.showMask())\n\n\t\t// graceful exit\n\t\ttry {\n\t\t\tawait onBeforeTask?.(this)\n\n\t\t\twhile (true) {\n\t\t\t\tawait onBeforeStep?.(this, step)\n\n\t\t\t\t// handle internal agent errors\n\t\t\t\ttry {\n\t\t\t\t\tconsole.group(`step: ${step}`)\n\n\t\t\t\t\t// @note It's convenient to treat stepDelay as part of the next step.\n\t\t\t\t\t// Maybe move it to a dedicated try block for better semantics?\n\t\t\t\t\tif (step > 0) await waitFor(stepDelay, signal)\n\n\t\t\t\t\tsignal.throwIfAborted()\n\n\t\t\t\t\t// observe\n\n\t\t\t\t\tconsole.log(chalk.blue.bold('👀 Observing...'))\n\n\t\t\t\t\tthis.#states.browserState = await this.pageController.getBrowserState()\n\t\t\t\t\tawait this.#handleObservations(step)\n\n\t\t\t\t\t// assemble prompts\n\n\t\t\t\t\tconst messages = [\n\t\t\t\t\t\t{ role: 'system' as const, content: this.#getSystemPrompt() },\n\t\t\t\t\t\t{ role: 'user' as const, content: await this.#assembleUserPrompt() },\n\t\t\t\t\t]\n\n\t\t\t\t\tconst macroTool = { AgentOutput: this.#packMacroTool() }\n\n\t\t\t\t\t// invoke LLM\n\n\t\t\t\t\tconsole.log(chalk.blue.bold('🧠 Thinking...'))\n\t\t\t\t\tthis.#emitActivity({ type: 'thinking' })\n\n\t\t\t\t\tconst result = await this.#llm.invoke(messages, macroTool, signal, {\n\t\t\t\t\t\ttoolChoiceName: 'AgentOutput',\n\t\t\t\t\t\tnormalizeResponse: (res) => normalizeResponse(res, this.tools),\n\t\t\t\t\t})\n\n\t\t\t\t\t// assemble history\n\n\t\t\t\t\tconst macroResult = result.toolResult as MacroToolResult\n\t\t\t\t\tconst input = macroResult.input\n\t\t\t\t\tconst output = macroResult.output\n\t\t\t\t\tconst reflection: Partial<AgentReflection> = {\n\t\t\t\t\t\tevaluation_previous_goal: input.evaluation_previous_goal,\n\t\t\t\t\t\tmemory: input.memory,\n\t\t\t\t\t\tnext_goal: input.next_goal,\n\t\t\t\t\t}\n\t\t\t\t\tconst actionName = Object.keys(input.action)[0]\n\t\t\t\t\tconst action: AgentStepEvent['action'] = {\n\t\t\t\t\t\tname: actionName,\n\t\t\t\t\t\tinput: input.action[actionName],\n\t\t\t\t\t\toutput: output,\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.#emitHistoryChange({\n\t\t\t\t\t\ttype: 'step',\n\t\t\t\t\t\tstepIndex: step,\n\t\t\t\t\t\treflection,\n\t\t\t\t\t\taction,\n\t\t\t\t\t\tusage: result.usage,\n\t\t\t\t\t\trawResponse: result.rawResponse,\n\t\t\t\t\t\trawRequest: result.rawRequest,\n\t\t\t\t\t})\n\n\t\t\t\t\tif (actionName === 'done') {\n\t\t\t\t\t\tconst success = action.input?.success ?? false\n\t\t\t\t\t\tconst data = action.input?.text || 'no text provided'\n\t\t\t\t\t\tconsole.log(chalk.green.bold('Task completed'), success, data)\n\t\t\t\t\t\ttaskResult = { success, data, history: this.history }\n\t\t\t\t\t\tthis.#lastResult = taskResult\n\t\t\t\t\t\tfinalStatus = 'completed'\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\t// catch block must not throw error. otherwise the error may be overridden if finally block also throws error.\n\n\t\t\t\t\tconst isAbortError = (error as any)?.name === 'AbortError'\n\t\t\t\t\tif (!isAbortError) console.error('Task failed', error)\n\t\t\t\t\t// FORK: texto que o painel mostra ao encerrar.\n\t\t\t\t\tconst message = isAbortError ? 'Tarefa interrompida' : String(error)\n\t\t\t\t\tthis.#emitActivity({ type: 'error', message: message })\n\t\t\t\t\tthis.#emitHistoryChange({ type: 'error', message: message, rawResponse: error })\n\t\t\t\t\ttaskResult = { success: false, data: message, history: this.history }\n\t\t\t\t\tthis.#lastResult = taskResult\n\t\t\t\t\tfinalStatus = isAbortError ? 'stopped' : 'error'\n\t\t\t\t\tbreak\n\t\t\t\t} finally {\n\t\t\t\t\t// finally block runs before the break above.\n\n\t\t\t\t\tconsole.groupEnd()\n\t\t\t\t\t// @note hook may throw error.\n\t\t\t\t\t// which will override the `break` above and be handled as an external error.\n\t\t\t\t\t// as expected.\n\t\t\t\t\tawait onAfterStep?.(this, this.history)\n\t\t\t\t}\n\n\t\t\t\tstep++\n\t\t\t\tif (step > maxSteps) {\n\t\t\t\t\tconst message = 'Step count exceeded maximum limit'\n\t\t\t\t\tconsole.error(message)\n\t\t\t\t\tthis.#emitActivity({ type: 'error', message: message })\n\t\t\t\t\tthis.#emitHistoryChange({ type: 'error', message: message })\n\t\t\t\t\ttaskResult = { success: false, data: message, history: this.history }\n\t\t\t\t\tthis.#lastResult = taskResult\n\t\t\t\t\tfinalStatus = 'error'\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t} // while\n\n\t\t\tawait onAfterTask?.(this, taskResult)\n\n\t\t\treturn taskResult\n\t\t} catch (error) {\n\t\t\tthis.#emitActivity({ type: 'error', message: String(error) })\n\t\t\tfinalStatus = 'error'\n\t\t\tthrow error\n\t\t} finally {\n\t\t\tawait suppress(() => this.pageController.cleanUpHighlights())\n\t\t\tawait suppress(() => this.pageController.hideMask())\n\t\t\tthis.#abortController.abort()\n\t\t\tresolveRunning()\n\t\t\tthis.#setStatus(finalStatus)\n\t\t}\n\t}\n\n\t/**\n\t * Merge all tools into a single MacroTool with the following input:\n\t * - thinking: string\n\t * - evaluation_previous_goal: string\n\t * - memory: string\n\t * - next_goal: string\n\t * - action: { toolName: toolInput }\n\t * where action must be selected from tools defined in this.tools\n\t */\n\t#packMacroTool(): Tool<MacroToolInput, MacroToolResult> {\n\t\tconst tools = this.tools\n\n\t\tconst actionSchemas = Array.from(tools.entries()).map(([toolName, tool]) => {\n\t\t\treturn z.object({ [toolName]: tool.inputSchema }).describe(tool.description)\n\t\t})\n\n\t\tconst actionSchema = z.union(actionSchemas as unknown as [z.ZodType, z.ZodType, ...z.ZodType[]])\n\n\t\tconst macroToolSchema = z.object({\n\t\t\t// thinking: z.string().optional(),\n\t\t\tevaluation_previous_goal: z.string().optional(),\n\t\t\tmemory: z.string().optional(),\n\t\t\tnext_goal: z.string().optional(),\n\t\t\taction: actionSchema,\n\t\t})\n\n\t\treturn {\n\t\t\tdescription: 'You MUST call this tool every step!',\n\t\t\tinputSchema: macroToolSchema as z.ZodType<MacroToolInput>,\n\t\t\texecute: async (input: MacroToolInput): Promise<MacroToolResult> => {\n\t\t\t\tconst signal = this.#abortController.signal\n\t\t\t\tsignal.throwIfAborted()\n\n\t\t\t\tconsole.log(chalk.blue.bold('MacroTool input'), input)\n\t\t\t\tconst action = input.action\n\n\t\t\t\tconst toolName = Object.keys(action)[0]\n\t\t\t\tconst toolInput = action[toolName]\n\n\t\t\t\t// Build reflection text, only include non-empty fields\n\t\t\t\tconst reflectionLines: string[] = []\n\t\t\t\tif (input.evaluation_previous_goal)\n\t\t\t\t\treflectionLines.push(`✅: ${input.evaluation_previous_goal}`)\n\t\t\t\tif (input.memory) reflectionLines.push(`💾: ${input.memory}`)\n\t\t\t\tif (input.next_goal) reflectionLines.push(`🎯: ${input.next_goal}`)\n\n\t\t\t\tconst reflectionText = reflectionLines.length > 0 ? reflectionLines.join('\\n') : ''\n\n\t\t\t\tif (reflectionText) {\n\t\t\t\t\tconsole.log(reflectionText)\n\t\t\t\t}\n\n\t\t\t\t// Find the corresponding tool\n\t\t\t\tconst tool = tools.get(toolName)\n\t\t\t\tassert(tool, `Tool ${toolName} not found`)\n\n\t\t\t\tconsole.log(chalk.blue.bold(`Executing tool: ${toolName}`), toolInput)\n\n\t\t\t\t// Emit executing activity\n\t\t\t\tthis.#emitActivity({ type: 'executing', tool: toolName, input: toolInput })\n\n\t\t\t\tconst startTime = Date.now()\n\n\t\t\t\tconst result = await tool.execute.bind(this)(toolInput, { signal })\n\t\t\t\t// Enforce abort even if the tool ignored the signal and resolved normally.\n\t\t\t\tsignal.throwIfAborted()\n\n\t\t\t\tconst duration = Date.now() - startTime\n\t\t\t\tconsole.log(chalk.green.bold(`Tool (${toolName}) executed for ${duration}ms`), result)\n\n\t\t\t\t// Emit executed activity\n\t\t\t\tthis.#emitActivity({\n\t\t\t\t\ttype: 'executed',\n\t\t\t\t\ttool: toolName,\n\t\t\t\t\tinput: toolInput,\n\t\t\t\t\toutput: result,\n\t\t\t\t\tduration,\n\t\t\t\t})\n\n\t\t\t\t// counting wait time\n\t\t\t\tif (toolName === 'wait') {\n\t\t\t\t\tthis.#states.totalWaitTime += toolInput?.seconds || 0\n\t\t\t\t} else {\n\t\t\t\t\tthis.#states.totalWaitTime = 0\n\t\t\t\t}\n\n\t\t\t\t// Return structured result\n\t\t\t\treturn {\n\t\t\t\t\tinput,\n\t\t\t\t\toutput: result,\n\t\t\t\t}\n\t\t\t},\n\t\t}\n\t}\n\n\t/**\n\t * Get system prompt, dynamically replace language settings based on configured language\n\t */\n\t#getSystemPrompt(): string {\n\t\tif (this.config.customSystemPrompt) {\n\t\t\treturn this.config.customSystemPrompt\n\t\t}\n\n\t\t// FORK: a língua de trabalho do modelo acompanha a da interface.\n\t\tconst targetLanguage =\n\t\t\tthis.config.language === 'pt-BR'\n\t\t\t\t? 'Portuguese (Brazil)'\n\t\t\t\t: this.config.language === 'zh-CN'\n\t\t\t\t\t? 'Chinese'\n\t\t\t\t\t: 'English'\n\t\tconst systemPrompt = SYSTEM_PROMPT.replace(\n\t\t\t/Default working language: \\*\\*.*?\\*\\*/,\n\t\t\t`Default working language: **${targetLanguage}**`\n\t\t)\n\n\t\treturn systemPrompt\n\t}\n\n\t/**\n\t * Get instructions from config\n\t */\n\tasync #getInstructions(): Promise<string> {\n\t\tconst { instructions, experimentalLlmsTxt } = this.config\n\n\t\tconst systemInstructions = instructions?.system?.trim()\n\t\tlet pageInstructions: string | undefined\n\n\t\tconst url = this.#states.browserState?.url || ''\n\t\tif (instructions?.getPageInstructions && url) {\n\t\t\ttry {\n\t\t\t\tpageInstructions = instructions.getPageInstructions(url)?.trim()\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\n\t\t\t\t\tchalk.red('[PageAgent] Failed to execute getPageInstructions callback:'),\n\t\t\t\t\terror\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tconst llmsTxt = experimentalLlmsTxt && url ? await fetchLlmsTxt(url) : undefined\n\n\t\tif (!systemInstructions && !pageInstructions && !llmsTxt) return ''\n\n\t\tlet result = '<instructions>\\n'\n\n\t\tif (systemInstructions) {\n\t\t\tresult += `<system_instructions>\\n${systemInstructions}\\n</system_instructions>\\n`\n\t\t}\n\n\t\tif (pageInstructions) {\n\t\t\tresult += `<page_instructions>\\n${pageInstructions}\\n</page_instructions>\\n`\n\t\t}\n\n\t\tif (llmsTxt) {\n\t\t\tresult += `<llms_txt>\\n${llmsTxt}\\n</llms_txt>\\n`\n\t\t}\n\n\t\tresult += '</instructions>\\n\\n'\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Generate system observations before each step\n\t * @todo loop detection\n\t * @todo console error\n\t */\n\tasync #handleObservations(step: number): Promise<void> {\n\t\t// Accumulated wait time warning\n\t\tif (this.#states.totalWaitTime >= 3) {\n\t\t\tthis.pushObservation(\n\t\t\t\t`You have waited ${this.#states.totalWaitTime} seconds accumulatively. ` +\n\t\t\t\t\t`DO NOT wait any longer unless you have a good reason.`\n\t\t\t)\n\t\t}\n\n\t\t// Detect URL change\n\t\tconst currentURL = this.#states.browserState?.url || ''\n\t\tif (currentURL !== this.#states.lastURL) {\n\t\t\tthis.pushObservation(`A página navegou para → ${currentURL}`)\n\t\t\tthis.#states.lastURL = currentURL\n\t\t\tawait waitFor(0.5) // wait for page to stabilize\n\t\t}\n\n\t\t// Remaining steps warning\n\t\tconst remaining = this.config.maxSteps - step\n\t\tif (remaining === 5) {\n\t\t\tthis.pushObservation(\n\t\t\t\t`⚠️ Only ${remaining} steps remaining. ` +\n\t\t\t\t\t`Consider wrapping up or calling done with partial results.`\n\t\t\t)\n\t\t} else if (remaining === 2) {\n\t\t\tthis.pushObservation(\n\t\t\t\t`⚠️ Critical: Only ${remaining} steps left! You must finish the task or call done immediately.`\n\t\t\t)\n\t\t}\n\n\t\t// Push observations to history and emit\n\t\tif (this.#observations.length > 0) {\n\t\t\tfor (const content of this.#observations) {\n\t\t\t\tthis.history.push({ type: 'observation', content })\n\t\t\t\tconsole.log(chalk.cyan('Observation:'), content)\n\t\t\t}\n\t\t\tthis.#observations = []\n\t\t\tthis.#emitHistoryChange()\n\t\t}\n\t}\n\n\tasync #assembleUserPrompt(): Promise<string> {\n\t\tconst browserState = this.#states.browserState!\n\n\t\tlet prompt = ''\n\n\t\t// <instructions> (optional)\n\n\t\tprompt += await this.#getInstructions()\n\n\t\t// <agent_state>\n\t\t// - <user_request>\n\t\t// - <step_info>\n\t\t// <agent_state>\n\n\t\tconst stepCount = this.history.filter((e) => e.type === 'step').length\n\n\t\tprompt += '<agent_state>\\n'\n\t\tprompt += '<user_request>\\n'\n\t\tprompt += `${this.task}\\n`\n\t\tprompt += '</user_request>\\n'\n\t\tprompt += '<step_info>\\n'\n\t\tprompt += `Step ${stepCount + 1} of ${this.config.maxSteps} max possible steps\\n`\n\t\tprompt += `Current time: ${new Date().toLocaleString()}\\n`\n\t\tprompt += '</step_info>\\n'\n\t\tprompt += '</agent_state>\\n\\n'\n\n\t\t// <agent_history>\n\t\t// - <step_N> for steps\n\t\t// - <sys> for observations and system messages\n\n\t\tprompt += '<agent_history>\\n'\n\n\t\tlet stepIndex = 0\n\t\tfor (const event of this.history) {\n\t\t\tif (event.type === 'step') {\n\t\t\t\tstepIndex++\n\t\t\t\tprompt += `<step_${stepIndex}>\\n`\n\t\t\t\tprompt += `Evaluation of Previous Step: ${event.reflection.evaluation_previous_goal}\\n`\n\t\t\t\tprompt += `Memory: ${event.reflection.memory}\\n`\n\t\t\t\tprompt += `Next Goal: ${event.reflection.next_goal}\\n`\n\t\t\t\tprompt += `Action Results: ${event.action.output}\\n`\n\t\t\t\tprompt += `</step_${stepIndex}>\\n`\n\t\t\t} else if (event.type === 'observation') {\n\t\t\t\tprompt += `<sys>${event.content}</sys>\\n`\n\t\t\t} else if (event.type === 'user_takeover') {\n\t\t\t\tprompt += `<sys>User took over control and made changes to the page</sys>\\n`\n\t\t\t} else if (event.type === 'error') {\n\t\t\t\t// Error events are mainly for panel rendering, not included in LLM context\n\t\t\t\t// to avoid polluting the agent's reasoning with transient errors\n\t\t\t}\n\t\t}\n\n\t\tprompt += '</agent_history>\\n\\n'\n\n\t\t// <browser_state>\n\n\t\tlet pageContent = browserState.content\n\t\tif (this.config.transformPageContent) {\n\t\t\tpageContent = await this.config.transformPageContent(pageContent)\n\t\t}\n\n\t\tprompt += '<browser_state>\\n'\n\t\tprompt += browserState.header + '\\n'\n\t\tprompt += pageContent + '\\n'\n\t\tprompt += browserState.footer + '\\n\\n'\n\t\tprompt += '</browser_state>\\n\\n'\n\n\t\treturn prompt\n\t}\n\n\tdispose() {\n\t\tconsole.log('Disposing PageAgent...')\n\t\tthis.disposed = true\n\t\tthis.pageController.dispose()\n\t\t// this.history = []\n\t\tthis.#abortController.abort()\n\n\t\t// Emit dispose event for UI cleanup\n\t\tthis.dispatchEvent(new Event('dispose'))\n\n\t\tthis.config.onDispose?.(this)\n\t}\n}\n","// ======= type guards =======\n// @note instanceof fails for elements inside iframes\n\nexport function isHTMLElement(el: unknown): el is HTMLElement {\n\t// @todo either specify to HTMLElement or allow Element here.\n\treturn !!el && (el as Node).nodeType === 1\n}\n\nexport function isInputElement(el: Element): el is HTMLInputElement {\n\treturn el?.nodeType === 1 && el.tagName === 'INPUT'\n}\n\nexport function isTextAreaElement(el: Element): el is HTMLTextAreaElement {\n\treturn el?.nodeType === 1 && el.tagName === 'TEXTAREA'\n}\n\nexport function isSelectElement(el: Element): el is HTMLSelectElement {\n\treturn el?.nodeType === 1 && el.tagName === 'SELECT'\n}\n\nexport function isAnchorElement(el: Element): el is HTMLAnchorElement {\n\treturn el?.nodeType === 1 && el.tagName === 'A'\n}\n\n// ======= iframe helpers =======\n\n/** Iframe offset for translating element coordinates to top-frame viewport. */\nexport function getIframeOffset(element: HTMLElement): { x: number; y: number } {\n\tconst frame = element.ownerDocument.defaultView?.frameElement as HTMLElement | null\n\tif (!frame) return { x: 0, y: 0 }\n\tconst rect = frame.getBoundingClientRect()\n\treturn { x: rect.left, y: rect.top }\n}\n\n/**\n * Get native value setter from the element's own prototype (iframe-safe).\n * @note for React\n */\nexport function getNativeValueSetter(element: HTMLInputElement | HTMLTextAreaElement) {\n\t// eslint-disable-next-line @typescript-eslint/unbound-method\n\treturn Object.getOwnPropertyDescriptor(Object.getPrototypeOf(element) as object, 'value')!\n\t\t.set as (v: string) => void\n}\n\n// ======= general utils =======\n\nexport async function waitFor(seconds: number): Promise<void> {\n\tawait new Promise((resolve) => setTimeout(resolve, seconds * 1000))\n}\n\n// ======= mask events =======\n\n/**\n * Move the visual pointer to a position within an element.\n * @param x - x coordinate in the element's document viewport\n * @param y - y coordinate in the element's document viewport\n */\nexport async function movePointerToElement(element: HTMLElement, x: number, y: number) {\n\tconst offset = getIframeOffset(element)\n\n\twindow.dispatchEvent(\n\t\tnew CustomEvent('PageAgent::MovePointerTo', {\n\t\t\tdetail: { x: x + offset.x, y: y + offset.y },\n\t\t})\n\t)\n\n\tawait waitFor(0.3)\n}\n\nexport async function clickPointer() {\n\twindow.dispatchEvent(new CustomEvent('PageAgent::ClickPointer'))\n}\n\nexport async function enablePassThrough() {\n\twindow.dispatchEvent(new CustomEvent('PageAgent::EnablePassThrough'))\n}\n\nexport async function disablePassThrough() {\n\twindow.dispatchEvent(new CustomEvent('PageAgent::DisablePassThrough'))\n}\n","/**\n * Copyright (C) 2025 Alibaba Group Holding Limited\n * All rights reserved.\n */\nimport type { InteractiveElementDomNode } from './dom/dom_tree/type'\nimport {\n\tclickPointer,\n\tdisablePassThrough,\n\tenablePassThrough,\n\tgetNativeValueSetter,\n\tisHTMLElement,\n\tisInputElement,\n\tisSelectElement,\n\tisTextAreaElement,\n\tmovePointerToElement,\n\twaitFor,\n} from './utils'\n\n/**\n * Get the HTMLElement by index from a selectorMap.\n * @private Internal method, subject to change at any time.\n */\nexport function getElementByIndex(\n\tselectorMap: Map<number, InteractiveElementDomNode>,\n\tindex: number\n): HTMLElement {\n\tconst interactiveNode = selectorMap.get(index)\n\tif (!interactiveNode) {\n\t\tthrow new Error(`No interactive element found at index ${index}`)\n\t}\n\n\tconst element = interactiveNode.ref\n\tif (!element) {\n\t\tthrow new Error(`Element at index ${index} does not have a reference`)\n\t}\n\n\tif (!isHTMLElement(element)) {\n\t\tthrow new Error(`Element at index ${index} is not an HTMLElement`)\n\t}\n\n\treturn element\n}\n\nlet lastClickedElement: HTMLElement | null = null\n\nfunction blurLastClickedElement() {\n\tif (lastClickedElement) {\n\t\tlastClickedElement.dispatchEvent(new PointerEvent('pointerout', { bubbles: true }))\n\t\tlastClickedElement.dispatchEvent(new PointerEvent('pointerleave', { bubbles: false }))\n\t\tlastClickedElement.dispatchEvent(new MouseEvent('mouseout', { bubbles: true }))\n\t\tlastClickedElement.dispatchEvent(new MouseEvent('mouseleave', { bubbles: false }))\n\t\tlastClickedElement.blur()\n\t\tlastClickedElement = null\n\t}\n}\n\n/**\n * Simulate a full click following W3C Pointer Events + UI Events spec order:\n * pointerover/enter → mouseover/enter → pointerdown → mousedown → [focus] →\n * pointerup → mouseup → click\n *\n * @private Internal method, subject to change at any time.\n */\nexport async function clickElement(element: HTMLElement) {\n\tblurLastClickedElement()\n\n\tlastClickedElement = element\n\n\tawait scrollIntoViewIfNeeded(element)\n\tconst frame = element.ownerDocument.defaultView?.frameElement\n\tif (frame) await scrollIntoViewIfNeeded(frame)\n\n\tconst rect = element.getBoundingClientRect()\n\tconst x = rect.left + rect.width / 2\n\tconst y = rect.top + rect.height / 2\n\n\tawait movePointerToElement(element, x, y)\n\tawait clickPointer()\n\n\tawait waitFor(0.1)\n\n\t// Hit-test to find the deepest element at click coordinates, matching\n\t// real browser behavior where events target the innermost element.\n\t// @note This may hit a element in the blacklist\n\t// TODO: This is a temporary workaround. Should have been handled during dom extraction.\n\tconst doc = element.ownerDocument\n\tawait enablePassThrough()\n\tconst hitTarget = doc.elementFromPoint(x, y)\n\tawait disablePassThrough()\n\tconst target =\n\t\thitTarget instanceof HTMLElement && element.contains(hitTarget) ? hitTarget : element\n\n\tconst pointerOpts = {\n\t\tbubbles: true,\n\t\tcancelable: true,\n\t\tclientX: x,\n\t\tclientY: y,\n\t\tpointerType: 'mouse',\n\t}\n\tconst mouseOpts = { bubbles: true, cancelable: true, clientX: x, clientY: y, button: 0 }\n\n\t// Hover — pointer events first, then mouse events (spec order)\n\ttarget.dispatchEvent(new PointerEvent('pointerover', pointerOpts))\n\ttarget.dispatchEvent(new PointerEvent('pointerenter', { ...pointerOpts, bubbles: false }))\n\ttarget.dispatchEvent(new MouseEvent('mouseover', mouseOpts))\n\ttarget.dispatchEvent(new MouseEvent('mouseenter', { ...mouseOpts, bubbles: false }))\n\n\t// Press\n\ttarget.dispatchEvent(new PointerEvent('pointerdown', pointerOpts))\n\ttarget.dispatchEvent(new MouseEvent('mousedown', mouseOpts))\n\n\t// Focus is not part of the standard pointer/mouse event sequence\n\t// \"undefined and varies between user agents\".\n\t// We focus the original element (nearest focusable ancestor), not the hit-test target, matching browser behavior.\n\telement.focus({ preventScroll: true })\n\n\t// Release\n\ttarget.dispatchEvent(new PointerEvent('pointerup', pointerOpts))\n\ttarget.dispatchEvent(new MouseEvent('mouseup', mouseOpts))\n\n\t// Click — activation behavior (navigation, form submit, etc.) triggers\n\t// via bubbling from target up to the interactive ancestor.\n\ttarget.click()\n\n\tawait waitFor(0.2)\n}\n\n/**\n * @private Internal method, subject to change at any time.\n */\nexport async function inputTextElement(element: HTMLElement, text: string) {\n\tconst isContentEditable = element.isContentEditable\n\tif (!isInputElement(element) && !isTextAreaElement(element) && !isContentEditable) {\n\t\tthrow new Error('Element is not an input, textarea, or contenteditable')\n\t}\n\n\tawait clickElement(element)\n\n\tif (isContentEditable) {\n\t\t// Contenteditable support (partial)\n\t\t// Not supported:\n\t\t// - Monaco/CodeMirror: Require direct JS instance access. No universal way to obtain.\n\t\t// - Draft.js: Not responsive to synthetic/execCommand/Range/DataTransfer. Unmaintained.\n\t\t//\n\t\t// Strategy: Try Plan A (synthetic events) first, then verify and fall back\n\t\t// to Plan B (execCommand) if the text wasn't actually inserted.\n\t\t//\n\t\t// Plan A: Dispatch synthetic events\n\t\t// Works: React contenteditable, Quill.\n\t\t// Fails: Slate.js, some contenteditable editors that ignore synthetic events.\n\t\t// Sequence: beforeinput -> mutation -> input -> change -> blur\n\n\t\t// Dispatch beforeinput + mutation + input for clearing\n\t\tif (\n\t\t\telement.dispatchEvent(\n\t\t\t\tnew InputEvent('beforeinput', {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tcancelable: true,\n\t\t\t\t\tinputType: 'deleteContent',\n\t\t\t\t})\n\t\t\t)\n\t\t) {\n\t\t\telement.innerText = ''\n\t\t\telement.dispatchEvent(\n\t\t\t\tnew InputEvent('input', {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tinputType: 'deleteContent',\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\n\t\t// Dispatch beforeinput + mutation + input for insertion (important for React apps)\n\t\tif (\n\t\t\telement.dispatchEvent(\n\t\t\t\tnew InputEvent('beforeinput', {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tcancelable: true,\n\t\t\t\t\tinputType: 'insertText',\n\t\t\t\t\tdata: text,\n\t\t\t\t})\n\t\t\t)\n\t\t) {\n\t\t\telement.innerText = text\n\t\t\telement.dispatchEvent(\n\t\t\t\tnew InputEvent('input', {\n\t\t\t\t\tbubbles: true,\n\t\t\t\t\tinputType: 'insertText',\n\t\t\t\t\tdata: text,\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\n\t\t// Verify Plan A worked by checking if the text was actually inserted\n\t\tconst planASucceeded = element.innerText.trim() === text.trim()\n\n\t\tif (!planASucceeded) {\n\t\t\t// Plan B: execCommand fallback (deprecated but widely supported)\n\t\t\t// Works: Quill, Slate.js, react contenteditable components.\n\t\t\t// This approach integrates with the browser's undo stack and is handled\n\t\t\t// natively by most rich-text editors.\n\t\t\telement.focus()\n\n\t\t\t// Select all existing content and delete it\n\t\t\tconst doc = element.ownerDocument\n\t\t\tconst selection = (doc.defaultView || window).getSelection()\n\t\t\tconst range = doc.createRange()\n\t\t\trange.selectNodeContents(element)\n\t\t\tselection?.removeAllRanges()\n\t\t\tselection?.addRange(range)\n\n\t\t\tdoc.execCommand('delete', false)\n\t\t\tdoc.execCommand('insertText', false, text)\n\t\t}\n\n\t\t// Dispatch change event (for good measure)\n\t\telement.dispatchEvent(new Event('change', { bubbles: true }))\n\n\t\t// Trigger blur for validation\n\t\telement.blur()\n\t} else {\n\t\tgetNativeValueSetter(element as HTMLInputElement | HTMLTextAreaElement).call(element, text)\n\t}\n\n\t// Only dispatch shared input event for non-contenteditable (contenteditable has its own)\n\tif (!isContentEditable) {\n\t\telement.dispatchEvent(new Event('input', { bubbles: true }))\n\t}\n\n\tawait waitFor(0.1)\n}\n\n/**\n * @todo browser-use version is very complex and supports menu tags, need to follow up\n * @private Internal method, subject to change at any time.\n */\nexport async function selectOptionElement(selectElement: HTMLSelectElement, optionText: string) {\n\tif (!isSelectElement(selectElement)) {\n\t\tthrow new Error('Element is not a select element')\n\t}\n\n\tconst options = Array.from(selectElement.options)\n\tconst option = options.find((opt) => opt.textContent?.trim() === optionText.trim())\n\n\tif (!option) {\n\t\tthrow new Error(`Option with text \"${optionText}\" not found in select element`)\n\t}\n\n\tselectElement.value = option.value\n\tselectElement.dispatchEvent(new Event('change', { bubbles: true }))\n\n\tawait waitFor(0.1) // Wait to ensure change event processing completes\n}\n\ninterface ScrollableElement extends Element {\n\tscrollIntoViewIfNeeded?: (centerIfNeeded?: boolean) => void\n}\n\n/**\n * @private Internal method, subject to change at any time.\n */\nexport async function scrollIntoViewIfNeeded(element: Element) {\n\tconst el = element as ScrollableElement\n\tif (typeof el.scrollIntoViewIfNeeded === 'function') {\n\t\tel.scrollIntoViewIfNeeded()\n\t\t// await waitFor(0.5) // Animation playback\n\t} else {\n\t\t// @todo visibility check\n\t\telement.scrollIntoView({ behavior: 'auto', block: 'center', inline: 'nearest' })\n\t\t// await waitFor(0.5) // Animation playback\n\t}\n}\n\nexport async function scrollVertically(scroll_amount: number, element?: HTMLElement | null) {\n\t// Element-specific scrolling if element is provided\n\tif (element) {\n\t\tconst targetElement = element\n\t\tlet currentElement = targetElement as HTMLElement | null\n\t\tlet scrollSuccess = false\n\t\tlet scrolledElement: HTMLElement | null = null\n\t\tlet scrollDelta = 0\n\t\tlet attempts = 0\n\t\tconst dy = scroll_amount\n\n\t\twhile (currentElement && attempts < 10) {\n\t\t\tconst computedStyle = window.getComputedStyle(currentElement)\n\t\t\tconst hasScrollableY =\n\t\t\t\t/(auto|scroll|overlay)/.test(computedStyle.overflowY) ||\n\t\t\t\t(computedStyle.scrollbarWidth && computedStyle.scrollbarWidth !== 'auto') ||\n\t\t\t\t(computedStyle.scrollbarGutter && computedStyle.scrollbarGutter !== 'auto')\n\t\t\tconst canScrollVertically = currentElement.scrollHeight > currentElement.clientHeight\n\n\t\t\tif (hasScrollableY && canScrollVertically) {\n\t\t\t\tconst beforeScroll = currentElement.scrollTop\n\t\t\t\tconst maxScroll = currentElement.scrollHeight - currentElement.clientHeight\n\n\t\t\t\tlet scrollAmount = dy / 3\n\n\t\t\t\tif (scrollAmount > 0) {\n\t\t\t\t\tscrollAmount = Math.min(scrollAmount, maxScroll - beforeScroll)\n\t\t\t\t} else {\n\t\t\t\t\tscrollAmount = Math.max(scrollAmount, -beforeScroll)\n\t\t\t\t}\n\n\t\t\t\tcurrentElement.scrollTop = beforeScroll + scrollAmount\n\n\t\t\t\tconst afterScroll = currentElement.scrollTop\n\t\t\t\tconst actualScrollDelta = afterScroll - beforeScroll\n\n\t\t\t\tif (Math.abs(actualScrollDelta) > 0.5) {\n\t\t\t\t\tscrollSuccess = true\n\t\t\t\t\tscrolledElement = currentElement\n\t\t\t\t\tscrollDelta = actualScrollDelta\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentElement === document.body || currentElement === document.documentElement) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcurrentElement = currentElement.parentElement\n\t\t\tattempts++\n\t\t}\n\n\t\tif (scrollSuccess) {\n\t\t\treturn `Scrolled container (${scrolledElement?.tagName}) by ${scrollDelta}px`\n\t\t} else {\n\t\t\treturn `No scrollable container found for element (${targetElement.tagName})`\n\t\t}\n\t}\n\n\t// Page-level scrolling (default or fallback)\n\n\tconst dy = scroll_amount\n\tconst bigEnough = (el: HTMLElement) => el.clientHeight >= window.innerHeight * 0.5\n\tconst canScroll = (el: HTMLElement | null): boolean =>\n\t\tBoolean(\n\t\t\tel &&\n\t\t\t/(auto|scroll|overlay)/.test(getComputedStyle(el).overflowY) &&\n\t\t\tel.scrollHeight > el.clientHeight &&\n\t\t\tbigEnough(el)\n\t\t)\n\n\t// @deprecated Heuristic container search.\n\t// Unreliable in multi-panel layouts. Should guide LLMs to use indexed scroll for consistency.\n\t// TODO: remove this fallback\n\n\t// try to find the nearest scrollable container\n\t// document.activeElement is usually body.\n\t// After a successful element.focus(), activeElement become the nearest focusable parent\n\n\tlet el: HTMLElement | null = document.activeElement as HTMLElement | null\n\twhile (el && !canScroll(el) && el !== document.body) el = el.parentElement\n\n\t// Something is wrong if it falls back to global '*' search\n\t// TODO: Return error message instead of global '*' search\n\n\tel = canScroll(el)\n\t\t? el\n\t\t: Array.from(document.querySelectorAll<HTMLElement>('*')).find(canScroll) ||\n\t\t\t(document.scrollingElement as HTMLElement) ||\n\t\t\t(document.documentElement as HTMLElement)\n\n\tif (el === document.scrollingElement || el === document.documentElement || el === document.body) {\n\t\t// Page-level scroll\n\t\tconst scrollBefore = window.scrollY\n\t\tconst scrollMax = document.documentElement.scrollHeight - window.innerHeight\n\n\t\twindow.scrollBy(0, dy)\n\n\t\tconst scrollAfter = window.scrollY\n\t\tconst scrolled = scrollAfter - scrollBefore\n\n\t\tif (Math.abs(scrolled) < 1) {\n\t\t\treturn dy > 0\n\t\t\t\t? `⚠️ Already at the bottom of the page, cannot scroll down further.`\n\t\t\t\t: `⚠️ Already at the top of the page, cannot scroll up further.`\n\t\t}\n\n\t\tconst reachedBottom = dy > 0 && scrollAfter >= scrollMax - 1\n\t\tconst reachedTop = dy < 0 && scrollAfter <= 1\n\n\t\tif (reachedBottom) return `✅ Scrolled page by ${scrolled}px. Reached the bottom of the page.`\n\t\tif (reachedTop) return `✅ Scrolled page by ${scrolled}px. Reached the top of the page.`\n\t\treturn `✅ Scrolled page by ${scrolled}px.`\n\t} else {\n\t\t// Container scroll\n\n\t\tconst warningMsg = `The document is not scrollable. Falling back to container scroll.`\n\t\tconsole.log(`[PageController] ${warningMsg}`)\n\n\t\tconst scrollBefore = el!.scrollTop\n\t\tconst scrollMax = el!.scrollHeight - el!.clientHeight\n\n\t\tel!.scrollBy({ top: dy, behavior: 'smooth' })\n\t\tawait waitFor(0.1)\n\n\t\tconst scrollAfter = el!.scrollTop\n\t\tconst scrolled = scrollAfter - scrollBefore\n\n\t\tif (Math.abs(scrolled) < 1) {\n\t\t\treturn dy > 0\n\t\t\t\t? `⚠️ ${warningMsg} Already at the bottom of container (${el!.tagName}), cannot scroll down further.`\n\t\t\t\t: `⚠️ ${warningMsg} Already at the top of container (${el!.tagName}), cannot scroll up further.`\n\t\t}\n\n\t\tconst reachedBottom = dy > 0 && scrollAfter >= scrollMax - 1\n\t\tconst reachedTop = dy < 0 && scrollAfter <= 1\n\n\t\tif (reachedBottom)\n\t\t\treturn `✅ ${warningMsg} Scrolled container (${el!.tagName}) by ${scrolled}px. Reached the bottom.`\n\t\tif (reachedTop)\n\t\t\treturn `✅ ${warningMsg} Scrolled container (${el!.tagName}) by ${scrolled}px. Reached the top.`\n\t\treturn `✅ ${warningMsg} Scrolled container (${el!.tagName}) by ${scrolled}px.`\n\t}\n}\n\nexport async function scrollHorizontally(scroll_amount: number, element?: HTMLElement | null) {\n\t// Element-specific scrolling if element is provided\n\tif (element) {\n\t\tconst targetElement = element\n\t\tlet currentElement = targetElement as HTMLElement | null\n\t\tlet scrollSuccess = false\n\t\tlet scrolledElement: HTMLElement | null = null\n\t\tlet scrollDelta = 0\n\t\tlet attempts = 0\n\t\tconst dx = scroll_amount\n\n\t\twhile (currentElement && attempts < 10) {\n\t\t\tconst computedStyle = window.getComputedStyle(currentElement)\n\t\t\tconst hasScrollableX =\n\t\t\t\t/(auto|scroll|overlay)/.test(computedStyle.overflowX) ||\n\t\t\t\t(computedStyle.scrollbarWidth && computedStyle.scrollbarWidth !== 'auto') ||\n\t\t\t\t(computedStyle.scrollbarGutter && computedStyle.scrollbarGutter !== 'auto')\n\t\t\tconst canScrollHorizontally = currentElement.scrollWidth > currentElement.clientWidth\n\n\t\t\tif (hasScrollableX && canScrollHorizontally) {\n\t\t\t\tconst beforeScroll = currentElement.scrollLeft\n\t\t\t\tconst maxScroll = currentElement.scrollWidth - currentElement.clientWidth\n\n\t\t\t\tlet scrollAmount = dx / 3\n\n\t\t\t\tif (scrollAmount > 0) {\n\t\t\t\t\tscrollAmount = Math.min(scrollAmount, maxScroll - beforeScroll)\n\t\t\t\t} else {\n\t\t\t\t\tscrollAmount = Math.max(scrollAmount, -beforeScroll)\n\t\t\t\t}\n\n\t\t\t\tcurrentElement.scrollLeft = beforeScroll + scrollAmount\n\n\t\t\t\tconst afterScroll = currentElement.scrollLeft\n\t\t\t\tconst actualScrollDelta = afterScroll - beforeScroll\n\n\t\t\t\tif (Math.abs(actualScrollDelta) > 0.5) {\n\t\t\t\t\tscrollSuccess = true\n\t\t\t\t\tscrolledElement = currentElement\n\t\t\t\t\tscrollDelta = actualScrollDelta\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentElement === document.body || currentElement === document.documentElement) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcurrentElement = currentElement.parentElement\n\t\t\tattempts++\n\t\t}\n\n\t\tif (scrollSuccess) {\n\t\t\treturn `Scrolled container (${scrolledElement?.tagName}) horizontally by ${scrollDelta}px`\n\t\t} else {\n\t\t\treturn `No horizontally scrollable container found for element (${targetElement.tagName})`\n\t\t}\n\t}\n\n\t// Page-level scrolling (default or fallback)\n\n\tconst dx = scroll_amount\n\n\tconst bigEnough = (el: HTMLElement) => el.clientWidth >= window.innerWidth * 0.5\n\tconst canScroll = (el: HTMLElement | null): boolean =>\n\t\tBoolean(\n\t\t\tel &&\n\t\t\t/(auto|scroll|overlay)/.test(getComputedStyle(el).overflowX) &&\n\t\t\tel.scrollWidth > el.clientWidth &&\n\t\t\tbigEnough(el)\n\t\t)\n\n\t// @deprecated Same heuristic container search as scrollVertically.\n\t// TODO: Remove once LLMs reliably use indexed scrolling via data-scrollable.\n\n\tlet el: HTMLElement | null = document.activeElement as HTMLElement | null\n\twhile (el && !canScroll(el) && el !== document.body) el = el.parentElement\n\n\tel = canScroll(el)\n\t\t? el\n\t\t: Array.from(document.querySelectorAll<HTMLElement>('*')).find(canScroll) ||\n\t\t\t(document.scrollingElement as HTMLElement) ||\n\t\t\t(document.documentElement as HTMLElement)\n\n\tif (el === document.scrollingElement || el === document.documentElement || el === document.body) {\n\t\t// Page-level scroll\n\t\tconst scrollBefore = window.scrollX\n\t\tconst scrollMax = document.documentElement.scrollWidth - window.innerWidth\n\n\t\twindow.scrollBy(dx, 0)\n\n\t\tconst scrollAfter = window.scrollX\n\t\tconst scrolled = scrollAfter - scrollBefore\n\n\t\tif (Math.abs(scrolled) < 1) {\n\t\t\treturn dx > 0\n\t\t\t\t? `⚠️ Already at the right edge of the page, cannot scroll right further.`\n\t\t\t\t: `⚠️ Already at the left edge of the page, cannot scroll left further.`\n\t\t}\n\n\t\tconst reachedRight = dx > 0 && scrollAfter >= scrollMax - 1\n\t\tconst reachedLeft = dx < 0 && scrollAfter <= 1\n\n\t\tif (reachedRight)\n\t\t\treturn `✅ Scrolled page by ${scrolled}px. Reached the right edge of the page.`\n\t\tif (reachedLeft) return `✅ Scrolled page by ${scrolled}px. Reached the left edge of the page.`\n\t\treturn `✅ Scrolled page horizontally by ${scrolled}px.`\n\t} else {\n\t\t// Container scroll\n\t\tconst warningMsg = `The document is not scrollable. Falling back to container scroll.`\n\t\tconsole.log(`[PageController] ${warningMsg}`)\n\n\t\tconst scrollBefore = el!.scrollLeft\n\t\tconst scrollMax = el!.scrollWidth - el!.clientWidth\n\n\t\tel!.scrollBy({ left: dx, behavior: 'smooth' })\n\t\tawait waitFor(0.1)\n\n\t\tconst scrollAfter = el!.scrollLeft\n\t\tconst scrolled = scrollAfter - scrollBefore\n\n\t\tif (Math.abs(scrolled) < 1) {\n\t\t\treturn dx > 0\n\t\t\t\t? `⚠️ ${warningMsg} Already at the right edge of container (${el!.tagName}), cannot scroll right further.`\n\t\t\t\t: `⚠️ ${warningMsg} Already at the left edge of container (${el!.tagName}), cannot scroll left further.`\n\t\t}\n\n\t\tconst reachedRight = dx > 0 && scrollAfter >= scrollMax - 1\n\t\tconst reachedLeft = dx < 0 && scrollAfter <= 1\n\n\t\tif (reachedRight)\n\t\t\treturn `✅ ${warningMsg} Scrolled container (${el!.tagName}) by ${scrolled}px. Reached the right edge.`\n\t\tif (reachedLeft)\n\t\t\treturn `✅ ${warningMsg} Scrolled container (${el!.tagName}) by ${scrolled}px. Reached the left edge.`\n\t\treturn `✅ ${warningMsg} Scrolled container (${el!.tagName}) horizontally by ${scrolled}px.`\n\t}\n}\n","/**\n * @file port from browser-use\n * @see https://github.com/browser-use/browser-use/commits/main/browser_use/dom/dom_tree/index.js\n * @match 0.5.9 d51b6e73daff7165fdd3e44debd667e7f5f7fdc5\n *\n * search @edit for all the changed lines.\n *\n * @edit export\n * @edit add interactiveBlacklist interactiveWhitelist\n * @edit adjustable opacity\n * @edit direct dom ref\n * @edit @workaround input.checked\n * @edit smaller zIndex for highlight\n * @edit no need for xpath\n * @edit add `extra` field for extra data\n * @edit scrollable element detection\n * @edit add `data-browser-use-ignore` attribute\n * @edit improve `sampleRect`, filter out rects with 0 area\n * @edit exclude aria-hidden elements\n * @edit make sure attributes exist for interactive candidates.\n * @edit fix \"aria-*\" attributes check\n */\n\nexport default (\n\targs = {\n\t\tdoHighlightElements: true,\n\t\tfocusHighlightIndex: -1,\n\t\tviewportExpansion: 0,\n\t\tdebugMode: false,\n\n\t\t/**\n\t\t * @edit\n\t\t */\n\t\t/** @type {Element[]} */\n\t\tinteractiveBlacklist: [],\n\t\t/** @type {Element[]} */\n\t\tinteractiveWhitelist: [],\n\t\thighlightOpacity: 0.1,\n\t\thighlightLabelOpacity: 0.5,\n\t}\n) => {\n\t/**\n\t * @edit\n\t */\n\tconst { interactiveBlacklist, interactiveWhitelist, highlightOpacity, highlightLabelOpacity } =\n\t\targs\n\n\tconst { doHighlightElements, focusHighlightIndex, viewportExpansion, debugMode } = args\n\tlet highlightIndex = 0 // Reset highlight index\n\n\t/**\n\t * @edit add `extra` field for extra data\n\t */\n\tconst extraData = new WeakMap()\n\tfunction addExtraData(element, data) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) return\n\t\textraData.set(element, { ...extraData.get(element), ...data })\n\t}\n\n\t// Add caching mechanisms at the top level\n\tconst DOM_CACHE = {\n\t\tboundingRects: new WeakMap(),\n\t\tclientRects: new WeakMap(),\n\t\tcomputedStyles: new WeakMap(),\n\t\tclearCache: () => {\n\t\t\tDOM_CACHE.boundingRects = new WeakMap()\n\t\t\tDOM_CACHE.clientRects = new WeakMap()\n\t\t\tDOM_CACHE.computedStyles = new WeakMap()\n\t\t},\n\t}\n\n\t/**\n\t * Gets the cached bounding rect for an element.\n\t *\n\t * @param {HTMLElement} element - The element to get the bounding rect for.\n\t * @returns {DOMRect | null} The cached bounding rect, or null if the element is not found.\n\t */\n\tfunction getCachedBoundingRect(element) {\n\t\tif (!element) return null\n\n\t\tif (DOM_CACHE.boundingRects.has(element)) {\n\t\t\treturn DOM_CACHE.boundingRects.get(element)\n\t\t}\n\n\t\tconst rect = element.getBoundingClientRect()\n\n\t\tif (rect) {\n\t\t\tDOM_CACHE.boundingRects.set(element, rect)\n\t\t}\n\t\treturn rect\n\t}\n\n\t/**\n\t * Gets the cached computed style for an element.\n\t *\n\t * @param {HTMLElement} element - The element to get the computed style for.\n\t * @returns {CSSStyleDeclaration | null} The cached computed style, or null if the element is not found.\n\t */\n\tfunction getCachedComputedStyle(element) {\n\t\tif (!element) return null\n\n\t\tif (DOM_CACHE.computedStyles.has(element)) {\n\t\t\treturn DOM_CACHE.computedStyles.get(element)\n\t\t}\n\n\t\tconst style = window.getComputedStyle(element)\n\n\t\tif (style) {\n\t\t\tDOM_CACHE.computedStyles.set(element, style)\n\t\t}\n\t\treturn style\n\t}\n\n\t/**\n\t * Gets the cached client rects for an element.\n\t *\n\t * @param {HTMLElement} element - The element to get the client rects for.\n\t * @returns {DOMRectList | null} The cached client rects, or null if the element is not found.\n\t */\n\tfunction getCachedClientRects(element) {\n\t\tif (!element) return null\n\n\t\tif (DOM_CACHE.clientRects.has(element)) {\n\t\t\treturn DOM_CACHE.clientRects.get(element)\n\t\t}\n\n\t\tconst rects = element.getClientRects()\n\n\t\tif (rects) {\n\t\t\tDOM_CACHE.clientRects.set(element, rects)\n\t\t}\n\t\treturn rects\n\t}\n\n\t/**\n\t * Hash map of DOM nodes indexed by their highlight index.\n\t *\n\t * @type {Object<string, any>}\n\t */\n\tconst DOM_HASH_MAP = {}\n\n\tconst ID = { current: 0 }\n\n\tconst HIGHLIGHT_CONTAINER_ID = 'playwright-highlight-container'\n\n\t// Add a WeakMap cache for XPath strings\n\tconst xpathCache = new WeakMap()\n\n\t// // Initialize once and reuse\n\t// const viewportObserver = new IntersectionObserver(\n\t// (entries) => {\n\t// entries.forEach(entry => {\n\t// elementVisibilityMap.set(entry.target, entry.isIntersecting);\n\t// });\n\t// },\n\t// { rootMargin: `${viewportExpansion}px` }\n\t// );\n\n\t/**\n\t * Highlights an element in the DOM and returns the index of the next element.\n\t *\n\t * @param {HTMLElement} element - The element to highlight.\n\t * @param {number} index - The index of the element.\n\t * @param {HTMLElement | null} parentIframe - The parent iframe node.\n\t * @returns {number} The index of the next element.\n\t */\n\tfunction highlightElement(element, index, parentIframe = null) {\n\t\tif (!element) return index\n\n\t\tconst overlays = []\n\t\t/**\n\t\t * @type {HTMLElement | null}\n\t\t */\n\t\tlet label = null\n\t\tlet labelWidth = 20\n\t\tlet labelHeight = 16\n\t\tlet cleanupFn = null\n\n\t\ttry {\n\t\t\t// Create or get highlight container\n\t\t\tlet container = document.getElementById(HIGHLIGHT_CONTAINER_ID)\n\t\t\tif (!container) {\n\t\t\t\tcontainer = document.createElement('div')\n\t\t\t\tcontainer.id = HIGHLIGHT_CONTAINER_ID\n\t\t\t\tcontainer.style.position = 'fixed'\n\t\t\t\tcontainer.style.pointerEvents = 'none'\n\t\t\t\tcontainer.style.top = '0'\n\t\t\t\tcontainer.style.left = '0'\n\t\t\t\tcontainer.style.width = '100%'\n\t\t\t\tcontainer.style.height = '100%'\n\n\t\t\t\t/**\n\t\t\t\t * @edit smaller zIndex for highlight\n\t\t\t\t */\n\t\t\t\t// Use the maximum valid value in zIndex to ensure the element is not blocked by overlapping elements.\n\t\t\t\t// container.style.zIndex = \"2147483647\";\n\t\t\t\tcontainer.style.zIndex = '2147483640'\n\n\t\t\t\tcontainer.style.backgroundColor = 'transparent'\n\t\t\t\tdocument.body.appendChild(container)\n\t\t\t}\n\n\t\t\t// Get element client rects\n\t\t\tconst rects = element.getClientRects() // Use getClientRects()\n\n\t\t\tif (!rects || rects.length === 0) return index // Exit if no rects\n\n\t\t\t// Generate a color based on the index\n\t\t\tconst colors = [\n\t\t\t\t'#FF0000',\n\t\t\t\t'#00FF00',\n\t\t\t\t'#0000FF',\n\t\t\t\t'#FFA500',\n\t\t\t\t'#800080',\n\t\t\t\t'#008080',\n\t\t\t\t'#FF69B4',\n\t\t\t\t'#4B0082',\n\t\t\t\t'#FF4500',\n\t\t\t\t'#2E8B57',\n\t\t\t\t'#DC143C',\n\t\t\t\t'#4682B4',\n\t\t\t]\n\t\t\tconst colorIndex = index % colors.length\n\t\t\tlet baseColor = colors[colorIndex]\n\n\t\t\t/**\n\t\t\t * @edit adjustable opacity\n\t\t\t */\n\t\t\t// const backgroundColor = baseColor + \"1A\"; // 10% opacity version of the color\n\t\t\tconst backgroundColor =\n\t\t\t\tbaseColor +\n\t\t\t\tMath.floor(highlightOpacity * 255)\n\t\t\t\t\t.toString(16)\n\t\t\t\t\t.padStart(2, '0')\n\t\t\tbaseColor =\n\t\t\t\tbaseColor +\n\t\t\t\tMath.floor(highlightLabelOpacity * 255)\n\t\t\t\t\t.toString(16)\n\t\t\t\t\t.padStart(2, '0')\n\n\t\t\t// Get iframe offset if necessary\n\t\t\tlet iframeOffset = { x: 0, y: 0 }\n\t\t\tif (parentIframe) {\n\t\t\t\tconst iframeRect = parentIframe.getBoundingClientRect() // Keep getBoundingClientRect for iframe offset\n\t\t\t\tiframeOffset.x = iframeRect.left\n\t\t\t\tiframeOffset.y = iframeRect.top\n\t\t\t}\n\n\t\t\t// Create fragment to hold overlay elements\n\t\t\tconst fragment = document.createDocumentFragment()\n\n\t\t\t// Create highlight overlays for each client rect\n\t\t\tfor (const rect of rects) {\n\t\t\t\tif (rect.width === 0 || rect.height === 0) continue // Skip empty rects\n\n\t\t\t\tconst overlay = document.createElement('div')\n\t\t\t\toverlay.style.position = 'fixed'\n\t\t\t\toverlay.style.border = `2px solid ${baseColor}`\n\t\t\t\toverlay.style.backgroundColor = backgroundColor\n\t\t\t\toverlay.style.pointerEvents = 'none'\n\t\t\t\toverlay.style.boxSizing = 'border-box'\n\n\t\t\t\tconst top = rect.top + iframeOffset.y\n\t\t\t\tconst left = rect.left + iframeOffset.x\n\n\t\t\t\toverlay.style.top = `${top}px`\n\t\t\t\toverlay.style.left = `${left}px`\n\t\t\t\toverlay.style.width = `${rect.width}px`\n\t\t\t\toverlay.style.height = `${rect.height}px`\n\n\t\t\t\tfragment.appendChild(overlay)\n\t\t\t\toverlays.push({ element: overlay, initialRect: rect }) // Store overlay and its rect\n\t\t\t}\n\n\t\t\t// Create and position a single label relative to the first rect\n\t\t\tconst firstRect = rects[0]\n\t\t\tlabel = document.createElement('div')\n\t\t\tlabel.className = 'playwright-highlight-label'\n\t\t\tlabel.style.position = 'fixed'\n\t\t\tlabel.style.background = baseColor\n\t\t\tlabel.style.color = 'white'\n\t\t\tlabel.style.padding = '1px 4px'\n\t\t\tlabel.style.borderRadius = '4px'\n\t\t\tlabel.style.fontSize = `${Math.min(12, Math.max(8, firstRect.height / 2))}px`\n\t\t\tlabel.textContent = index.toString()\n\n\t\t\tlabelWidth = label.offsetWidth > 0 ? label.offsetWidth : labelWidth // Update actual width if possible\n\t\t\tlabelHeight = label.offsetHeight > 0 ? label.offsetHeight : labelHeight // Update actual height if possible\n\n\t\t\tconst firstRectTop = firstRect.top + iframeOffset.y\n\t\t\tconst firstRectLeft = firstRect.left + iframeOffset.x\n\n\t\t\tlet labelTop = firstRectTop + 2\n\t\t\tlet labelLeft = firstRectLeft + firstRect.width - labelWidth - 2\n\n\t\t\t// Adjust label position if first rect is too small\n\t\t\tif (firstRect.width < labelWidth + 4 || firstRect.height < labelHeight + 4) {\n\t\t\t\tlabelTop = firstRectTop - labelHeight - 2\n\t\t\t\tlabelLeft = firstRectLeft + firstRect.width - labelWidth // Align with right edge\n\t\t\t\tif (labelLeft < iframeOffset.x) labelLeft = firstRectLeft // Prevent going off-left\n\t\t\t}\n\n\t\t\t// Ensure label stays within viewport bounds slightly better\n\t\t\tlabelTop = Math.max(0, Math.min(labelTop, window.innerHeight - labelHeight))\n\t\t\tlabelLeft = Math.max(0, Math.min(labelLeft, window.innerWidth - labelWidth))\n\n\t\t\tlabel.style.top = `${labelTop}px`\n\t\t\tlabel.style.left = `${labelLeft}px`\n\n\t\t\tfragment.appendChild(label)\n\n\t\t\t// Update positions on scroll/resize\n\t\t\tconst updatePositions = () => {\n\t\t\t\tconst newRects = element.getClientRects() // Get fresh rects\n\t\t\t\tlet newIframeOffset = { x: 0, y: 0 }\n\n\t\t\t\tif (parentIframe) {\n\t\t\t\t\tconst iframeRect = parentIframe.getBoundingClientRect() // Keep getBoundingClientRect for iframe\n\t\t\t\t\tnewIframeOffset.x = iframeRect.left\n\t\t\t\t\tnewIframeOffset.y = iframeRect.top\n\t\t\t\t}\n\n\t\t\t\t// Update each overlay\n\t\t\t\toverlays.forEach((overlayData, i) => {\n\t\t\t\t\tif (i < newRects.length) {\n\t\t\t\t\t\t// Check if rect still exists\n\t\t\t\t\t\tconst newRect = newRects[i]\n\t\t\t\t\t\tconst newTop = newRect.top + newIframeOffset.y\n\t\t\t\t\t\tconst newLeft = newRect.left + newIframeOffset.x\n\n\t\t\t\t\t\toverlayData.element.style.top = `${newTop}px`\n\t\t\t\t\t\toverlayData.element.style.left = `${newLeft}px`\n\t\t\t\t\t\toverlayData.element.style.width = `${newRect.width}px`\n\t\t\t\t\t\toverlayData.element.style.height = `${newRect.height}px`\n\t\t\t\t\t\toverlayData.element.style.display =\n\t\t\t\t\t\t\tnewRect.width === 0 || newRect.height === 0 ? 'none' : 'block'\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If fewer rects now, hide extra overlays\n\t\t\t\t\t\toverlayData.element.style.display = 'none'\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\t// If there are fewer new rects than overlays, hide the extras\n\t\t\t\tif (newRects.length < overlays.length) {\n\t\t\t\t\tfor (let i = newRects.length; i < overlays.length; i++) {\n\t\t\t\t\t\toverlays[i].element.style.display = 'none'\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Update label position based on the first new rect\n\t\t\t\tif (label && newRects.length > 0) {\n\t\t\t\t\tconst firstNewRect = newRects[0]\n\t\t\t\t\tconst firstNewRectTop = firstNewRect.top + newIframeOffset.y\n\t\t\t\t\tconst firstNewRectLeft = firstNewRect.left + newIframeOffset.x\n\n\t\t\t\t\tlet newLabelTop = firstNewRectTop + 2\n\t\t\t\t\tlet newLabelLeft = firstNewRectLeft + firstNewRect.width - labelWidth - 2\n\n\t\t\t\t\tif (firstNewRect.width < labelWidth + 4 || firstNewRect.height < labelHeight + 4) {\n\t\t\t\t\t\tnewLabelTop = firstNewRectTop - labelHeight - 2\n\t\t\t\t\t\tnewLabelLeft = firstNewRectLeft + firstNewRect.width - labelWidth\n\t\t\t\t\t\tif (newLabelLeft < newIframeOffset.x) newLabelLeft = firstNewRectLeft\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ensure label stays within viewport bounds\n\t\t\t\t\tnewLabelTop = Math.max(0, Math.min(newLabelTop, window.innerHeight - labelHeight))\n\t\t\t\t\tnewLabelLeft = Math.max(0, Math.min(newLabelLeft, window.innerWidth - labelWidth))\n\n\t\t\t\t\tlabel.style.top = `${newLabelTop}px`\n\t\t\t\t\tlabel.style.left = `${newLabelLeft}px`\n\t\t\t\t\tlabel.style.display = 'block'\n\t\t\t\t} else if (label) {\n\t\t\t\t\t// Hide label if element has no rects anymore\n\t\t\t\t\tlabel.style.display = 'none'\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst throttleFunction = (func, delay) => {\n\t\t\t\tlet lastCall = 0\n\t\t\t\treturn (...args) => {\n\t\t\t\t\tconst now = performance.now()\n\t\t\t\t\tif (now - lastCall < delay) return\n\t\t\t\t\tlastCall = now\n\t\t\t\t\treturn func(...args)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst throttledUpdatePositions = throttleFunction(updatePositions, 16) // ~60fps\n\t\t\twindow.addEventListener('scroll', throttledUpdatePositions, true)\n\t\t\twindow.addEventListener('resize', throttledUpdatePositions)\n\n\t\t\t// Add cleanup function\n\t\t\tcleanupFn = () => {\n\t\t\t\twindow.removeEventListener('scroll', throttledUpdatePositions, true)\n\t\t\t\twindow.removeEventListener('resize', throttledUpdatePositions)\n\t\t\t\t// Remove overlay elements if needed\n\t\t\t\toverlays.forEach((overlay) => overlay.element.remove())\n\t\t\t\tif (label) label.remove()\n\t\t\t}\n\n\t\t\t// Then add fragment to container in one operation\n\t\t\tcontainer.appendChild(fragment)\n\n\t\t\treturn index + 1\n\t\t} finally {\n\t\t\t// Store cleanup function for later use\n\t\t\tif (cleanupFn) {\n\t\t\t\t// Keep a reference to cleanup functions in a global array\n\t\t\t\t;(window._highlightCleanupFunctions = window._highlightCleanupFunctions || []).push(\n\t\t\t\t\tcleanupFn\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// // Add this function to perform cleanup when needed\n\t// function cleanupHighlights() {\n\t// if (window._highlightCleanupFunctions && window._highlightCleanupFunctions.length) {\n\t// window._highlightCleanupFunctions.forEach(fn => fn());\n\t// window._highlightCleanupFunctions = [];\n\t// }\n\n\t// // Also remove the container\n\t// const container = document.getElementById(HIGHLIGHT_CONTAINER_ID);\n\t// if (container) container.remove();\n\t// }\n\n\t/**\n\t * Gets the position of an element in its parent.\n\t *\n\t * @param {HTMLElement} currentElement - The element to get the position for.\n\t * @returns {number} The position of the element in its parent.\n\t */\n\tfunction getElementPosition(currentElement) {\n\t\tif (!currentElement.parentElement) {\n\t\t\treturn 0 // No parent means no siblings\n\t\t}\n\n\t\tconst tagName = currentElement.nodeName.toLowerCase()\n\n\t\tconst siblings = Array.from(currentElement.parentElement.children).filter(\n\t\t\t(sib) => sib.nodeName.toLowerCase() === tagName\n\t\t)\n\n\t\tif (siblings.length === 1) {\n\t\t\treturn 0 // Only element of its type\n\t\t}\n\n\t\tconst index = siblings.indexOf(currentElement) + 1 // 1-based index\n\t\treturn index\n\t}\n\n\tfunction getXPathTree(element, stopAtBoundary = true) {\n\t\tif (xpathCache.has(element)) return xpathCache.get(element)\n\n\t\tconst segments = []\n\t\tlet currentElement = element\n\n\t\twhile (currentElement && currentElement.nodeType === Node.ELEMENT_NODE) {\n\t\t\t// Stop if we hit a shadow root or iframe\n\t\t\tif (\n\t\t\t\tstopAtBoundary &&\n\t\t\t\t(currentElement.parentNode instanceof ShadowRoot ||\n\t\t\t\t\tcurrentElement.parentNode instanceof HTMLIFrameElement)\n\t\t\t) {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tconst position = getElementPosition(currentElement)\n\t\t\tconst tagName = currentElement.nodeName.toLowerCase()\n\t\t\tconst xpathIndex = position > 0 ? `[${position}]` : ''\n\t\t\tsegments.unshift(`${tagName}${xpathIndex}`)\n\n\t\t\tcurrentElement = currentElement.parentNode\n\t\t}\n\n\t\tconst result = segments.join('/')\n\t\txpathCache.set(element, result)\n\t\treturn result\n\t}\n\n\t/**\n\t * @edit scrollable element detection\n\t * Checks if an element is scrollable. if so, return the scrollable distance on each direction (left right top bottom). if not return null.\n\t * @note distance smaller than 4 will be considered as not scrollable.\n\t * @note only check block elements, not inline elements.\n\t */\n\tfunction isScrollableElement(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) {\n\t\t\treturn null // Not a valid element\n\t\t}\n\n\t\tconst style = getCachedComputedStyle(element)\n\t\tif (!style) return null\n\n\t\t// Check if the element is a block-level element\n\t\tconst display = style.display\n\t\tif (display === 'inline' || display === 'inline-block') {\n\t\t\treturn null // Not a block-level element\n\t\t}\n\n\t\t// Check overflow properties\n\t\tconst overflowX = style.overflowX\n\t\tconst overflowY = style.overflowY\n\n\t\t// scrollbar-width/scrollbar-gutter are only set on elements designed to scroll;\n\t\t// their presence signals scroll intent even when overflow is hidden (e.g. overflow: auto on :hover)\n\t\tconst hasScrollbarSignal =\n\t\t\t(style.scrollbarWidth && style.scrollbarWidth !== 'auto') ||\n\t\t\t(style.scrollbarGutter && style.scrollbarGutter !== 'auto')\n\n\t\tconst scrollableX = overflowX === 'auto' || overflowX === 'scroll'\n\t\tconst scrollableY = overflowY === 'auto' || overflowY === 'scroll'\n\n\t\tif (!scrollableX && !scrollableY && !hasScrollbarSignal) {\n\t\t\treturn null // Not scrollable in any direction\n\t\t}\n\n\t\tconst scrollWidth = element.scrollWidth - element.clientWidth\n\t\tconst scrollHeight = element.scrollHeight - element.clientHeight\n\n\t\t// Consider small distances as not scrollable\n\t\tconst threshold = 4\n\n\t\tif (scrollWidth < threshold && scrollHeight < threshold) {\n\t\t\treturn null // Not scrollable\n\t\t}\n\n\t\tif (!scrollableY && !hasScrollbarSignal && scrollWidth < threshold) {\n\t\t\treturn null // Not scrollable horizontally\n\t\t}\n\n\t\tif (!scrollableX && !hasScrollbarSignal && scrollHeight < threshold) {\n\t\t\treturn null // Not scrollable vertically\n\t\t}\n\n\t\tconst distanceToTop = element.scrollTop\n\t\tconst distanceToLeft = element.scrollLeft\n\t\tconst distanceToRight = element.scrollWidth - element.clientWidth - element.scrollLeft\n\t\tconst distanceToBottom = element.scrollHeight - element.clientHeight - element.scrollTop\n\n\t\tconst scrollData = {\n\t\t\ttop: distanceToTop,\n\t\t\tright: distanceToRight,\n\t\t\tbottom: distanceToBottom,\n\t\t\tleft: distanceToLeft,\n\t\t}\n\n\t\t// Store extra data for the element\n\t\taddExtraData(element, {\n\t\t\tscrollable: true,\n\t\t\tscrollData: scrollData,\n\t\t})\n\n\t\treturn scrollData\n\t}\n\n\t/**\n\t * Checks if a text node is visible.\n\t *\n\t * @param {Text} textNode - The text node to check.\n\t * @returns {boolean} Whether the text node is visible.\n\t */\n\tfunction isTextNodeVisible(textNode) {\n\t\ttry {\n\t\t\t// Special case: when viewportExpansion is -1, consider all text nodes as visible\n\t\t\tif (viewportExpansion === -1) {\n\t\t\t\t// Still check parent visibility for basic filtering\n\t\t\t\tconst parentElement = textNode.parentElement\n\t\t\t\tif (!parentElement) return false\n\n\t\t\t\ttry {\n\t\t\t\t\treturn parentElement.checkVisibility({\n\t\t\t\t\t\tcheckOpacity: true,\n\t\t\t\t\t\tcheckVisibilityCSS: true,\n\t\t\t\t\t})\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Fallback if checkVisibility is not supported\n\t\t\t\t\tconst style = window.getComputedStyle(parentElement)\n\t\t\t\t\treturn style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst range = document.createRange()\n\t\t\trange.selectNodeContents(textNode)\n\t\t\tconst rects = range.getClientRects() // Use getClientRects for Range\n\n\t\t\tif (!rects || rects.length === 0) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tlet isAnyRectVisible = false\n\t\t\tlet isAnyRectInViewport = false\n\n\t\t\tfor (const rect of rects) {\n\t\t\t\t// Check size\n\t\t\t\tif (rect.width > 0 && rect.height > 0) {\n\t\t\t\t\tisAnyRectVisible = true\n\n\t\t\t\t\t// Viewport check for this rect\n\t\t\t\t\tif (!(\n\t\t\t\t\t\trect.bottom < -viewportExpansion ||\n\t\t\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\t\t\trect.left > window.innerWidth + viewportExpansion\n\t\t\t\t\t)) {\n\t\t\t\t\t\tisAnyRectInViewport = true\n\t\t\t\t\t\tbreak // Found a visible rect in viewport, no need to check others\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!isAnyRectVisible || !isAnyRectInViewport) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check parent visibility\n\t\t\tconst parentElement = textNode.parentElement\n\t\t\tif (!parentElement) return false\n\n\t\t\ttry {\n\t\t\t\treturn parentElement.checkVisibility({\n\t\t\t\t\tcheckOpacity: true,\n\t\t\t\t\tcheckVisibilityCSS: true,\n\t\t\t\t})\n\t\t\t} catch (e) {\n\t\t\t\t// Fallback if checkVisibility is not supported\n\t\t\t\tconst style = window.getComputedStyle(parentElement)\n\t\t\t\treturn style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.warn('Error checking text node visibility:', e)\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Checks if an element is accepted.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is accepted.\n\t */\n\tfunction isElementAccepted(element) {\n\t\tif (!element || !element.tagName) return false\n\n\t\t// Always accept body and common container elements\n\t\tconst alwaysAccept = new Set([\n\t\t\t'body',\n\t\t\t'div',\n\t\t\t'main',\n\t\t\t'article',\n\t\t\t'section',\n\t\t\t'nav',\n\t\t\t'header',\n\t\t\t'footer',\n\t\t])\n\t\tconst tagName = element.tagName.toLowerCase()\n\n\t\tif (alwaysAccept.has(tagName)) return true\n\n\t\tconst leafElementDenyList = new Set([\n\t\t\t'svg',\n\t\t\t'script',\n\t\t\t'style',\n\t\t\t'link',\n\t\t\t'meta',\n\t\t\t'noscript',\n\t\t\t'template',\n\t\t])\n\n\t\treturn !leafElementDenyList.has(tagName)\n\t}\n\n\t/**\n\t * Checks if an element is visible.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is visible.\n\t */\n\tfunction isElementVisible(element) {\n\t\tconst style = getCachedComputedStyle(element)\n\t\treturn (\n\t\t\telement.offsetWidth > 0 &&\n\t\t\telement.offsetHeight > 0 &&\n\t\t\tstyle?.visibility !== 'hidden' &&\n\t\t\tstyle?.display !== 'none'\n\t\t)\n\t}\n\n\t/**\n\t * Checks if an element is interactive.\n\t *\n\t * lots of comments, and uncommented code - to show the logic of what we already tried\n\t *\n\t * One of the things we tried at the beginning was also to use event listeners, and other fancy class, style stuff -> what actually worked best was just combining most things with computed cursor style :)\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t */\n\tfunction isInteractiveElement(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) {\n\t\t\treturn false\n\t\t}\n\n\t\t/**\n\t\t * @edit add interactiveBlacklist interactiveWhitelist\n\t\t */\n\t\tif (interactiveBlacklist.includes(element)) {\n\t\t\treturn false // Skip blacklisted elements\n\t\t}\n\t\tif (interactiveWhitelist.includes(element)) {\n\t\t\treturn true // Skip whitelisted elements\n\t\t}\n\n\t\t// Cache the tagName and style lookups\n\t\tconst tagName = element.tagName.toLowerCase()\n\t\tconst style = getCachedComputedStyle(element)\n\n\t\t// Define interactive cursors\n\t\tconst interactiveCursors = new Set([\n\t\t\t'pointer', // Link/clickable elements\n\t\t\t'move', // Movable elements\n\t\t\t'text', // Text selection\n\t\t\t'grab', // Grabbable elements\n\t\t\t'grabbing', // Currently grabbing\n\t\t\t'cell', // Table cell selection\n\t\t\t'copy', // Copy operation\n\t\t\t'alias', // Alias creation\n\t\t\t'all-scroll', // Scrollable content\n\t\t\t'col-resize', // Column resize\n\t\t\t'context-menu', // Context menu available\n\t\t\t'crosshair', // Precise selection\n\t\t\t'e-resize', // East resize\n\t\t\t'ew-resize', // East-west resize\n\t\t\t'help', // Help available\n\t\t\t'n-resize', // North resize\n\t\t\t'ne-resize', // Northeast resize\n\t\t\t'nesw-resize', // Northeast-southwest resize\n\t\t\t'ns-resize', // North-south resize\n\t\t\t'nw-resize', // Northwest resize\n\t\t\t'nwse-resize', // Northwest-southeast resize\n\t\t\t'row-resize', // Row resize\n\t\t\t's-resize', // South resize\n\t\t\t'se-resize', // Southeast resize\n\t\t\t'sw-resize', // Southwest resize\n\t\t\t'vertical-text', // Vertical text selection\n\t\t\t'w-resize', // West resize\n\t\t\t'zoom-in', // Zoom in\n\t\t\t'zoom-out', // Zoom out\n\t\t])\n\n\t\t// Define non-interactive cursors\n\t\tconst nonInteractiveCursors = new Set([\n\t\t\t'not-allowed', // Action not allowed\n\t\t\t'no-drop', // Drop not allowed\n\t\t\t'wait', // Processing\n\t\t\t'progress', // In progress\n\t\t\t'initial', // Initial value\n\t\t\t'inherit', // Inherited value\n\t\t\t//? Let's just include all potentially clickable elements that are not specifically blocked\n\t\t\t// 'none', // No cursor\n\t\t\t// 'default', // Default cursor\n\t\t\t// 'auto', // Browser default\n\t\t])\n\n\t\t/**\n\t\t * Checks if an element has an interactive pointer.\n\t\t *\n\t\t * @param {HTMLElement} element - The element to check.\n\t\t * @returns {boolean} Whether the element has an interactive pointer.\n\t\t */\n\t\tfunction doesElementHaveInteractivePointer(element) {\n\t\t\tif (element.tagName.toLowerCase() === 'html') return false\n\n\t\t\tif (style?.cursor && interactiveCursors.has(style.cursor)) return true\n\n\t\t\treturn false\n\t\t}\n\n\t\tlet isInteractiveCursor = doesElementHaveInteractivePointer(element)\n\n\t\t// Genius fix for almost all interactive elements\n\t\tif (isInteractiveCursor) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst interactiveElements = new Set([\n\t\t\t'a', // Links\n\t\t\t'button', // Buttons\n\t\t\t'input', // All input types (text, checkbox, radio, etc.)\n\t\t\t'select', // Dropdown menus\n\t\t\t'textarea', // Text areas\n\t\t\t'details', // Expandable details\n\t\t\t'summary', // Summary element (clickable part of details)\n\t\t\t'label', // Form labels (often clickable)\n\t\t\t'option', // Select options\n\t\t\t'optgroup', // Option groups\n\t\t\t'fieldset', // Form fieldsets (can be interactive with legend)\n\t\t\t'legend', // Fieldset legends\n\t\t])\n\n\t\t// Define explicit disable attributes and properties\n\t\tconst explicitDisableTags = new Set([\n\t\t\t'disabled', // Standard disabled attribute\n\t\t\t// 'aria-disabled', // ARIA disabled state\n\t\t\t'readonly', // Read-only state\n\t\t\t// 'aria-readonly', // ARIA read-only state\n\t\t\t// 'aria-hidden', // Hidden from accessibility\n\t\t\t// 'hidden', // Hidden attribute\n\t\t\t// 'inert', // Inert attribute\n\t\t\t// 'aria-inert', // ARIA inert state\n\t\t\t// 'tabindex=\"-1\"', // Removed from tab order\n\t\t\t// 'aria-hidden=\"true\"' // Hidden from screen readers\n\t\t])\n\n\t\t// handle inputs, select, checkbox, radio, textarea, button and make sure they are not cursor style disabled/not-allowed\n\t\tif (interactiveElements.has(tagName)) {\n\t\t\t// Check for non-interactive cursor\n\t\t\tif (style?.cursor && nonInteractiveCursors.has(style.cursor)) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check for explicit disable attributes\n\t\t\tfor (const disableTag of explicitDisableTags) {\n\t\t\t\tif (\n\t\t\t\t\telement.hasAttribute(disableTag) ||\n\t\t\t\t\telement.getAttribute(disableTag) === 'true' ||\n\t\t\t\t\telement.getAttribute(disableTag) === ''\n\t\t\t\t) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check for disabled property on form elements\n\t\t\tif (element.disabled) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check for readonly property on form elements\n\t\t\tif (element.readOnly) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check for inert property\n\t\t\tif (element.inert) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t}\n\n\t\tconst role = element.getAttribute('role')\n\t\tconst ariaRole = element.getAttribute('aria-role')\n\n\t\t// Check for contenteditable attribute\n\t\tif (element.getAttribute('contenteditable') === 'true' || element.isContentEditable) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Added enhancement to capture dropdown interactive elements\n\t\tif (\n\t\t\telement.classList &&\n\t\t\t(element.classList.contains('button') ||\n\t\t\t\telement.classList.contains('dropdown-toggle') ||\n\t\t\t\telement.getAttribute('data-index') ||\n\t\t\t\telement.getAttribute('data-toggle') === 'dropdown' ||\n\t\t\t\telement.getAttribute('aria-haspopup') === 'true')\n\t\t) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst interactiveRoles = new Set([\n\t\t\t'button', // Directly clickable element\n\t\t\t// 'link', // Clickable link\n\t\t\t'menu', // Menu container (ARIA menus)\n\t\t\t'menubar', // Menu bar container\n\t\t\t'menuitem', // Clickable menu item\n\t\t\t'menuitemradio', // Radio-style menu item (selectable)\n\t\t\t'menuitemcheckbox', // Checkbox-style menu item (toggleable)\n\t\t\t'radio', // Radio button (selectable)\n\t\t\t'checkbox', // Checkbox (toggleable)\n\t\t\t'tab', // Tab (clickable to switch content)\n\t\t\t'switch', // Toggle switch (clickable to change state)\n\t\t\t'slider', // Slider control (draggable)\n\t\t\t'spinbutton', // Number input with up/down controls\n\t\t\t'combobox', // Dropdown with text input\n\t\t\t'searchbox', // Search input field\n\t\t\t'textbox', // Text input field\n\t\t\t'listbox', // Selectable list\n\t\t\t'option', // Selectable option in a list\n\t\t\t'scrollbar', // Scrollable control\n\t\t])\n\n\t\t// Basic role/attribute checks\n\t\tconst hasInteractiveRole =\n\t\t\tinteractiveElements.has(tagName) ||\n\t\t\t(role && interactiveRoles.has(role)) ||\n\t\t\t(ariaRole && interactiveRoles.has(ariaRole))\n\n\t\tif (hasInteractiveRole) return true\n\n\t\t// check whether element has event listeners by window.getEventListeners\n\t\ttry {\n\t\t\tif (typeof getEventListeners === 'function') {\n\t\t\t\tconst listeners = getEventListeners(element)\n\t\t\t\tconst mouseEvents = ['click', 'mousedown', 'mouseup', 'dblclick']\n\t\t\t\tfor (const eventType of mouseEvents) {\n\t\t\t\t\tif (listeners[eventType] && listeners[eventType].length > 0) {\n\t\t\t\t\t\treturn true // Found a mouse interaction listener\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst getEventListenersForNode =\n\t\t\t\telement?.ownerDocument?.defaultView?.getEventListenersForNode ||\n\t\t\t\twindow.getEventListenersForNode\n\t\t\tif (typeof getEventListenersForNode === 'function') {\n\t\t\t\tconst listeners = getEventListenersForNode(element)\n\t\t\t\tconst interactionEvents = [\n\t\t\t\t\t'click',\n\t\t\t\t\t'mousedown',\n\t\t\t\t\t'mouseup',\n\t\t\t\t\t'keydown',\n\t\t\t\t\t'keyup',\n\t\t\t\t\t'submit',\n\t\t\t\t\t'change',\n\t\t\t\t\t'input',\n\t\t\t\t\t'focus',\n\t\t\t\t\t'blur',\n\t\t\t\t]\n\t\t\t\tfor (const eventType of interactionEvents) {\n\t\t\t\t\tfor (const listener of listeners) {\n\t\t\t\t\t\tif (listener.type === eventType) {\n\t\t\t\t\t\t\treturn true // Found a common interaction listener\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Fallback: Check common event attributes if getEventListeners is not available (getEventListeners doesn't work in page.evaluate context)\n\t\t\tconst commonMouseAttrs = ['onclick', 'onmousedown', 'onmouseup', 'ondblclick']\n\t\t\tfor (const attr of commonMouseAttrs) {\n\t\t\t\tif (element.hasAttribute(attr) || typeof element[attr] === 'function') {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t// console.warn(`Could not check event listeners for ${element.tagName}:`, e);\n\t\t\t// If checking listeners fails, rely on other checks\n\t\t}\n\n\t\t/**\n\t\t * @edit scrollable element detection\n\t\t */\n\t\tif (isScrollableElement(element)) {\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\t}\n\n\t/**\n\t * Checks if an element is the topmost element at its position.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is the topmost element at its position.\n\t */\n\tfunction isTopElement(element) {\n\t\t// Special case: when viewportExpansion is -1, consider all elements as \"top\" elements\n\t\tif (viewportExpansion === -1) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst rects = getCachedClientRects(element) // Replace element.getClientRects()\n\n\t\tif (!rects || rects.length === 0) {\n\t\t\treturn false // No geometry, cannot be top\n\t\t}\n\n\t\tlet isAnyRectInViewport = false\n\t\tfor (const rect of rects) {\n\t\t\t// Use the same logic as isInExpandedViewport check\n\t\t\tif (\n\t\t\t\trect.width > 0 &&\n\t\t\t\trect.height > 0 &&\n\t\t\t\t!(\n\t\t\t\t\t// Only check non-empty rects\n\t\t\t\t\trect.bottom < -viewportExpansion ||\n\t\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\t\trect.left > window.innerWidth + viewportExpansion\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tisAnyRectInViewport = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (!isAnyRectInViewport) {\n\t\t\treturn false // All rects are outside the viewport area\n\t\t}\n\n\t\t// Find the correct document context and root element\n\t\tlet doc = element.ownerDocument\n\n\t\t// If we're in an iframe, elements are considered top by default\n\t\tif (doc !== window.document) {\n\t\t\treturn true\n\t\t}\n\n\t\t/**\n\t\t * @edit improve `sampleRect`, filter out rects with 0 area\n\t\t */\n\t\t// find a rect that has width and height as sample\n\t\tlet rect = Array.from(rects).find((r) => r.width > 0 && r.height > 0)\n\t\tif (!rect) {\n\t\t\treturn false // No valid rect found\n\t\t}\n\n\t\t// For shadow DOM, we need to check within its own root context\n\t\tconst shadowRoot = element.getRootNode()\n\t\tif (shadowRoot instanceof ShadowRoot) {\n\t\t\tconst centerX = rect.left + rect.width / 2\n\t\t\tconst centerY = rect.top + rect.height / 2\n\n\t\t\ttry {\n\t\t\t\tconst topEl = shadowRoot.elementFromPoint(centerX, centerY)\n\t\t\t\tif (!topEl) return false\n\n\t\t\t\tlet current = topEl\n\t\t\t\twhile (current && current !== shadowRoot) {\n\t\t\t\t\tif (current === element) return true\n\t\t\t\t\tcurrent = current.parentElement\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t} catch (e) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\tconst margin = 5\n\n\t\t// For elements in viewport, check if they're topmost. Do the check in the\n\t\t// center of the element and at the corners to ensure we catch more cases.\n\t\tconst checkPoints = [\n\t\t\t// Initially only this was used, but it was not enough\n\t\t\t{ x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 },\n\t\t\t{ x: rect.left + margin, y: rect.top + margin }, // top left\n\t\t\t// { x: rect.right - margin, y: rect.top + margin }, // top right\n\t\t\t// { x: rect.left + margin, y: rect.bottom - margin }, // bottom left\n\t\t\t{ x: rect.right - margin, y: rect.bottom - margin }, // bottom right\n\t\t]\n\n\t\treturn checkPoints.some(({ x, y }) => {\n\t\t\ttry {\n\t\t\t\tconst topEl = document.elementFromPoint(x, y)\n\t\t\t\tif (!topEl) return false\n\n\t\t\t\tlet current = topEl\n\t\t\t\twhile (current && current !== document.documentElement) {\n\t\t\t\t\tif (current === element) return true\n\t\t\t\t\tcurrent = current.parentElement\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t} catch (e) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Checks if an element is within the expanded viewport.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @param {number} viewportExpansion - The viewport expansion.\n\t * @returns {boolean} Whether the element is within the expanded viewport.\n\t */\n\tfunction isInExpandedViewport(element, viewportExpansion) {\n\t\tif (viewportExpansion === -1) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst rects = element.getClientRects() // Use getClientRects\n\n\t\tif (!rects || rects.length === 0) {\n\t\t\t// Fallback to getBoundingClientRect if getClientRects is empty,\n\t\t\t// useful for elements like <svg> that might not have client rects but have a bounding box.\n\t\t\tconst boundingRect = getCachedBoundingRect(element)\n\t\t\tif (!boundingRect || boundingRect.width === 0 || boundingRect.height === 0) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !(\n\t\t\t\tboundingRect.bottom < -viewportExpansion ||\n\t\t\t\tboundingRect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\tboundingRect.right < -viewportExpansion ||\n\t\t\t\tboundingRect.left > window.innerWidth + viewportExpansion\n\t\t\t)\n\t\t}\n\n\t\t// Check if *any* client rect is within the viewport\n\t\tfor (const rect of rects) {\n\t\t\tif (rect.width === 0 || rect.height === 0) continue // Skip empty rects\n\n\t\t\tif (!(\n\t\t\t\trect.bottom < -viewportExpansion ||\n\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\trect.left > window.innerWidth + viewportExpansion\n\t\t\t)) {\n\t\t\t\treturn true // Found at least one rect in the viewport\n\t\t\t}\n\t\t}\n\n\t\treturn false // No rects were found in the viewport\n\t}\n\n\t// /**\n\t// * Gets the effective scroll of an element.\n\t// *\n\t// * @param {HTMLElement} element - The element to get the effective scroll for.\n\t// * @returns {Object} The effective scroll of the element.\n\t// */\n\t// function getEffectiveScroll(element) {\n\t// let currentEl = element;\n\t// let scrollX = 0;\n\t// let scrollY = 0;\n\n\t// while (currentEl && currentEl !== document.documentElement) {\n\t// if (currentEl.scrollLeft || currentEl.scrollTop) {\n\t// scrollX += currentEl.scrollLeft;\n\t// scrollY += currentEl.scrollTop;\n\t// }\n\t// currentEl = currentEl.parentElement;\n\t// }\n\n\t// scrollX += window.scrollX;\n\t// scrollY += window.scrollY;\n\n\t// return { scrollX, scrollY };\n\t// }\n\n\t/**\n\t * Checks if an element is an interactive candidate.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is an interactive candidate.\n\t */\n\n\t// @edit fix \"aria-*\" attributes check\n\tconst INTERACTIVE_ARIA_ATTRS = [\n\t\t'aria-expanded',\n\t\t'aria-checked',\n\t\t'aria-selected',\n\t\t'aria-pressed',\n\t\t'aria-haspopup',\n\t\t'aria-controls',\n\t\t'aria-owns',\n\t\t'aria-activedescendant',\n\t\t'aria-valuenow',\n\t\t'aria-valuetext',\n\t\t'aria-valuemax',\n\t\t'aria-valuemin',\n\t\t'aria-autocomplete',\n\t]\n\n\tfunction hasInteractiveAria(el) {\n\t\tfor (let i = 0; i < INTERACTIVE_ARIA_ATTRS.length; i++) {\n\t\t\tif (el.hasAttribute(INTERACTIVE_ARIA_ATTRS[i])) return true\n\t\t}\n\t\treturn false\n\t}\n\n\tfunction isInteractiveCandidate(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) return false\n\n\t\tconst tagName = element.tagName.toLowerCase()\n\n\t\t// Fast-path for common interactive elements\n\t\tconst interactiveElements = new Set([\n\t\t\t'a',\n\t\t\t'button',\n\t\t\t'input',\n\t\t\t'select',\n\t\t\t'textarea',\n\t\t\t'details',\n\t\t\t'summary',\n\t\t\t'label',\n\t\t])\n\n\t\tif (interactiveElements.has(tagName)) return true\n\n\t\t// Quick attribute checks without getting full lists\n\t\tconst hasQuickInteractiveAttr =\n\t\t\telement.hasAttribute('onclick') ||\n\t\t\telement.hasAttribute('role') ||\n\t\t\telement.hasAttribute('tabindex') ||\n\t\t\thasInteractiveAria(element) ||\n\t\t\telement.hasAttribute('data-action') ||\n\t\t\telement.getAttribute('contenteditable') === 'true'\n\n\t\treturn hasQuickInteractiveAttr\n\t}\n\n\t// --- Define constants for distinct interaction check ---\n\tconst DISTINCT_INTERACTIVE_TAGS = new Set([\n\t\t'a',\n\t\t'button',\n\t\t'input',\n\t\t'select',\n\t\t'textarea',\n\t\t'summary',\n\t\t'details',\n\t\t'label',\n\t\t'option',\n\t\t'li',\n\t])\n\tconst DISTINCT_INTERACTIVE_ROLES = new Set([\n\t\t'button',\n\t\t'link',\n\t\t'menuitem',\n\t\t'menuitemradio',\n\t\t'menuitemcheckbox',\n\t\t'radio',\n\t\t'checkbox',\n\t\t'tab',\n\t\t'switch',\n\t\t'slider',\n\t\t'spinbutton',\n\t\t'combobox',\n\t\t'searchbox',\n\t\t'textbox',\n\t\t'listbox',\n\t\t'listitem',\n\t\t'treeitem',\n\t\t'row',\n\t\t'option',\n\t\t'scrollbar',\n\t])\n\n\t/**\n\t * Heuristically determines if an element should be considered as independently interactive,\n\t * even if it's nested inside another interactive container.\n\t *\n\t * This function helps detect deeply nested actionable elements (e.g., menu items within a button)\n\t * that may not be picked up by strict interactivity checks.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is heuristically interactive.\n\t */\n\tfunction isHeuristicallyInteractive(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) return false\n\n\t\t// Skip non-visible elements early for performance\n\t\tif (!isElementVisible(element)) return false\n\n\t\t// Check for common attributes that often indicate interactivity\n\t\tconst hasInteractiveAttributes =\n\t\t\telement.hasAttribute('role') ||\n\t\t\telement.hasAttribute('tabindex') ||\n\t\t\telement.hasAttribute('onclick') ||\n\t\t\ttypeof element.onclick === 'function'\n\n\t\t// Check for semantic class names suggesting interactivity\n\t\tconst hasInteractiveClass = /\\b(btn|clickable|menu|item|entry|link)\\b/i.test(\n\t\t\telement.className || ''\n\t\t)\n\n\t\t// Determine whether the element is inside a known interactive container\n\t\tconst isInKnownContainer = Boolean(\n\t\t\telement.closest('button,a,[role=\"button\"],.menu,.dropdown,.list,.toolbar')\n\t\t)\n\n\t\t// Ensure the element has at least one visible child (to avoid marking empty wrappers)\n\t\tconst hasVisibleChildren = [...element.children].some(isElementVisible)\n\n\t\t// Avoid highlighting elements whose parent is <body> (top-level wrappers)\n\t\tconst isParentBody = element.parentElement && element.parentElement.isSameNode(document.body)\n\n\t\treturn (\n\t\t\t(isInteractiveElement(element) || hasInteractiveAttributes || hasInteractiveClass) &&\n\t\t\thasVisibleChildren &&\n\t\t\tisInKnownContainer &&\n\t\t\t!isParentBody\n\t\t)\n\t}\n\n\t/**\n\t * Checks if an element likely represents a distinct interaction\n\t * separate from its parent (if the parent is also interactive).\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is a distinct interaction.\n\t */\n\tfunction isElementDistinctInteraction(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) {\n\t\t\treturn false\n\t\t}\n\n\t\tconst tagName = element.tagName.toLowerCase()\n\t\tconst role = element.getAttribute('role')\n\n\t\t// Check if it's an iframe - always distinct boundary\n\t\tif (tagName === 'iframe') {\n\t\t\treturn true\n\t\t}\n\n\t\t// Check tag name\n\t\tif (DISTINCT_INTERACTIVE_TAGS.has(tagName)) {\n\t\t\treturn true\n\t\t}\n\t\t// Check interactive roles\n\t\tif (role && DISTINCT_INTERACTIVE_ROLES.has(role)) {\n\t\t\treturn true\n\t\t}\n\t\t// Check contenteditable\n\t\tif (element.isContentEditable || element.getAttribute('contenteditable') === 'true') {\n\t\t\treturn true\n\t\t}\n\t\t// Check for common testing/automation attributes\n\t\tif (\n\t\t\telement.hasAttribute('data-testid') ||\n\t\t\telement.hasAttribute('data-cy') ||\n\t\t\telement.hasAttribute('data-test')\n\t\t) {\n\t\t\treturn true\n\t\t}\n\t\t// Check for explicit onclick handler (attribute or property)\n\t\tif (element.hasAttribute('onclick') || typeof element.onclick === 'function') {\n\t\t\treturn true\n\t\t}\n\t\t// ARIA state attributes imply the element manages its own interaction state\n\t\tif (hasInteractiveAria(element)) {\n\t\t\treturn true\n\t\t}\n\n\t\t// return false\n\n\t\t// Check for other common interaction event listeners\n\t\ttry {\n\t\t\tconst getEventListenersForNode =\n\t\t\t\telement?.ownerDocument?.defaultView?.getEventListenersForNode ||\n\t\t\t\twindow.getEventListenersForNode\n\t\t\tif (typeof getEventListenersForNode === 'function') {\n\t\t\t\tconst listeners = getEventListenersForNode(element)\n\t\t\t\tconst interactionEvents = [\n\t\t\t\t\t'click',\n\t\t\t\t\t'mousedown',\n\t\t\t\t\t'mouseup',\n\t\t\t\t\t'keydown',\n\t\t\t\t\t'keyup',\n\t\t\t\t\t'submit',\n\t\t\t\t\t'change',\n\t\t\t\t\t'input',\n\t\t\t\t\t'focus',\n\t\t\t\t\t'blur',\n\t\t\t\t]\n\t\t\t\tfor (const eventType of interactionEvents) {\n\t\t\t\t\tfor (const listener of listeners) {\n\t\t\t\t\t\tif (listener.type === eventType) {\n\t\t\t\t\t\t\treturn true // Found a common interaction listener\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Fallback: Check common event attributes if getEventListeners is not available (getEventListenersForNode doesn't work in page.evaluate context)\n\t\t\tconst commonEventAttrs = [\n\t\t\t\t'onmousedown',\n\t\t\t\t'onmouseup',\n\t\t\t\t'onkeydown',\n\t\t\t\t'onkeyup',\n\t\t\t\t'onsubmit',\n\t\t\t\t'onchange',\n\t\t\t\t'oninput',\n\t\t\t\t'onfocus',\n\t\t\t\t'onblur',\n\t\t\t]\n\t\t\tif (commonEventAttrs.some((attr) => element.hasAttribute(attr))) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t// console.warn(`Could not check event listeners for ${element.tagName}:`, e);\n\t\t\t// If checking listeners fails, rely on other checks\n\t\t}\n\n\t\t// if the element is not strictly interactive but appears clickable based on heuristic signals\n\t\tif (isHeuristicallyInteractive(element)) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Scrollable containers are always distinct — the LLM needs their index for targeted scrolling.\n\t\t// Check extraData (already set by isScrollableElement in isInteractiveElement) to avoid redundant layout reads.\n\t\tif (extraData.get(element)?.scrollable) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Default to false: if it's interactive but doesn't match above,\n\t\t// assume it triggers the same action as the parent.\n\t\treturn false\n\t}\n\t// --- End distinct interaction check ---\n\n\t/**\n * Handles the logic for deciding whether to highlight an element and performing the highlight.\n * @param {\n {\n tagName: string;\n attributes: Record<string, string>;\n xpath: any;\n children: never[];\n isVisible?: boolean;\n isTopElement?: boolean;\n isInteractive?: boolean;\n isInViewport?: boolean;\n highlightIndex?: number;\n shadowRoot?: boolean;\n }} nodeData - The node data object.\n * @param {HTMLElement} node - The node to highlight.\n * @param {HTMLElement | null} parentIframe - The parent iframe node.\n * @param {boolean} isParentHighlighted - Whether the parent node is highlighted.\n * @returns {boolean} Whether the element was highlighted.\n */\n\tfunction handleHighlighting(nodeData, node, parentIframe, isParentHighlighted) {\n\t\tif (!nodeData.isInteractive) return false // Not interactive, definitely don't highlight\n\n\t\tlet shouldHighlight = false\n\t\tif (!isParentHighlighted) {\n\t\t\t// Parent wasn't highlighted, this interactive node can be highlighted.\n\t\t\tshouldHighlight = true\n\t\t} else {\n\t\t\t// Parent *was* highlighted. Only highlight this node if it represents a distinct interaction.\n\t\t\tif (isElementDistinctInteraction(node)) {\n\t\t\t\tshouldHighlight = true\n\t\t\t} else {\n\t\t\t\t// console.log(`Skipping highlight for ${nodeData.tagName} (parent highlighted)`);\n\t\t\t\tshouldHighlight = false\n\t\t\t}\n\t\t}\n\n\t\tif (shouldHighlight) {\n\t\t\t// Check viewport status before assigning index and highlighting\n\t\t\tnodeData.isInViewport = isInExpandedViewport(node, viewportExpansion)\n\n\t\t\t// When viewportExpansion is -1, all interactive elements should get a highlight index\n\t\t\t// regardless of viewport status\n\t\t\tif (nodeData.isInViewport || viewportExpansion === -1) {\n\t\t\t\tnodeData.highlightIndex = highlightIndex++\n\n\t\t\t\tif (doHighlightElements) {\n\t\t\t\t\tif (focusHighlightIndex >= 0) {\n\t\t\t\t\t\tif (focusHighlightIndex === nodeData.highlightIndex) {\n\t\t\t\t\t\t\thighlightElement(node, nodeData.highlightIndex, parentIframe)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\thighlightElement(node, nodeData.highlightIndex, parentIframe)\n\t\t\t\t\t}\n\t\t\t\t\treturn true // Successfully highlighted\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// console.log(`Skipping highlight for ${nodeData.tagName} (outside viewport)`);\n\t\t\t}\n\t\t}\n\n\t\treturn false // Did not highlight\n\t}\n\n\t/**\n\t * Creates a node data object for a given node and its descendants.\n\t *\n\t * @param {HTMLElement} node - The node to process.\n\t * @param {HTMLElement | null} parentIframe - The parent iframe node.\n\t * @param {boolean} isParentHighlighted - Whether the parent node is highlighted.\n\t * @returns {string | null} The ID of the node data object, or null if the node is not processed.\n\t */\n\tfunction buildDomTree(node, parentIframe = null, isParentHighlighted = false) {\n\t\t// Fast rejection checks first\n\t\tif (\n\t\t\t!node ||\n\t\t\tnode.id === HIGHLIGHT_CONTAINER_ID ||\n\t\t\t(node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE)\n\t\t) {\n\t\t\treturn null\n\t\t}\n\n\t\tif (!node || node.id === HIGHLIGHT_CONTAINER_ID) {\n\t\t\treturn null\n\t\t}\n\n\t\t/**\n\t\t * @edit add `data-browser-use-ignore` attribute\n\t\t */\n\t\tif (node.dataset?.browserUseIgnore === 'true' || node.dataset?.pageAgentIgnore === 'true') {\n\t\t\treturn null // Skip this node and its children\n\t\t}\n\n\t\t/**\n\t\t * @edit exclude aria-hidden elements\n\t\t */\n\t\tif (node.getAttribute && node.getAttribute('aria-hidden') === 'true') {\n\t\t\treturn null // Skip this node and its children\n\t\t}\n\n\t\t// Special handling for root node (body)\n\t\tif (node === document.body) {\n\t\t\tconst nodeData = {\n\t\t\t\ttagName: 'body',\n\t\t\t\tattributes: {},\n\t\t\t\txpath: '/body',\n\t\t\t\tchildren: [],\n\t\t\t}\n\n\t\t\t// Process children of body\n\t\t\tfor (const child of node.childNodes) {\n\t\t\t\tconst domElement = buildDomTree(child, parentIframe, false) // Body's children have no highlighted parent initially\n\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t}\n\n\t\t\tconst id = `${ID.current++}`\n\t\t\tDOM_HASH_MAP[id] = nodeData\n\t\t\treturn id\n\t\t}\n\n\t\t// Early bailout for non-element nodes except text\n\t\tif (node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Process text nodes\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst textContent = node.textContent?.trim()\n\t\t\tif (!textContent) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\t// Only check visibility for text nodes that might be visible\n\t\t\tconst parentElement = node.parentElement\n\t\t\tif (!parentElement || parentElement.tagName.toLowerCase() === 'script') {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst id = `${ID.current++}`\n\t\t\tDOM_HASH_MAP[id] = {\n\t\t\t\ttype: 'TEXT_NODE',\n\t\t\t\ttext: textContent,\n\t\t\t\tisVisible: isTextNodeVisible(node),\n\t\t\t}\n\t\t\treturn id\n\t\t}\n\n\t\t// Quick checks for element nodes\n\t\tif (node.nodeType === Node.ELEMENT_NODE && !isElementAccepted(node)) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Early viewport check - only filter out elements clearly outside viewport\n\t\t// The getBoundingClientRect() of the Shadow DOM host element may return width/height = 0\n\t\tif (viewportExpansion !== -1 && !node.shadowRoot) {\n\t\t\tconst rect = getCachedBoundingRect(node) // Keep for initial quick check\n\t\t\tconst style = getCachedComputedStyle(node)\n\n\t\t\t// Skip viewport check for fixed/sticky elements as they may appear anywhere\n\t\t\tconst isFixedOrSticky = style && (style.position === 'fixed' || style.position === 'sticky')\n\n\t\t\t// Check if element has actual dimensions using offsetWidth/Height (quick check)\n\t\t\tconst hasSize = node.offsetWidth > 0 || node.offsetHeight > 0\n\n\t\t\t// Use getBoundingClientRect for the quick OUTSIDE check.\n\t\t\t// isInExpandedViewport will do the more accurate check later if needed.\n\t\t\tif (\n\t\t\t\t!rect ||\n\t\t\t\t(!isFixedOrSticky &&\n\t\t\t\t\t!hasSize &&\n\t\t\t\t\t(rect.bottom < -viewportExpansion ||\n\t\t\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\t\t\trect.left > window.innerWidth + viewportExpansion))\n\t\t\t) {\n\t\t\t\t// console.log(\"Skipping node outside viewport (quick check):\", node.tagName, rect);\n\t\t\t\treturn null\n\t\t\t}\n\t\t}\n\n\t\t/**\n * @type {\n {\n tagName: string;\n attributes: Record<string, string | null>;\n xpath: any;\n children: never[];\n isVisible?: boolean;\n isTopElement?: boolean;\n isInteractive?: boolean;\n isInViewport?: boolean;\n highlightIndex?: number;\n shadowRoot?: boolean;\n }\n } nodeData - The node data object.\n */\n\t\tconst nodeData = {\n\t\t\ttagName: node.tagName.toLowerCase(),\n\t\t\tattributes: {},\n\n\t\t\t/**\n\t\t\t * @edit no need for xpath\n\t\t\t */\n\t\t\t// xpath: getXPathTree(node, true),\n\n\t\t\tchildren: [],\n\t\t}\n\n\t\t// Get attributes for interactive elements or potential text containers\n\t\tif (\n\t\t\tisInteractiveCandidate(node) ||\n\t\t\tnode.tagName.toLowerCase() === 'iframe' ||\n\t\t\tnode.tagName.toLowerCase() === 'body'\n\t\t) {\n\t\t\tconst attributeNames = node.getAttributeNames?.() || []\n\t\t\tfor (const name of attributeNames) {\n\t\t\t\tconst value = node.getAttribute(name)\n\t\t\t\tnodeData.attributes[name] = value\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * @edit @workaround input.checked\n\t\t\t */\n\t\t\tif (\n\t\t\t\tnode.tagName.toLowerCase() === 'input' &&\n\t\t\t\t(node.type === 'checkbox' || node.type === 'radio')\n\t\t\t) {\n\t\t\t\tnodeData.attributes.checked = node.checked ? 'true' : 'false' // Store as string for consistency\n\t\t\t}\n\t\t}\n\n\t\tlet nodeWasHighlighted = false\n\t\t// Perform visibility, interactivity, and highlighting checks\n\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\tnodeData.isVisible = isElementVisible(node) // isElementVisible uses offsetWidth/Height, which is fine\n\t\t\tif (nodeData.isVisible) {\n\t\t\t\tnodeData.isTopElement = isTopElement(node)\n\n\t\t\t\t// Special handling for ARIA menu containers - check interactivity even if not top element\n\t\t\t\tconst role = node.getAttribute('role')\n\t\t\t\tconst isMenuContainer = role === 'menu' || role === 'menubar' || role === 'listbox'\n\n\t\t\t\tif (nodeData.isTopElement || isMenuContainer) {\n\t\t\t\t\tnodeData.isInteractive = isInteractiveElement(node)\n\t\t\t\t\t// Call the dedicated highlighting function\n\t\t\t\t\tnodeWasHighlighted = handleHighlighting(nodeData, node, parentIframe, isParentHighlighted)\n\n\t\t\t\t\t/**\n\t\t\t\t\t * @edit direct dom ref\n\t\t\t\t\t */\n\t\t\t\t\tnodeData.ref = node\n\n\t\t\t\t\t/**\n\t\t\t\t\t * @edit make sure attributes exist for interactive candidates.\n\t\t\t\t\t * @note if the element failed the isInteractiveCandidate, attributes would be empty.\n\t\t\t\t\t */\n\t\t\t\t\tif (nodeData.isInteractive && Object.keys(nodeData.attributes).length === 0) {\n\t\t\t\t\t\tconst attributeNames = node.getAttributeNames?.() || []\n\t\t\t\t\t\tfor (const name of attributeNames) {\n\t\t\t\t\t\t\tconst value = node.getAttribute(name)\n\t\t\t\t\t\t\tnodeData.attributes[name] = value\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Process children, with special handling for iframes and rich text editors\n\t\tif (node.tagName) {\n\t\t\tconst tagName = node.tagName.toLowerCase()\n\n\t\t\t// Handle iframes\n\t\t\tif (tagName === 'iframe') {\n\t\t\t\ttry {\n\t\t\t\t\tconst iframeDoc = node.contentDocument || node.contentWindow?.document\n\t\t\t\t\tif (iframeDoc) {\n\t\t\t\t\t\tfor (const child of iframeDoc.childNodes) {\n\t\t\t\t\t\t\tconst domElement = buildDomTree(child, node, false)\n\t\t\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.warn('Unable to access iframe:', e)\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Handle rich text editors and contenteditable elements\n\t\t\telse if (\n\t\t\t\tnode.isContentEditable ||\n\t\t\t\tnode.getAttribute('contenteditable') === 'true' ||\n\t\t\t\tnode.id === 'tinymce' ||\n\t\t\t\tnode.classList.contains('mce-content-body') ||\n\t\t\t\t(tagName === 'body' && node.getAttribute('data-id')?.startsWith('mce_'))\n\t\t\t) {\n\t\t\t\t// Process all child nodes to capture formatted text\n\t\t\t\tfor (const child of node.childNodes) {\n\t\t\t\t\tconst domElement = buildDomTree(child, parentIframe, nodeWasHighlighted)\n\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Handle shadow DOM\n\t\t\t\tif (node.shadowRoot) {\n\t\t\t\t\tnodeData.shadowRoot = true\n\t\t\t\t\tfor (const child of node.shadowRoot.childNodes) {\n\t\t\t\t\t\tconst domElement = buildDomTree(child, parentIframe, nodeWasHighlighted)\n\t\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle regular elements\n\t\t\t\tfor (const child of node.childNodes) {\n\t\t\t\t\t// Pass the highlighted status of the *current* node to its children\n\t\t\t\t\tconst passHighlightStatusToChild = nodeWasHighlighted || isParentHighlighted\n\t\t\t\t\tconst domElement = buildDomTree(child, parentIframe, passHighlightStatusToChild)\n\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Skip empty anchor tags only if they have no dimensions and no children\n\t\tif (nodeData.tagName === 'a' && nodeData.children.length === 0 && !nodeData.attributes.href) {\n\t\t\t// Check if the anchor has actual dimensions\n\t\t\tconst rect = getCachedBoundingRect(node)\n\t\t\tconst hasSize =\n\t\t\t\t(rect && rect.width > 0 && rect.height > 0) || node.offsetWidth > 0 || node.offsetHeight > 0\n\n\t\t\tif (!hasSize) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * @edit add `extra` field for extra data\n\t\t */\n\t\tnodeData.extra = extraData.get(node) || null\n\n\t\tconst id = `${ID.current++}`\n\t\tDOM_HASH_MAP[id] = nodeData\n\t\treturn id\n\t}\n\n\tconst rootId = buildDomTree(document.body)\n\n\t// Clear the cache before starting\n\tDOM_CACHE.clearCache()\n\n\treturn { rootId, map: DOM_HASH_MAP }\n}\n","import domTree from './dom_tree/index.js'\nimport {\n\tElementDomNode,\n\tFlatDomTree,\n\tInteractiveElementDomNode,\n\tTextDomNode,\n} from './dom_tree/type'\n\n/**\n * Viewport expansion for DOM tree extraction.\n * -1 means full page (no viewport restriction)\n * 0 means viewport only\n * positive values expand the viewport by that many pixels\n *\n * @note Since isTopElement depends on elementFromPoint,\n * it returns null when out of viewport, this feature has no practical use, only differ between -1 and 0\n */\nconst DEFAULT_VIEWPORT_EXPANSION = -1\n\nexport function resolveViewportExpansion(viewportExpansion?: number): number {\n\treturn viewportExpansion ?? DEFAULT_VIEWPORT_EXPANSION\n}\n\nexport interface DomConfig {\n\tviewportExpansion?: number\n\tinteractiveBlacklist?: (Element | (() => Element))[]\n\tinteractiveWhitelist?: (Element | (() => Element))[]\n\tincludeAttributes?: string[]\n\thighlightOpacity?: number\n\thighlightLabelOpacity?: number\n\n\t/**\n\t * Preserve semantic landmark tags in dehydrated output even if not interactive\n\t * @note maybe confusing for LLM combining with page scrolling, use with caution\n\t **/\n\tkeepSemanticTags?: boolean\n}\n\n// TODO: corresponding roles\nconst SEMANTIC_TAGS = new Set([\n\t'nav',\n\t'menu',\n\t// 'main',\n\t'header',\n\t'footer',\n\t'aside',\n\t// 'article',\n\t// 'form',\n\t'dialog',\n])\n\n/**\n * 用于检测可交互元素是否是新出现的。\n */\nconst newElementsCache = new WeakMap<HTMLElement, string>()\n\nexport function getFlatTree(config: DomConfig): FlatDomTree {\n\tconst viewportExpansion = resolveViewportExpansion(config.viewportExpansion)\n\n\tconst interactiveBlacklist = [] as Element[]\n\tfor (const item of config.interactiveBlacklist || []) {\n\t\tif (typeof item === 'function') {\n\t\t\tinteractiveBlacklist.push(item())\n\t\t} else {\n\t\t\tinteractiveBlacklist.push(item)\n\t\t}\n\t}\n\n\tconst interactiveWhitelist = [] as Element[]\n\tfor (const item of config.interactiveWhitelist || []) {\n\t\tif (typeof item === 'function') {\n\t\t\tinteractiveWhitelist.push(item())\n\t\t} else {\n\t\t\tinteractiveWhitelist.push(item)\n\t\t}\n\t}\n\n\tconst elements = domTree({\n\t\tdoHighlightElements: true,\n\t\tdebugMode: true,\n\t\tfocusHighlightIndex: -1,\n\t\tviewportExpansion,\n\t\tinteractiveBlacklist,\n\t\tinteractiveWhitelist,\n\t\thighlightOpacity: config.highlightOpacity ?? 0.0,\n\t\thighlightLabelOpacity: config.highlightLabelOpacity ?? 0.1,\n\t}) as FlatDomTree\n\n\tconst currentUrl = window.location.href\n\n\t/**\n\t * 标记新出现的元素\n\t * @todo browser-use 使用 hash(位置,属性等信息) 来判断是否同一个元素,\n\t * 能够解决 1. 元素被删除后重新添加 2. 页面卸载 等问题。\n\t * 这里先简单做.\n\t */\n\tfor (const nodeId in elements.map) {\n\t\tconst node = elements.map[nodeId]\n\t\tif (node.isInteractive && node.ref) {\n\t\t\tconst ref = node.ref as HTMLElement\n\t\t\t// @note 这样太严格,元素是可以跨页面存在的\n\t\t\t// if (newElementsCache.get(ref) !== currentUrl) {\n\t\t\tif (!newElementsCache.has(ref)) {\n\t\t\t\tnewElementsCache.set(ref, currentUrl)\n\t\t\t\tnode.isNew = true\n\t\t\t}\n\t\t}\n\t}\n\n\treturn elements\n}\n\nconst globRegexCache = new Map<string, RegExp>()\n\nfunction globToRegex(pattern: string): RegExp {\n\tlet regex = globRegexCache.get(pattern)\n\tif (!regex) {\n\t\tconst escaped = pattern.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&')\n\t\tregex = new RegExp(`^${escaped.replace(/\\*/g, '.*')}$`)\n\t\tglobRegexCache.set(pattern, regex)\n\t}\n\treturn regex\n}\n\nfunction matchAttributes(\n\tattrs: Record<string, string>,\n\tpatterns: string[]\n): Record<string, string> {\n\tconst result: Record<string, string> = {}\n\n\tfor (const pattern of patterns) {\n\t\tif (pattern.includes('*')) {\n\t\t\tconst regex = globToRegex(pattern)\n\t\t\tfor (const key of Object.keys(attrs)) {\n\t\t\t\tif (regex.test(key) && attrs[key].trim()) {\n\t\t\t\t\tresult[key] = attrs[key].trim()\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tconst value = attrs[pattern]\n\t\t\tif (value && value.trim()) {\n\t\t\t\tresult[pattern] = value.trim()\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\n/**\n * elementsToString 内部使用的类型\n */\ninterface TreeNode {\n\ttype: 'text' | 'element'\n\tparent: TreeNode | null\n\tchildren: TreeNode[]\n\tisVisible: boolean\n\t// Text node properties\n\ttext?: string\n\t// Element node properties\n\ttagName?: string\n\tattributes?: Record<string, string>\n\tisInteractive?: boolean\n\tisTopElement?: boolean\n\tisNew?: boolean\n\thighlightIndex?: number\n\textra?: Record<string, any>\n}\n\n/**\n * 对应 python 中的 views::clickable_elements_to_string,\n * 将 dom 信息处理成适合 llm 阅读的文本格式\n * @形如\n * ``` text\n * [0]<a aria-label=page-agent.js 首页 />\n * [1]<div >P />\n * [2]<div >page-agent.js\n * UI Agent in your webpage />\n * [3]<a >文档 />\n * [4]<a aria-label=查看源码(在新窗口打开)>源码 />\n * UI Agent in your webpage\n * 用户输入需求,AI 理解页面并自动操作。\n * [5]<a role=button>快速开始 />\n * [6]<a role=button>查看文档 />\n * 无需后端\n * ```\n * 其中可交互元素用序号标出,提示llm可以用序号操作。\n * 缩进代表父子关系。\n * 普通文本则直接列出来。\n *\n * @todo 数据脱敏过滤器\n */\nexport function flatTreeToString(\n\tflatTree: FlatDomTree,\n\tincludeAttributes: string[] = [],\n\tkeepSemanticTags = false\n): string {\n\tconst DEFAULT_INCLUDE_ATTRIBUTES = [\n\t\t'title',\n\t\t'type',\n\t\t'checked',\n\t\t'name',\n\t\t'role',\n\t\t'value',\n\t\t'placeholder',\n\t\t'data-date-format',\n\t\t'alt',\n\t\t'aria-label',\n\t\t'aria-expanded',\n\t\t'data-state',\n\t\t'aria-checked',\n\n\t\t// @edit added for better form handling\n\t\t'id',\n\t\t'for',\n\n\t\t// for jump check\n\t\t'target',\n\n\t\t// absolute position dropdown menu\n\t\t'aria-haspopup',\n\t\t'aria-controls',\n\t\t'aria-owns',\n\n\t\t// content editable\n\t\t'contenteditable',\n\t]\n\n\tconst includeAttrs = [...includeAttributes, ...DEFAULT_INCLUDE_ATTRIBUTES]\n\n\t// Helper function to cap text length\n\tconst capTextLength = (text: string, maxLength: number): string => {\n\t\tif (text.length > maxLength) {\n\t\t\treturn text.substring(0, maxLength) + '...'\n\t\t}\n\t\treturn text\n\t}\n\n\t// Build tree structure from flat map\n\tconst buildTreeNode = (nodeId: string): TreeNode | null => {\n\t\tconst node = flatTree.map[nodeId]\n\t\tif (!node) return null\n\n\t\tif (node.type === 'TEXT_NODE') {\n\t\t\tconst textNode = node as TextDomNode\n\t\t\treturn {\n\t\t\t\ttype: 'text',\n\t\t\t\ttext: textNode.text,\n\t\t\t\tisVisible: textNode.isVisible,\n\t\t\t\tparent: null,\n\t\t\t\tchildren: [],\n\t\t\t}\n\t\t} else {\n\t\t\tconst elementNode = node as ElementDomNode\n\t\t\tconst children: TreeNode[] = []\n\n\t\t\tif (elementNode.children) {\n\t\t\t\tfor (const childId of elementNode.children) {\n\t\t\t\t\tconst child = buildTreeNode(childId)\n\t\t\t\t\tif (child) {\n\t\t\t\t\t\tchild.parent = null // Will be set later\n\t\t\t\t\t\tchildren.push(child)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: elementNode.tagName,\n\t\t\t\tattributes: elementNode.attributes ?? {},\n\t\t\t\tisVisible: elementNode.isVisible ?? false,\n\t\t\t\tisInteractive: elementNode.isInteractive ?? false,\n\t\t\t\tisTopElement: elementNode.isTopElement ?? false,\n\t\t\t\tisNew: elementNode.isNew ?? false,\n\t\t\t\thighlightIndex: elementNode.highlightIndex,\n\t\t\t\tparent: null,\n\t\t\t\tchildren,\n\t\t\t\textra: elementNode.extra ?? {},\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set parent references\n\tconst setParentReferences = (node: TreeNode, parent: TreeNode | null = null) => {\n\t\tnode.parent = parent\n\t\tfor (const child of node.children) {\n\t\t\tsetParentReferences(child, node)\n\t\t}\n\t}\n\n\t// Build root node\n\tconst rootNode = buildTreeNode(flatTree.rootId)\n\tif (!rootNode) return ''\n\n\tsetParentReferences(rootNode)\n\n\t// Helper to check if text node has parent with highlight index\n\tconst hasParentWithHighlightIndex = (node: TreeNode): boolean => {\n\t\tlet current = node.parent\n\t\twhile (current) {\n\t\t\tif (current.type === 'element' && current.highlightIndex !== undefined) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tcurrent = current.parent\n\t\t}\n\t\treturn false\n\t}\n\n\t// Helper to check if parent is top element\n\t// const isParentTopElement = (node: TreeNode): boolean => {\n\t// \treturn node.parent?.type === 'element' && node.parent.isTopElement === true\n\t// }\n\n\t// Main processing function\n\tconst processNode = (node: TreeNode, depth: number, result: string[]): void => {\n\t\tlet nextDepth = depth\n\t\tconst depthStr = '\\t'.repeat(depth)\n\n\t\tif (node.type === 'element') {\n\t\t\tconst isSemantic = keepSemanticTags && node.tagName && SEMANTIC_TAGS.has(node.tagName)\n\n\t\t\t// Add element with highlight_index\n\t\t\tif (node.highlightIndex !== undefined) {\n\t\t\t\tnextDepth += 1\n\n\t\t\t\tconst text = getAllTextTillNextClickableElement(node)\n\t\t\t\tlet attributesHtmlStr = ''\n\n\t\t\t\tif (includeAttrs.length > 0 && node.attributes) {\n\t\t\t\t\tconst attributesToInclude = matchAttributes(node.attributes, includeAttrs)\n\n\t\t\t\t\t// Remove duplicate values (for attributes longer than 5 chars)\n\t\t\t\t\tconst keys = Object.keys(attributesToInclude)\n\t\t\t\t\tif (keys.length > 1) {\n\t\t\t\t\t\tconst keysToRemove = new Set<string>()\n\t\t\t\t\t\tconst seenValues: Record<string, string> = {}\n\n\t\t\t\t\t\tfor (const key of keys) {\n\t\t\t\t\t\t\tconst value = attributesToInclude[key]\n\t\t\t\t\t\t\tif (value.length > 5) {\n\t\t\t\t\t\t\t\tif (value in seenValues) {\n\t\t\t\t\t\t\t\t\tkeysToRemove.add(key)\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tseenValues[value] = key\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor (const key of keysToRemove) {\n\t\t\t\t\t\t\tdelete attributesToInclude[key]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove role if it matches tagName\n\t\t\t\t\tif (attributesToInclude.role === node.tagName) {\n\t\t\t\t\t\tdelete attributesToInclude.role\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove attributes that duplicate text content\n\t\t\t\t\tconst attrsToRemoveIfTextMatches = ['aria-label', 'placeholder', 'title']\n\t\t\t\t\tfor (const attr of attrsToRemoveIfTextMatches) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tattributesToInclude[attr] &&\n\t\t\t\t\t\t\tattributesToInclude[attr].toLowerCase().trim() === text.toLowerCase().trim()\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tdelete attributesToInclude[attr]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Object.keys(attributesToInclude).length > 0) {\n\t\t\t\t\t\tattributesHtmlStr = Object.entries(attributesToInclude)\n\t\t\t\t\t\t\t.map(([key, value]) => `${key}=${capTextLength(value, 20)}`)\n\t\t\t\t\t\t\t.join(' ')\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Build the line\n\t\t\t\tconst highlightIndicator = node.isNew\n\t\t\t\t\t? `*[${node.highlightIndex}]`\n\t\t\t\t\t: `[${node.highlightIndex}]`\n\t\t\t\tlet line = `${depthStr}${highlightIndicator}<${node.tagName ?? ''}`\n\n\t\t\t\tif (attributesHtmlStr) {\n\t\t\t\t\tline += ` ${attributesHtmlStr}`\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * @edit scrollable 数据\n\t\t\t\t */\n\t\t\t\tif (node.extra) {\n\t\t\t\t\tif (node.extra.scrollable) {\n\t\t\t\t\t\tlet scrollDataText = ''\n\t\t\t\t\t\tif (node.extra.scrollData?.left)\n\t\t\t\t\t\t\tscrollDataText += `left=${node.extra.scrollData.left}, `\n\t\t\t\t\t\tif (node.extra.scrollData?.top) scrollDataText += `top=${node.extra.scrollData.top}, `\n\t\t\t\t\t\tif (node.extra.scrollData?.right)\n\t\t\t\t\t\t\tscrollDataText += `right=${node.extra.scrollData.right}, `\n\t\t\t\t\t\tif (node.extra.scrollData?.bottom)\n\t\t\t\t\t\t\tscrollDataText += `bottom=${node.extra.scrollData.bottom}`\n\n\t\t\t\t\t\tline += ` data-scrollable=\"${scrollDataText}\"`\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (text) {\n\t\t\t\t\tconst trimmedText = text.trim()\n\t\t\t\t\tif (!attributesHtmlStr) {\n\t\t\t\t\t\tline += ' '\n\t\t\t\t\t}\n\t\t\t\t\tline += `>${trimmedText}`\n\t\t\t\t} else if (!attributesHtmlStr) {\n\t\t\t\t\tline += ' '\n\t\t\t\t}\n\n\t\t\t\tline += ' />'\n\t\t\t\tresult.push(line)\n\t\t\t}\n\n\t\t\t// special treatment for semantic tags\n\t\t\t// even if they are not interactive, we can keep them for clear context\n\n\t\t\tconst emitSemantic = isSemantic && node.highlightIndex === undefined\n\t\t\t// to check if this tag is empty\n\t\t\tconst mark = emitSemantic ? result.length : -1\n\n\t\t\tif (emitSemantic) {\n\t\t\t\tresult.push(`${depthStr}<${node.tagName}>`)\n\t\t\t\tnextDepth += 1\n\t\t\t}\n\n\t\t\tfor (const child of node.children) {\n\t\t\t\tprocessNode(child, nextDepth, result)\n\t\t\t}\n\n\t\t\tif (emitSemantic) {\n\t\t\t\t// empty tag should be removed\n\t\t\t\tif (result.length === mark + 1) {\n\t\t\t\t\tresult.pop()\n\t\t\t\t} else {\n\t\t\t\t\tresult.push(`${depthStr}</${node.tagName}>`)\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (node.type === 'text') {\n\t\t\t// Add text only if it doesn't have a highlighted parent\n\t\t\tif (hasParentWithHighlightIndex(node)) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tnode.parent &&\n\t\t\t\tnode.parent.type === 'element' &&\n\t\t\t\tnode.parent.isVisible &&\n\t\t\t\tnode.parent.isTopElement\n\t\t\t) {\n\t\t\t\tresult.push(`${depthStr}${node.text ?? ''}`)\n\t\t\t}\n\t\t}\n\t}\n\n\tconst result: string[] = []\n\tprocessNode(rootNode, 0, result)\n\treturn result.join('\\n')\n}\n\n// Get all text until next clickable element\nexport const getAllTextTillNextClickableElement = (node: TreeNode, maxDepth = -1): string => {\n\tconst textParts: string[] = []\n\n\tconst collectText = (currentNode: TreeNode, currentDepth: number) => {\n\t\tif (maxDepth !== -1 && currentDepth > maxDepth) {\n\t\t\treturn\n\t\t}\n\n\t\t// Skip this branch if we hit a highlighted element (except for the current node)\n\t\tif (\n\t\t\tcurrentNode.type === 'element' &&\n\t\t\tcurrentNode !== node &&\n\t\t\tcurrentNode.highlightIndex !== undefined\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tif (currentNode.type === 'text' && currentNode.text) {\n\t\t\ttextParts.push(currentNode.text)\n\t\t} else if (currentNode.type === 'element') {\n\t\t\tfor (const child of currentNode.children) {\n\t\t\t\tcollectText(child, currentDepth + 1)\n\t\t\t}\n\t\t}\n\t}\n\n\tcollectText(node, 0)\n\treturn textParts.join('\\n').trim()\n}\n\nexport function getSelectorMap(flatTree: FlatDomTree): Map<number, InteractiveElementDomNode> {\n\tconst selectorMap = new Map<number, InteractiveElementDomNode>()\n\n\tconst keys = Object.keys(flatTree.map)\n\tfor (const key of keys) {\n\t\tconst node = flatTree.map[key]\n\t\tif (node.isInteractive && typeof node.highlightIndex === 'number') {\n\t\t\tselectorMap.set(node.highlightIndex, node as InteractiveElementDomNode)\n\t\t}\n\t}\n\n\treturn selectorMap\n}\n\nexport function getElementTextMap(simplifiedHTML: string) {\n\tconst lines = simplifiedHTML\n\t\t.split('\\n')\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0)\n\tconst elementTextMap = new Map<number, string>()\n\tfor (const line of lines) {\n\t\tconst regex = /^\\[(\\d+)\\]<[^>]+>([^<]*)/\n\t\tconst match = regex.exec(line)\n\t\tif (match) {\n\t\t\tconst index = parseInt(match[1], 10)\n\t\t\telementTextMap.set(index, line)\n\t\t}\n\t}\n\n\treturn elementTextMap\n}\n\nexport function cleanUpHighlights() {\n\tconst cleanupFunctions = (window as any)._highlightCleanupFunctions || []\n\tfor (const cleanup of cleanupFunctions) {\n\t\tif (typeof cleanup === 'function') {\n\t\t\tcleanup()\n\t\t}\n\t}\n\n\t;(window as any)._highlightCleanupFunctions = []\n}\n\n// 监听 URL 的任何变化,立刻清空 highLights\nwindow.addEventListener('popstate', () => {\n\t// console.log('URL changed (popstate), highlights cleaned up.')\n\tcleanUpHighlights()\n})\nwindow.addEventListener('hashchange', () => {\n\t// console.log('URL changed (hashchange), highlights cleaned up.')\n\tcleanUpHighlights()\n})\nwindow.addEventListener('beforeunload', () => {\n\t// console.log('Page is unloading, highlights cleaned up.')\n\tcleanUpHighlights()\n})\n\nconst navigation = (window as any).navigation\nif (navigation && typeof navigation.addEventListener === 'function') {\n\tnavigation.addEventListener('navigate', () => {\n\t\t// console.log('Navigation event detected, highlights cleaned up.')\n\t\tcleanUpHighlights()\n\t})\n} else {\n\t// 定时器\n\tlet currentUrl = window.location.href\n\tsetInterval(() => {\n\t\tif (window.location.href !== currentUrl) {\n\t\t\tcurrentUrl = window.location.href\n\t\t\t// console.log('URL changed (interval), highlights cleaned up.')\n\t\t\tcleanUpHighlights()\n\t\t}\n\t}, 500)\n}\n","export function getPageInfo() {\n\tconst viewport_width = window.innerWidth\n\tconst viewport_height = window.innerHeight\n\n\tconst page_width = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth || 0)\n\tconst page_height = Math.max(\n\t\tdocument.documentElement.scrollHeight,\n\t\tdocument.body.scrollHeight || 0\n\t)\n\n\tconst scroll_x = window.scrollX || window.pageXOffset || document.documentElement.scrollLeft || 0\n\tconst scroll_y = window.scrollY || window.pageYOffset || document.documentElement.scrollTop || 0\n\n\tconst pixels_below = Math.max(0, page_height - (window.innerHeight + scroll_y))\n\tconst pixels_right = Math.max(0, page_width - (window.innerWidth + scroll_x))\n\n\treturn {\n\t\t// Current viewport dimensions\n\t\tviewport_width,\n\t\tviewport_height,\n\n\t\t// Total page dimensions\n\t\tpage_width,\n\t\tpage_height,\n\n\t\t// Current scroll position\n\t\tscroll_x,\n\t\tscroll_y,\n\n\t\tpixels_above: scroll_y,\n\t\tpixels_below,\n\n\t\tpages_above: viewport_height > 0 ? scroll_y / viewport_height : 0,\n\t\tpages_below: viewport_height > 0 ? pixels_below / viewport_height : 0,\n\t\ttotal_pages: viewport_height > 0 ? page_height / viewport_height : 0,\n\n\t\tcurrent_page_position: scroll_y / Math.max(1, page_height - viewport_height),\n\n\t\tpixels_left: scroll_x,\n\t\tpixels_right,\n\t}\n}\n","import type { PageController } from '../PageController'\n\n// Find common React root elements and add data-page-agent-not-interactive attribute\nexport function patchReact(pageController: PageController) {\n\tconst reactRootElements = document.querySelectorAll(\n\t\t'[data-reactroot], [data-reactid], [data-react-checksum], #root, #app, [id^=\"root-\"], [id^=\"app-\"], #adex-wrapper, #adex-root'\n\t)\n\n\tfor (const element of reactRootElements) {\n\t\telement.setAttribute('data-page-agent-not-interactive', 'true')\n\t}\n}\n\n/**\n * @todo (Heavy, might have false negatives) Interaction detection, if element width/height equals body offsetWidth/Height, consider it root element and non-interactive (React often attaches many events to root elements, causing false positives)\n */\n","/**\n * Copyright (C) 2025 Alibaba Group Holding Limited\n * All rights reserved.\n *\n * PageController - Manages DOM operations and element interactions.\n * Designed to be independent of LLM and can be tested in unit tests.\n * All public methods are async for potential remote calling support.\n */\nimport {\n\tclickElement,\n\tgetElementByIndex,\n\tinputTextElement,\n\tscrollHorizontally,\n\tscrollVertically,\n\tselectOptionElement,\n} from './actions'\nimport * as dom from './dom'\nimport type { FlatDomTree, InteractiveElementDomNode } from './dom/dom_tree/type'\nimport { getPageInfo } from './dom/getPageInfo'\nimport { patchReact } from './patches/react'\nimport { isAnchorElement } from './utils'\n\n/**\n * Configuration for PageController\n */\nexport interface PageControllerConfig extends dom.DomConfig {\n\t/** Enable visual mask overlay during operations (default: false) */\n\tenableMask?: boolean\n}\n\n/**\n * Structured browser state for LLM consumption\n */\nexport interface BrowserState {\n\turl: string\n\ttitle: string\n\t/** Page info + scroll position hint (e.g. \"Page info: 1920x1080px...\\n[Start of page]\") */\n\theader: string\n\t/** Simplified HTML of interactive elements */\n\tcontent: string\n\t/** Page footer hint (e.g. \"... 300 pixels below ...\" or \"[End of page]\") */\n\tfooter: string\n}\n\ninterface ActionResult {\n\tsuccess: boolean\n\tmessage: string\n}\n\n/**\n * PageController manages DOM state and element interactions.\n * It provides async methods for all DOM operations, keeping state isolated.\n *\n * @lifecycle\n * - beforeUpdate: Emitted before the DOM tree is updated.\n * - afterUpdate: Emitted after the DOM tree is updated.\n */\nexport class PageController extends EventTarget {\n\tprivate config: PageControllerConfig\n\n\t/** Corresponds to eval_page in browser-use */\n\tprivate flatTree: FlatDomTree | null = null\n\n\t/**\n\t * All highlighted index-mapped interactive elements\n\t * Corresponds to DOMState.selector_map in browser-use\n\t */\n\tprivate selectorMap = new Map<number, InteractiveElementDomNode>()\n\n\t/** Index -> element text description mapping */\n\tprivate elementTextMap = new Map<number, string>()\n\n\t/**\n\t * Simplified HTML for LLM consumption.\n\t * Corresponds to clickable_elements_to_string in browser-use\n\t */\n\tprivate simplifiedHTML = '<EMPTY>'\n\n\t/** last time the tree was updated */\n\tprivate lastTimeUpdate = 0\n\n\t/** Whether the tree has been indexed at least once */\n\tprivate isIndexed = false\n\n\t/** Visual mask overlay for blocking user interaction during automation */\n\tprivate mask: InstanceType<typeof import('./mask/SimulatorMask').SimulatorMask> | null = null\n\tprivate maskReady: Promise<void> | null = null\n\n\tconstructor(config: PageControllerConfig = {}) {\n\t\tsuper()\n\n\t\tthis.config = config\n\n\t\tpatchReact(this)\n\n\t\tif (config.enableMask) this.initMask()\n\t}\n\n\t/**\n\t * FORK: expõe, somente leitura, a árvore achatada da última `updateTree()`.\n\t * O perfilador da página precisa descrever os mesmos elementos que o agente vê, e `flatTree`\n\t * é privado (o pacote nem exporta o namespace `dom`). O campo continua privado: quem lê\n\t * não pode substituir a árvore do agente. Ver vendor/UPSTREAM.md.\n\t */\n\treadFlatTree(): FlatDomTree | null {\n\t\treturn this.flatTree\n\t}\n\n\t/**\n\t * FORK: expõe, somente leitura, o mapa índice -> elemento interativo da última `updateTree()`.\n\t * Mesmo motivo de `readFlatTree()`; o tipo `ReadonlyMap` impede `set`/`delete` por quem lê.\n\t */\n\treadSelectorMap(): ReadonlyMap<number, InteractiveElementDomNode> {\n\t\treturn this.selectorMap\n\t}\n\n\t/**\n\t * Initialize mask asynchronously (dynamic import to avoid CSS loading in Node)\n\t */\n\tinitMask() {\n\t\tif (this.maskReady !== null) return\n\t\tthis.maskReady = (async () => {\n\t\t\tconst { SimulatorMask } = await import('./mask/SimulatorMask')\n\t\t\tthis.mask = new SimulatorMask()\n\t\t})()\n\t}\n\t// ======= State Queries =======\n\n\t/**\n\t * Get current page URL\n\t */\n\tasync getCurrentUrl(): Promise<string> {\n\t\treturn window.location.href\n\t}\n\n\t/**\n\t * Get last tree update timestamp\n\t */\n\tasync getLastUpdateTime(): Promise<number> {\n\t\treturn this.lastTimeUpdate\n\t}\n\n\t/**\n\t * Get structured browser state for LLM consumption.\n\t * Automatically calls updateTree() to refresh the DOM state.\n\t */\n\tasync getBrowserState(): Promise<BrowserState> {\n\t\tconst url = window.location.href\n\t\tconst title = document.title\n\t\tconst pi = getPageInfo()\n\t\tconst viewportExpansion = dom.resolveViewportExpansion(this.config.viewportExpansion)\n\n\t\tawait this.updateTree()\n\n\t\tconst content = this.simplifiedHTML\n\n\t\t// Build header: page info + scroll position hint\n\t\tconst titleLine = `Current Page: [${title}](${url})`\n\n\t\tconst pageInfoLine = `Page info: ${pi.viewport_width}x${pi.viewport_height}px viewport, ${pi.page_width}x${pi.page_height}px total page size, ${pi.pages_above.toFixed(1)} pages above, ${pi.pages_below.toFixed(1)} pages below, ${pi.total_pages.toFixed(1)} total pages, at ${(pi.current_page_position * 100).toFixed(0)}% of page`\n\n\t\tconst elementsLabel =\n\t\t\tviewportExpansion === -1\n\t\t\t\t? 'Interactive elements from top layer of the current page (full page):'\n\t\t\t\t: 'Interactive elements from top layer of the current page inside the viewport:'\n\n\t\tconst hasContentAbove = pi.pixels_above > 4\n\t\tconst scrollHintAbove =\n\t\t\thasContentAbove && viewportExpansion !== -1\n\t\t\t\t? `... ${pi.pixels_above} pixels above (${pi.pages_above.toFixed(1)} pages) - scroll to see more ...`\n\t\t\t\t: '[Start of page]'\n\n\t\tconst header = `${titleLine}\\n${pageInfoLine}\\n\\n${elementsLabel}\\n\\n${scrollHintAbove}`\n\n\t\t// Build footer: scroll position hint\n\t\tconst hasContentBelow = pi.pixels_below > 4\n\t\tconst footer =\n\t\t\thasContentBelow && viewportExpansion !== -1\n\t\t\t\t? `... ${pi.pixels_below} pixels below (${pi.pages_below.toFixed(1)} pages) - scroll to see more ...`\n\t\t\t\t: '[End of page]'\n\n\t\treturn { url, title, header, content, footer }\n\t}\n\n\t// ======= DOM Tree Operations =======\n\n\t/**\n\t * Update DOM tree, returns simplified HTML for LLM.\n\t * This is the main method to refresh the page state.\n\t * Automatically bypasses mask during DOM extraction if enabled.\n\t */\n\tasync updateTree(): Promise<string> {\n\t\tthis.dispatchEvent(new Event('beforeUpdate'))\n\n\t\tthis.lastTimeUpdate = Date.now()\n\n\t\t// Temporarily bypass mask to allow DOM extraction\n\t\tif (this.mask) {\n\t\t\tthis.mask.wrapper.style.pointerEvents = 'none'\n\t\t}\n\n\t\tdom.cleanUpHighlights()\n\n\t\tconst blacklist = [\n\t\t\t...(this.config.interactiveBlacklist || []),\n\t\t\t...Array.from(document.querySelectorAll('[data-page-agent-not-interactive]')),\n\t\t]\n\n\t\tthis.flatTree = dom.getFlatTree({\n\t\t\t...this.config,\n\t\t\tinteractiveBlacklist: blacklist,\n\t\t})\n\n\t\tthis.simplifiedHTML = dom.flatTreeToString(\n\t\t\tthis.flatTree,\n\t\t\tthis.config.includeAttributes,\n\t\t\tthis.config.keepSemanticTags\n\t\t)\n\n\t\tthis.selectorMap.clear()\n\t\tthis.selectorMap = dom.getSelectorMap(this.flatTree)\n\n\t\tthis.elementTextMap.clear()\n\t\tthis.elementTextMap = dom.getElementTextMap(this.simplifiedHTML)\n\n\t\t// Mark as indexed - now element actions are allowed\n\t\tthis.isIndexed = true\n\n\t\t// Restore mask blocking\n\t\tif (this.mask) {\n\t\t\tthis.mask.wrapper.style.pointerEvents = 'auto'\n\t\t}\n\n\t\tthis.dispatchEvent(new Event('afterUpdate'))\n\n\t\treturn this.simplifiedHTML\n\t}\n\n\t/**\n\t * Clean up all element highlights\n\t */\n\tasync cleanUpHighlights(): Promise<void> {\n\t\tconsole.log('[PageController] cleanUpHighlights')\n\t\tdom.cleanUpHighlights()\n\t}\n\n\t// ======= Element Actions =======\n\n\t/**\n\t * Ensure the tree has been indexed before any index-based operation.\n\t * Throws if updateTree() hasn't been called yet.\n\t */\n\tprivate assertIndexed(): void {\n\t\tif (!this.isIndexed) {\n\t\t\tthrow new Error('DOM tree not indexed yet. Can not perform actions on elements.')\n\t\t}\n\t}\n\n\t/**\n\t * Click element by index\n\t */\n\tasync clickElement(index: number): Promise<ActionResult> {\n\t\ttry {\n\t\t\tthis.assertIndexed()\n\t\t\tconst element = getElementByIndex(this.selectorMap, index)\n\t\t\tconst elemText = this.elementTextMap.get(index)\n\t\t\tawait clickElement(element)\n\n\t\t\t// Handle links that open in new tabs\n\t\t\tif (isAnchorElement(element) && element.target === '_blank') {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `OK: elemento (${elemText ?? index}) clicado. ATENÇÃO: o link abriu em uma nova aba.`,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `OK: elemento (${elemText ?? index}) clicado.`,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `ERRO: não foi possível clicar no elemento: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Input text into element by index\n\t */\n\tasync inputText(index: number, text: string): Promise<ActionResult> {\n\t\ttry {\n\t\t\tthis.assertIndexed()\n\t\t\tconst element = getElementByIndex(this.selectorMap, index)\n\t\t\tconst elemText = this.elementTextMap.get(index)\n\t\t\tawait inputTextElement(element, text)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `OK: texto (${text}) digitado no elemento (${elemText ?? index}).`,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `ERRO: não foi possível digitar o texto: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Select dropdown option by index and option text\n\t */\n\tasync selectOption(index: number, optionText: string): Promise<ActionResult> {\n\t\ttry {\n\t\t\tthis.assertIndexed()\n\t\t\tconst element = getElementByIndex(this.selectorMap, index)\n\t\t\tconst elemText = this.elementTextMap.get(index)\n\t\t\tawait selectOptionElement(element as HTMLSelectElement, optionText)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `OK: opção (${optionText}) escolhida no elemento (${elemText ?? index}).`,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `ERRO: não foi possível escolher a opção: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Scroll vertically\n\t */\n\tasync scroll(options: {\n\t\tdown: boolean\n\t\tnumPages: number\n\t\tpixels?: number\n\t\tindex?: number\n\t}): Promise<ActionResult> {\n\t\ttry {\n\t\t\tconst { down, numPages, pixels, index } = options\n\n\t\t\tthis.assertIndexed()\n\n\t\t\tconst scrollAmount = (pixels ?? numPages * window.innerHeight) * (down ? 1 : -1)\n\n\t\t\tconst element = index !== undefined ? getElementByIndex(this.selectorMap, index) : null\n\n\t\t\tconst message = await scrollVertically(scrollAmount, element)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `ERRO: não foi possível rolar a página: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Scroll horizontally\n\t */\n\tasync scrollHorizontally(options: {\n\t\tright: boolean\n\t\tpixels: number\n\t\tindex?: number\n\t}): Promise<ActionResult> {\n\t\ttry {\n\t\t\tconst { right, pixels, index } = options\n\n\t\t\tthis.assertIndexed()\n\n\t\t\tconst scrollAmount = pixels * (right ? 1 : -1)\n\n\t\t\tconst element = index !== undefined ? getElementByIndex(this.selectorMap, index) : null\n\n\t\t\tconst message = await scrollHorizontally(scrollAmount, element)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `ERRO: não foi possível rolar na horizontal: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Execute arbitrary JavaScript on the page.\n\t * The optional `signal` is exposed to the script scope so cooperative code\n\t * can abort promptly when the task is stopped.\n\t */\n\tasync executeJavascript(script: string, signal?: AbortSignal): Promise<ActionResult> {\n\t\ttry {\n\t\t\t// Wrap script in async function to support await, exposing `signal`.\n\t\t\tconst asyncFunction = eval(`(async (signal) => { ${script} })`)\n\t\t\tconst result = await asyncFunction(signal)\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `OK: JavaScript executado. Resultado: ${result}`,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `ERRO: falha ao executar JavaScript: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t// ======= Mask Operations =======\n\n\t/**\n\t * Show the visual mask overlay.\n\t * Only works after mask is setup.\n\t */\n\tasync showMask(): Promise<void> {\n\t\tawait this.maskReady\n\t\tthis.mask?.show()\n\t}\n\n\t/**\n\t * Hide the visual mask overlay.\n\t * Only works after mask is setup.\n\t */\n\tasync hideMask(): Promise<void> {\n\t\tawait this.maskReady\n\t\tthis.mask?.hide()\n\t}\n\n\t/**\n\t * Dispose and clean up resources\n\t */\n\tdispose(): void {\n\t\tdom.cleanUpHighlights()\n\t\tthis.flatTree = null\n\t\tthis.selectorMap.clear()\n\t\tthis.elementTextMap.clear()\n\t\tthis.simplifiedHTML = '<EMPTY>'\n\t\tthis.isIndexed = false\n\t\tthis.mask?.dispose()\n\t\tthis.mask = null\n\t}\n}\n\nexport * from './actions'\n","// English translations (base/reference language)\nconst enUS = {\n\tui: {\n\t\tpanel: {\n\t\t\tready: 'Ready',\n\t\t\tthinking: 'Thinking...',\n\t\t\ttaskInput: 'Enter new task, describe steps in detail, press Enter to submit',\n\t\t\tuserAnswerPrompt: 'Please answer the question above, press Enter to submit',\n\t\t\ttaskTerminated: 'Task terminated',\n\t\t\ttaskCompleted: 'Task completed',\n\t\t\tuserAnswer: 'User answer: {{input}}',\n\t\t\tquestion: 'Question: {{question}}',\n\t\t\twaitingPlaceholder: 'Waiting for task to start...',\n\t\t\tstop: 'Stop',\n\t\t\tclose: 'Close',\n\t\t\texpand: 'Expand history',\n\t\t\tcollapse: 'Collapse history',\n\t\t\tstep: 'Step {{number}}',\n\t\t\t// FORK: textos que estavam cravados em inglês dentro do Panel.ts.\n\t\t\tuserTakeover: 'User takeover',\n\t\t\tretrying: 'Retrying',\n\t\t\terrorLabel: 'Error',\n\t\t\treflectionEvaluation: 'Assessment',\n\t\t\treflectionMemory: 'Memory',\n\t\t\treflectionNextGoal: 'Next goal',\n\t\t\t// FORK: nome de quem fala em cada mensagem, e rótulos das regiões.\n\t\t\tauthorPerson: 'You',\n\t\t\tauthorAgent: 'Agent',\n\t\t\tauthorReasoning: 'Reasoning',\n\t\t\tauthorAction: 'Action',\n\t\t\tauthorResult: 'Result',\n\t\t\tauthorPage: 'Page',\n\t\t\tauthorSystem: 'System',\n\t\t\thistoryLabel: 'Agent activity history',\n\t\t\tpanelLabel: 'Agent panel',\n\t\t},\n\t\ttools: {\n\t\t\tclicking: 'Clicking element [{{index}}]...',\n\t\t\tinputting: 'Inputting text to element [{{index}}]...',\n\t\t\tselecting: 'Selecting option \"{{text}}\"...',\n\t\t\tscrolling: 'Scrolling page...',\n\t\t\twaiting: 'Waiting {{seconds}} seconds...',\n\t\t\taskingUser: 'Asking user...',\n\t\t\tdone: 'Task done',\n\t\t\tclicked: 'Clicked element [{{index}}]',\n\t\t\tinputted: 'Inputted text \"{{text}}\"',\n\t\t\tselected: 'Selected option \"{{text}}\"',\n\t\t\tscrolled: 'Page scrolled',\n\t\t\twaited: 'Wait completed',\n\t\t\texecuting: 'Executing {{toolName}}...',\n\t\t\tresultSuccess: 'success',\n\t\t\tresultFailure: 'failed',\n\t\t\tresultError: 'error',\n\t\t},\n\t\terrors: {\n\t\t\telementNotFound: 'No interactive element found at index {{index}}',\n\t\t\ttaskRequired: 'Task description is required',\n\t\t\texecutionFailed: 'Task execution failed',\n\t\t\tnotInputElement: 'Element is not an input or textarea',\n\t\t\tnotSelectElement: 'Element is not a select element',\n\t\t\toptionNotFound: 'Option \"{{text}}\" not found',\n\t\t},\n\t},\n} as const\n\n// FORK: tradução pt-BR. O painel é a superfície que a pessoa lê durante a execução, então ele fala\n// a língua dela. Sem emoji nos textos: o card já carrega um ícone, e emoji dentro da frase muda de\n// desenho por plataforma e atrapalha a leitura.\nconst ptBR = {\n\tui: {\n\t\tpanel: {\n\t\t\tready: 'Pronto',\n\t\t\tthinking: 'Pensando...',\n\t\t\ttaskInput: 'Descreva a próxima tarefa com os passos em detalhe e tecle Enter',\n\t\t\tuserAnswerPrompt: 'Responda à pergunta acima e tecle Enter',\n\t\t\ttaskTerminated: 'Tarefa interrompida',\n\t\t\ttaskCompleted: 'Tarefa concluída',\n\t\t\tuserAnswer: 'Resposta: {{input}}',\n\t\t\tquestion: 'Pergunta: {{question}}',\n\t\t\twaitingPlaceholder: 'Aguardando o início da tarefa...',\n\t\t\tstop: 'Parar',\n\t\t\tclose: 'Fechar',\n\t\t\texpand: 'Abrir histórico',\n\t\t\tcollapse: 'Fechar histórico',\n\t\t\tstep: 'Passo {{number}}',\n\t\t\tuserTakeover: 'A pessoa assumiu o controle',\n\t\t\tretrying: 'Tentando de novo',\n\t\t\terrorLabel: 'Erro',\n\t\t\treflectionEvaluation: 'Avaliação',\n\t\t\treflectionMemory: 'Memória',\n\t\t\treflectionNextGoal: 'Próximo passo',\n\t\t\tauthorPerson: 'Você',\n\t\t\tauthorAgent: 'Agente',\n\t\t\tauthorReasoning: 'Raciocínio',\n\t\t\tauthorAction: 'Ação',\n\t\t\tauthorResult: 'Resultado',\n\t\t\tauthorPage: 'Página',\n\t\t\tauthorSystem: 'Sistema',\n\t\t\thistoryLabel: 'Histórico de atividade do agente',\n\t\t\tpanelLabel: 'Painel do agente',\n\t\t},\n\t\ttools: {\n\t\t\tclicking: 'Clicando no elemento [{{index}}]...',\n\t\t\tinputting: 'Digitando no elemento [{{index}}]...',\n\t\t\tselecting: 'Escolhendo a opção \"{{text}}\"...',\n\t\t\tscrolling: 'Rolando a página...',\n\t\t\twaiting: 'Aguardando {{seconds}} segundos...',\n\t\t\taskingUser: 'Perguntando à pessoa...',\n\t\t\tdone: 'Tarefa encerrada',\n\t\t\tclicked: 'Elemento [{{index}}] clicado',\n\t\t\tinputted: 'Texto \"{{text}}\" digitado',\n\t\t\tselected: 'Opção \"{{text}}\" escolhida',\n\t\t\tscrolled: 'Página rolada',\n\t\t\twaited: 'Espera concluída',\n\t\t\texecuting: 'Executando {{toolName}}...',\n\t\t\tresultSuccess: 'sucesso',\n\t\t\tresultFailure: 'falha',\n\t\t\tresultError: 'erro',\n\t\t},\n\t\terrors: {\n\t\t\telementNotFound: 'Nenhum elemento interativo no índice {{index}}',\n\t\t\ttaskRequired: 'A descrição da tarefa é obrigatória',\n\t\t\texecutionFailed: 'A execução da tarefa falhou',\n\t\t\tnotInputElement: 'O elemento não é um campo de texto',\n\t\t\tnotSelectElement: 'O elemento não é uma lista de seleção',\n\t\t\toptionNotFound: 'Opção \"{{text}}\" não encontrada',\n\t\t},\n\t},\n} as const\n\n// Type definitions generated from English base structure (but with string values)\ntype DeepStringify<T> = {\n\t[K in keyof T]: T[K] extends string ? string : T[K] extends object ? DeepStringify<T[K]> : T[K]\n}\n\nexport type TranslationSchema = DeepStringify<typeof enUS>\n\n// Utility type: Extract all nested paths from translation object\ntype NestedKeyOf<ObjectType extends object> = {\n\t[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object\n\t\t? `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key]>}`\n\t\t: `${Key}`\n}[keyof ObjectType & (string | number)]\n\n// Extract all possible key paths from translation structure\nexport type TranslationKey = NestedKeyOf<TranslationSchema>\n\n// Parameterized translation types\nexport type TranslationParams = Record<string, string | number>\n\nexport const locales = {\n\t'en-US': enUS,\n\t'pt-BR': ptBR,\n} as const\n\nexport type SupportedLanguage = keyof typeof locales\n","import {\n\ttype SupportedLanguage,\n\ttype TranslationKey,\n\ttype TranslationParams,\n\ttype TranslationSchema,\n\tlocales,\n} from './locales'\n\nexport class I18n {\n\tprivate language: SupportedLanguage\n\tprivate translations: TranslationSchema\n\n\t/**\n\t * FORK: aceita qualquer identificador de língua, porque o corpo já trata o caso desconhecido\n\t * caindo em 'en-US'. O tipo estreito contradizia essa checagem: ou ela era morta, ou o tipo\n\t * mentia. O núcleo conhece línguas que o painel ainda não traduz, e isso é normal.\n\t */\n\tconstructor(language: string = 'en-US') {\n\t\tthis.language = (language in locales ? language : 'en-US') as SupportedLanguage\n\t\tthis.translations = locales[this.language]\n\t}\n\n\t// 类型安全的翻译方法\n\tt(key: TranslationKey, params?: TranslationParams): string {\n\t\tconst value = this.getNestedValue(this.translations, key)\n\t\tif (!value) {\n\t\t\tconsole.warn(`Translation key \"${key}\" not found for language \"${this.language}\"`)\n\t\t\treturn key\n\t\t}\n\n\t\tif (params) {\n\t\t\treturn this.interpolate(value, params)\n\t\t}\n\t\treturn value\n\t}\n\n\tprivate getNestedValue(obj: any, path: string): string | undefined {\n\t\treturn path.split('.').reduce((current, key) => current?.[key], obj)\n\t}\n\n\tprivate interpolate(template: string, params: TranslationParams): string {\n\t\treturn template.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key) => {\n\t\t\t// Use != null to check for both null and undefined, allow empty strings\n\t\t\treturn params[key] != null ? params[key].toString() : match\n\t\t})\n\t}\n\n\tgetLanguage(): SupportedLanguage {\n\t\treturn this.language\n\t}\n}\n\n// 导出类型和实例创建函数\nexport type { TranslationKey, SupportedLanguage, TranslationParams }\nexport { locales }\n","export function truncate(text: string, maxLength: number): string {\n\tif (text.length > maxLength) {\n\t\treturn text.substring(0, maxLength) + '...'\n\t}\n\treturn text\n}\n\n/**\n * Escape HTML special characters to prevent XSS and rendering issues\n */\nexport function escapeHtml(text: string): string {\n\treturn text\n\t\t.replace(/&/g, '&')\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/\"/g, '"')\n\t\t.replace(/'/g, ''')\n}\n","/**\n * FORK: componentes de mensagem do painel.\n *\n * O upstream renderizava todo evento como a mesma lajota translúcida com uma barra colorida à\n * esquerda. Três problemas, nesta ordem de gravidade:\n *\n * 1. O fundo era translúcido sobre a página do usuário, então o contraste do texto dependia do\n * que estivesse atrás. Sobre uma página clara o texto branco sumia. Contraste que não dá para\n * medir não dá para garantir, e é por isso que a bolha aqui é OPACA.\n * 2. `word-break: break-all` partia palavra no meio (\"corretamen/te\"). Quebra só deve acontecer\n * quando o token não cabe de jeito nenhum — uma URL longa, não uma palavra comum.\n * 3. Nada dizia de quem era a fala. Num log de conversa isso é a primeira informação, e para\n * quem usa leitor de tela era a única ausente.\n *\n * O formato segue o de um aplicativo de mensagens: a fala da pessoa de um lado, a do agente do\n * outro, cada bolha com autor declarado. Quem enxerga lê pelo alinhamento e pela cor; quem usa\n * leitor de tela lê o mesmo autor, em texto.\n */\nimport { escapeHtml } from '../utils'\n\nimport styles from './Panel.module.css'\n\ntype CardType = 'default' | 'input' | 'output' | 'question' | 'observation'\n\n/** De quem é a fala. Decide o lado, a cor da bolha e o autor anunciado. */\nexport type CardFrom = 'pessoa' | 'agente' | 'sistema'\n\n/**\n * Uma linha de reflexão passa a ser rótulo + texto, em vez de uma frase com emoji na frente.\n * O emoji carregava o significado (\"🔍 é avaliação\") e exigia que a pessoa soubesse a convenção;\n * o rótulo diz. Também permite traduzir, o que o emoji não permitia.\n */\nexport interface ReflectionLine {\n\tlabel: string\n\ttext: string\n}\n\ninterface CardOptions {\n\ticon: string\n\tcontent: string | ReflectionLine[]\n\tmeta?: string\n\ttype?: CardType\n\t/** Quem falou. O padrão é o agente, que é a maioria das mensagens. */\n\tfrom?: CardFrom\n\t/** Nome do autor, já traduzido, mostrado no cabeçalho da bolha. */\n\tauthor?: string\n}\n\n/** Create a single history card */\nexport function createCard({ icon, content, meta, type, from = 'agente', author }: CardOptions): string {\n\tconst typeClass = type ? styles[type] : ''\n\tconst fromClass = from === 'pessoa' ? styles.fromPessoa : from === 'sistema' ? styles.fromSistema : styles.fromAgente\n\tconst contentHtml = Array.isArray(content)\n\t\t? `<div class=\"${styles.reflectionLines}\">${content\n\t\t\t\t.map(\n\t\t\t\t\t(line) =>\n\t\t\t\t\t\t`<span class=\"${styles.reflectionLine}\"><span class=\"${styles.reflectionLabel}\">${escapeHtml(line.label)}</span>${escapeHtml(line.text)}</span>`\n\t\t\t\t)\n\t\t\t\t.join('')}</div>`\n\t\t: `<span>${escapeHtml(content)}</span>`\n\n\t// O cabeçalho carrega ícone, autor e passo. O ícone é decorativo (o autor já está em texto),\n\t// então fica fora da árvore de acessibilidade — ver aria-hidden dentro do próprio SVG.\n\tconst cabecalho = `\n\t\t\t<div class=\"${styles.historyHeader}\">\n\t\t\t\t<span class=\"${styles.statusIcon}\">${icon}</span>\n\t\t\t\t<span class=\"${styles.historyAuthor}\" data-autor=\"${from}\">${escapeHtml(author || '')}</span>\n\t\t\t\t${meta ? `<span class=\"${styles.historyMeta}\">${escapeHtml(meta)}</span>` : ''}\n\t\t\t</div>`\n\n\treturn `\n\t\t<div class=\"${styles.historyRow} ${fromClass}\">\n\t\t\t<div class=\"${styles.historyItem} ${typeClass}\" data-mensagem=\"${from}\">\n\t\t\t\t${cabecalho}\n\t\t\t\t<div class=\"${styles.historyContent}\" data-conteudo>${contentHtml}</div>\n\t\t\t</div>\n\t\t</div>\n\t`\n}\n\n/** Create reflection lines from reflection object */\nexport function createReflectionLines(\n\treflection: {\n\t\tevaluation_previous_goal?: string\n\t\tmemory?: string\n\t\tnext_goal?: string\n\t},\n\tlabels: { evaluation: string; memory: string; nextGoal: string }\n): ReflectionLine[] {\n\tconst lines: ReflectionLine[] = []\n\tif (reflection.evaluation_previous_goal) {\n\t\tlines.push({ label: labels.evaluation, text: reflection.evaluation_previous_goal })\n\t}\n\tif (reflection.memory) {\n\t\tlines.push({ label: labels.memory, text: reflection.memory })\n\t}\n\tif (reflection.next_goal) {\n\t\tlines.push({ label: labels.nextGoal, text: reflection.next_goal })\n\t}\n\treturn lines\n}\n","/**\n * FORK: ícones do painel.\n *\n * O upstream usa emoji como ícone de card. Emoji é renderizado pela fonte do sistema, então muda de\n * desenho, de peso e de alinhamento entre plataformas, não herda a cor do tema, e em vários\n * ambientes sai grande demais ao lado de um texto de 12px. Trocamos por SVG inline monocromático:\n * tamanho vem do CSS, cor vem de `currentColor`, e o desenho é o mesmo em qualquer sistema.\n *\n * Traço de 1.75 e viewBox 24 para a linha ficar nítida em 14px sem virar borrão.\n */\nconst svg = (paths: string): string =>\n\t`<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\">${paths}</svg>`\n\n/** Tarefa pedida pelo usuário. */\nexport const iconTask = svg('<circle cx=\"12\" cy=\"12\" r=\"9\"/><circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 3v2M12 19v2M3 12h2M19 12h2\"/>')\n\n/** Raciocínio do modelo. */\nexport const iconThinking = svg('<path d=\"M12 3l1.8 4.2L18 9l-4.2 1.8L12 15l-1.8-4.2L6 9l4.2-1.8z\"/><path d=\"M18 15l.9 2.1L21 18l-2.1.9L18 21l-.9-2.1L15 18l2.1-.9z\"/>')\n\n/** Observação do ambiente. */\nexport const iconObservation = svg('<path d=\"M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6-10-6-10-6z\"/><circle cx=\"12\" cy=\"12\" r=\"2.5\"/>')\n\n/** Intervenção da pessoa. */\nexport const iconUser = svg('<circle cx=\"12\" cy=\"8\" r=\"3.5\"/><path d=\"M5 20c0-3.3 3.1-5.5 7-5.5s7 2.2 7 5.5\"/>')\n\n/** Nova tentativa. */\nexport const iconRetry = svg('<path d=\"M20 11a8 8 0 1 0-2.3 6.3\"/><path d=\"M20 5v6h-6\"/>')\n\n/** Erro. */\nexport const iconError = svg('<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M12 7.5v5\"/><path d=\"M12 16.2h.01\"/>')\n\n/** Resposta final do agente. */\nexport const iconDone = svg('<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M8.2 12.3l2.6 2.6 5-5.2\"/>')\n\n/** Pergunta do agente. */\nexport const iconQuestion = svg('<circle cx=\"12\" cy=\"12\" r=\"9\"/><path d=\"M9.6 9.4a2.5 2.5 0 1 1 3.3 2.4c-.6.2-.9.8-.9 1.4v.3\"/><path d=\"M12 16.6h.01\"/>')\n\n/** Resposta da pessoa. */\nexport const iconAnswer = svg('<path d=\"M20 14.5a2.5 2.5 0 0 1-2.5 2.5H9l-5 3.5V6.5A2.5 2.5 0 0 1 6.5 4h11A2.5 2.5 0 0 1 20 6.5z\"/>')\n\n/** Execução de ferramenta. */\nexport const iconTool = svg('<path d=\"M5 7.5l3.5 3.5L5 14.5\"/><path d=\"M11.5 15.5H19\"/><rect x=\"2.5\" y=\"3.5\" width=\"19\" height=\"17\" rx=\"2.5\"/>')\n","import { I18n, type SupportedLanguage } from '../i18n'\nimport { truncate } from '../utils'\nimport { createCard, createReflectionLines } from './cards'\n// FORK: ícones SVG no lugar de emoji — ver icons.ts.\nimport {\n\ticonAnswer,\n\ticonDone,\n\ticonError,\n\ticonObservation,\n\ticonQuestion,\n\ticonRetry,\n\ticonTask,\n\ticonThinking,\n\ticonTool,\n\ticonUser,\n} from './icons'\nimport type { AgentActivity, PanelAgentAdapter } from './types'\n\nimport styles from './Panel.module.css'\n\n/**\n * Panel configuration\n */\nexport interface PanelConfig {\n\t/**\n\t * FORK: aceita qualquer língua do núcleo, inclusive uma que o painel não traduza. O I18n já\n\t * cai em 'en-US' nesse caso, e recusar no tipo obrigaria o chamador a converter sem ganho.\n\t */\n\tlanguage?: SupportedLanguage | 'en-US' | 'zh-CN' | 'pt-BR'\n\t/**\n\t * Whether to prompt for next task after task completion\n\t * @default true\n\t */\n\tpromptForNextTask?: boolean\n}\n\n/**\n * Agent control panel\n *\n * Architecture:\n * - History list: renders directly from agent.history (historical events)\n * - Header bar: shows activity events (transient state) and agent status\n *\n * This separation ensures data consistency - history is the single source of truth\n * for what has been done, while activity shows what is happening now.\n */\nexport class Panel {\n\t#wrapper: HTMLElement\n\t#indicator: HTMLElement\n\t#statusText: HTMLElement\n\t#historySection: HTMLElement\n\t#expandButton: HTMLElement\n\t#actionButton: HTMLElement\n\t#inputSection: HTMLElement\n\t#taskInput: HTMLInputElement\n\n\t#agent: PanelAgentAdapter\n\t#config: PanelConfig\n\t#isExpanded = false\n\t#i18n: I18n\n\t#userAnswerResolver: ((input: string) => void) | null = null\n\t#isWaitingForUserAnswer: boolean = false\n\t#headerUpdateTimer: ReturnType<typeof setInterval> | null = null\n\t#pendingHeaderText: string | null = null\n\t#isAnimating = false\n\n\t// Event handlers (bound for removal)\n\t#onStatusChange = () => this.#handleStatusChange()\n\t#onHistoryChange = () => this.#handleHistoryChange()\n\t#onActivity = (e: Event) => this.#handleActivity((e as CustomEvent<AgentActivity>).detail)\n\t#onAgentDispose = () => this.dispose()\n\n\tget wrapper(): HTMLElement {\n\t\treturn this.#wrapper\n\t}\n\n\t/**\n\t * Create a Panel bound to an agent\n\t * @param agent - Agent instance that implements PanelAgentAdapter\n\t * @param config - Optional panel configuration\n\t */\n\tconstructor(agent: PanelAgentAdapter, config: PanelConfig = {}) {\n\t\tthis.#agent = agent\n\t\tthis.#config = config\n\t\tthis.#i18n = new I18n(config.language ?? 'en-US')\n\n\t\t// Set up askUser callback on agent\n\t\tthis.#agent.onAskUser = (question, options) => this.#askUser(question, options?.signal)\n\n\t\t// Create UI elements\n\t\tthis.#wrapper = this.#createWrapper()\n\t\tthis.#indicator = this.#wrapper.querySelector(`.${styles.indicator}`)!\n\t\tthis.#statusText = this.#wrapper.querySelector(`.${styles.statusText}`)!\n\t\tthis.#historySection = this.#wrapper.querySelector(`.${styles.historySection}`)!\n\t\tthis.#expandButton = this.#wrapper.querySelector(`.${styles.expandButton}`)!\n\t\tthis.#actionButton = this.#wrapper.querySelector(`.${styles.stopButton}`)!\n\t\tthis.#inputSection = this.#wrapper.querySelector(`.${styles.inputSectionWrapper}`)!\n\t\tthis.#taskInput = this.#wrapper.querySelector(`.${styles.taskInput}`)!\n\n\t\t// Listen to agent events\n\t\tthis.#agent.addEventListener('statuschange', this.#onStatusChange)\n\t\tthis.#agent.addEventListener('historychange', this.#onHistoryChange)\n\t\tthis.#agent.addEventListener('activity', this.#onActivity)\n\t\tthis.#agent.addEventListener('dispose', this.#onAgentDispose)\n\n\t\tthis.#setupEventListeners()\n\t\tthis.#startHeaderUpdateLoop()\n\n\t\tthis.#showInputArea()\n\n\t\tthis.hide() // Start hidden\n\t}\n\n\t// ========== Agent event handlers ==========\n\n\t/** Handle agent status change */\n\t#handleStatusChange(): void {\n\t\tconst status = this.#agent.status\n\n\t\t// Map agent status to UI indicator. A `completed` run whose result reports\n\t\t// failure shows as error; other statuses map to their own indicator.\n\t\tconst failed = status === 'completed' && this.#agent.lastResult?.success === false\n\t\tthis.#updateStatusIndicator(failed ? 'error' : status)\n\n\t\t// Morph action button: running = stop (■), not running = close (X)\n\t\tif (status === 'running') {\n\t\t\tthis.#actionButton.textContent = '■'\n\t\t\tthis.#actionButton.title = this.#i18n.t('ui.panel.stop')\n\t\t} else {\n\t\t\tthis.#actionButton.textContent = 'X'\n\t\t\tthis.#actionButton.title = this.#i18n.t('ui.panel.close')\n\t\t}\n\n\t\t// Show/hide based on status\n\t\tif (status === 'running') {\n\t\t\tthis.show()\n\t\t\tthis.#hideInputArea() // Hide input while running\n\t\t}\n\n\t\t// Handle completion\n\t\tif (status === 'completed' || status === 'error' || status === 'stopped') {\n\t\t\tif (!this.#isExpanded) {\n\t\t\t\tthis.#expand()\n\t\t\t}\n\t\t\tif (this.#shouldShowInputArea()) {\n\t\t\t\tthis.#showInputArea()\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Handle agent history change - re-render history list from agent.history */\n\t#handleHistoryChange(): void {\n\t\tthis.#renderHistory()\n\t}\n\n\t/**\n\t * Handle agent activity - transient state for immediate UI feedback\n\t * Activity events are NOT persisted in history, only used for header bar updates\n\t */\n\t#handleActivity(activity: AgentActivity): void {\n\t\tswitch (activity.type) {\n\t\t\tcase 'thinking':\n\t\t\t\tthis.#pendingHeaderText = this.#i18n.t('ui.panel.thinking')\n\t\t\t\tthis.#updateStatusIndicator('thinking')\n\t\t\t\tbreak\n\n\t\t\tcase 'executing':\n\t\t\t\tthis.#pendingHeaderText = this.#getToolExecutingText(activity.tool, activity.input)\n\t\t\t\tthis.#updateStatusIndicator('executing')\n\t\t\t\tbreak\n\n\t\t\tcase 'executed':\n\t\t\t\tthis.#pendingHeaderText = truncate(activity.output, 50)\n\t\t\t\tbreak\n\n\t\t\tcase 'retrying':\n\t\t\t\tthis.#pendingHeaderText = `Retrying (${activity.attempt}/${activity.maxAttempts})`\n\t\t\t\tthis.#updateStatusIndicator('retrying')\n\t\t\t\tbreak\n\n\t\t\tcase 'error':\n\t\t\t\tthis.#pendingHeaderText = truncate(activity.message, 50)\n\t\t\t\tthis.#updateStatusIndicator('error')\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\t/**\n\t * Ask for user input (internal, called by agent via onAskUser).\n\t * Rejects when `signal` aborts (task stopped or disposed), cleaning up the\n\t * question card and pending state so the agent loop can settle.\n\t */\n\t#askUser(question: string, signal?: AbortSignal): Promise<string> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t// Set `waiting for user answer` state\n\t\t\tthis.#isWaitingForUserAnswer = true\n\t\t\tthis.#userAnswerResolver = resolve\n\n\t\t\t// Expand history panel\n\t\t\tif (!this.#isExpanded) {\n\t\t\t\tthis.#expand()\n\t\t\t}\n\n\t\t\t// Add temporary question card so user can see the full question\n\t\t\tconst tempCard = document.createElement('div')\n\t\t\ttempCard.innerHTML = createCard({\n\t\t\t\ticon: iconQuestion,\n\t\t\t\tcontent: this.#i18n.t('ui.panel.question', { question }),\n\t\t\t\ttype: 'question',\n\t\t\t\tauthor: this.#i18n.t('ui.panel.authorAgent'),\n\t\t\t})\n\t\t\tconst cardElement = tempCard.firstElementChild as HTMLElement\n\t\t\tcardElement.setAttribute('data-temp-card', 'true')\n\t\t\tthis.#historySection.appendChild(cardElement)\n\t\t\tthis.#scrollToBottom()\n\n\t\t\tthis.#showInputArea(this.#i18n.t('ui.panel.userAnswerPrompt'))\n\n\t\t\tsignal?.addEventListener(\n\t\t\t\t'abort',\n\t\t\t\t() => {\n\t\t\t\t\tthis.#removeTempCards()\n\t\t\t\t\tthis.#isWaitingForUserAnswer = false\n\t\t\t\t\tthis.#userAnswerResolver = null\n\t\t\t\t\t// reason is a DOMException AbortError (abort() takes no args).\n\t\t\t\t\treject(signal.reason as DOMException)\n\t\t\t\t},\n\t\t\t\t{ once: true }\n\t\t\t)\n\t\t})\n\t}\n\n\t/** Remove temporary question cards (only direct children for safety) */\n\t#removeTempCards(): void {\n\t\tArray.from(this.#historySection.children).forEach((child) => {\n\t\t\tif (child.getAttribute('data-temp-card') === 'true') {\n\t\t\t\tchild.remove()\n\t\t\t}\n\t\t})\n\t}\n\n\t// ========== Public control methods ==========\n\n\tshow(): void {\n\t\tthis.wrapper.style.display = 'block'\n\t\tthis.wrapper.getBoundingClientRect() // force reflow before opacity transition\n\t\tthis.wrapper.style.opacity = '1'\n\t\tthis.wrapper.style.transform = 'translateX(-50%) translateY(0)'\n\t}\n\n\thide(): void {\n\t\tthis.wrapper.style.opacity = '0'\n\t\tthis.wrapper.style.transform = 'translateX(-50%) translateY(20px)'\n\t\tthis.wrapper.style.display = 'none'\n\t}\n\n\treset(): void {\n\t\tthis.#statusText.textContent = this.#i18n.t('ui.panel.ready')\n\t\tthis.#updateStatusIndicator('thinking')\n\t\tthis.#renderHistory()\n\t\tthis.#collapse()\n\t\t// Reset user input state\n\t\tthis.#isWaitingForUserAnswer = false\n\t\tthis.#userAnswerResolver = null\n\t\t// Show input area\n\t\tthis.#showInputArea()\n\t}\n\n\texpand(): void {\n\t\tthis.#expand()\n\t}\n\n\tcollapse(): void {\n\t\tthis.#collapse()\n\t}\n\n\t/**\n\t * Dispose panel and clean up event listeners\n\t */\n\tdispose(): void {\n\t\t// Remove agent event listeners\n\t\tthis.#agent.removeEventListener('statuschange', this.#onStatusChange)\n\t\tthis.#agent.removeEventListener('historychange', this.#onHistoryChange)\n\t\tthis.#agent.removeEventListener('activity', this.#onActivity)\n\t\tthis.#agent.removeEventListener('dispose', this.#onAgentDispose)\n\n\t\t// Clean up UI\n\t\tthis.#isWaitingForUserAnswer = false\n\t\tthis.#stopHeaderUpdateLoop()\n\t\tthis.wrapper.remove()\n\t}\n\n\t// ========== Private methods ==========\n\n\t#getToolExecutingText(toolName: string, args: unknown): string {\n\t\tconst a = args as Record<string, string | number>\n\t\tswitch (toolName) {\n\t\t\tcase 'click_element_by_index':\n\t\t\t\treturn this.#i18n.t('ui.tools.clicking', { index: a.index })\n\t\t\tcase 'input_text':\n\t\t\t\treturn this.#i18n.t('ui.tools.inputting', { index: a.index })\n\t\t\tcase 'select_dropdown_option':\n\t\t\t\treturn this.#i18n.t('ui.tools.selecting', { text: a.text })\n\t\t\tcase 'scroll':\n\t\t\t\treturn this.#i18n.t('ui.tools.scrolling')\n\t\t\tcase 'wait':\n\t\t\t\treturn this.#i18n.t('ui.tools.waiting', { seconds: a.seconds })\n\t\t\tcase 'ask_user':\n\t\t\t\treturn this.#i18n.t('ui.tools.askingUser')\n\t\t\tcase 'done':\n\t\t\t\treturn this.#i18n.t('ui.tools.done')\n\t\t\tdefault:\n\t\t\t\treturn this.#i18n.t('ui.tools.executing', { toolName })\n\t\t}\n\t}\n\n\t/**\n\t * Action button handler: stop when running, close (dispose) when idle\n\t */\n\t#handleActionButton(): void {\n\t\tif (this.#agent.status === 'running') {\n\t\t\tthis.#agent.stop()\n\t\t} else {\n\t\t\tthis.#agent.dispose()\n\t\t}\n\t}\n\n\t/**\n\t * Submit task\n\t */\n\t#submitTask() {\n\t\tconst input = this.#taskInput.value.trim()\n\t\tif (!input) return\n\n\t\t// Hide input area\n\t\tthis.#hideInputArea()\n\n\t\tif (this.#isWaitingForUserAnswer) {\n\t\t\t// Handle user input mode\n\t\t\tthis.#handleUserAnswer(input)\n\t\t} else {\n\t\t\t// Execute task via agent\n\t\t\tthis.#agent.execute(input)\n\t\t}\n\t}\n\n\t/**\n\t * Handle user answer\n\t */\n\t#handleUserAnswer(input: string): void {\n\t\tthis.#removeTempCards()\n\n\t\t// Reset state\n\t\tthis.#isWaitingForUserAnswer = false\n\n\t\t// Call resolver to return user input\n\t\tif (this.#userAnswerResolver) {\n\t\t\tthis.#userAnswerResolver(input)\n\t\t\tthis.#userAnswerResolver = null\n\t\t}\n\t}\n\n\t/**\n\t * Show input area\n\t */\n\t#showInputArea(placeholder?: string): void {\n\t\t// Clear input field\n\t\tthis.#taskInput.value = ''\n\t\tthis.#taskInput.placeholder = placeholder || this.#i18n.t('ui.panel.taskInput')\n\t\tthis.#inputSection.classList.remove(styles.hidden)\n\t\t// Focus on input field\n\t\tsetTimeout(() => {\n\t\t\tthis.#taskInput.focus()\n\t\t}, 100)\n\t}\n\n\t/**\n\t * Hide input area\n\t */\n\t#hideInputArea(): void {\n\t\tthis.#inputSection.classList.add(styles.hidden)\n\t}\n\n\t/**\n\t * Check if input area should be shown\n\t */\n\t#shouldShowInputArea(): boolean {\n\t\t// Always show input area if waiting for user input\n\t\tif (this.#isWaitingForUserAnswer) return true\n\n\t\tconst history = this.#agent.history\n\t\tif (history.length === 0) {\n\t\t\treturn true // Initial state\n\t\t}\n\n\t\tconst status = this.#agent.status\n\t\tconst isTaskEnded = status === 'completed' || status === 'error' || status === 'stopped'\n\n\t\t// Only show input area after task completion if configured to do so\n\t\tif (isTaskEnded) {\n\t\t\treturn this.#config.promptForNextTask ?? true\n\t\t}\n\n\t\treturn false\n\t}\n\n\t#createWrapper(): HTMLElement {\n\t\tconst taskInputMaxLength = 1000\n\t\tconst wrapper = document.createElement('div')\n\t\twrapper.id = 'page-agent-runtime_agent-panel'\n\t\twrapper.className = styles.wrapper\n\t\twrapper.setAttribute('data-browser-use-ignore', 'true')\n\t\twrapper.setAttribute('data-page-agent-ignore', 'true')\n\t\t// FORK: o painel é uma região complementar à página; nomear permite pular direto para ele.\n\t\twrapper.setAttribute('role', 'complementary')\n\t\twrapper.setAttribute('aria-label', this.#i18n.t('ui.panel.panelLabel'))\n\n\t\twrapper.innerHTML = `\n\t\t\t<div class=\"${styles.background}\"></div>\n\t\t\t<div class=\"${styles.historySectionWrapper}\">\n\t\t\t\t<!-- FORK: role=log + aria-live faz o leitor de tela anunciar cada mensagem nova sem\n\t\t\t\t roubar o foco de quem está usando a página. aria-relevant=additions evita\n\t\t\t\t reanunciar o histórico inteiro a cada render. -->\n\t\t\t\t<div\n\t\t\t\t\tclass=\"${styles.historySection}\"\n\t\t\t\t\trole=\"log\"\n\t\t\t\t\taria-live=\"polite\"\n\t\t\t\t\taria-relevant=\"additions\"\n\t\t\t\t\taria-label=\"${this.#i18n.t('ui.panel.historyLabel')}\"\n\t\t\t\t>\n\t\t\t\t\t<div class=\"${styles.historyRow} ${styles.fromSistema}\">\n\t\t\t\t\t\t<div class=\"${styles.historyItem}\" data-mensagem=\"sistema\">\n\t\t\t\t\t\t\t<div class=\"${styles.historyHeader}\">\n\t\t\t\t\t\t\t\t<span class=\"${styles.statusIcon}\">${iconThinking}</span>\n\t\t\t\t\t\t\t\t<span class=\"${styles.historyAuthor}\" data-autor=\"sistema\">${this.#i18n.t('ui.panel.authorSystem')}</span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"${styles.historyContent}\" data-conteudo><span>${this.#i18n.t('ui.panel.waitingPlaceholder')}</span></div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"${styles.header}\">\n\t\t\t\t<div class=\"${styles.statusSection}\">\n\t\t\t\t\t<div class=\"${styles.indicator} ${styles.thinking}\"></div>\n\t\t\t\t\t<div class=\"${styles.statusText}\">${this.#i18n.t('ui.panel.ready')}</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"${styles.controls}\">\n\t\t\t\t\t<button class=\"${styles.controlButton} ${styles.expandButton}\" title=\"${this.#i18n.t('ui.panel.expand')}\">\n\t\t\t\t\t\t▼\n\t\t\t\t\t</button>\n\t\t\t\t\t<button class=\"${styles.controlButton} ${styles.stopButton}\" title=\"${this.#i18n.t('ui.panel.close')}\">\n\t\t\t\t\t\tX\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"${styles.inputSectionWrapper} ${styles.hidden}\">\n\t\t\t\t<div class=\"${styles.inputSection}\">\n\t\t\t\t\t<input \n\t\t\t\t\t\ttype=\"text\" \n\t\t\t\t\t\tclass=\"${styles.taskInput}\" \n\t\t\t\t\t\tmaxlength=\"${taskInputMaxLength}\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\n\t\tdocument.body.appendChild(wrapper)\n\t\treturn wrapper\n\t}\n\n\t#setupEventListeners(): void {\n\t\t// Click header area to expand/collapse\n\t\tconst header = this.wrapper.querySelector(`.${styles.header}`)!\n\t\theader.addEventListener('click', (e) => {\n\t\t\t// Don't trigger expand/collapse if clicking on buttons\n\t\t\tif ((e.target as HTMLElement).closest(`.${styles.controlButton}`)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.#toggle()\n\t\t})\n\n\t\t// Expand button\n\t\tthis.#expandButton.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t\tthis.#toggle()\n\t\t})\n\n\t\t// Action button (stop / close)\n\t\tthis.#actionButton.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t\tthis.#handleActionButton()\n\t\t})\n\n\t\t// Submit on Enter key in input field\n\t\tthis.#taskInput.addEventListener('keydown', (e) => {\n\t\t\tif (e.isComposing) return // Ignore IME composition keys\n\t\t\tif (e.key === 'Enter') {\n\t\t\t\te.preventDefault()\n\t\t\t\tthis.#submitTask()\n\t\t\t}\n\t\t})\n\n\t\t// Prevent input area click event bubbling\n\t\tthis.#inputSection.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t})\n\t}\n\n\t#toggle(): void {\n\t\tif (this.#isExpanded) {\n\t\t\tthis.#collapse()\n\t\t} else {\n\t\t\tthis.#expand()\n\t\t}\n\t}\n\n\t#expand(): void {\n\t\tthis.#isExpanded = true\n\t\tthis.wrapper.classList.add(styles.expanded)\n\t\tthis.#expandButton.textContent = '▲'\n\t}\n\n\t#collapse(): void {\n\t\tthis.#isExpanded = false\n\t\tthis.wrapper.classList.remove(styles.expanded)\n\t\tthis.#expandButton.textContent = '▼'\n\t}\n\n\t/**\n\t * Start periodic header update loop\n\t */\n\t#startHeaderUpdateLoop(): void {\n\t\t// Check every 450ms (same as total animation duration)\n\t\tthis.#headerUpdateTimer = setInterval(() => {\n\t\t\tthis.#checkAndUpdateHeader()\n\t\t}, 450)\n\t}\n\n\t/**\n\t * Stop periodic header update loop\n\t */\n\t#stopHeaderUpdateLoop(): void {\n\t\tif (this.#headerUpdateTimer) {\n\t\t\tclearInterval(this.#headerUpdateTimer)\n\t\t\tthis.#headerUpdateTimer = null\n\t\t}\n\t}\n\n\t/**\n\t * Check if header needs update and trigger animation if not currently animating\n\t */\n\t#checkAndUpdateHeader(): void {\n\t\t// If no pending text or currently animating, skip\n\t\tif (!this.#pendingHeaderText || this.#isAnimating) {\n\t\t\treturn\n\t\t}\n\n\t\t// If text is already displayed, clear pending and skip\n\t\tif (this.#statusText.textContent === this.#pendingHeaderText) {\n\t\t\tthis.#pendingHeaderText = null\n\t\t\treturn\n\t\t}\n\n\t\t// Start animation\n\t\tconst textToShow = this.#pendingHeaderText\n\t\tthis.#pendingHeaderText = null\n\t\tthis.#animateTextChange(textToShow)\n\t}\n\n\t/**\n\t * Animate text change with fade out/in effect\n\t */\n\t#animateTextChange(newText: string): void {\n\t\tthis.#isAnimating = true\n\n\t\t// Fade out current text\n\t\tthis.#statusText.classList.add(styles.fadeOut)\n\n\t\tsetTimeout(() => {\n\t\t\t// Update text content\n\t\t\tthis.#statusText.textContent = newText\n\n\t\t\t// Fade in new text\n\t\t\tthis.#statusText.classList.remove(styles.fadeOut)\n\t\t\tthis.#statusText.classList.add(styles.fadeIn)\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.#statusText.classList.remove(styles.fadeIn)\n\t\t\t\tthis.#isAnimating = false\n\t\t\t}, 300)\n\t\t}, 150) // Half the duration of fade out animation\n\t}\n\n\t#updateStatusIndicator(\n\t\ttype:\n\t\t\t| 'idle'\n\t\t\t| 'running'\n\t\t\t| 'thinking'\n\t\t\t| 'executing'\n\t\t\t| 'executed'\n\t\t\t| 'retrying'\n\t\t\t| 'completed'\n\t\t\t| 'error'\n\t\t\t| 'stopped'\n\t): void {\n\t\t// `running` animates like thinking; `idle`/`stopped` use the neutral base.\n\t\tconst variant = type === 'running' ? 'thinking' : type\n\t\tthis.#indicator.className = styles.indicator\n\t\tif (variant !== 'idle' && variant !== 'stopped') {\n\t\t\tthis.#indicator.classList.add(styles[variant])\n\t\t}\n\t}\n\n\t#scrollToBottom(): void {\n\t\t// Execute in next event loop to ensure DOM update completion\n\t\tsetTimeout(() => {\n\t\t\tthis.#historySection.scrollTop = this.#historySection.scrollHeight\n\t\t}, 0)\n\t}\n\n\t/**\n\t * Render history directly from agent.history\n\t *\n\t * Renders:\n\t * 1. Task (first item, from agent.task)\n\t * 2. Reflection cards (evaluation, memory, next_goal)\n\t * 3. Tool execution with output\n\t * 4. Observations\n\t */\n\t#renderHistory(): void {\n\t\tconst items: string[] = []\n\n\t\t// 1. Task card (always first)\n\t\tconst task = this.#agent.task\n\t\tif (task) {\n\t\t\titems.push(this.#createTaskCard(task))\n\t\t}\n\n\t\t// 2. Render each history event\n\t\tconst history = this.#agent.history\n\t\tfor (const event of history) {\n\t\t\titems.push(...this.#createHistoryCards(event))\n\t\t}\n\n\t\tthis.#historySection.innerHTML = items.join('')\n\t\tthis.#scrollToBottom()\n\t}\n\n\t#createTaskCard(task: string): string {\n\t\treturn createCard({\n\t\t\ticon: iconTask,\n\t\t\tcontent: task,\n\t\t\ttype: 'input',\n\t\t\tfrom: 'pessoa',\n\t\t\tauthor: this.#i18n.t('ui.panel.authorPerson'),\n\t\t})\n\t}\n\n\t/** Create cards for a history event */\n\t#createHistoryCards(event: PanelAgentAdapter['history'][number]): string[] {\n\t\tconst cards: string[] = []\n\t\tconst meta =\n\t\t\tevent.type === 'step' && event.stepIndex !== undefined\n\t\t\t\t? this.#i18n.t('ui.panel.step', {\n\t\t\t\t\t\tnumber: (event.stepIndex + 1).toString(),\n\t\t\t\t\t})\n\t\t\t\t: undefined\n\n\t\tif (event.type === 'step') {\n\t\t\t// Reflection card\n\t\t\tif (event.reflection) {\n\t\t\t\tconst lines = createReflectionLines(event.reflection, {\n\t\t\t\t\tevaluation: this.#i18n.t('ui.panel.reflectionEvaluation'),\n\t\t\t\t\tmemory: this.#i18n.t('ui.panel.reflectionMemory'),\n\t\t\t\t\tnextGoal: this.#i18n.t('ui.panel.reflectionNextGoal'),\n\t\t\t\t})\n\t\t\t\tif (lines.length > 0) {\n\t\t\t\t\tcards.push(\n\t\t\t\t\t\tcreateCard({\n\t\t\t\t\t\t\ticon: iconThinking,\n\t\t\t\t\t\t\tcontent: lines,\n\t\t\t\t\t\t\tmeta,\n\t\t\t\t\t\t\tauthor: this.#i18n.t('ui.panel.authorReasoning'),\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Action card\n\t\t\tconst action = event.action\n\t\t\tif (action) {\n\t\t\t\tcards.push(...this.#createActionCards(action, meta))\n\t\t\t}\n\t\t} else if (event.type === 'observation') {\n\t\t\tcards.push(\n\t\t\t\tcreateCard({\n\t\t\t\t\ticon: iconObservation,\n\t\t\t\t\tcontent: event.content || '',\n\t\t\t\t\tmeta,\n\t\t\t\t\ttype: 'observation',\n\t\t\t\t\tauthor: this.#i18n.t('ui.panel.authorPage'),\n\t\t\t\t})\n\t\t\t)\n\t\t} else if (event.type === 'user_takeover') {\n\t\t\tcards.push(\n\t\t\t\tcreateCard({\n\t\t\t\t\ticon: iconUser,\n\t\t\t\t\tcontent: this.#i18n.t('ui.panel.userTakeover'),\n\t\t\t\t\tmeta,\n\t\t\t\t\ttype: 'input',\n\t\t\t\t\tfrom: 'pessoa',\n\t\t\t\t\tauthor: this.#i18n.t('ui.panel.authorPerson'),\n\t\t\t\t})\n\t\t\t)\n\t\t} else if (event.type === 'retry') {\n\t\t\tconst retryInfo = `${event.message || this.#i18n.t('ui.panel.retrying')} (${event.attempt}/${event.maxAttempts})`\n\t\t\tcards.push(\n\t\t\t\tcreateCard({\n\t\t\t\t\ticon: iconRetry,\n\t\t\t\t\tcontent: retryInfo,\n\t\t\t\t\tmeta,\n\t\t\t\t\ttype: 'observation',\n\t\t\t\t\tfrom: 'sistema',\n\t\t\t\t\tauthor: this.#i18n.t('ui.panel.authorSystem'),\n\t\t\t\t})\n\t\t\t)\n\t\t} else if (event.type === 'error') {\n\t\t\tcards.push(\n\t\t\t\tcreateCard({\n\t\t\t\t\ticon: iconError,\n\t\t\t\t\tcontent: event.message || this.#i18n.t('ui.panel.errorLabel'),\n\t\t\t\t\tmeta,\n\t\t\t\t\ttype: 'observation',\n\t\t\t\t\tfrom: 'sistema',\n\t\t\t\t\tauthor: this.#i18n.t('ui.panel.authorSystem'),\n\t\t\t\t})\n\t\t\t)\n\t\t}\n\n\t\treturn cards\n\t}\n\n\t/** Create cards for an action */\n\t#createActionCards(\n\t\taction: { name: string; input: unknown; output: string },\n\t\tmeta?: string\n\t): string[] {\n\t\tconst cards: string[] = []\n\n\t\tif (action.name === 'done') {\n\t\t\tconst input = action.input as { text?: string }\n\t\t\tconst text = input.text || action.output || ''\n\t\t\tif (text) {\n\t\t\t\tcards.push(\n\t\t\t\t\tcreateCard({\n\t\t\t\t\t\ticon: iconDone,\n\t\t\t\t\t\tcontent: text,\n\t\t\t\t\t\tmeta,\n\t\t\t\t\t\ttype: 'output',\n\t\t\t\t\t\tauthor: this.#i18n.t('ui.panel.authorAgent'),\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t}\n\t\t} else if (action.name === 'ask_user') {\n\t\t\tconst input = action.input as { question?: string }\n\t\t\tconst answer = action.output.replace(/^User answered:\\s*/i, '')\n\t\t\tcards.push(\n\t\t\t\tcreateCard({\n\t\t\t\t\ticon: iconQuestion,\n\t\t\t\t\tcontent: this.#i18n.t('ui.panel.question', { question: input.question || '' }),\n\t\t\t\t\tmeta,\n\t\t\t\t\ttype: 'question',\n\t\t\t\t\tauthor: this.#i18n.t('ui.panel.authorAgent'),\n\t\t\t\t})\n\t\t\t)\n\t\t\tcards.push(\n\t\t\t\tcreateCard({\n\t\t\t\t\ticon: iconAnswer,\n\t\t\t\t\tcontent: this.#i18n.t('ui.panel.userAnswer', { input: answer }),\n\t\t\t\t\tmeta,\n\t\t\t\t\ttype: 'input',\n\t\t\t\t\tfrom: 'pessoa',\n\t\t\t\t\tauthor: this.#i18n.t('ui.panel.authorPerson'),\n\t\t\t\t})\n\t\t\t)\n\t\t} else {\n\t\t\tconst toolText = this.#getToolExecutingText(action.name, action.input)\n\t\t\tcards.push(\n\t\t\t\tcreateCard({ icon: iconTool, content: toolText, meta, author: this.#i18n.t('ui.panel.authorAction') })\n\t\t\t)\n\t\t\tif (action.output?.length > 0) {\n\t\t\t\tcards.push(\n\t\t\t\t\tcreateCard({\n\t\t\t\t\t\ticon: iconTool,\n\t\t\t\t\t\tcontent: action.output,\n\t\t\t\t\t\tmeta,\n\t\t\t\t\t\ttype: 'output',\n\t\t\t\t\t\tauthor: this.#i18n.t('ui.panel.authorResult'),\n\t\t\t\t\t})\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\treturn cards\n\t}\n}\n","/**\n * Copyright (C) 2025 Alibaba Group Holding Limited\n * All rights reserved.\n */\nimport { type AgentConfig, PageAgentCore } from '@page-agent/core'\nimport { PageController, type PageControllerConfig } from '@page-agent/page-controller'\nimport { Panel, type PanelConfig } from '@page-agent/ui'\n\nexport * from '@page-agent/core'\n\nexport type PageAgentConfig = AgentConfig & PageControllerConfig & Omit<PanelConfig, 'language'>\n\nexport class PageAgent extends PageAgentCore {\n\tpanel: Panel\n\n\tconstructor(config: PageAgentConfig) {\n\t\tconst pageController = new PageController({\n\t\t\t...config,\n\t\t\tenableMask: config.enableMask ?? true,\n\t\t})\n\n\t\tsuper({ ...config, pageController })\n\n\t\tthis.panel = new Panel(this, {\n\t\t\tlanguage: config.language,\n\t\t\tpromptForNextTask: config.promptForNextTask,\n\t\t})\n\t}\n}\n","/**\n * FORK: módulo de voz do widget. Zero dependências — usa apenas a Web Speech API nativa do\n * navegador (reconhecimento + síntese), o que mantém o bundle leve e funciona offline/sem rede\n * além das chamadas do próprio agente.\n *\n * Filosofia (regras do laboratório):\n * - Degrada sem quebrar: se o navegador não tem mic nem síntese, `supported` informa e os\n * métodos viram no-op silenciosos — a UI decide esconder os botões, o agente segue funcionando.\n * - Espera por condição, nunca por relógio: `listen()` resolve quando chega o resultado final;\n * o timeout é só uma trava de segurança contra um reconhecimento que \"prende\" a UI.\n * - Nada de rede própria: o reconhecimento/síntese são do navegador (Chrome/Edge/Safari enviam\n * apenas o áudio necessário para o serviço de voz do SO; em rede limitada isso é mínimo).\n */\n\ntype VoiceStatus = 'idle' | 'listening' | 'speaking'\n\ninterface VoiceRecognitionLike {\n\tlang: string\n\tcontinuous: boolean\n\tinterimResults: boolean\n\tmaxAlternatives: number\n\tabort(): void\n\tstart(): void\n\tstop(): void\n\tonresult: ((event: { resultIndex: number; results: ArrayLike<ArrayLike<{ transcript: string }> & { isFinal: boolean }> }) => void) | null\n\tonerror: ((event: { error?: string }) => void) | null\n\tonend: (() => void) | null\n\tonstart: (() => void) | null\n}\n\nfunction getRecognitionCtor(): (new () => VoiceRecognitionLike) | null {\n\tconst w = globalThis as unknown as {\n\t\tSpeechRecognition?: new () => VoiceRecognitionLike\n\t\twebkitSpeechRecognition?: new () => VoiceRecognitionLike\n\t}\n\treturn w.SpeechRecognition ?? w.webkitSpeechRecognition ?? null\n}\n\nexport interface VoiceOptions {\n\t/** Idioma BCP-47 do reconhecimento e da síntese. @default 'pt-BR' */\n\tlang?: string\n\t/** Habilita o reconhecimento de fala (botão de microfone). @default true */\n\tinput?: boolean\n\t/** Habilita a síntese de fala (agente fala o resultado). @default false */\n\toutput?: boolean\n\t/** URI de uma voz específica do speechSynthesis (deixa o módulo escolher quando ausente). */\n\tvoiceURI?: string\n\t/** Velocidade da síntese (0.1–10). @default 1 */\n\trate?: number\n\t/** Tom da síntese (0–2). @default 1 */\n\tpitch?: number\n\t/** Trava de segurança para `listen()`: ms até rejeitar se o reconhecimento não terminar. @default 30000 */\n\tlistenTimeoutMs?: number\n}\n\nexport interface Voice {\n\t/** O que o navegador realmente oferece. A UI usa isto para mostrar/ocultar controles. */\n\treadonly supported: { input: boolean; output: boolean }\n\t/**\n\t * Escuta uma vez e resolve com a transcrição final. Rejeita em erro real; resolve com \"\"\n\t * quando o usuário não fala nada ('no-speech') — não é falha, é \"nada foi dito\".\n\t */\n\tlisten(): Promise<string>\n\t/** Interrompe a escuta em andamento. */\n\tstopListening(): void\n\t/** Fala um texto. `interrupt` corta o que estiver sendo dito antes de começar. */\n\tspeak(text: string, opts?: { interrupt?: boolean }): void\n\t/** Para a síntese em andamento. */\n\tstopSpeaking(): void\n\t/** Observa transições de estado (a UI mostra o indicador de \"ouvindo/falando\"). */\n\tonStatus(cb: (status: VoiceStatus) => void): () => void\n}\n\nconst STATUS_LISTENING = 'listening'\nconst STATUS_SPEAKING = 'speaking'\nconst STATUS_IDLE = 'idle'\n\nexport function createVoice(options: VoiceOptions = {}): Voice {\n\tconst lang = options.lang ?? 'pt-BR'\n\tconst rate = options.rate ?? 1\n\tconst pitch = options.pitch ?? 1\n\tconst inputEnabled = options.input ?? true\n\tconst outputEnabled = options.output ?? false\n\tconst listenTimeoutMs = options.listenTimeoutMs ?? 30_000\n\n\tconst Recognition = inputEnabled ? getRecognitionCtor() : null\n\tconst synth = typeof window !== 'undefined' ? window.speechSynthesis : undefined\n\n\tconst supported: Voice['supported'] = {\n\t\tinput: Boolean(inputEnabled && Recognition),\n\t\toutput: Boolean(outputEnabled && synth),\n\t}\n\n\tlet status: VoiceStatus = STATUS_IDLE\n\tconst statusListeners = new Set<(s: VoiceStatus) => void>()\n\tfunction setStatus(next: VoiceStatus) {\n\t\tif (status === next) return\n\t\tstatus = next\n\t\tstatusListeners.forEach(cb => {\n\t\t\ttry {\n\t\t\t\tcb(next)\n\t\t\t} catch {\n\t\t\t\t// ouvinte quebrado não derruba o módulo de voz\n\t\t\t}\n\t\t})\n\t}\n\n\tlet activeRecognition: VoiceRecognitionLike | null = null\n\tlet currentVoice: SpeechSynthesisVoice | null = null\n\n\t// A lista de vozes carrega de forma assíncrona em alguns navegadores; escolhe a melhor pt-BR\n\t// (ou a língua pedida) quando ela ficar disponível.\n\tif (synth) {\n\t\tconst pickVoice = () => {\n\t\t\tif (options.voiceURI) {\n\t\t\t\tcurrentVoice = synth.getVoices().find(v => v.voiceURI === options.voiceURI) ?? null\n\t\t\t} else {\n\t\t\t\tconst voices = synth.getVoices()\n\t\t\t\tconst prefix = lang.split('-')[0].toLowerCase()\n\t\t\t\tcurrentVoice =\n\t\t\t\t\tvoices.find(v => v.lang?.toLowerCase() === lang.toLowerCase()) ??\n\t\t\t\t\tvoices.find(v => v.lang?.toLowerCase().startsWith(prefix)) ??\n\t\t\t\t\tnull\n\t\t\t}\n\t\t}\n\t\tpickVoice()\n\t\tsynth.onvoiceschanged = pickVoice\n\t}\n\n\tfunction speak(text: string, opts?: { interrupt?: boolean }) {\n\t\tif (!synth || !outputEnabled) return\n\t\tconst clean = (text ?? '').trim()\n\t\tif (!clean) return\n\t\tif (opts?.interrupt !== false) {\n\t\t\tsynth.cancel()\n\t\t}\n\t\tconst utterance = new SpeechSynthesisUtterance(clean)\n\t\tutterance.lang = lang\n\t\tutterance.rate = rate\n\t\tutterance.pitch = pitch\n\t\tif (currentVoice) utterance.voice = currentVoice\n\t\tutterance.onend = () => setStatus(STATUS_IDLE)\n\t\tutterance.onerror = () => setStatus(STATUS_IDLE)\n\t\tsetStatus(STATUS_SPEAKING)\n\t\tsynth.speak(utterance)\n\t}\n\n\tfunction listen(): Promise<string> {\n\t\tif (!Recognition) {\n\t\t\treturn Promise.reject(new Error('Voz de entrada não suportada neste navegador'))\n\t\t}\n\t\treturn new Promise<string>((resolve, reject) => {\n\t\t\tconst recognition = new Recognition()\n\t\t\tactiveRecognition = recognition\n\t\t\tlet finalText = ''\n\t\t\tlet settled = false\n\t\t\tlet timer: ReturnType<typeof setTimeout> | undefined\n\n\t\t\tconst finish = (fn: () => void) => {\n\t\t\t\tif (settled) return\n\t\t\t\tsettled = true\n\t\t\t\tif (timer) clearTimeout(timer)\n\t\t\t\tif (activeRecognition === recognition) activeRecognition = null\n\t\t\t\tsetStatus(STATUS_IDLE)\n\t\t\t\tfn()\n\t\t\t}\n\n\t\t\t// Trava de segurança: nunca deixar a UI presa num reconhecimento que não termina.\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\ttry {\n\t\t\t\t\trecognition.stop()\n\t\t\t\t} catch {\n\t\t\t\t\t/* já parado */\n\t\t\t\t}\n\t\t\t\tfinish(() => reject(new Error('Tempo de escuta esgotado')))\n\t\t\t}, listenTimeoutMs)\n\n\t\t\trecognition.lang = lang\n\t\t\trecognition.continuous = false\n\t\t\trecognition.interimResults = true\n\t\t\trecognition.maxAlternatives = 1\n\n\t\t\trecognition.onstart = () => setStatus(STATUS_LISTENING)\n\t\t\trecognition.onresult = event => {\n\t\t\t\tfor (let i = event.resultIndex; i < event.results.length; i++) {\n\t\t\t\t\tconst result = event.results[i]\n\t\t\t\t\tif (result?.isFinal) finalText = result[0]?.transcript ?? finalText\n\t\t\t\t}\n\t\t\t}\n\t\t\trecognition.onerror = event => {\n\t\t\t\tconst code = event?.error\n\t\t\t\t// 'no-speech' e 'aborted' não são falhas: o usuário não falou / cancelou.\n\t\t\t\tif (code === 'no-speech' || code === 'aborted') {\n\t\t\t\t\tfinish(() => resolve(finalText.trim()))\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tfinish(() => reject(new Error(`Erro de reconhecimento de voz: ${code ?? 'desconhecido'}`)))\n\t\t\t}\n\t\t\trecognition.onend = () => {\n\t\t\t\tfinish(() => resolve(finalText.trim()))\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\trecognition.start()\n\t\t\t} catch (error) {\n\t\t\t\tfinish(() => reject(error instanceof Error ? error : new Error(String(error))))\n\t\t\t}\n\t\t})\n\t}\n\n\treturn {\n\t\tsupported,\n\t\tlisten,\n\t\tstopListening() {\n\t\t\ttry {\n\t\t\t\tactiveRecognition?.stop()\n\t\t\t} catch {\n\t\t\t\t/* já parado */\n\t\t\t}\n\t\t\tactiveRecognition = null\n\t\t\tsetStatus(STATUS_IDLE)\n\t\t},\n\t\tspeak,\n\t\tstopSpeaking() {\n\t\t\tif (!synth) return\n\t\t\tsynth.cancel()\n\t\t\tsetStatus(STATUS_IDLE)\n\t\t},\n\t\tonStatus(cb) {\n\t\t\tstatusListeners.add(cb)\n\t\t\treturn () => statusListeners.delete(cb)\n\t\t},\n\t}\n}\n","/**\n * FORK: widget central do page-agent. É o ÚNICO ponto de integração para um projeto host:\n * uma chamada `mountWidget(config)` centraliza agente + painel + voz + config, com defaults\n * sensatos, criação lazy do agente (a página não paga startup até o widget abrir) e degradação\n * graciosa de voz. Pensado para mobile/desktop e rede limitada/offline: arquivo único, sem\n * assets externos, agente criado sob demanda.\n *\n * Uso em projeto host (npm):\n * import { mountWidget } from \"@omnivoice/page-agent\";\n * const w = mountWidget({ model, baseURL, apiKey, voice: { input: true, output: true } });\n *\n * Uso via CDN (IIFE):\n * <script src=\".../page-agent.demo.js\" data-auto-init=\"false\"></script>\n * <script>PageAgent.mountWidget({ model, baseURL, apiKey })</script>\n */\nimport { PageAgent, type PageAgentConfig } from './PageAgent'\nimport type { ExecutionResult } from '@omnivoice/core'\nimport { createVoice, type Voice, type VoiceOptions } from './voice'\nimport './widget.css'\n\nexport type { Voice, VoiceOptions }\nexport { createVoice }\n\nexport interface WidgetVoiceOptions extends VoiceOptions {\n\t/** Fala o resultado quando a tarefa termina (requer `output: true`). @default true */\n\tspeakOnComplete?: boolean\n\t/** Fala o próximo objetivo a cada passo (mais falante; útil para mãos-livres). @default false */\n\tspeakSteps?: boolean\n}\n\nexport interface WidgetOptions {\n\t// --- LLM (config central; um lugar só) ---\n\t/** Modelo. Ex.: \"gpt-4o-mini\". */\n\tmodel?: string\n\t/** Endpoint OpenAI-compatible. */\n\tbaseURL?: string\n\t/**\n\t * Chave da API. Só para uso local/sem gateway (ex.: laboratório). Em produção, prefira\n\t * `configUrl` + gateway: a chave fica no servidor e não aparece no front-end.\n\t */\n\tapiKey?: string\n\t/**\n\t * URL de uma config pública servida pelo gateway do projeto (ex.: \"/api/agent/config\").\n\t * O widget busca model/idioma/passos/voz DE LÁ — o front nunca precisa da chave. O gateway\n\t * é a autoridade: ele injeta a `apiKey` no servidor e força o modelo configurado.\n\t */\n\tconfigUrl?: string\n\t/** Customiza o corpo da request (providers específicos). */\n\ttransformRequestBody?: PageAgentConfig['transformRequestBody']\n\t/** `fetch` custom (proxy, credentials, baixa latência). */\n\tcustomFetch?: PageAgentConfig['customFetch']\n\tmaxRetries?: number\n\n\t// --- Agente ---\n\t/** Idioma da interface e do raciocínio. @default 'pt-BR' */\n\tlanguage?: PageAgentConfig['language']\n\t/** Máximo de passos por tarefa. @default 30 */\n\tmaxSteps?: number\n\t/** Instruções globais/por página. */\n\tinstructions?: PageAgentConfig['instructions']\n\t/** Ferramentas customizadas. */\n\tcustomTools?: PageAgentConfig['customTools']\n\t/** Máscula sobre a página durante a execução. @default true */\n\tenableMask?: boolean\n\t/** Expansão da viewport ao enumerar elementos. @default 0 (só o que está visível) */\n\tviewportExpansion?: number\n\t/** Pergunta pela próxima tarefa ao concluir. @default true */\n\tpromptForNextTask?: boolean\n\n\t// --- UI ---\n\t/** Posição do botão-lançador. @default 'bottom-right' */\n\tposition?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'\n\t/** Rótulo acessível do botão-lançador. @default 'Abrir assistente da página' */\n\tlauncherLabel?: string\n\t/** Começa com o painel aberto (em vez de só o botão). @default false */\n\topen?: boolean\n\n\t// --- Voz ---\n\tvoice?: WidgetVoiceOptions\n}\n\nexport interface Widget {\n\t/** Agente centralizado (mesma instância que o painel controla). `null` até a primeira abertura. */\n\treadonly agent: PageAgent | null\n\t/** Voz centralizada (reconhecimento + síntese). `null` até a primeira abertura. */\n\treadonly voice: Voice | null\n\t/** Posição do botão-lançador. */\n\treadonly launcher: HTMLElement\n\t/** Garante config (busca o `configUrl`) + voz + agente prontos. Idempotente; devolve o agente. */\n\tready(): Promise<PageAgent>\n\t/** Executa uma tarefa programaticamente. */\n\trun(task: string): Promise<ExecutionResult>\n\t/** Para a tarefa em andamento (o agente segue reutilizável). */\n\tstop(): Promise<void>\n\t/** Abre o painel (propaga erro de config). `hide()`/`toggle()` para fechar/alternar. */\n\tshow(): Promise<void>\n\thide(): void\n\ttoggle(): void\n\t/** Atualiza config em runtime (recria o agente quando muda algo de LLM/agente). */\n\tsetConfig(patch: Partial<WidgetOptions>): void\n\t/** Remove launcher, painel e voz da página. */\n\tunmount(): void\n}\n\nconst DEFAULTS = {\n\tlanguage: 'pt-BR' as const,\n\tmaxSteps: 30,\n\tenableMask: true,\n\tviewportExpansion: 0,\n\tpromptForNextTask: true,\n\tposition: 'bottom-right' as const,\n\tlauncherLabel: 'Abrir assistente da página',\n\topen: false,\n}\n\nconst LAUNCHER_ICON =\n\t'<svg viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M12 3l1.9 4.6L18.5 9l-4.6 1.9L12 15.5l-1.9-4.6L5.5 9l4.6-1.4L12 3z\"/><path d=\"M19 14l.8 2 2 .8-2 .8-.8 2-.8-2-2-.8 2-.8.8-2z\"/></svg>'\n\nconst MIC_ICON =\n\t'<svg viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><rect x=\"9\" y=\"3\" width=\"6\" height=\"11\" rx=\"3\"/><path d=\"M5 11a7 7 0 0 0 14 0M12 18v3\"/></svg>'\n\ntype LauncherPosition = { top?: string; bottom?: string; left?: string; right?: string }\n\nfunction positionCss(position: WidgetOptions['position']): LauncherPosition {\n\tswitch (position) {\n\t\tcase 'bottom-left':\n\t\t\treturn { bottom: '20px', left: '20px', right: 'auto', top: 'auto' }\n\t\tcase 'top-right':\n\t\t\treturn { top: '20px', right: '20px', bottom: 'auto', left: 'auto' }\n\t\tcase 'top-left':\n\t\t\treturn { top: '20px', left: '20px', bottom: 'auto', right: 'auto' }\n\t\tdefault:\n\t\t\treturn { bottom: '20px', right: '20px', top: 'auto', left: 'auto' }\n\t}\n}\n\nexport function mountWidget(options: WidgetOptions = {}): Widget {\n\t// UI do launcher é decisão do cliente (posição/rotulo/abrir já). Config de LLM/agente/voz\n\t// pode vir do gateway (configUrl) — resolvida lazy em ensureConfig(), antes de criar o agente.\n\tconst position = options.position ?? DEFAULTS.position\n\tconst launcherLabel = options.launcherLabel ?? DEFAULTS.launcherLabel\n\tconst open = options.open ?? DEFAULTS.open\n\n\tlet agent: PageAgent | null = null\n\tlet voice: Voice | null = null\n\tlet micButton: HTMLButtonElement | null = null\n\tlet listening = false\n\tlet configPromise: Promise<void> | null = null\n\n\t// ---- Config pública do gateway (a chave NUNCA vem aqui) ----\n\t// O front manda só a configUrl; modelo/idioma/passos/voz vêm do servidor do projeto. Se não\n\t// houver configUrl, a config é a passada em `options` (modo local, ex.: laboratório).\n\tasync function ensureConfig(): Promise<void> {\n\t\tif (configPromise) return configPromise\n\t\tif (!options.configUrl) return\n\t\tconfigPromise = (async () => {\n\t\t\tconst res = await fetch(options.configUrl as string, { headers: { accept: 'application/json' } })\n\t\t\tif (!res.ok) throw new Error(`mountWidget: configUrl respondeu ${res.status} — o gateway está no ar?`)\n\t\t\tconst server = (await res.json()) as Partial<WidgetOptions>\n\t\t\t// O gateway é a autoridade do LLM/agente/voz. Não deixa o server tocar em\n\t\t\t// baseURL/configUrl/UI (essas são do cliente) nem injetar segredos novos.\n\t\t\tfor (const key of ['model', 'language', 'maxSteps', 'promptForNextTask', 'instructions', 'voice'] as const) {\n\t\t\t\tconst value = (server as Record<string, unknown>)[key]\n\t\t\t\tif (value !== undefined && value !== null) {\n\t\t\t\t\t;(options as Record<string, unknown>)[key] = value\n\t\t\t\t}\n\t\t\t}\n\t\t})()\n\t\treturn configPromise\n\t}\n\n\t// ---- Voz (lazy: só existe após a config resolvida, pois o gateway controla \"voz ativa\") ----\n\tfunction ensureVoice(): Voice {\n\t\tif (!voice) voice = createVoice(options.voice ?? {})\n\t\treturn voice\n\t}\n\n\t// ---- Agente (lazy: config → voz → instância) ----\n\tasync function ensureAgent(): Promise<PageAgent> {\n\t\tif (agent && !agent.disposed) return agent\n\t\tawait ensureConfig()\n\t\tconst v = ensureVoice()\n\t\t// model e baseURL são o mínimo p/ o agente existir. Com configUrl, model vem do gateway;\n\t\t// baseURL o cliente sempre sabe (é onde o gateway escuta). Falhar cedo = mensagem clara.\n\t\tconst model = options.model\n\t\tconst baseURL = options.baseURL\n\t\tif (!model || !baseURL) {\n\t\t\tthrow new Error(\n\t\t\t\toptions.configUrl\n\t\t\t\t\t? 'mountWidget: o gateway não enviou `model` e/ou falta `baseURL` no front. Confira AGENT_MODEL no gateway e a baseURL do widget.'\n\t\t\t\t\t: 'mountWidget: configure `model` e `baseURL` (config central do LLM) antes de abrir o agente.',\n\t\t\t)\n\t\t}\n\t\tagent = new PageAgent({\n\t\t\tmodel,\n\t\t\tbaseURL,\n\t\t\tapiKey: options.apiKey,\n\t\t\ttransformRequestBody: options.transformRequestBody,\n\t\t\tcustomFetch: options.customFetch,\n\t\t\tmaxRetries: options.maxRetries,\n\t\t\tlanguage: options.language ?? DEFAULTS.language,\n\t\t\tmaxSteps: options.maxSteps ?? DEFAULTS.maxSteps,\n\t\t\tenableMask: options.enableMask ?? DEFAULTS.enableMask,\n\t\t\tviewportExpansion: options.viewportExpansion ?? DEFAULTS.viewportExpansion,\n\t\t\tinstructions: options.instructions,\n\t\t\tcustomTools: options.customTools,\n\t\t\tpromptForNextTask: options.promptForNextTask ?? DEFAULTS.promptForNextTask,\n\t\t})\n\t\twireVoiceOutput(agent, v)\n\t\tinjectMicButton(agent, v)\n\t\treturn agent\n\t}\n\n\t// ---- Voz de saída (o gateway já decidiu se fala; a UI só executa) ----\n\tfunction wireVoiceOutput(a: PageAgent, v: Voice) {\n\t\t// lido AQUI (depois do ensureConfig) para refletir a decisão do gateway\n\t\tconst speakOnComplete = options.voice?.speakOnComplete ?? true\n\t\tconst speakSteps = options.voice?.speakSteps ?? false\n\t\tconst onStatus = () => {\n\t\t\tconst status = a.status\n\t\t\tconst result = a.lastResult\n\t\t\tif (status === 'completed' || status === 'error') {\n\t\t\t\tif (speakOnComplete && v.supported.output) {\n\t\t\t\t\tif (status === 'error') {\n\t\t\t\t\t\tv.speak('A tarefa encontrou um problema e foi parada.')\n\t\t\t\t\t} else if (result?.success) {\n\t\t\t\t\t\tv.speak('Tarefa concluída com sucesso.')\n\t\t\t\t\t} else {\n\t\t\t\t\t\tv.speak('A tarefa terminou, mas o resultado não foi confirmado.')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (speakSteps && status === 'running' && v.supported.output) {\n\t\t\t\tconst lastStep = [...a.history].reverse().find(h => h.type === 'step')\n\t\t\t\tconst goal = (lastStep as { reflection?: { next_goal?: string } } | undefined)?.reflection?.next_goal\n\t\t\t\tif (goal) v.speak(goal, { interrupt: true })\n\t\t\t}\n\t\t}\n\t\ta.addEventListener('statuschange', onStatus)\n\t\ta.addEventListener('activity', (event: Event) => {\n\t\t\tconst detail = (event as CustomEvent).detail as { type?: string; message?: string } | undefined\n\t\t\tif (detail?.type === 'error' && detail.message && v.supported.output) {\n\t\t\t\tv.speak(detail.message, { interrupt: true })\n\t\t\t}\n\t\t})\n\t}\n\n\t// ---- Botão de microfone (injetado no input de tarefa do painel) ----\n\tfunction injectMicButton(a: PageAgent, v: Voice) {\n\t\tconst wrapper = a.panel.wrapper\n\t\tconst input = wrapper.querySelector('input') as HTMLInputElement | null\n\t\tif (!input || !v.supported.input) return\n\t\tif (wrapper.querySelector('[data-page-agent-voice=\"mic\"]')) return\n\t\tif (micButton) micButton.remove()\n\n\t\tmicButton = document.createElement('button')\n\t\tmicButton.type = 'button'\n\t\tmicButton.className = 'page-agent-voice-mic'\n\t\tmicButton.setAttribute('data-page-agent-voice', 'mic')\n\t\tmicButton.setAttribute('aria-label', 'Ditar tarefa por voz')\n\t\tmicButton.title = 'Ditar tarefa por voz'\n\t\tmicButton.innerHTML = MIC_ICON\n\t\tmicButton.style.display = 'inline-flex'\n\n\t\t// Insere o mic junto ao input (dentro do mesmo contêiner, antes do input).\n\t\tconst host = input.parentElement ?? wrapper\n\t\thost.insertBefore(micButton, input)\n\n\t\tconst unsubscribe = v.onStatus(s => {\n\t\t\tmicButton?.classList.toggle('is-listening', s === 'listening')\n\t\t})\n\n\t\tmicButton.addEventListener('click', async () => {\n\t\t\tif (listening) {\n\t\t\t\tv.stopListening()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tlistening = true\n\t\t\ttry {\n\t\t\t\tconst transcript = await v.listen()\n\t\t\t\tif (transcript) {\n\t\t\t\t\tinput.value = transcript\n\t\t\t\t\tinput.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }))\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// Sem rede/permissão de mic: degrada para digitar. O widget não quebra.\n\t\t\t\tinput.setAttribute('placeholder', error instanceof Error ? error.message : 'Não foi possível ouvir; digite a tarefa.')\n\t\t\t\tsetTimeout(() => input.removeAttribute('placeholder'), 6000)\n\t\t\t} finally {\n\t\t\t\tlistening = false\n\t\t\t}\n\t\t})\n\n\t\tvoid unsubscribe\n\t}\n\n\t// ---- Launcher (FAB) ----\n\tconst launcher = document.createElement('button')\n\tlauncher.type = 'button'\n\tlauncher.className = 'page-agent-widget-launcher'\n\tlauncher.setAttribute('aria-label', launcherLabel)\n\tlauncher.title = launcherLabel\n\tlauncher.innerHTML = LAUNCHER_ICON\n\tconst pos = positionCss(position)\n\tObject.assign(launcher.style, pos)\n\n\tlet panelVisible = false\n\t// silent=true (clique no FAB / abrir inicial): loga e deixa o botão disponível para retry.\n\t// silent=false (w.show()/w.ready()/w.run): propaga o erro para quem chamou programaticamente.\n\tasync function openPanel(silent = false) {\n\t\ttry {\n\t\t\tconst a = await ensureAgent()\n\t\t\ta.panel.show()\n\t\t\tpanelVisible = true\n\t\t} catch (error) {\n\t\t\tif (silent) console.error('[page-agent-widget] não abriu o agente:', error)\n\t\t\telse throw error\n\t\t}\n\t}\n\tfunction closePanel() {\n\t\tagent?.panel.hide?.()\n\t\tpanelVisible = false\n\t}\n\tlauncher.addEventListener('click', () => {\n\t\tif (panelVisible) {\n\t\t\tclosePanel()\n\t\t} else {\n\t\t\tvoid openPanel(true)\n\t\t}\n\t})\n\n\tdocument.body.appendChild(launcher)\n\n\tif (open) {\n\t\tvoid openPanel(true)\n\t}\n\n\t// ---- Handle ----\n\tconst widget: Widget = {\n\t\tget agent() {\n\t\t\treturn agent\n\t\t},\n\t\tget voice() {\n\t\t\treturn voice\n\t\t},\n\t\tlauncher,\n\t\tready() {\n\t\t\treturn ensureAgent()\n\t\t},\n\t\tasync run(task: string) {\n\t\t\tconst a = await ensureAgent()\n\t\t\treturn await a.execute(task)\n\t\t},\n\t\tasync stop() {\n\t\t\tif (agent) await agent.stop()\n\t\t},\n\t\tshow() {\n\t\t\treturn openPanel(false)\n\t\t},\n\t\thide() {\n\t\t\tclosePanel()\n\t\t},\n\t\ttoggle() {\n\t\t\tlauncher.click()\n\t\t},\n\t\tsetConfig(patch: Partial<WidgetOptions>) {\n\t\t\t// Config de LLM/agente muda a identidade da instância: recria o agente na próxima abertura.\n\t\t\tObject.assign(options, patch)\n\t\t\tif (agent) {\n\t\t\t\tagent.dispose()\n\t\t\t\tagent = null\n\t\t\t}\n\t\t\tif (panelVisible) {\n\t\t\t\tpanelVisible = false\n\t\t\t\tvoid openPanel(true)\n\t\t\t}\n\t\t},\n\t\tunmount() {\n\t\t\tvoice?.stopSpeaking()\n\t\t\tvoice?.stopListening()\n\t\t\tagent?.dispose()\n\t\t\tagent = null\n\t\t\tvoice = null\n\t\t\tmicButton?.remove()\n\t\t\tmicButton = null\n\t\t\tlauncher.remove()\n\t\t},\n\t}\n\n\treturn widget\n}\n"],"names":["tool","tools","error","result","input","waitFor","signal","truncate","output","reflectionLines","dy","el","dx","args","parentElement","element","rect","viewportExpansion","nodeData","id","dom.resolveViewportExpansion","header","dom.cleanUpHighlights","dom.getFlatTree","dom.flatTreeToString","dom.getSelectorMap","dom.getElementTextMap","question","wrapper"],"mappings":"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"}
|