illuma-agents 1.0.20 → 1.0.22
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/dist/cjs/graphs/Graph.cjs +3 -3
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/main.cjs +18 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/run.cjs +137 -3
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/tools/BrowserInterruptTools.cjs +431 -0
- package/dist/cjs/tools/BrowserInterruptTools.cjs.map +1 -0
- package/dist/cjs/tools/BrowserTools.cjs +15 -10
- package/dist/cjs/tools/BrowserTools.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +3 -3
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/main.mjs +2 -1
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/run.mjs +136 -4
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/tools/BrowserInterruptTools.mjs +415 -0
- package/dist/esm/tools/BrowserInterruptTools.mjs.map +1 -0
- package/dist/esm/tools/BrowserTools.mjs +15 -10
- package/dist/esm/tools/BrowserTools.mjs.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/run.d.ts +47 -0
- package/dist/types/tools/BrowserInterruptTools.d.ts +282 -0
- package/dist/types/tools/BrowserTools.d.ts +2 -2
- package/dist/types/types/run.d.ts +8 -0
- package/package.json +1 -1
- package/src/graphs/Graph.ts +3 -3
- package/src/index.ts +1 -0
- package/src/run.ts +176 -3
- package/src/specs/browser-interrupt-tools.test.ts +235 -0
- package/src/tools/BrowserInterruptTools.ts +571 -0
- package/src/tools/BrowserTools.test.ts +41 -6
- package/src/tools/BrowserTools.ts +15 -10
- package/src/types/run.ts +8 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BrowserTools.mjs","sources":["../../../src/tools/BrowserTools.ts"],"sourcesContent":["/**\r\n * Browser Automation Tools for Ranger Browser Extension\r\n * \r\n * These tools allow the LLM to interact with the browser through the \r\n * ranger-browser extension. They generate structured actions that are\r\n * sent to the extension via SSE streaming for execution.\r\n * \r\n * The extension handles:\r\n * - DOM extraction with element indexing\r\n * - Click, type, hover, scroll actions\r\n * - Navigation and page context\r\n * - Visual element highlighting\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\r\n\r\n// ============================================\r\n// Tool Schemas\r\n// ============================================\r\n\r\n/**\r\n * Enhanced click schema that supports both index-based and coordinate-based clicking\r\n */\r\nconst BrowserClickSchema = z.object({\r\n index: z.number().optional().describe(\r\n 'The index of the element to click, as shown in the page context (e.g., [0], [1], [2]). ' +\r\n 'Use the element index from the interactive elements list provided in the page context. ' +\r\n 'Either index OR coordinates must be provided.'\r\n ),\r\n coordinates: z.object({\r\n x: z.number().describe('X coordinate in viewport pixels'),\r\n y: z.number().describe('Y coordinate in viewport pixels'),\r\n }).optional().describe(\r\n 'Coordinates for clicking elements that lack semantic info (marked with ⚠️). ' +\r\n 'The coordinates are provided in the element listing as coords:(x,y). ' +\r\n 'Either index OR coordinates must be provided.'\r\n ),\r\n visualDescription: z.string().optional().describe(\r\n 'Description of what the element looks like visually. Used when clicking by appearance ' +\r\n '(e.g., \"blue button in top right corner\", \"hamburger menu icon\")'\r\n ),\r\n reason: z.string().optional().describe(\r\n 'Brief explanation of why you are clicking this element (for user transparency)'\r\n ),\r\n});\r\n\r\nconst BrowserTypeSchema = z.object({\r\n index: z.number().describe(\r\n 'The index of the input element to type into, as shown in the page context'\r\n ),\r\n text: z.string().describe(\r\n 'The text to type into the input field'\r\n ),\r\n clear: z.boolean().optional().describe(\r\n 'Whether to clear the existing content before typing (default: false)'\r\n ),\r\n pressEnter: z.boolean().optional().describe(\r\n 'Whether to press Enter after typing (useful for search fields, default: false)'\r\n ),\r\n});\r\n\r\nconst BrowserNavigateSchema = z.object({\r\n url: z.string().describe(\r\n 'The URL to navigate to. Can be a full URL or a relative path.'\r\n ),\r\n reason: z.string().optional().describe(\r\n 'Brief explanation of why you are navigating to this URL'\r\n ),\r\n});\r\n\r\nconst BrowserScrollSchema = z.object({\r\n direction: z.enum(['up', 'down', 'left', 'right']).describe(\r\n 'The direction to scroll'\r\n ),\r\n amount: z.number().optional().describe(\r\n 'The amount to scroll in pixels (default: 500)'\r\n ),\r\n});\r\n\r\nconst BrowserExtractSchema = z.object({\r\n query: z.string().optional().describe(\r\n 'Optional query to filter extracted content. If provided, only content related to the query will be extracted.'\r\n ),\r\n selector: z.string().optional().describe(\r\n 'Optional CSS selector to extract content from a specific element'\r\n ),\r\n});\r\n\r\nconst BrowserHoverSchema = z.object({\r\n index: z.number().describe(\r\n 'The index of the element to hover over, as shown in the page context'\r\n ),\r\n});\r\n\r\nconst BrowserWaitSchema = z.object({\r\n duration: z.number().optional().describe(\r\n 'Duration to wait in milliseconds (default: 1000)'\r\n ),\r\n reason: z.string().optional().describe(\r\n 'Why we are waiting (e.g., \"for page to load\", \"for animation to complete\")'\r\n ),\r\n});\r\n\r\nconst BrowserGoBackSchema = z.object({\r\n reason: z.string().optional().describe(\r\n 'Brief explanation of why you are going back'\r\n ),\r\n});\r\n\r\nconst BrowserScreenshotSchema = z.object({\r\n fullPage: z.boolean().optional().describe(\r\n 'Whether to capture the full page or just the viewport (default: viewport only)'\r\n ),\r\n reason: z.string().optional().describe(\r\n 'Why you need a screenshot (e.g., \"to identify visual elements\", \"to analyze page layout\")'\r\n ),\r\n});\r\n\r\nconst BrowserGetPageStateSchema = z.object({\r\n reason: z.string().optional().describe(\r\n 'Why you need fresh page state (e.g., \"after navigation\", \"to see updated elements\")'\r\n ),\r\n});\r\n\r\n// ============================================\r\n// Tool Implementations\r\n// ============================================\r\n\r\n/**\r\n * Browser click tool - clicks an element by index or coordinates\r\n * Supports both semantic (index-based) and vision (coordinate-based) clicking\r\n */\r\nexport function createBrowserClickTool(): DynamicStructuredTool<typeof BrowserClickSchema> {\r\n return tool<typeof BrowserClickSchema>(\r\n async ({ index, coordinates, visualDescription, reason }) => {\r\n // Validate that at least one targeting method is provided\r\n if (index === undefined && !coordinates) {\r\n return JSON.stringify({\r\n type: 'error',\r\n error: 'Either index or coordinates must be provided to click an element',\r\n });\r\n }\r\n\r\n // Return a structured action for the extension to execute\r\n // The actual execution happens in the browser extension\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'click',\r\n ...(index !== undefined && { index }),\r\n ...(coordinates && { coordinates }),\r\n ...(visualDescription && { visualDescription }),\r\n reason,\r\n },\r\n // Signal that this requires browser execution\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.CLICK,\r\n description: `Click an interactive element on the current page.\r\n\r\n**Two ways to target elements:**\r\n\r\n1. **By index (preferred)**: Use the element's index number from the interactive elements list\r\n - Format: [index] {semantic role} <tag>text</tag>\r\n - Example: browser_click({ index: 5 }) to click element [5]\r\n\r\n2. **By coordinates (vision fallback)**: For elements marked with ⚠️ that lack semantic info\r\n - Use the coords:(x,y) shown after the ⚠️ marker\r\n - Example: browser_click({ coordinates: { x: 150, y: 200 } })\r\n\r\n**When to use coordinates:**\r\n- Elements marked with ⚠️ have poor semantic understanding\r\n- Icon-only buttons without labels\r\n- Custom canvas/SVG elements\r\n- When you identify an element visually in a screenshot\r\n\r\nExample: If element shows \\`[12] {button} <div>⚠️ [left side, small, clickable] coords:(45,120)\\`\r\nUse either: browser_click({ index: 12 }) or browser_click({ coordinates: { x: 45, y: 120 } })`,\r\n schema: BrowserClickSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser type tool - types text into an input field\r\n */\r\nexport function createBrowserTypeTool(): DynamicStructuredTool<typeof BrowserTypeSchema> {\r\n return tool<typeof BrowserTypeSchema>(\r\n async ({ index, text, clear, pressEnter }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'type',\r\n index,\r\n text,\r\n clear: clear ?? false,\r\n pressEnter: pressEnter ?? false,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.TYPE,\r\n description: `Type text into an input field on the current page.\r\n\r\nUse this tool when you need to:\r\n- Fill in a text input or textarea\r\n- Enter a search query\r\n- Fill out form fields\r\n\r\nThe element index comes from the page context's interactive elements list.\r\nSet 'clear: true' to clear existing content before typing.\r\nSet 'pressEnter: true' to submit after typing (useful for search fields).\r\n\r\nExample: To type \"hello world\" into a search field shown as \"[2]<input>Search...</input>\",\r\nuse index: 2, text: \"hello world\"`,\r\n schema: BrowserTypeSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser navigate tool - navigates to a URL\r\n */\r\nexport function createBrowserNavigateTool(): DynamicStructuredTool<typeof BrowserNavigateSchema> {\r\n return tool<typeof BrowserNavigateSchema>(\r\n async ({ url, reason }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'navigate',\r\n url,\r\n reason,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.NAVIGATE,\r\n description: `Navigate to a specific URL in the browser.\r\n\r\nUse this tool when you need to:\r\n- Go to a specific website\r\n- Navigate to a different page\r\n- Open a new URL\r\n\r\n**IMPORTANT**: After calling browser_navigate, you MUST call browser_get_page_state \r\nbefore using browser_click or browser_type. This is because navigation changes the page,\r\nand you need to see the new page's elements before you can interact with them.\r\n\r\nProvide the full URL including the protocol (https://).\r\n\r\n**Correct workflow**:\r\n1. browser_navigate({ url: \"https://www.amazon.com\" })\r\n2. browser_get_page_state({ reason: \"see elements on Amazon\" })\r\n3. Now find the search input's [index] in the returned state\r\n4. browser_type({ index: <search_input_index>, text: \"query\", pressEnter: true })\r\n\r\nExample: browser_navigate({ url: \"https://www.google.com\" })`,\r\n schema: BrowserNavigateSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser scroll tool - scrolls the page\r\n */\r\nexport function createBrowserScrollTool(): DynamicStructuredTool<typeof BrowserScrollSchema> {\r\n return tool<typeof BrowserScrollSchema>(\r\n async ({ direction, amount }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'scroll',\r\n scroll: {\r\n direction,\r\n amount: amount ?? 500,\r\n },\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.SCROLL,\r\n description: `Scroll the current page in a specified direction.\r\n\r\nUse this tool when you need to:\r\n- See more content on the page\r\n- Scroll to find elements not currently visible\r\n- Navigate long pages\r\n\r\nDefault scroll amount is 500 pixels. Adjust as needed.\r\n\r\nExample: browser_scroll({ direction: \"down\", amount: 800 })`,\r\n schema: BrowserScrollSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser extract tool - extracts content from the page\r\n */\r\nexport function createBrowserExtractTool(): DynamicStructuredTool<typeof BrowserExtractSchema> {\r\n return tool<typeof BrowserExtractSchema>(\r\n async ({ query, selector }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'extract',\r\n query,\r\n selector,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.EXTRACT,\r\n description: `Extract text content from the current page.\r\n\r\nUse this tool when you need to:\r\n- Get specific information from the page\r\n- Extract text that matches a query\r\n- Read content from a specific element\r\n\r\nIf no query or selector is provided, extracts the main page content.\r\nUse a CSS selector to extract from a specific element.\r\nUse a query to filter for relevant content.\r\n\r\nExample: browser_extract({ query: \"price\" }) - extracts content related to pricing`,\r\n schema: BrowserExtractSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser hover tool - hovers over an element\r\n */\r\nexport function createBrowserHoverTool(): DynamicStructuredTool<typeof BrowserHoverSchema> {\r\n return tool<typeof BrowserHoverSchema>(\r\n async ({ index }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'hover',\r\n index,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.HOVER,\r\n description: `Hover over an element to reveal tooltips or dropdown menus.\r\n\r\nUse this tool when you need to:\r\n- Reveal a dropdown menu\r\n- Show a tooltip\r\n- Trigger hover effects\r\n\r\nExample: browser_hover({ index: 3 }) - hovers over element at index 3`,\r\n schema: BrowserHoverSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser wait tool - waits for a specified duration\r\n */\r\nexport function createBrowserWaitTool(): DynamicStructuredTool<typeof BrowserWaitSchema> {\r\n return tool<typeof BrowserWaitSchema>(\r\n async ({ duration, reason }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'wait',\r\n duration: duration ?? 1000,\r\n reason,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.WAIT,\r\n description: `Wait for a specified duration before the next action.\r\n\r\nUse this tool when you need to:\r\n- Wait for a page to load\r\n- Wait for an animation to complete\r\n- Add delay between actions\r\n\r\nDefault wait time is 1000ms (1 second).\r\n\r\nExample: browser_wait({ duration: 2000, reason: \"waiting for page to load\" })`,\r\n schema: BrowserWaitSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser go back tool - navigates back in history\r\n */\r\nexport function createBrowserGoBackTool(): DynamicStructuredTool<typeof BrowserGoBackSchema> {\r\n return tool<typeof BrowserGoBackSchema>(\r\n async ({ reason }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'back',\r\n reason,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.BACK,\r\n description: `Navigate back to the previous page in browser history.\r\n\r\nUse this tool when you need to:\r\n- Return to a previous page\r\n- Undo a navigation\r\n\r\nExample: browser_back({ reason: \"returning to search results\" })`,\r\n schema: BrowserGoBackSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser screenshot tool - captures a screenshot\r\n */\r\nexport function createBrowserScreenshotTool(): DynamicStructuredTool<typeof BrowserScreenshotSchema> {\r\n return tool<typeof BrowserScreenshotSchema>(\r\n async ({ fullPage }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'screenshot',\r\n fullPage: fullPage ?? false,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.SCREENSHOT,\r\n description: `Capture a screenshot of the current page.\r\n\r\nUse this tool when you need to:\r\n- Capture the current state of a page\r\n- Document visual elements\r\n- Verify page appearance\r\n\r\nSet fullPage: true to capture the entire page (may be large).\r\nDefault captures only the visible viewport.\r\n\r\nExample: browser_screenshot({ fullPage: false })`,\r\n schema: BrowserScreenshotSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser get page state tool - gets fresh page context after navigation or actions\r\n * CRITICAL: Use this after browser_navigate or any action that changes the page\r\n */\r\nexport function createBrowserGetPageStateTool(): DynamicStructuredTool<typeof BrowserGetPageStateSchema> {\r\n return tool<typeof BrowserGetPageStateSchema>(\r\n async ({ reason }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'get_page_state',\r\n reason,\r\n },\r\n requiresBrowserExecution: true,\r\n // Special flag: extension should inject fresh context into the conversation\r\n requiresContextRefresh: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.GET_PAGE_STATE,\r\n description: `Get fresh page state showing current interactive elements.\r\n\r\n**CRITICAL**: You MUST call this tool after:\r\n- browser_navigate (to see elements on the new page)\r\n- browser_click (if it caused navigation or page changes)\r\n- Any action that might have changed the visible elements\r\n\r\nThis tool returns the updated list of interactive elements with their [index] numbers.\r\nWithout calling this after navigation, you will NOT know what elements exist on the new page.\r\n\r\n**Workflow example**:\r\n1. browser_navigate to amazon.com\r\n2. browser_get_page_state to see Amazon's elements\r\n3. Now you can see the search input's [index] and use browser_type\r\n\r\nExample: browser_get_page_state({ reason: \"to see elements after navigation\" })`,\r\n schema: BrowserGetPageStateSchema,\r\n }\r\n );\r\n}\r\n\r\n// ============================================\r\n// Tool Collection\r\n// ============================================\r\n\r\nexport type BrowserToolsConfig = {\r\n /** Enable click tool */\r\n enableClick?: boolean;\r\n /** Enable type tool */\r\n enableType?: boolean;\r\n /** Enable navigate tool */\r\n enableNavigate?: boolean;\r\n /** Enable scroll tool */\r\n enableScroll?: boolean;\r\n /** Enable extract tool */\r\n enableExtract?: boolean;\r\n /** Enable hover tool */\r\n enableHover?: boolean;\r\n /** Enable wait tool */\r\n enableWait?: boolean;\r\n /** Enable back tool */\r\n enableBack?: boolean;\r\n /** Enable screenshot tool */\r\n enableScreenshot?: boolean;\r\n /** Enable get page state tool */\r\n enableGetPageState?: boolean;\r\n};\r\n\r\n/**\r\n * Create all browser automation tools\r\n * \r\n * IMPORTANT: These tools should ONLY be registered when:\r\n * 1. The request comes from a browser extension that can execute them\r\n * 2. The client has indicated browser capability (e.g., via header or parameter)\r\n * \r\n * DO NOT register these for normal web UI users - they cannot execute browser actions.\r\n * \r\n * Detection in Ranger API:\r\n * - Check for `X-Ranger-Browser-Extension: true` header\r\n * - Or check for `browserCapable: true` in request body\r\n * - Or check user agent for extension identifier\r\n * \r\n * @example\r\n * // In Ranger API endpoint:\r\n * const hasBrowserExtension = req.headers['x-ranger-browser-extension'] === 'true';\r\n * const tools = hasBrowserExtension \r\n * ? [...normalTools, ...createBrowserTools()]\r\n * : normalTools;\r\n */\r\nexport function createBrowserTools(config: BrowserToolsConfig = {}): DynamicStructuredTool[] {\r\n const tools: DynamicStructuredTool[] = [];\r\n \r\n // Enable all by default\r\n const {\r\n enableClick = true,\r\n enableType = true,\r\n enableNavigate = true,\r\n enableScroll = true,\r\n enableExtract = true,\r\n enableHover = true,\r\n enableWait = true,\r\n enableBack = true,\r\n enableScreenshot = true,\r\n enableGetPageState = true,\r\n } = config;\r\n \r\n if (enableClick) tools.push(createBrowserClickTool());\r\n if (enableType) tools.push(createBrowserTypeTool());\r\n if (enableNavigate) tools.push(createBrowserNavigateTool());\r\n if (enableScroll) tools.push(createBrowserScrollTool());\r\n if (enableExtract) tools.push(createBrowserExtractTool());\r\n if (enableHover) tools.push(createBrowserHoverTool());\r\n if (enableWait) tools.push(createBrowserWaitTool());\r\n if (enableBack) tools.push(createBrowserGoBackTool());\r\n if (enableScreenshot) tools.push(createBrowserScreenshotTool());\r\n if (enableGetPageState) tools.push(createBrowserGetPageStateTool());\r\n \r\n return tools;\r\n}\r\n\r\n/**\r\n * Browser tool name constants\r\n * Use these instead of magic strings\r\n */\r\nexport const EBrowserTools = {\r\n CLICK: 'browser_click',\r\n TYPE: 'browser_type',\r\n NAVIGATE: 'browser_navigate',\r\n SCROLL: 'browser_scroll',\r\n EXTRACT: 'browser_extract',\r\n HOVER: 'browser_hover',\r\n WAIT: 'browser_wait',\r\n BACK: 'browser_back',\r\n SCREENSHOT: 'browser_screenshot',\r\n GET_PAGE_STATE: 'browser_get_page_state',\r\n} as const;\r\n\r\n/**\r\n * Get browser tool names for filtering/identification\r\n */\r\nexport const BROWSER_TOOL_NAMES = [\r\n EBrowserTools.CLICK,\r\n EBrowserTools.TYPE,\r\n EBrowserTools.NAVIGATE,\r\n EBrowserTools.SCROLL,\r\n EBrowserTools.EXTRACT,\r\n EBrowserTools.HOVER,\r\n EBrowserTools.WAIT,\r\n EBrowserTools.BACK,\r\n EBrowserTools.SCREENSHOT,\r\n EBrowserTools.GET_PAGE_STATE,\r\n] as const;\r\n\r\nexport type BrowserToolName = typeof BROWSER_TOOL_NAMES[number];\r\n\r\n/**\r\n * Check if a tool call is a browser action\r\n */\r\nexport function isBrowserToolCall(toolName: string): toolName is BrowserToolName {\r\n return BROWSER_TOOL_NAMES.includes(toolName as BrowserToolName);\r\n}\r\n\r\n/**\r\n * Check if request indicates browser extension capability\r\n * Use this to conditionally register browser tools\r\n * \r\n * @example\r\n * // In Express middleware or endpoint:\r\n * if (hasBrowserCapability(req.headers)) {\r\n * tools.push(...createBrowserTools());\r\n * }\r\n */\r\nexport function hasBrowserCapability(headers: Record<string, string | string[] | undefined>): boolean {\r\n const extensionHeader = headers['x-ranger-browser-extension'];\r\n const capableHeader = headers['x-ranger-browser-capable'];\r\n \r\n return (\r\n extensionHeader === 'true' || \r\n capableHeader === 'true' ||\r\n (Array.isArray(extensionHeader) && extensionHeader.includes('true')) ||\r\n (Array.isArray(capableHeader) && capableHeader.includes('true'))\r\n );\r\n}\r\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BrowserTools.mjs","sources":["../../../src/tools/BrowserTools.ts"],"sourcesContent":["/**\r\n * Browser Automation Tools for Ranger Browser Extension\r\n * \r\n * These tools allow the LLM to interact with the browser through the \r\n * ranger-browser extension. They generate structured actions that are\r\n * sent to the extension via SSE streaming for execution.\r\n * \r\n * The extension handles:\r\n * - DOM extraction with element indexing\r\n * - Click, type, hover, scroll actions\r\n * - Navigation and page context\r\n * - Visual element highlighting\r\n */\r\n\r\nimport { z } from 'zod';\r\nimport { tool, DynamicStructuredTool } from '@langchain/core/tools';\r\n\r\n// ============================================\r\n// Tool Schemas\r\n// ============================================\r\n\r\n/**\r\n * Enhanced click schema that supports both index-based and coordinate-based clicking\r\n */\r\nconst BrowserClickSchema = z.object({\r\n index: z.number().optional().describe(\r\n 'The index of the element to click, as shown in the page context (e.g., [0], [1], [2]). ' +\r\n 'Use the element index from the interactive elements list provided in the page context. ' +\r\n 'Either index OR coordinates must be provided.'\r\n ),\r\n coordinates: z.object({\r\n x: z.number().describe('X coordinate in viewport pixels'),\r\n y: z.number().describe('Y coordinate in viewport pixels'),\r\n }).optional().describe(\r\n 'Coordinates for clicking elements that lack semantic info (marked with ⚠️). ' +\r\n 'The coordinates are provided in the element listing as coords:(x,y). ' +\r\n 'Either index OR coordinates must be provided.'\r\n ),\r\n visualDescription: z.string().optional().describe(\r\n 'Description of what the element looks like visually. Used when clicking by appearance ' +\r\n '(e.g., \"blue button in top right corner\", \"hamburger menu icon\")'\r\n ),\r\n reason: z.string().optional().describe(\r\n 'Brief explanation of why you are clicking this element (for user transparency)'\r\n ),\r\n});\r\n\r\nconst BrowserTypeSchema = z.object({\r\n index: z.number().describe(\r\n 'The index of the input element to type into, as shown in the page context'\r\n ),\r\n text: z.string().describe(\r\n 'The text to type into the input field'\r\n ),\r\n clear: z.boolean().optional().describe(\r\n 'Whether to clear the existing content before typing (default: false)'\r\n ),\r\n pressEnter: z.boolean().optional().describe(\r\n 'Whether to press Enter after typing (useful for search fields, default: false)'\r\n ),\r\n});\r\n\r\nconst BrowserNavigateSchema = z.object({\r\n url: z.string().describe(\r\n 'The URL to navigate to. Can be a full URL or a relative path.'\r\n ),\r\n reason: z.string().optional().describe(\r\n 'Brief explanation of why you are navigating to this URL'\r\n ),\r\n});\r\n\r\nconst BrowserScrollSchema = z.object({\r\n direction: z.enum(['up', 'down', 'left', 'right']).describe(\r\n 'The direction to scroll'\r\n ),\r\n amount: z.number().optional().describe(\r\n 'The amount to scroll in pixels (default: 500)'\r\n ),\r\n});\r\n\r\nconst BrowserExtractSchema = z.object({\r\n query: z.string().optional().describe(\r\n 'Optional query to filter extracted content. If provided, only content related to the query will be extracted.'\r\n ),\r\n selector: z.string().optional().describe(\r\n 'Optional CSS selector to extract content from a specific element'\r\n ),\r\n});\r\n\r\nconst BrowserHoverSchema = z.object({\r\n index: z.number().describe(\r\n 'The index of the element to hover over, as shown in the page context'\r\n ),\r\n});\r\n\r\nconst BrowserWaitSchema = z.object({\r\n duration: z.number().optional().describe(\r\n 'Duration to wait in milliseconds (default: 1000)'\r\n ),\r\n reason: z.string().optional().describe(\r\n 'Why we are waiting (e.g., \"for page to load\", \"for animation to complete\")'\r\n ),\r\n});\r\n\r\nconst BrowserGoBackSchema = z.object({\r\n reason: z.string().optional().describe(\r\n 'Brief explanation of why you are going back'\r\n ),\r\n});\r\n\r\nconst BrowserScreenshotSchema = z.object({\r\n fullPage: z.boolean().optional().describe(\r\n 'Whether to capture the full page or just the viewport (default: viewport only)'\r\n ),\r\n reason: z.string().optional().describe(\r\n 'Why you need a screenshot (e.g., \"to identify visual elements\", \"to analyze page layout\")'\r\n ),\r\n});\r\n\r\nconst BrowserGetPageStateSchema = z.object({\r\n reason: z.string().optional().describe(\r\n 'Why you need fresh page state (e.g., \"after navigation\", \"to see updated elements\")'\r\n ),\r\n});\r\n\r\n// ============================================\r\n// Tool Implementations\r\n// ============================================\r\n\r\n/**\r\n * Browser click tool - clicks an element by index or coordinates\r\n * Supports both semantic (index-based) and vision (coordinate-based) clicking\r\n */\r\nexport function createBrowserClickTool(): DynamicStructuredTool<typeof BrowserClickSchema> {\r\n return tool<typeof BrowserClickSchema>(\r\n async ({ index, coordinates, visualDescription, reason }) => {\r\n // Validate that at least one targeting method is provided\r\n if (index === undefined && !coordinates) {\r\n return JSON.stringify({\r\n type: 'error',\r\n error: 'Either index or coordinates must be provided to click an element',\r\n });\r\n }\r\n\r\n // Return a structured action for the extension to execute\r\n // The actual execution happens in the browser extension\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'click',\r\n ...(index !== undefined && { index }),\r\n ...(coordinates && { coordinates }),\r\n ...(visualDescription && { visualDescription }),\r\n reason,\r\n },\r\n // Signal that this requires browser execution\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.CLICK,\r\n description: `Click an interactive element on the current page.\r\n\r\n**Two ways to target elements:**\r\n\r\n1. **By index (preferred)**: Use the element's index number from the interactive elements list\r\n - Format: [index] {semantic role} <tag>text</tag>\r\n - Example: browser_click({ index: 5 }) to click element [5]\r\n\r\n2. **By coordinates (vision fallback)**: For elements marked with ⚠️ that lack semantic info\r\n - Use the coords:(x,y) shown after the ⚠️ marker\r\n - Example: browser_click({ coordinates: { x: 150, y: 200 } })\r\n\r\n**When to use coordinates:**\r\n- Elements marked with ⚠️ have poor semantic understanding\r\n- Icon-only buttons without labels\r\n- Custom canvas/SVG elements\r\n- When you identify an element visually in a screenshot\r\n\r\nExample: If element shows \\`[12] {button} <div>⚠️ [left side, small, clickable] coords:(45,120)\\`\r\nUse either: browser_click({ index: 12 }) or browser_click({ coordinates: { x: 45, y: 120 } })`,\r\n schema: BrowserClickSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser type tool - types text into an input field\r\n */\r\nexport function createBrowserTypeTool(): DynamicStructuredTool<typeof BrowserTypeSchema> {\r\n return tool<typeof BrowserTypeSchema>(\r\n async ({ index, text, clear, pressEnter }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'type',\r\n index,\r\n text,\r\n clear: clear ?? false,\r\n pressEnter: pressEnter ?? false,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.TYPE,\r\n description: `Type text into an input field on the current page.\r\n\r\nUse this tool when you need to:\r\n- Fill in a text input or textarea\r\n- Enter a search query\r\n- Fill out form fields\r\n\r\nThe element index comes from the page context's interactive elements list.\r\nSet 'clear: true' to clear existing content before typing.\r\nSet 'pressEnter: true' to submit after typing (useful for search fields).\r\n\r\nExample: To type \"hello world\" into a search field shown as \"[2]<input>Search...</input>\",\r\nuse index: 2, text: \"hello world\"`,\r\n schema: BrowserTypeSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser navigate tool - navigates to a URL\r\n */\r\nexport function createBrowserNavigateTool(): DynamicStructuredTool<typeof BrowserNavigateSchema> {\r\n return tool<typeof BrowserNavigateSchema>(\r\n async ({ url, reason }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'navigate',\r\n url,\r\n reason,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.NAVIGATE,\r\n description: `Navigate to a specific URL in the browser.\r\n\r\nUse this tool when you need to:\r\n- Go to a specific website\r\n- Navigate to a different page\r\n- Open a new URL\r\n\r\n**IMPORTANT**: After calling browser_navigate, you MUST call browser_get_page_state \r\nbefore using browser_click or browser_type. This is because navigation changes the page,\r\nand you need to see the new page's elements before you can interact with them.\r\n\r\nProvide the full URL including the protocol (https://).\r\n\r\n**Correct workflow**:\r\n1. browser_navigate({ url: \"https://www.amazon.com\" })\r\n2. browser_get_page_state({ reason: \"see elements on Amazon\" })\r\n3. Now find the search input's [index] in the returned state\r\n4. browser_type({ index: <search_input_index>, text: \"query\", pressEnter: true })\r\n\r\nExample: browser_navigate({ url: \"https://www.google.com\" })`,\r\n schema: BrowserNavigateSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser scroll tool - scrolls the page\r\n */\r\nexport function createBrowserScrollTool(): DynamicStructuredTool<typeof BrowserScrollSchema> {\r\n return tool<typeof BrowserScrollSchema>(\r\n async ({ direction, amount }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'scroll',\r\n scroll: {\r\n direction,\r\n amount: amount ?? 500,\r\n },\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.SCROLL,\r\n description: `Scroll the current page in a specified direction.\r\n\r\nUse this tool when you need to:\r\n- See more content on the page\r\n- Scroll to find elements not currently visible\r\n- Navigate long pages\r\n\r\nDefault scroll amount is 500 pixels. Adjust as needed.\r\n\r\nExample: browser_scroll({ direction: \"down\", amount: 800 })`,\r\n schema: BrowserScrollSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser extract tool - extracts content from the page\r\n */\r\nexport function createBrowserExtractTool(): DynamicStructuredTool<typeof BrowserExtractSchema> {\r\n return tool<typeof BrowserExtractSchema>(\r\n async ({ query, selector }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'extract',\r\n query,\r\n selector,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.EXTRACT,\r\n description: `Extract text content from the current page.\r\n\r\nUse this tool when you need to:\r\n- Get specific information from the page\r\n- Extract text that matches a query\r\n- Read content from a specific element\r\n\r\nIf no query or selector is provided, extracts the main page content.\r\nUse a CSS selector to extract from a specific element.\r\nUse a query to filter for relevant content.\r\n\r\nExample: browser_extract({ query: \"price\" }) - extracts content related to pricing`,\r\n schema: BrowserExtractSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser hover tool - hovers over an element\r\n */\r\nexport function createBrowserHoverTool(): DynamicStructuredTool<typeof BrowserHoverSchema> {\r\n return tool<typeof BrowserHoverSchema>(\r\n async ({ index }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'hover',\r\n index,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.HOVER,\r\n description: `Hover over an element to reveal tooltips or dropdown menus.\r\n\r\nUse this tool when you need to:\r\n- Reveal a dropdown menu\r\n- Show a tooltip\r\n- Trigger hover effects\r\n\r\nExample: browser_hover({ index: 3 }) - hovers over element at index 3`,\r\n schema: BrowserHoverSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser wait tool - waits for a specified duration\r\n */\r\nexport function createBrowserWaitTool(): DynamicStructuredTool<typeof BrowserWaitSchema> {\r\n return tool<typeof BrowserWaitSchema>(\r\n async ({ duration, reason }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'wait',\r\n duration: duration ?? 1000,\r\n reason,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.WAIT,\r\n description: `Wait for a specified duration before the next action.\r\n\r\nUse this tool when you need to:\r\n- Wait for a page to load\r\n- Wait for an animation to complete\r\n- Add delay between actions\r\n\r\nDefault wait time is 1000ms (1 second).\r\n\r\nExample: browser_wait({ duration: 2000, reason: \"waiting for page to load\" })`,\r\n schema: BrowserWaitSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser go back tool - navigates back in history\r\n */\r\nexport function createBrowserGoBackTool(): DynamicStructuredTool<typeof BrowserGoBackSchema> {\r\n return tool<typeof BrowserGoBackSchema>(\r\n async ({ reason }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'back',\r\n reason,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.BACK,\r\n description: `Navigate back to the previous page in browser history.\r\n\r\nUse this tool when you need to:\r\n- Return to a previous page\r\n- Undo a navigation\r\n\r\nExample: browser_back({ reason: \"returning to search results\" })`,\r\n schema: BrowserGoBackSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser screenshot tool - captures a screenshot\r\n */\r\nexport function createBrowserScreenshotTool(): DynamicStructuredTool<typeof BrowserScreenshotSchema> {\r\n return tool<typeof BrowserScreenshotSchema>(\r\n async ({ fullPage }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'screenshot',\r\n fullPage: fullPage ?? false,\r\n },\r\n requiresBrowserExecution: true,\r\n });\r\n },\r\n {\r\n name: EBrowserTools.SCREENSHOT,\r\n description: `Capture a screenshot of the current page.\r\n\r\nUse this tool when you need to:\r\n- Capture the current state of a page\r\n- Document visual elements\r\n- Verify page appearance\r\n\r\nSet fullPage: true to capture the entire page (may be large).\r\nDefault captures only the visible viewport.\r\n\r\nExample: browser_screenshot({ fullPage: false })`,\r\n schema: BrowserScreenshotSchema,\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * Browser get page state tool - gets fresh page context after navigation or actions\r\n * CRITICAL: Use this after browser_navigate or any action that changes the page\r\n */\r\nexport function createBrowserGetPageStateTool(): DynamicStructuredTool<typeof BrowserGetPageStateSchema> {\r\n return tool<typeof BrowserGetPageStateSchema>(\r\n async ({ reason }) => {\r\n return JSON.stringify({\r\n type: 'browser_action',\r\n action: {\r\n type: 'get_page_state',\r\n reason,\r\n },\r\n requiresBrowserExecution: true,\r\n // Special flag: extension should inject fresh context into the conversation\r\n requiresContextRefresh: true,\r\n // IMPORTANT: Tell the agent to wait\r\n message: 'Page state is being captured by the browser extension. The element list will be provided in the next message. DO NOT proceed with click or type actions until you receive the actual element list.',\r\n });\r\n },\r\n {\r\n name: EBrowserTools.GET_PAGE_STATE,\r\n description: `Get fresh page state showing current interactive elements.\r\n\r\n**CRITICAL WORKFLOW**: After calling this tool, you MUST STOP and WAIT. The browser extension will capture the page state and return the element list. DO NOT plan any browser_click or browser_type actions in the same response - you don't have the element indices yet!\r\n\r\n**When to use**:\r\n- After browser_navigate (to see elements on the new page)\r\n- After browser_click (if it caused navigation or page changes)\r\n- Any time you need to see what elements are currently on the page\r\n\r\n**IMPORTANT**: This tool captures the page state asynchronously. The actual element list will be provided AFTER this tool completes. You should:\r\n1. Call this tool\r\n2. STOP and wait for the response with the element list\r\n3. In your NEXT response, use the element indices for click/type actions\r\n\r\nExample workflow:\r\n- Turn 1: browser_navigate to amazon.com, then browser_get_page_state\r\n- Turn 2: (After receiving element list) browser_type with the correct search input index\r\n\r\nExample: browser_get_page_state({ reason: \"to see elements after navigation\" })`,\r\n schema: BrowserGetPageStateSchema,\r\n }\r\n );\r\n}\r\n\r\n// ============================================\r\n// Tool Collection\r\n// ============================================\r\n\r\nexport type BrowserToolsConfig = {\r\n /** Enable click tool */\r\n enableClick?: boolean;\r\n /** Enable type tool */\r\n enableType?: boolean;\r\n /** Enable navigate tool */\r\n enableNavigate?: boolean;\r\n /** Enable scroll tool */\r\n enableScroll?: boolean;\r\n /** Enable extract tool */\r\n enableExtract?: boolean;\r\n /** Enable hover tool */\r\n enableHover?: boolean;\r\n /** Enable wait tool */\r\n enableWait?: boolean;\r\n /** Enable back tool */\r\n enableBack?: boolean;\r\n /** Enable screenshot tool */\r\n enableScreenshot?: boolean;\r\n /** Enable get page state tool */\r\n enableGetPageState?: boolean;\r\n};\r\n\r\n/**\r\n * Create all browser automation tools\r\n * \r\n * IMPORTANT: These tools should ONLY be registered when:\r\n * 1. The request comes from a browser extension that can execute them\r\n * 2. The client has indicated browser capability (e.g., via header or parameter)\r\n * \r\n * DO NOT register these for normal web UI users - they cannot execute browser actions.\r\n * \r\n * Detection in Ranger API:\r\n * - Check for `X-Ranger-Browser-Extension: true` header\r\n * - Or check for `browserCapable: true` in request body\r\n * - Or check user agent for extension identifier\r\n * \r\n * @example\r\n * // In Ranger API endpoint:\r\n * const hasBrowserExtension = req.headers['x-ranger-browser-extension'] === 'true';\r\n * const tools = hasBrowserExtension \r\n * ? [...normalTools, ...createBrowserTools()]\r\n * : normalTools;\r\n */\r\nexport function createBrowserTools(config: BrowserToolsConfig = {}): DynamicStructuredTool[] {\r\n const tools: DynamicStructuredTool[] = [];\r\n \r\n // Enable all by default\r\n const {\r\n enableClick = true,\r\n enableType = true,\r\n enableNavigate = true,\r\n enableScroll = true,\r\n enableExtract = true,\r\n enableHover = true,\r\n enableWait = true,\r\n enableBack = true,\r\n enableScreenshot = true,\r\n enableGetPageState = true,\r\n } = config;\r\n \r\n if (enableClick) tools.push(createBrowserClickTool());\r\n if (enableType) tools.push(createBrowserTypeTool());\r\n if (enableNavigate) tools.push(createBrowserNavigateTool());\r\n if (enableScroll) tools.push(createBrowserScrollTool());\r\n if (enableExtract) tools.push(createBrowserExtractTool());\r\n if (enableHover) tools.push(createBrowserHoverTool());\r\n if (enableWait) tools.push(createBrowserWaitTool());\r\n if (enableBack) tools.push(createBrowserGoBackTool());\r\n if (enableScreenshot) tools.push(createBrowserScreenshotTool());\r\n if (enableGetPageState) tools.push(createBrowserGetPageStateTool());\r\n \r\n return tools;\r\n}\r\n\r\n/**\r\n * Browser tool name constants\r\n * Use these instead of magic strings\r\n */\r\nexport const EBrowserTools = {\r\n CLICK: 'browser_click',\r\n TYPE: 'browser_type',\r\n NAVIGATE: 'browser_navigate',\r\n SCROLL: 'browser_scroll',\r\n EXTRACT: 'browser_extract',\r\n HOVER: 'browser_hover',\r\n WAIT: 'browser_wait',\r\n BACK: 'browser_back',\r\n SCREENSHOT: 'browser_screenshot',\r\n GET_PAGE_STATE: 'browser_get_page_state',\r\n} as const;\r\n\r\n/**\r\n * Get browser tool names for filtering/identification\r\n */\r\nexport const BROWSER_TOOL_NAMES = [\r\n EBrowserTools.CLICK,\r\n EBrowserTools.TYPE,\r\n EBrowserTools.NAVIGATE,\r\n EBrowserTools.SCROLL,\r\n EBrowserTools.EXTRACT,\r\n EBrowserTools.HOVER,\r\n EBrowserTools.WAIT,\r\n EBrowserTools.BACK,\r\n EBrowserTools.SCREENSHOT,\r\n EBrowserTools.GET_PAGE_STATE,\r\n] as const;\r\n\r\nexport type BrowserToolName = typeof BROWSER_TOOL_NAMES[number];\r\n\r\n/**\r\n * Check if a tool call is a browser action\r\n */\r\nexport function isBrowserToolCall(toolName: string): toolName is BrowserToolName {\r\n return BROWSER_TOOL_NAMES.includes(toolName as BrowserToolName);\r\n}\r\n\r\n/**\r\n * Check if request indicates browser extension capability\r\n * Use this to conditionally register browser tools\r\n * \r\n * @example\r\n * // In Express middleware or endpoint:\r\n * if (hasBrowserCapability(req.headers)) {\r\n * tools.push(...createBrowserTools());\r\n * }\r\n */\r\nexport function hasBrowserCapability(headers: Record<string, string | string[] | undefined>): boolean {\r\n const extensionHeader = headers['x-ranger-browser-extension'];\r\n const capableHeader = headers['x-ranger-browser-capable'];\r\n \r\n return (\r\n extensionHeader === 'true' || \r\n capableHeader === 'true' ||\r\n (Array.isArray(extensionHeader) && extensionHeader.includes('true')) ||\r\n (Array.isArray(capableHeader) && capableHeader.includes('true'))\r\n );\r\n}\r\n"],"names":[],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from './tools/CodeExecutor';
|
|
|
9
9
|
export * from './tools/ProgrammaticToolCalling';
|
|
10
10
|
export * from './tools/ToolSearchRegex';
|
|
11
11
|
export * from './tools/BrowserTools';
|
|
12
|
+
export * from './tools/BrowserInterruptTools';
|
|
12
13
|
export * from './tools/handlers';
|
|
13
14
|
export * from './tools/search';
|
|
14
15
|
export * from './common';
|
package/dist/types/run.d.ts
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import './instrumentation';
|
|
2
|
+
import { MemorySaver } from '@langchain/langgraph-checkpoint';
|
|
2
3
|
import type { MessageContentComplex, BaseMessage } from '@langchain/core/messages';
|
|
3
4
|
import type { RunnableConfig } from '@langchain/core/runnables';
|
|
4
5
|
import type * as t from '@/types';
|
|
5
6
|
import { MultiAgentGraph } from '@/graphs/MultiAgentGraph';
|
|
6
7
|
import { StandardGraph } from '@/graphs/Graph';
|
|
8
|
+
import type { BrowserInterrupt, BrowserActionResult } from '@/tools/BrowserInterruptTools';
|
|
7
9
|
export declare const defaultOmitOptions: Set<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Get or create a checkpointer for browser mode
|
|
12
|
+
*/
|
|
13
|
+
export declare function getBrowserCheckpointer(runId: string): MemorySaver;
|
|
14
|
+
/**
|
|
15
|
+
* Clean up a browser checkpointer when done
|
|
16
|
+
*/
|
|
17
|
+
export declare function cleanupBrowserCheckpointer(runId: string): void;
|
|
8
18
|
export declare class Run<_T extends t.BaseGraphState> {
|
|
9
19
|
id: string;
|
|
10
20
|
private tokenCounter?;
|
|
11
21
|
private handlerRegistry?;
|
|
12
22
|
private indexTokenCountMap?;
|
|
23
|
+
/** Whether this run is in browser extension mode */
|
|
24
|
+
browserMode: boolean;
|
|
13
25
|
graphRunnable?: t.CompiledStateWorkflow;
|
|
14
26
|
Graph: StandardGraph | MultiAgentGraph | undefined;
|
|
15
27
|
returnContent: boolean;
|
|
@@ -33,4 +45,39 @@ export declare class Run<_T extends t.BaseGraphState> {
|
|
|
33
45
|
language?: string;
|
|
34
46
|
title?: string;
|
|
35
47
|
}>;
|
|
48
|
+
/**
|
|
49
|
+
* Process stream with browser interrupt support.
|
|
50
|
+
* Uses regular stream() instead of streamEvents() to properly detect interrupts.
|
|
51
|
+
* Returns interrupt data when graph is paused waiting for browser action.
|
|
52
|
+
*/
|
|
53
|
+
processBrowserStream(inputs: t.IState, config: Partial<RunnableConfig> & {
|
|
54
|
+
version: 'v1' | 'v2';
|
|
55
|
+
run_id?: string;
|
|
56
|
+
}, streamOptions?: t.EventStreamOptions): AsyncGenerator<{
|
|
57
|
+
type: 'event';
|
|
58
|
+
data: unknown;
|
|
59
|
+
} | {
|
|
60
|
+
type: 'interrupt';
|
|
61
|
+
data: BrowserInterrupt;
|
|
62
|
+
} | {
|
|
63
|
+
type: 'done';
|
|
64
|
+
data?: MessageContentComplex[];
|
|
65
|
+
}>;
|
|
66
|
+
/**
|
|
67
|
+
* Resume a browser stream after interrupt.
|
|
68
|
+
* Call this with the result from the browser extension.
|
|
69
|
+
*/
|
|
70
|
+
resumeBrowserStream(result: BrowserActionResult, config: Partial<RunnableConfig> & {
|
|
71
|
+
version: 'v1' | 'v2';
|
|
72
|
+
run_id?: string;
|
|
73
|
+
}): AsyncGenerator<{
|
|
74
|
+
type: 'event';
|
|
75
|
+
data: unknown;
|
|
76
|
+
} | {
|
|
77
|
+
type: 'interrupt';
|
|
78
|
+
data: BrowserInterrupt;
|
|
79
|
+
} | {
|
|
80
|
+
type: 'done';
|
|
81
|
+
data?: MessageContentComplex[];
|
|
82
|
+
}>;
|
|
36
83
|
}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser Automation Tools with LangGraph Interrupt Support
|
|
3
|
+
*
|
|
4
|
+
* These tools use LangGraph's interrupt() mechanism to pause execution
|
|
5
|
+
* and wait for the browser extension to execute actions and return results.
|
|
6
|
+
*
|
|
7
|
+
* Flow:
|
|
8
|
+
* 1. Agent calls browser tool (e.g., browser_navigate)
|
|
9
|
+
* 2. Tool calls interrupt() with action details
|
|
10
|
+
* 3. Graph pauses and returns interrupt to client
|
|
11
|
+
* 4. Extension executes action in browser
|
|
12
|
+
* 5. Extension sends resume Command with actual result
|
|
13
|
+
* 6. Graph continues with real browser data
|
|
14
|
+
*
|
|
15
|
+
* This enables proper chain-of-thought with browser context because
|
|
16
|
+
* the agent receives ACTUAL results (page elements, screenshots, etc.)
|
|
17
|
+
* instead of placeholder acknowledgments.
|
|
18
|
+
*/
|
|
19
|
+
import { z } from 'zod';
|
|
20
|
+
import { DynamicStructuredTool } from '@langchain/core/tools';
|
|
21
|
+
/**
|
|
22
|
+
* Interrupt payload sent to the extension
|
|
23
|
+
*/
|
|
24
|
+
export interface BrowserInterrupt {
|
|
25
|
+
/** Type of browser action to execute */
|
|
26
|
+
type: 'browser_interrupt';
|
|
27
|
+
/** The specific action to perform */
|
|
28
|
+
action: BrowserAction;
|
|
29
|
+
/** Unique ID for this interrupt (for matching resume) */
|
|
30
|
+
interruptId: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Browser action types
|
|
34
|
+
*/
|
|
35
|
+
export type BrowserAction = {
|
|
36
|
+
type: 'navigate';
|
|
37
|
+
url: string;
|
|
38
|
+
reason?: string;
|
|
39
|
+
} | {
|
|
40
|
+
type: 'click';
|
|
41
|
+
index?: number;
|
|
42
|
+
coordinates?: {
|
|
43
|
+
x: number;
|
|
44
|
+
y: number;
|
|
45
|
+
};
|
|
46
|
+
reason?: string;
|
|
47
|
+
} | {
|
|
48
|
+
type: 'type';
|
|
49
|
+
index: number;
|
|
50
|
+
text: string;
|
|
51
|
+
clear?: boolean;
|
|
52
|
+
pressEnter?: boolean;
|
|
53
|
+
} | {
|
|
54
|
+
type: 'scroll';
|
|
55
|
+
direction: 'up' | 'down' | 'left' | 'right';
|
|
56
|
+
amount?: number;
|
|
57
|
+
} | {
|
|
58
|
+
type: 'extract';
|
|
59
|
+
query?: string;
|
|
60
|
+
selector?: string;
|
|
61
|
+
} | {
|
|
62
|
+
type: 'hover';
|
|
63
|
+
index: number;
|
|
64
|
+
} | {
|
|
65
|
+
type: 'wait';
|
|
66
|
+
duration?: number;
|
|
67
|
+
reason?: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: 'back';
|
|
70
|
+
reason?: string;
|
|
71
|
+
} | {
|
|
72
|
+
type: 'screenshot';
|
|
73
|
+
fullPage?: boolean;
|
|
74
|
+
} | {
|
|
75
|
+
type: 'get_page_state';
|
|
76
|
+
reason?: string;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Result returned from extension after executing action
|
|
80
|
+
*/
|
|
81
|
+
export interface BrowserActionResult {
|
|
82
|
+
success: boolean;
|
|
83
|
+
error?: string;
|
|
84
|
+
/** Page state after action (for navigate, click, get_page_state) */
|
|
85
|
+
pageState?: {
|
|
86
|
+
url: string;
|
|
87
|
+
title: string;
|
|
88
|
+
/** Formatted element list for LLM */
|
|
89
|
+
elementList: string;
|
|
90
|
+
elementCount: number;
|
|
91
|
+
scrollPosition: number;
|
|
92
|
+
scrollHeight: number;
|
|
93
|
+
viewportHeight: number;
|
|
94
|
+
};
|
|
95
|
+
/** Screenshot data URL */
|
|
96
|
+
screenshot?: string;
|
|
97
|
+
/** Extracted content */
|
|
98
|
+
extractedContent?: string;
|
|
99
|
+
/** Any additional data */
|
|
100
|
+
data?: unknown;
|
|
101
|
+
}
|
|
102
|
+
declare const BrowserClickSchema: z.ZodObject<{
|
|
103
|
+
index: z.ZodOptional<z.ZodNumber>;
|
|
104
|
+
coordinates: z.ZodOptional<z.ZodObject<{
|
|
105
|
+
x: z.ZodNumber;
|
|
106
|
+
y: z.ZodNumber;
|
|
107
|
+
}, "strip", z.ZodTypeAny, {
|
|
108
|
+
y: number;
|
|
109
|
+
x: number;
|
|
110
|
+
}, {
|
|
111
|
+
y: number;
|
|
112
|
+
x: number;
|
|
113
|
+
}>>;
|
|
114
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
115
|
+
}, "strip", z.ZodTypeAny, {
|
|
116
|
+
index?: number | undefined;
|
|
117
|
+
coordinates?: {
|
|
118
|
+
y: number;
|
|
119
|
+
x: number;
|
|
120
|
+
} | undefined;
|
|
121
|
+
reason?: string | undefined;
|
|
122
|
+
}, {
|
|
123
|
+
index?: number | undefined;
|
|
124
|
+
coordinates?: {
|
|
125
|
+
y: number;
|
|
126
|
+
x: number;
|
|
127
|
+
} | undefined;
|
|
128
|
+
reason?: string | undefined;
|
|
129
|
+
}>;
|
|
130
|
+
declare const BrowserTypeSchema: z.ZodObject<{
|
|
131
|
+
index: z.ZodNumber;
|
|
132
|
+
text: z.ZodString;
|
|
133
|
+
clear: z.ZodOptional<z.ZodBoolean>;
|
|
134
|
+
pressEnter: z.ZodOptional<z.ZodBoolean>;
|
|
135
|
+
}, "strip", z.ZodTypeAny, {
|
|
136
|
+
text: string;
|
|
137
|
+
index: number;
|
|
138
|
+
clear?: boolean | undefined;
|
|
139
|
+
pressEnter?: boolean | undefined;
|
|
140
|
+
}, {
|
|
141
|
+
text: string;
|
|
142
|
+
index: number;
|
|
143
|
+
clear?: boolean | undefined;
|
|
144
|
+
pressEnter?: boolean | undefined;
|
|
145
|
+
}>;
|
|
146
|
+
declare const BrowserNavigateSchema: z.ZodObject<{
|
|
147
|
+
url: z.ZodString;
|
|
148
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
149
|
+
}, "strip", z.ZodTypeAny, {
|
|
150
|
+
url: string;
|
|
151
|
+
reason?: string | undefined;
|
|
152
|
+
}, {
|
|
153
|
+
url: string;
|
|
154
|
+
reason?: string | undefined;
|
|
155
|
+
}>;
|
|
156
|
+
declare const BrowserScrollSchema: z.ZodObject<{
|
|
157
|
+
direction: z.ZodEnum<["up", "down", "left", "right"]>;
|
|
158
|
+
amount: z.ZodOptional<z.ZodNumber>;
|
|
159
|
+
}, "strip", z.ZodTypeAny, {
|
|
160
|
+
direction: "up" | "down" | "left" | "right";
|
|
161
|
+
amount?: number | undefined;
|
|
162
|
+
}, {
|
|
163
|
+
direction: "up" | "down" | "left" | "right";
|
|
164
|
+
amount?: number | undefined;
|
|
165
|
+
}>;
|
|
166
|
+
declare const BrowserExtractSchema: z.ZodObject<{
|
|
167
|
+
query: z.ZodOptional<z.ZodString>;
|
|
168
|
+
selector: z.ZodOptional<z.ZodString>;
|
|
169
|
+
}, "strip", z.ZodTypeAny, {
|
|
170
|
+
query?: string | undefined;
|
|
171
|
+
selector?: string | undefined;
|
|
172
|
+
}, {
|
|
173
|
+
query?: string | undefined;
|
|
174
|
+
selector?: string | undefined;
|
|
175
|
+
}>;
|
|
176
|
+
declare const BrowserHoverSchema: z.ZodObject<{
|
|
177
|
+
index: z.ZodNumber;
|
|
178
|
+
}, "strip", z.ZodTypeAny, {
|
|
179
|
+
index: number;
|
|
180
|
+
}, {
|
|
181
|
+
index: number;
|
|
182
|
+
}>;
|
|
183
|
+
declare const BrowserWaitSchema: z.ZodObject<{
|
|
184
|
+
duration: z.ZodOptional<z.ZodNumber>;
|
|
185
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
186
|
+
}, "strip", z.ZodTypeAny, {
|
|
187
|
+
duration?: number | undefined;
|
|
188
|
+
reason?: string | undefined;
|
|
189
|
+
}, {
|
|
190
|
+
duration?: number | undefined;
|
|
191
|
+
reason?: string | undefined;
|
|
192
|
+
}>;
|
|
193
|
+
declare const BrowserGoBackSchema: z.ZodObject<{
|
|
194
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
195
|
+
}, "strip", z.ZodTypeAny, {
|
|
196
|
+
reason?: string | undefined;
|
|
197
|
+
}, {
|
|
198
|
+
reason?: string | undefined;
|
|
199
|
+
}>;
|
|
200
|
+
declare const BrowserScreenshotSchema: z.ZodObject<{
|
|
201
|
+
fullPage: z.ZodOptional<z.ZodBoolean>;
|
|
202
|
+
}, "strip", z.ZodTypeAny, {
|
|
203
|
+
fullPage?: boolean | undefined;
|
|
204
|
+
}, {
|
|
205
|
+
fullPage?: boolean | undefined;
|
|
206
|
+
}>;
|
|
207
|
+
declare const BrowserGetPageStateSchema: z.ZodObject<{
|
|
208
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
209
|
+
}, "strip", z.ZodTypeAny, {
|
|
210
|
+
reason?: string | undefined;
|
|
211
|
+
}, {
|
|
212
|
+
reason?: string | undefined;
|
|
213
|
+
}>;
|
|
214
|
+
/**
|
|
215
|
+
* Navigate tool - navigates to URL and returns page state
|
|
216
|
+
*/
|
|
217
|
+
export declare function createBrowserNavigateInterruptTool(): DynamicStructuredTool<typeof BrowserNavigateSchema>;
|
|
218
|
+
/**
|
|
219
|
+
* Click tool - clicks element and returns updated state
|
|
220
|
+
*/
|
|
221
|
+
export declare function createBrowserClickInterruptTool(): DynamicStructuredTool<typeof BrowserClickSchema>;
|
|
222
|
+
/**
|
|
223
|
+
* Type tool - types text into input field
|
|
224
|
+
*/
|
|
225
|
+
export declare function createBrowserTypeInterruptTool(): DynamicStructuredTool<typeof BrowserTypeSchema>;
|
|
226
|
+
/**
|
|
227
|
+
* Get page state tool - captures current page elements
|
|
228
|
+
*/
|
|
229
|
+
export declare function createBrowserGetPageStateInterruptTool(): DynamicStructuredTool<typeof BrowserGetPageStateSchema>;
|
|
230
|
+
/**
|
|
231
|
+
* Scroll tool
|
|
232
|
+
*/
|
|
233
|
+
export declare function createBrowserScrollInterruptTool(): DynamicStructuredTool<typeof BrowserScrollSchema>;
|
|
234
|
+
/**
|
|
235
|
+
* Extract tool
|
|
236
|
+
*/
|
|
237
|
+
export declare function createBrowserExtractInterruptTool(): DynamicStructuredTool<typeof BrowserExtractSchema>;
|
|
238
|
+
/**
|
|
239
|
+
* Hover tool
|
|
240
|
+
*/
|
|
241
|
+
export declare function createBrowserHoverInterruptTool(): DynamicStructuredTool<typeof BrowserHoverSchema>;
|
|
242
|
+
/**
|
|
243
|
+
* Wait tool
|
|
244
|
+
*/
|
|
245
|
+
export declare function createBrowserWaitInterruptTool(): DynamicStructuredTool<typeof BrowserWaitSchema>;
|
|
246
|
+
/**
|
|
247
|
+
* Go back tool
|
|
248
|
+
*/
|
|
249
|
+
export declare function createBrowserGoBackInterruptTool(): DynamicStructuredTool<typeof BrowserGoBackSchema>;
|
|
250
|
+
/**
|
|
251
|
+
* Screenshot tool
|
|
252
|
+
*/
|
|
253
|
+
export declare function createBrowserScreenshotInterruptTool(): DynamicStructuredTool<typeof BrowserScreenshotSchema>;
|
|
254
|
+
export declare const EBrowserInterruptTools: {
|
|
255
|
+
readonly CLICK: "browser_click";
|
|
256
|
+
readonly TYPE: "browser_type";
|
|
257
|
+
readonly NAVIGATE: "browser_navigate";
|
|
258
|
+
readonly SCROLL: "browser_scroll";
|
|
259
|
+
readonly EXTRACT: "browser_extract";
|
|
260
|
+
readonly HOVER: "browser_hover";
|
|
261
|
+
readonly WAIT: "browser_wait";
|
|
262
|
+
readonly BACK: "browser_back";
|
|
263
|
+
readonly SCREENSHOT: "browser_screenshot";
|
|
264
|
+
readonly GET_PAGE_STATE: "browser_get_page_state";
|
|
265
|
+
};
|
|
266
|
+
export declare const BROWSER_INTERRUPT_TOOL_NAMES: ("browser_navigate" | "browser_click" | "browser_type" | "browser_get_page_state" | "browser_scroll" | "browser_extract" | "browser_hover" | "browser_wait" | "browser_back" | "browser_screenshot")[];
|
|
267
|
+
export type BrowserInterruptToolName = typeof BROWSER_INTERRUPT_TOOL_NAMES[number];
|
|
268
|
+
export declare function isBrowserInterruptToolCall(toolName: string): toolName is BrowserInterruptToolName;
|
|
269
|
+
/**
|
|
270
|
+
* Create all interrupt-based browser tools
|
|
271
|
+
*
|
|
272
|
+
* Use these when the client is a browser extension that can:
|
|
273
|
+
* 1. Detect browser_interrupt events in the stream
|
|
274
|
+
* 2. Execute browser actions locally
|
|
275
|
+
* 3. Send Command({ resume: result }) to continue the graph
|
|
276
|
+
*/
|
|
277
|
+
export declare function createBrowserInterruptTools(): DynamicStructuredTool[];
|
|
278
|
+
/**
|
|
279
|
+
* Check if an interrupt is a browser interrupt
|
|
280
|
+
*/
|
|
281
|
+
export declare function isBrowserInterrupt(value: unknown): value is BrowserInterrupt;
|
|
282
|
+
export {};
|
|
@@ -36,16 +36,16 @@ declare const BrowserClickSchema: z.ZodObject<{
|
|
|
36
36
|
y: number;
|
|
37
37
|
x: number;
|
|
38
38
|
} | undefined;
|
|
39
|
-
visualDescription?: string | undefined;
|
|
40
39
|
reason?: string | undefined;
|
|
40
|
+
visualDescription?: string | undefined;
|
|
41
41
|
}, {
|
|
42
42
|
index?: number | undefined;
|
|
43
43
|
coordinates?: {
|
|
44
44
|
y: number;
|
|
45
45
|
x: number;
|
|
46
46
|
} | undefined;
|
|
47
|
-
visualDescription?: string | undefined;
|
|
48
47
|
reason?: string | undefined;
|
|
48
|
+
visualDescription?: string | undefined;
|
|
49
49
|
}>;
|
|
50
50
|
declare const BrowserTypeSchema: z.ZodObject<{
|
|
51
51
|
index: z.ZodNumber;
|
|
@@ -103,6 +103,14 @@ export type RunConfig = {
|
|
|
103
103
|
returnContent?: boolean;
|
|
104
104
|
tokenCounter?: TokenCounter;
|
|
105
105
|
indexTokenCountMap?: Record<string, number>;
|
|
106
|
+
/**
|
|
107
|
+
* Enable browser extension mode with interrupt-based tool execution.
|
|
108
|
+
* When true:
|
|
109
|
+
* - Uses MemorySaver checkpointer for pause/resume
|
|
110
|
+
* - Browser tools will interrupt execution and wait for extension results
|
|
111
|
+
* - Extension must call resume endpoint with Command to continue
|
|
112
|
+
*/
|
|
113
|
+
browserMode?: boolean;
|
|
106
114
|
};
|
|
107
115
|
export type ProvidedCallbacks = (BaseCallbackHandler | CallbackHandlerMethods)[] | undefined;
|
|
108
116
|
export type TokenCounter = (message: BaseMessage) => number;
|
package/package.json
CHANGED
package/src/graphs/Graph.ts
CHANGED
|
@@ -1240,10 +1240,10 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
|
|
|
1240
1240
|
});
|
|
1241
1241
|
const workflow = new StateGraph(StateAnnotation)
|
|
1242
1242
|
.addNode(this.defaultAgentId, agentNode, { ends: [END] })
|
|
1243
|
-
.addEdge(START, this.defaultAgentId)
|
|
1244
|
-
.compile();
|
|
1243
|
+
.addEdge(START, this.defaultAgentId);
|
|
1245
1244
|
|
|
1246
|
-
|
|
1245
|
+
// Pass compileOptions (e.g., checkpointer for browser interrupt support)
|
|
1246
|
+
return workflow.compile(this.compileOptions as unknown as never);
|
|
1247
1247
|
}
|
|
1248
1248
|
|
|
1249
1249
|
/* Dispatchers */
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from './tools/CodeExecutor';
|
|
|
14
14
|
export * from './tools/ProgrammaticToolCalling';
|
|
15
15
|
export * from './tools/ToolSearchRegex';
|
|
16
16
|
export * from './tools/BrowserTools';
|
|
17
|
+
export * from './tools/BrowserInterruptTools';
|
|
17
18
|
export * from './tools/handlers';
|
|
18
19
|
export * from './tools/search';
|
|
19
20
|
|