genkitx-playwright 0.3.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 +203 -0
- package/README.md +144 -0
- package/lib/index.d.mts +145 -0
- package/lib/index.d.ts +145 -0
- package/lib/index.js +803 -0
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +779 -0
- package/lib/index.mjs.map +1 -0
- package/package.json +57 -0
- package/samples/playwright.ts +35 -0
- package/src/browser.ts +142 -0
- package/src/index.ts +17 -0
- package/src/playwright.ts +149 -0
- package/src/tools.ts +759 -0
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/playwright.ts","../src/browser.ts","../src/tools.ts"],"sourcesContent":["export {\n playwright,\n PlaywrightOptionsSchema,\n type PlaywrightOptions,\n type PlaywrightPluginOptions,\n} from './playwright.js';\nexport {\n ALL_TOOL_NAMES,\n createPlaywrightTools,\n type PlaywrightToolName,\n type ToolFactoryOptions,\n} from './tools.js';\nexport {\n BrowserSession,\n type BrowserOptions,\n type BrowserType,\n} from './browser.js';\n","import {\n generateMiddleware,\n z,\n type GenerateMiddleware,\n type MessageData,\n} from 'genkit';\nimport { BrowserSession, type BrowserOptions } from './browser.js';\nimport {\n ALL_TOOL_NAMES,\n createPlaywrightTools,\n type PlaywrightToolName,\n} from './tools.js';\n\n\n/**\n * Browser-level options for the Playwright plugin, passed to\n * `playwright.plugin(...)`. These apply to every browser launched by the\n * middleware.\n */\nexport type PlaywrightPluginOptions = BrowserOptions;\n\n/**\n * Per-generation configuration for the Playwright middleware, passed to\n * `playwright(...)` in a `generate({ use: [...] })` call.\n */\nexport const PlaywrightOptionsSchema = z.object({\n readOnly: z\n .boolean()\n .optional()\n .describe(\n 'If true, only observe-only tools are injected (no clicking, typing, etc.).'\n ),\n allowEvaluate: z\n .boolean()\n .optional()\n .describe(\n 'If true, the browser_evaluate JS escape-hatch tool is enabled. Off by default.'\n ),\n tools: z\n .array(z.enum(ALL_TOOL_NAMES))\n .optional()\n .describe('Allow-list of tools to inject. Defaults to all tools.'),\n allowedDomains: z\n .array(z.string())\n .optional()\n .describe('If set, navigation is restricted to these hostnames.'),\n blockedDomains: z\n .array(z.string())\n .optional()\n .describe('Navigation to these hostnames is blocked.'),\n toolNamePrefix: z\n .string()\n .optional()\n .describe('Prefix prepended to every injected tool name.'),\n});\n\nexport type PlaywrightOptions = z.infer<typeof PlaywrightOptionsSchema>;\n\n/**\n * Genkit middleware that gives the model access to a real browser via\n * Playwright.\n *\n * Register the plugin once to configure the browser engine, then opt into the\n * tools per `generate` call:\n *\n * ```ts\n * import { genkit } from 'genkit';\n * import { playwright } from 'genkitx-playwright';\n *\n * const ai = genkit({ plugins: [playwright.plugin({ headless: true })] });\n *\n * await ai.generate({\n * prompt: 'Go to example.com and tell me the heading.',\n * use: [playwright()],\n * });\n * ```\n *\n * A fresh browser is launched lazily on the first tool call and closed\n * automatically when the generation completes.\n */\nexport const playwright: GenerateMiddleware<\n typeof PlaywrightOptionsSchema,\n PlaywrightPluginOptions\n> = generateMiddleware<\n PlaywrightPluginOptions,\n typeof PlaywrightOptionsSchema\n>(\n {\n name: 'playwright',\n description:\n 'Injects browser automation tools (navigate, snapshot, click, type, ' +\n 'etc.) backed by a Playwright browser.',\n configSchema: PlaywrightOptionsSchema,\n },\n ({ config, pluginConfig }) => {\n // One browser session per top-level generate call (by design, the\n // middleware factory runs once per generate).\n const session = new BrowserSession(pluginConfig ?? {});\n\n // Messages enqueued by tools (e.g. screenshots producing media parts) that\n // the generate hook injects into the conversation on the next turn.\n const messageQueue: MessageData[] = [];\n\n const tools = createPlaywrightTools({\n session,\n messageQueue,\n toolNamePrefix: config?.toolNamePrefix,\n readOnly: config?.readOnly,\n allowEvaluate: config?.allowEvaluate,\n tools: config?.tools as PlaywrightToolName[] | undefined,\n allowedDomains: config?.allowedDomains,\n blockedDomains: config?.blockedDomains,\n });\n\n return {\n tools,\n generate: async (envelope, ctx, next) => {\n try {\n const { request } = envelope;\n let { messageIndex } = envelope;\n\n // Drain any queued messages (e.g. screenshots) into the request so\n // media parts enter the model's context as real multimodal content\n // rather than a JSON blob in a tool response.\n if (messageQueue.length > 0) {\n if (ctx.onChunk) {\n for (const msg of messageQueue) {\n ctx.onChunk({\n role: msg.role,\n index: messageIndex++,\n content: msg.content,\n });\n }\n }\n request.messages.push(...messageQueue);\n messageQueue.length = 0;\n }\n\n return await next({ ...envelope, request, messageIndex }, ctx);\n } finally {\n // Always tear down the browser when the generation finishes,\n // regardless of success/failure.\n await session.close();\n }\n },\n };\n\n }\n);\n","import {\n chromium,\n firefox,\n webkit,\n type Browser,\n type BrowserContext,\n type BrowserContextOptions,\n type ConsoleMessage,\n type Dialog,\n type LaunchOptions,\n type Page,\n} from 'playwright';\n\nexport type BrowserType = 'chromium' | 'firefox' | 'webkit';\n\n/** Browser-level configuration, supplied via `playwright.plugin()`. */\nexport interface BrowserOptions {\n /** Which browser engine to use. Defaults to `chromium`. */\n browser?: BrowserType;\n /** Run the browser without a visible UI. Defaults to `true`. */\n headless?: boolean;\n /** Raw Playwright launch options, merged with the above. */\n launchOptions?: LaunchOptions;\n /** Raw Playwright browser-context options (viewport, userAgent, etc.). */\n contextOptions?: BrowserContextOptions;\n}\n\n/** A captured console message. */\nexport interface ConsoleLogEntry {\n type: string;\n text: string;\n}\n\n/** A pending dialog awaiting a decision from the model. */\nexport interface PendingDialog {\n type: string;\n message: string;\n defaultValue: string;\n}\n\nconst browserLaunchers = { chromium, firefox, webkit };\n\n/**\n * Manages a single Playwright browser + context for the lifetime of one\n * `ai.generate()` call. The browser is launched lazily on first use and must\n * be closed via {@link close} when generation completes.\n */\nexport class BrowserSession {\n private browser?: Browser;\n private context?: BrowserContext;\n private launchPromise?: Promise<void>;\n\n /** Captured console messages for the active page. */\n readonly consoleLogs: ConsoleLogEntry[] = [];\n /** The most recent dialog the page raised, awaiting handling. */\n pendingDialog?: PendingDialog;\n\n constructor(private readonly options: BrowserOptions = {}) {}\n\n /** Ensures the browser + context are launched (idempotent). */\n private async ensureLaunched(): Promise<void> {\n if (this.context) return;\n if (!this.launchPromise) {\n this.launchPromise = (async () => {\n const type = this.options.browser ?? 'chromium';\n const launcher = browserLaunchers[type];\n if (!launcher) {\n throw new Error(`Unsupported browser type: ${type}`);\n }\n this.browser = await launcher.launch({\n headless: this.options.headless ?? true,\n ...this.options.launchOptions,\n });\n this.context = await this.browser.newContext(\n this.options.contextOptions\n );\n })();\n }\n await this.launchPromise;\n }\n\n /** Returns the active page, creating one (and the browser) if needed. */\n async getPage(): Promise<Page> {\n await this.ensureLaunched();\n const pages = this.context!.pages();\n let page = pages[pages.length - 1];\n if (!page) {\n page = await this.newPage();\n }\n return page;\n }\n\n /** Creates and wires up a new page (tab). */\n async newPage(): Promise<Page> {\n await this.ensureLaunched();\n const page = await this.context!.newPage();\n this.attachListeners(page);\n return page;\n }\n\n /** Returns all open pages (tabs). */\n async getPages(): Promise<Page[]> {\n await this.ensureLaunched();\n return this.context!.pages();\n }\n\n private attachListeners(page: Page) {\n page.on('console', (msg: ConsoleMessage) => {\n this.consoleLogs.push({ type: msg.type(), text: msg.text() });\n });\n page.on('dialog', (dialog: Dialog) => {\n // Store the dialog so the model can decide how to respond via the\n // browser_handle_dialog tool. We deliberately do not auto-dismiss.\n this.pendingDialog = {\n type: dialog.type(),\n message: dialog.message(),\n defaultValue: dialog.defaultValue(),\n };\n (this.activeDialog = dialog);\n });\n }\n\n /** The raw Playwright dialog object awaiting a response, if any. */\n activeDialog?: Dialog;\n\n /** Closes the browser and releases all resources. Safe to call repeatedly. */\n async close(): Promise<void> {\n try {\n await this.context?.close();\n } catch {\n // ignore\n }\n try {\n await this.browser?.close();\n } catch {\n // ignore\n }\n this.context = undefined;\n this.browser = undefined;\n this.launchPromise = undefined;\n }\n}\n","import { MessageData, Part, z } from 'genkit';\nimport { tool } from 'genkit/beta';\nimport type { Locator, Page } from 'playwright';\nimport { BrowserSession } from './browser.js';\n\n\n/** Names of all tools this middleware can inject. */\nexport const ALL_TOOL_NAMES = [\n // navigation\n 'browser_navigate',\n 'browser_navigate_back',\n 'browser_navigate_forward',\n // observation\n 'browser_snapshot',\n 'browser_screenshot',\n 'browser_get_console_logs',\n 'browser_get_network_requests',\n // interaction\n 'browser_click',\n 'browser_type',\n 'browser_fill',\n 'browser_press_key',\n 'browser_hover',\n 'browser_select_option',\n 'browser_scroll',\n 'browser_drag',\n 'browser_file_upload',\n // synchronization\n 'browser_wait_for',\n // tabs\n 'browser_tab_list',\n 'browser_tab_new',\n 'browser_tab_select',\n 'browser_tab_close',\n // dialogs\n 'browser_handle_dialog',\n // escape hatch\n 'browser_evaluate',\n] as const;\n\nexport type PlaywrightToolName = (typeof ALL_TOOL_NAMES)[number];\n\n/** Tools that mutate page state. Disabled in read-only mode. */\nconst WRITE_TOOLS: PlaywrightToolName[] = [\n 'browser_click',\n 'browser_type',\n 'browser_fill',\n 'browser_press_key',\n 'browser_hover',\n 'browser_select_option',\n 'browser_scroll',\n 'browser_drag',\n 'browser_file_upload',\n 'browser_handle_dialog',\n];\n\nexport interface ToolFactoryOptions {\n /** The active browser session. */\n session: BrowserSession;\n /**\n * Queue of messages to inject into the conversation history. Tools that\n * produce media (e.g. screenshots) push `user` messages here; the middleware\n * drains the queue into the request on the next turn so the content enters\n * the model's context as proper multimodal parts instead of a JSON blob.\n */\n messageQueue?: MessageData[];\n /** Prefix to prepend to every tool name. */\n toolNamePrefix?: string;\n\n /** If true, only observe-only (non-mutating) tools are created. */\n readOnly?: boolean;\n /** If true, the `browser_evaluate` JS escape-hatch tool is created. */\n allowEvaluate?: boolean;\n /** Optional allow-list of (unprefixed) tool names to create. */\n tools?: PlaywrightToolName[];\n /** Restrict navigation to these hostnames (suffix match). */\n allowedDomains?: string[];\n /** Block navigation to these hostnames (suffix match). */\n blockedDomains?: string[];\n}\n\nfunction hostnameAllowed(\n url: string,\n allowed?: string[],\n blocked?: string[]\n): boolean {\n let host: string;\n try {\n host = new URL(url).hostname;\n } catch {\n // Relative or invalid URLs are allowed; Playwright will surface errors.\n return true;\n }\n const matches = (domain: string) =>\n host === domain || host.endsWith(`.${domain}`);\n if (blocked?.some(matches)) return false;\n if (allowed && allowed.length > 0) return allowed.some(matches);\n return true;\n}\n\n/**\n * Resolves a snapshot ref (e.g. \"e12\") to a Playwright locator using the\n * `aria-ref` selector engine populated by `browser_snapshot`.\n */\nfunction locatorForRef(page: Page, ref: string): Locator {\n return page.locator(`aria-ref=${ref}`);\n}\n\n/**\n * Produces an accessibility snapshot annotated with stable `ref` ids for each\n * interactive element. Refs can be passed to interaction tools.\n */\nasync function snapshotForAI(page: Page): Promise<string> {\n // The \"ai\" mode of ariaSnapshot yields an ARIA tree where each element is\n // tagged with a stable [ref=eN] id. Those refs resolve via the built-in\n // `aria-ref=` selector engine (see locatorForRef). This is the same\n // mechanism the official Playwright MCP server relies on.\n try {\n return await (\n page.ariaSnapshot as (opts: { mode: 'ai' }) => Promise<string>\n )({ mode: 'ai' });\n } catch {\n // Fallback: plain ARIA snapshot (no refs). Interaction tools won't be able\n // to resolve refs, but the model can still read the page structure.\n return page.locator('body').ariaSnapshot();\n }\n}\n\n/**\n * Creates the set of Playwright browser tools for a single generation.\n */\n\nexport function createPlaywrightTools(opts: ToolFactoryOptions) {\n const { session } = opts;\n const prefix = opts.toolNamePrefix ?? '';\n const name = (n: PlaywrightToolName) => `${prefix}${n}`;\n\n // Determine which tools are enabled.\n const enabled = new Set<PlaywrightToolName>(opts.tools ?? ALL_TOOL_NAMES);\n if (opts.readOnly) {\n for (const t of WRITE_TOOLS) enabled.delete(t);\n }\n if (!opts.allowEvaluate) {\n enabled.delete('browser_evaluate');\n }\n\n const refSchema = z\n .string()\n .describe('Element ref from the latest browser_snapshot, e.g. \"e12\".');\n\n /**\n * Enqueues parts as a `user` message for the middleware to inject into the\n * conversation history. Appends to the trailing queued `user` message when\n * possible so consecutive media parts coalesce into one message.\n */\n const enqueueParts = (parts: Part[], toolName: string) => {\n const queue = opts.messageQueue;\n if (!queue) return;\n const last = queue[queue.length - 1];\n if (last && last.role === 'user') {\n last.content.push(...parts);\n } else {\n queue.push({\n role: 'user',\n content: parts,\n metadata: { playwrightMiddlewareTool: toolName },\n });\n }\n };\n\n const tools: any[] = [];\n\n const add = (toolName: PlaywrightToolName, factory: () => any) => {\n if (enabled.has(toolName)) tools.push(factory());\n };\n\n // ---- Navigation ----------------------------------------------------------\n\n add('browser_navigate', () =>\n tool(\n {\n name: name('browser_navigate'),\n description: 'Navigate the current page to a URL.',\n inputSchema: z.object({\n url: z.string().describe('Absolute URL to navigate to.'),\n }),\n outputSchema: z.string(),\n },\n async ({ url }) => {\n if (!hostnameAllowed(url, opts.allowedDomains, opts.blockedDomains)) {\n throw new Error(`Navigation to \"${url}\" is not allowed by policy.`);\n }\n const page = await session.getPage();\n await page.goto(url, { waitUntil: 'domcontentloaded' });\n return `Navigated to ${page.url()} (title: \"${await page.title()}\").`;\n }\n )\n );\n\n add('browser_navigate_back', () =>\n tool(\n {\n name: name('browser_navigate_back'),\n description: 'Go back to the previous page in history.',\n inputSchema: z.object({}),\n outputSchema: z.string(),\n },\n async () => {\n const page = await session.getPage();\n await page.goBack({ waitUntil: 'domcontentloaded' });\n return `Went back to ${page.url()}.`;\n }\n )\n );\n\n add('browser_navigate_forward', () =>\n tool(\n {\n name: name('browser_navigate_forward'),\n description: 'Go forward to the next page in history.',\n inputSchema: z.object({}),\n outputSchema: z.string(),\n },\n async () => {\n const page = await session.getPage();\n await page.goForward({ waitUntil: 'domcontentloaded' });\n return `Went forward to ${page.url()}.`;\n }\n )\n );\n\n // ---- Observation ---------------------------------------------------------\n\n add('browser_snapshot', () =>\n tool(\n {\n name: name('browser_snapshot'),\n description:\n 'Capture an accessibility snapshot of the current page. Each ' +\n 'interactive element is tagged with a [ref=eN] id you can pass to ' +\n 'interaction tools (click, type, etc.). Prefer this over screenshots ' +\n 'for deciding what to interact with.',\n inputSchema: z.object({}),\n outputSchema: z.object({\n url: z.string(),\n title: z.string(),\n snapshot: z.string(),\n }),\n },\n async () => {\n const page = await session.getPage();\n return {\n url: page.url(),\n title: await page.title(),\n snapshot: await snapshotForAI(page),\n };\n }\n )\n );\n\n add('browser_screenshot', () =>\n tool(\n {\n name: name('browser_screenshot'),\n description:\n 'Take a screenshot of the current page. The image is added to the ' +\n 'conversation so you can view it on your next turn.',\n inputSchema: z.object({\n fullPage: z\n .boolean()\n .optional()\n .describe('Capture the full scrollable page. Defaults to false.'),\n }),\n outputSchema: z.string(),\n },\n async ({ fullPage }) => {\n const page = await session.getPage();\n const buffer = await page.screenshot({\n fullPage: fullPage ?? false,\n type: 'png',\n });\n const dataUri = `data:image/png;base64,${buffer.toString('base64')}`;\n\n // Enqueue the image as a real multimodal `user` message part so the\n // model actually \"sees\" it, instead of receiving a JSON blob in the\n // tool response. The middleware drains this queue into the request.\n enqueueParts(\n [\n { text: `\\n\\nbrowser_screenshot result image/png (${page.url()})` },\n { media: { url: dataUri, contentType: 'image/png' } },\n ],\n name('browser_screenshot')\n );\n\n return 'Screenshot captured. The image is shown below.';\n }\n )\n );\n\n\n add('browser_get_console_logs', () =>\n tool(\n {\n name: name('browser_get_console_logs'),\n description: 'Return console messages collected from the page.',\n inputSchema: z.object({}),\n outputSchema: z.array(\n z.object({ type: z.string(), text: z.string() })\n ),\n },\n async () => session.consoleLogs\n )\n );\n\n add('browser_get_network_requests', () =>\n tool(\n {\n name: name('browser_get_network_requests'),\n description:\n 'List network requests made by the current page (URL, method, ' +\n 'and response status when available).',\n inputSchema: z.object({}),\n outputSchema: z.array(\n z.object({\n url: z.string(),\n method: z.string(),\n status: z.number().optional(),\n })\n ),\n },\n async () => {\n const page = await session.getPage();\n // Best-effort: use the page's performance entries for a snapshot of\n // resources. Live request interception is intentionally avoided to keep\n // the session lightweight.\n const entries = await page.evaluate(() => {\n const list = performance.getEntriesByType(\n 'resource'\n ) as PerformanceResourceTiming[];\n return list.map((e) => ({\n url: e.name,\n method: 'GET',\n status: undefined as number | undefined,\n }));\n });\n return entries;\n }\n )\n );\n\n // ---- Interaction ---------------------------------------------------------\n\n add('browser_click', () =>\n tool(\n {\n name: name('browser_click'),\n description: 'Click an element identified by its snapshot ref.',\n inputSchema: z.object({\n ref: refSchema,\n doubleClick: z\n .boolean()\n .optional()\n .describe('Perform a double click instead of a single click.'),\n }),\n outputSchema: z.string(),\n },\n async ({ ref, doubleClick }) => {\n const page = await session.getPage();\n const locator = locatorForRef(page, ref);\n if (doubleClick) {\n await locator.dblclick();\n } else {\n await locator.click();\n }\n return `Clicked element ${ref}.`;\n }\n )\n );\n\n add('browser_type', () =>\n tool(\n {\n name: name('browser_type'),\n description:\n 'Type text into an element by ref, character by character ' +\n '(does not clear existing content).',\n inputSchema: z.object({\n ref: refSchema,\n text: z.string().describe('Text to type.'),\n submit: z\n .boolean()\n .optional()\n .describe('Press Enter after typing.'),\n }),\n outputSchema: z.string(),\n },\n async ({ ref, text, submit }) => {\n const page = await session.getPage();\n const locator = locatorForRef(page, ref);\n await locator.pressSequentially(text);\n if (submit) await locator.press('Enter');\n return `Typed into element ${ref}.`;\n }\n )\n );\n\n add('browser_fill', () =>\n tool(\n {\n name: name('browser_fill'),\n description:\n 'Set the value of an input/textarea by ref, clearing it first.',\n inputSchema: z.object({\n ref: refSchema,\n value: z.string().describe('Value to set.'),\n }),\n outputSchema: z.string(),\n },\n async ({ ref, value }) => {\n const page = await session.getPage();\n await locatorForRef(page, ref).fill(value);\n return `Filled element ${ref}.`;\n }\n )\n );\n\n add('browser_press_key', () =>\n tool(\n {\n name: name('browser_press_key'),\n description:\n 'Press a keyboard key (e.g. \"Enter\", \"Tab\", \"ArrowDown\", \"a\"). ' +\n 'Optionally targets an element by ref.',\n inputSchema: z.object({\n key: z.string().describe('Key to press.'),\n ref: refSchema.optional(),\n }),\n outputSchema: z.string(),\n },\n async ({ key, ref }) => {\n const page = await session.getPage();\n if (ref) {\n await locatorForRef(page, ref).press(key);\n } else {\n await page.keyboard.press(key);\n }\n return `Pressed key \"${key}\".`;\n }\n )\n );\n\n add('browser_hover', () =>\n tool(\n {\n name: name('browser_hover'),\n description: 'Hover the mouse over an element by ref.',\n inputSchema: z.object({ ref: refSchema }),\n outputSchema: z.string(),\n },\n async ({ ref }) => {\n const page = await session.getPage();\n await locatorForRef(page, ref).hover();\n return `Hovered element ${ref}.`;\n }\n )\n );\n\n add('browser_select_option', () =>\n tool(\n {\n name: name('browser_select_option'),\n description: 'Select option(s) in a <select> element by ref.',\n inputSchema: z.object({\n ref: refSchema,\n values: z\n .array(z.string())\n .describe('Option values or labels to select.'),\n }),\n outputSchema: z.string(),\n },\n async ({ ref, values }) => {\n const page = await session.getPage();\n await locatorForRef(page, ref).selectOption(values);\n return `Selected ${values.length} option(s) in ${ref}.`;\n }\n )\n );\n\n add('browser_scroll', () =>\n tool(\n {\n name: name('browser_scroll'),\n description:\n 'Scroll the page up or down, or scroll a specific element into view.',\n inputSchema: z.object({\n direction: z\n .enum(['up', 'down'])\n .optional()\n .describe('Direction to scroll the window. Defaults to \"down\".'),\n ref: refSchema\n .optional()\n .describe('If provided, scroll this element into view instead.'),\n }),\n outputSchema: z.string(),\n },\n async ({ direction, ref }) => {\n const page = await session.getPage();\n if (ref) {\n await locatorForRef(page, ref).scrollIntoViewIfNeeded();\n return `Scrolled element ${ref} into view.`;\n }\n const dir = direction ?? 'down';\n await page.evaluate((d) => {\n window.scrollBy(0, d === 'down' ? window.innerHeight : -window.innerHeight);\n }, dir);\n return `Scrolled ${dir}.`;\n }\n )\n );\n\n add('browser_drag', () =>\n tool(\n {\n name: name('browser_drag'),\n description: 'Drag one element onto another, by their refs.',\n inputSchema: z.object({\n startRef: refSchema.describe('Ref of the element to drag.'),\n endRef: refSchema.describe('Ref of the drop target.'),\n }),\n outputSchema: z.string(),\n },\n async ({ startRef, endRef }) => {\n const page = await session.getPage();\n await locatorForRef(page, startRef).dragTo(locatorForRef(page, endRef));\n return `Dragged ${startRef} onto ${endRef}.`;\n }\n )\n );\n\n add('browser_file_upload', () =>\n tool(\n {\n name: name('browser_file_upload'),\n description:\n 'Set files on a file input element by ref (provide local file paths).',\n inputSchema: z.object({\n ref: refSchema,\n paths: z.array(z.string()).describe('Local file paths to upload.'),\n }),\n outputSchema: z.string(),\n },\n async ({ ref, paths }) => {\n const page = await session.getPage();\n await locatorForRef(page, ref).setInputFiles(paths);\n return `Uploaded ${paths.length} file(s) to ${ref}.`;\n }\n )\n );\n\n // ---- Synchronization -----------------------------------------------------\n\n add('browser_wait_for', () =>\n tool(\n {\n name: name('browser_wait_for'),\n description:\n 'Wait for text to appear/disappear on the page, or for a fixed time.',\n inputSchema: z.object({\n text: z.string().optional().describe('Text to wait to appear.'),\n textGone: z\n .string()\n .optional()\n .describe('Text to wait to disappear.'),\n time: z\n .number()\n .optional()\n .describe('Seconds to wait. Capped at 30.'),\n }),\n outputSchema: z.string(),\n },\n async ({ text, textGone, time }) => {\n const page = await session.getPage();\n if (text) {\n await page.getByText(text).first().waitFor({ state: 'visible' });\n return `Text \"${text}\" appeared.`;\n }\n if (textGone) {\n await page.getByText(textGone).first().waitFor({ state: 'hidden' });\n return `Text \"${textGone}\" disappeared.`;\n }\n const seconds = Math.min(time ?? 1, 30);\n await page.waitForTimeout(seconds * 1000);\n return `Waited ${seconds}s.`;\n }\n )\n );\n\n // ---- Tabs ----------------------------------------------------------------\n\n add('browser_tab_list', () =>\n tool(\n {\n name: name('browser_tab_list'),\n description: 'List open tabs with their index, URL, and title.',\n inputSchema: z.object({}),\n outputSchema: z.array(\n z.object({\n index: z.number(),\n url: z.string(),\n title: z.string(),\n })\n ),\n },\n async () => {\n const pages = await session.getPages();\n return Promise.all(\n pages.map(async (p, index) => ({\n index,\n url: p.url(),\n title: await p.title(),\n }))\n );\n }\n )\n );\n\n add('browser_tab_new', () =>\n tool(\n {\n name: name('browser_tab_new'),\n description: 'Open a new tab, optionally navigating it to a URL.',\n inputSchema: z.object({\n url: z.string().optional().describe('URL to open in the new tab.'),\n }),\n outputSchema: z.string(),\n },\n async ({ url }) => {\n const page = await session.newPage();\n if (url) {\n if (!hostnameAllowed(url, opts.allowedDomains, opts.blockedDomains)) {\n throw new Error(`Navigation to \"${url}\" is not allowed by policy.`);\n }\n await page.goto(url, { waitUntil: 'domcontentloaded' });\n }\n const pages = await session.getPages();\n return `Opened tab ${pages.length - 1}${url ? ` at ${url}` : ''}.`;\n }\n )\n );\n\n add('browser_tab_select', () =>\n tool(\n {\n name: name('browser_tab_select'),\n description: 'Bring a tab to the front by its index.',\n inputSchema: z.object({\n index: z.number().describe('Tab index from browser_tab_list.'),\n }),\n outputSchema: z.string(),\n },\n async ({ index }) => {\n const pages = await session.getPages();\n const page = pages[index];\n if (!page) throw new Error(`No tab at index ${index}.`);\n await page.bringToFront();\n return `Selected tab ${index}.`;\n }\n )\n );\n\n add('browser_tab_close', () =>\n tool(\n {\n name: name('browser_tab_close'),\n description:\n 'Close a tab by index (defaults to the current/last tab).',\n inputSchema: z.object({\n index: z.number().optional().describe('Tab index to close.'),\n }),\n outputSchema: z.string(),\n },\n async ({ index }) => {\n const pages = await session.getPages();\n const page = index === undefined ? pages[pages.length - 1] : pages[index];\n if (!page) throw new Error(`No tab at index ${index}.`);\n await page.close();\n return `Closed tab ${index ?? pages.length - 1}.`;\n }\n )\n );\n\n // ---- Dialogs -------------------------------------------------------------\n\n add('browser_handle_dialog', () =>\n tool(\n {\n name: name('browser_handle_dialog'),\n description:\n 'Accept or dismiss a pending JavaScript dialog (alert/confirm/prompt).',\n inputSchema: z.object({\n accept: z.boolean().describe('Accept (true) or dismiss (false).'),\n promptText: z\n .string()\n .optional()\n .describe('Text to enter for prompt dialogs.'),\n }),\n outputSchema: z.string(),\n },\n async ({ accept, promptText }) => {\n const dialog = session.activeDialog;\n if (!dialog) return 'No pending dialog to handle.';\n if (accept) {\n await dialog.accept(promptText);\n } else {\n await dialog.dismiss();\n }\n session.activeDialog = undefined;\n session.pendingDialog = undefined;\n return `Dialog ${accept ? 'accepted' : 'dismissed'}.`;\n }\n )\n );\n\n // ---- Escape hatch --------------------------------------------------------\n\n add('browser_evaluate', () =>\n tool(\n {\n name: name('browser_evaluate'),\n description:\n 'Evaluate arbitrary JavaScript in the page context and return the ' +\n 'JSON-serializable result. Use only when other tools are insufficient.',\n inputSchema: z.object({\n script: z\n .string()\n .describe(\n 'A JS expression or function body, e.g. \"document.title\".'\n ),\n }),\n outputSchema: z.any(),\n },\n async ({ script }) => {\n const page = await session.getPage();\n // Wrap so both expressions and statements work.\n const result = await page.evaluate(\n (code) => {\n // eslint-disable-next-line no-new-func\n const fn = new Function(`return (async () => { ${code} })()`);\n return fn();\n },\n /(\\breturn\\b|;)/.test(script) ? script : `return (${script});`\n );\n return result ?? null;\n }\n )\n );\n\n return tools;\n}\n"],"mappings":"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","names":["import_genkit"]}
|