illuma-agents 1.0.19 → 1.0.20

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/main.cjs CHANGED
@@ -100,6 +100,7 @@ exports.BROWSER_TOOL_NAMES = BrowserTools.BROWSER_TOOL_NAMES;
100
100
  exports.EBrowserTools = BrowserTools.EBrowserTools;
101
101
  exports.createBrowserClickTool = BrowserTools.createBrowserClickTool;
102
102
  exports.createBrowserExtractTool = BrowserTools.createBrowserExtractTool;
103
+ exports.createBrowserGetPageStateTool = BrowserTools.createBrowserGetPageStateTool;
103
104
  exports.createBrowserGoBackTool = BrowserTools.createBrowserGoBackTool;
104
105
  exports.createBrowserHoverTool = BrowserTools.createBrowserHoverTool;
105
106
  exports.createBrowserNavigateTool = BrowserTools.createBrowserNavigateTool;
@@ -1 +1 @@
1
- {"version":3,"file":"main.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"main.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -68,6 +68,9 @@ const BrowserScreenshotSchema = zod.z.object({
68
68
  fullPage: zod.z.boolean().optional().describe('Whether to capture the full page or just the viewport (default: viewport only)'),
69
69
  reason: zod.z.string().optional().describe('Why you need a screenshot (e.g., "to identify visual elements", "to analyze page layout")'),
70
70
  });
71
+ const BrowserGetPageStateSchema = zod.z.object({
72
+ reason: zod.z.string().optional().describe('Why you need fresh page state (e.g., "after navigation", "to see updated elements")'),
73
+ });
71
74
  // ============================================
72
75
  // Tool Implementations
73
76
  // ============================================
@@ -180,8 +183,18 @@ Use this tool when you need to:
180
183
  - Navigate to a different page
181
184
  - Open a new URL
182
185
 
186
+ **IMPORTANT**: After calling browser_navigate, you MUST call browser_get_page_state
187
+ before using browser_click or browser_type. This is because navigation changes the page,
188
+ and you need to see the new page's elements before you can interact with them.
189
+
183
190
  Provide the full URL including the protocol (https://).
184
191
 
192
+ **Correct workflow**:
193
+ 1. browser_navigate({ url: "https://www.amazon.com" })
194
+ 2. browser_get_page_state({ reason: "see elements on Amazon" })
195
+ 3. Now find the search input's [index] in the returned state
196
+ 4. browser_type({ index: <search_input_index>, text: "query", pressEnter: true })
197
+
185
198
  Example: browser_navigate({ url: "https://www.google.com" })`,
186
199
  schema: BrowserNavigateSchema,
187
200
  });
@@ -357,6 +370,43 @@ Example: browser_screenshot({ fullPage: false })`,
357
370
  schema: BrowserScreenshotSchema,
358
371
  });
359
372
  }
373
+ /**
374
+ * Browser get page state tool - gets fresh page context after navigation or actions
375
+ * CRITICAL: Use this after browser_navigate or any action that changes the page
376
+ */
377
+ function createBrowserGetPageStateTool() {
378
+ return tools.tool(async ({ reason }) => {
379
+ return JSON.stringify({
380
+ type: 'browser_action',
381
+ action: {
382
+ type: 'get_page_state',
383
+ reason,
384
+ },
385
+ requiresBrowserExecution: true,
386
+ // Special flag: extension should inject fresh context into the conversation
387
+ requiresContextRefresh: true,
388
+ });
389
+ }, {
390
+ name: EBrowserTools.GET_PAGE_STATE,
391
+ description: `Get fresh page state showing current interactive elements.
392
+
393
+ **CRITICAL**: You MUST call this tool after:
394
+ - browser_navigate (to see elements on the new page)
395
+ - browser_click (if it caused navigation or page changes)
396
+ - Any action that might have changed the visible elements
397
+
398
+ This tool returns the updated list of interactive elements with their [index] numbers.
399
+ Without calling this after navigation, you will NOT know what elements exist on the new page.
400
+
401
+ **Workflow example**:
402
+ 1. browser_navigate to amazon.com
403
+ 2. browser_get_page_state to see Amazon's elements
404
+ 3. Now you can see the search input's [index] and use browser_type
405
+
406
+ Example: browser_get_page_state({ reason: "to see elements after navigation" })`,
407
+ schema: BrowserGetPageStateSchema,
408
+ });
409
+ }
360
410
  /**
361
411
  * Create all browser automation tools
362
412
  *
@@ -381,7 +431,7 @@ Example: browser_screenshot({ fullPage: false })`,
381
431
  function createBrowserTools(config = {}) {
382
432
  const tools = [];
383
433
  // Enable all by default
384
- const { enableClick = true, enableType = true, enableNavigate = true, enableScroll = true, enableExtract = true, enableHover = true, enableWait = true, enableBack = true, enableScreenshot = true, } = config;
434
+ const { enableClick = true, enableType = true, enableNavigate = true, enableScroll = true, enableExtract = true, enableHover = true, enableWait = true, enableBack = true, enableScreenshot = true, enableGetPageState = true, } = config;
385
435
  if (enableClick)
386
436
  tools.push(createBrowserClickTool());
387
437
  if (enableType)
@@ -400,6 +450,8 @@ function createBrowserTools(config = {}) {
400
450
  tools.push(createBrowserGoBackTool());
401
451
  if (enableScreenshot)
402
452
  tools.push(createBrowserScreenshotTool());
453
+ if (enableGetPageState)
454
+ tools.push(createBrowserGetPageStateTool());
403
455
  return tools;
404
456
  }
405
457
  /**
@@ -416,6 +468,7 @@ const EBrowserTools = {
416
468
  WAIT: 'browser_wait',
417
469
  BACK: 'browser_back',
418
470
  SCREENSHOT: 'browser_screenshot',
471
+ GET_PAGE_STATE: 'browser_get_page_state',
419
472
  };
420
473
  /**
421
474
  * Get browser tool names for filtering/identification
@@ -430,6 +483,7 @@ const BROWSER_TOOL_NAMES = [
430
483
  EBrowserTools.WAIT,
431
484
  EBrowserTools.BACK,
432
485
  EBrowserTools.SCREENSHOT,
486
+ EBrowserTools.GET_PAGE_STATE,
433
487
  ];
434
488
  /**
435
489
  * Check if a tool call is a browser action
@@ -460,6 +514,7 @@ exports.BROWSER_TOOL_NAMES = BROWSER_TOOL_NAMES;
460
514
  exports.EBrowserTools = EBrowserTools;
461
515
  exports.createBrowserClickTool = createBrowserClickTool;
462
516
  exports.createBrowserExtractTool = createBrowserExtractTool;
517
+ exports.createBrowserGetPageStateTool = createBrowserGetPageStateTool;
463
518
  exports.createBrowserGoBackTool = createBrowserGoBackTool;
464
519
  exports.createBrowserHoverTool = createBrowserHoverTool;
465
520
  exports.createBrowserNavigateTool = createBrowserNavigateTool;
@@ -1 +1 @@
1
- {"version":3,"file":"BrowserTools.cjs","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\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\nProvide the full URL including the protocol (https://).\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// 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};\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 } = 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 \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} 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] 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":["z","tool"],"mappings":"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"}
1
+ {"version":3,"file":"BrowserTools.cjs","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":["z","tool"],"mappings":";;;;;AAAA;;;;;;;;;;;;AAYG;AAKH;AACA;AACA;AAEA;;AAEG;AACH,MAAM,kBAAkB,GAAGA,KAAC,CAAC,MAAM,CAAC;IAClC,KAAK,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACnC,yFAAyF;QACzF,yFAAyF;AACzF,QAAA,+CAA+C,CAChD;AACD,IAAA,WAAW,EAAEA,KAAC,CAAC,MAAM,CAAC;QACpB,CAAC,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;QACzD,CAAC,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;AAC1D,KAAA,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACpB,8EAA8E;QAC9E,uEAAuE;AACvE,QAAA,+CAA+C,CAChD;IACD,iBAAiB,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAC/C,wFAAwF;AACxF,QAAA,kEAAkE,CACnE;AACD,IAAA,MAAM,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACpC,gFAAgF,CACjF;AACF,CAAA,CAAC;AAEF,MAAM,iBAAiB,GAAGA,KAAC,CAAC,MAAM,CAAC;IACjC,KAAK,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CACxB,2EAA2E,CAC5E;IACD,IAAI,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CACvB,uCAAuC,CACxC;AACD,IAAA,KAAK,EAAEA,KAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACpC,sEAAsE,CACvE;AACD,IAAA,UAAU,EAAEA,KAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACzC,gFAAgF,CACjF;AACF,CAAA,CAAC;AAEF,MAAM,qBAAqB,GAAGA,KAAC,CAAC,MAAM,CAAC;IACrC,GAAG,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CACtB,+DAA+D,CAChE;AACD,IAAA,MAAM,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACpC,yDAAyD,CAC1D;AACF,CAAA,CAAC;AAEF,MAAM,mBAAmB,GAAGA,KAAC,CAAC,MAAM,CAAC;AACnC,IAAA,SAAS,EAAEA,KAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CACzD,yBAAyB,CAC1B;AACD,IAAA,MAAM,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACpC,+CAA+C,CAChD;AACF,CAAA,CAAC;AAEF,MAAM,oBAAoB,GAAGA,KAAC,CAAC,MAAM,CAAC;AACpC,IAAA,KAAK,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACnC,+GAA+G,CAChH;AACD,IAAA,QAAQ,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACtC,kEAAkE,CACnE;AACF,CAAA,CAAC;AAEF,MAAM,kBAAkB,GAAGA,KAAC,CAAC,MAAM,CAAC;IAClC,KAAK,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CACxB,sEAAsE,CACvE;AACF,CAAA,CAAC;AAEF,MAAM,iBAAiB,GAAGA,KAAC,CAAC,MAAM,CAAC;AACjC,IAAA,QAAQ,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACtC,kDAAkD,CACnD;AACD,IAAA,MAAM,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACpC,4EAA4E,CAC7E;AACF,CAAA,CAAC;AAEF,MAAM,mBAAmB,GAAGA,KAAC,CAAC,MAAM,CAAC;AACnC,IAAA,MAAM,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACpC,6CAA6C,CAC9C;AACF,CAAA,CAAC;AAEF,MAAM,uBAAuB,GAAGA,KAAC,CAAC,MAAM,CAAC;AACvC,IAAA,QAAQ,EAAEA,KAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACvC,gFAAgF,CACjF;AACD,IAAA,MAAM,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACpC,2FAA2F,CAC5F;AACF,CAAA,CAAC;AAEF,MAAM,yBAAyB,GAAGA,KAAC,CAAC,MAAM,CAAC;AACzC,IAAA,MAAM,EAAEA,KAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CACpC,qFAAqF,CACtF;AACF,CAAA,CAAC;AAEF;AACA;AACA;AAEA;;;AAGG;SACa,sBAAsB,GAAA;AACpC,IAAA,OAAOC,UAAI,CACT,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,EAAE,KAAI;;AAE1D,QAAA,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,WAAW,EAAE;YACvC,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,gBAAA,IAAI,EAAE,OAAO;AACb,gBAAA,KAAK,EAAE,kEAAkE;AAC1E,aAAA,CAAC;;;;QAKJ,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,MAAM,EAAE;AACN,gBAAA,IAAI,EAAE,OAAO;gBACb,IAAI,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,EAAE,CAAC;AACrC,gBAAA,IAAI,WAAW,IAAI,EAAE,WAAW,EAAE,CAAC;AACnC,gBAAA,IAAI,iBAAiB,IAAI,EAAE,iBAAiB,EAAE,CAAC;gBAC/C,MAAM;AACP,aAAA;;AAED,YAAA,wBAAwB,EAAE,IAAI;AAC/B,SAAA,CAAC;AACJ,KAAC,EACD;QACE,IAAI,EAAE,aAAa,CAAC,KAAK;AACzB,QAAA,WAAW,EAAE,CAAA;;;;;;;;;;;;;;;;;;;AAmB2E,6FAAA,CAAA;AACxF,QAAA,MAAM,EAAE,kBAAkB;AAC3B,KAAA,CACF;AACH;AAEA;;AAEG;SACa,qBAAqB,GAAA;AACnC,IAAA,OAAOA,UAAI,CACT,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,KAAI;QAC3C,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,MAAM,EAAE;AACN,gBAAA,IAAI,EAAE,MAAM;gBACZ,KAAK;gBACL,IAAI;gBACJ,KAAK,EAAE,KAAK,IAAI,KAAK;gBACrB,UAAU,EAAE,UAAU,IAAI,KAAK;AAChC,aAAA;AACD,YAAA,wBAAwB,EAAE,IAAI;AAC/B,SAAA,CAAC;AACJ,KAAC,EACD;QACE,IAAI,EAAE,aAAa,CAAC,IAAI;AACxB,QAAA,WAAW,EAAE,CAAA;;;;;;;;;;;;AAYe,iCAAA,CAAA;AAC5B,QAAA,MAAM,EAAE,iBAAiB;AAC1B,KAAA,CACF;AACH;AAEA;;AAEG;SACa,yBAAyB,GAAA;IACvC,OAAOA,UAAI,CACT,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAI;QACxB,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,MAAM,EAAE;AACN,gBAAA,IAAI,EAAE,UAAU;gBAChB,GAAG;gBACH,MAAM;AACP,aAAA;AACD,YAAA,wBAAwB,EAAE,IAAI;AAC/B,SAAA,CAAC;AACJ,KAAC,EACD;QACE,IAAI,EAAE,aAAa,CAAC,QAAQ;AAC5B,QAAA,WAAW,EAAE,CAAA;;;;;;;;;;;;;;;;;;;AAmB0C,4DAAA,CAAA;AACvD,QAAA,MAAM,EAAE,qBAAqB;AAC9B,KAAA,CACF;AACH;AAEA;;AAEG;SACa,uBAAuB,GAAA;IACrC,OAAOA,UAAI,CACT,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,KAAI;QAC9B,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,MAAM,EAAE;AACN,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,MAAM,EAAE;oBACN,SAAS;oBACT,MAAM,EAAE,MAAM,IAAI,GAAG;AACtB,iBAAA;AACF,aAAA;AACD,YAAA,wBAAwB,EAAE,IAAI;AAC/B,SAAA,CAAC;AACJ,KAAC,EACD;QACE,IAAI,EAAE,aAAa,CAAC,MAAM;AAC1B,QAAA,WAAW,EAAE,CAAA;;;;;;;;;AASyC,2DAAA,CAAA;AACtD,QAAA,MAAM,EAAE,mBAAmB;AAC5B,KAAA,CACF;AACH;AAEA;;AAEG;SACa,wBAAwB,GAAA;IACtC,OAAOA,UAAI,CACT,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAI;QAC5B,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,MAAM,EAAE;AACN,gBAAA,IAAI,EAAE,SAAS;gBACf,KAAK;gBACL,QAAQ;AACT,aAAA;AACD,YAAA,wBAAwB,EAAE,IAAI;AAC/B,SAAA,CAAC;AACJ,KAAC,EACD;QACE,IAAI,EAAE,aAAa,CAAC,OAAO;AAC3B,QAAA,WAAW,EAAE,CAAA;;;;;;;;;;;AAWgE,kFAAA,CAAA;AAC7E,QAAA,MAAM,EAAE,oBAAoB;AAC7B,KAAA,CACF;AACH;AAEA;;AAEG;SACa,sBAAsB,GAAA;IACpC,OAAOA,UAAI,CACT,OAAO,EAAE,KAAK,EAAE,KAAI;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,MAAM,EAAE;AACN,gBAAA,IAAI,EAAE,OAAO;gBACb,KAAK;AACN,aAAA;AACD,YAAA,wBAAwB,EAAE,IAAI;AAC/B,SAAA,CAAC;AACJ,KAAC,EACD;QACE,IAAI,EAAE,aAAa,CAAC,KAAK;AACzB,QAAA,WAAW,EAAE,CAAA;;;;;;;AAOmD,qEAAA,CAAA;AAChE,QAAA,MAAM,EAAE,kBAAkB;AAC3B,KAAA,CACF;AACH;AAEA;;AAEG;SACa,qBAAqB,GAAA;IACnC,OAAOA,UAAI,CACT,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAI;QAC7B,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,MAAM,EAAE;AACN,gBAAA,IAAI,EAAE,MAAM;gBACZ,QAAQ,EAAE,QAAQ,IAAI,IAAI;gBAC1B,MAAM;AACP,aAAA;AACD,YAAA,wBAAwB,EAAE,IAAI;AAC/B,SAAA,CAAC;AACJ,KAAC,EACD;QACE,IAAI,EAAE,aAAa,CAAC,IAAI;AACxB,QAAA,WAAW,EAAE,CAAA;;;;;;;;;AAS2D,6EAAA,CAAA;AACxE,QAAA,MAAM,EAAE,iBAAiB;AAC1B,KAAA,CACF;AACH;AAEA;;AAEG;SACa,uBAAuB,GAAA;IACrC,OAAOA,UAAI,CACT,OAAO,EAAE,MAAM,EAAE,KAAI;QACnB,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,MAAM,EAAE;AACN,gBAAA,IAAI,EAAE,MAAM;gBACZ,MAAM;AACP,aAAA;AACD,YAAA,wBAAwB,EAAE,IAAI;AAC/B,SAAA,CAAC;AACJ,KAAC,EACD;QACE,IAAI,EAAE,aAAa,CAAC,IAAI;AACxB,QAAA,WAAW,EAAE,CAAA;;;;;;AAM8C,gEAAA,CAAA;AAC3D,QAAA,MAAM,EAAE,mBAAmB;AAC5B,KAAA,CACF;AACH;AAEA;;AAEG;SACa,2BAA2B,GAAA;IACzC,OAAOA,UAAI,CACT,OAAO,EAAE,QAAQ,EAAE,KAAI;QACrB,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,MAAM,EAAE;AACN,gBAAA,IAAI,EAAE,YAAY;gBAClB,QAAQ,EAAE,QAAQ,IAAI,KAAK;AAC5B,aAAA;AACD,YAAA,wBAAwB,EAAE,IAAI;AAC/B,SAAA,CAAC;AACJ,KAAC,EACD;QACE,IAAI,EAAE,aAAa,CAAC,UAAU;AAC9B,QAAA,WAAW,EAAE,CAAA;;;;;;;;;;AAU8B,gDAAA,CAAA;AAC3C,QAAA,MAAM,EAAE,uBAAuB;AAChC,KAAA,CACF;AACH;AAEA;;;AAGG;SACa,6BAA6B,GAAA;IAC3C,OAAOA,UAAI,CACT,OAAO,EAAE,MAAM,EAAE,KAAI;QACnB,OAAO,IAAI,CAAC,SAAS,CAAC;AACpB,YAAA,IAAI,EAAE,gBAAgB;AACtB,YAAA,MAAM,EAAE;AACN,gBAAA,IAAI,EAAE,gBAAgB;gBACtB,MAAM;AACP,aAAA;AACD,YAAA,wBAAwB,EAAE,IAAI;;AAE9B,YAAA,sBAAsB,EAAE,IAAI;AAC7B,SAAA,CAAC;AACJ,KAAC,EACD;QACE,IAAI,EAAE,aAAa,CAAC,cAAc;AAClC,QAAA,WAAW,EAAE,CAAA;;;;;;;;;;;;;;;AAe6D,+EAAA,CAAA;AAC1E,QAAA,MAAM,EAAE,yBAAyB;AAClC,KAAA,CACF;AACH;AA6BA;;;;;;;;;;;;;;;;;;;;AAoBG;AACa,SAAA,kBAAkB,CAAC,MAAA,GAA6B,EAAE,EAAA;IAChE,MAAM,KAAK,GAA4B,EAAE;;AAGzC,IAAA,MAAM,EACJ,WAAW,GAAG,IAAI,EAClB,UAAU,GAAG,IAAI,EACjB,cAAc,GAAG,IAAI,EACrB,YAAY,GAAG,IAAI,EACnB,aAAa,GAAG,IAAI,EACpB,WAAW,GAAG,IAAI,EAClB,UAAU,GAAG,IAAI,EACjB,UAAU,GAAG,IAAI,EACjB,gBAAgB,GAAG,IAAI,EACvB,kBAAkB,GAAG,IAAI,GAC1B,GAAG,MAAM;AAEV,IAAA,IAAI,WAAW;AAAE,QAAA,KAAK,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC;AACrD,IAAA,IAAI,UAAU;AAAE,QAAA,KAAK,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;AACnD,IAAA,IAAI,cAAc;AAAE,QAAA,KAAK,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC;AAC3D,IAAA,IAAI,YAAY;AAAE,QAAA,KAAK,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC;AACvD,IAAA,IAAI,aAAa;AAAE,QAAA,KAAK,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC;AACzD,IAAA,IAAI,WAAW;AAAE,QAAA,KAAK,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC;AACrD,IAAA,IAAI,UAAU;AAAE,QAAA,KAAK,CAAC,IAAI,CAAC,qBAAqB,EAAE,CAAC;AACnD,IAAA,IAAI,UAAU;AAAE,QAAA,KAAK,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC;AACrD,IAAA,IAAI,gBAAgB;AAAE,QAAA,KAAK,CAAC,IAAI,CAAC,2BAA2B,EAAE,CAAC;AAC/D,IAAA,IAAI,kBAAkB;AAAE,QAAA,KAAK,CAAC,IAAI,CAAC,6BAA6B,EAAE,CAAC;AAEnE,IAAA,OAAO,KAAK;AACd;AAEA;;;AAGG;AACU,MAAA,aAAa,GAAG;AAC3B,IAAA,KAAK,EAAE,eAAe;AACtB,IAAA,IAAI,EAAE,cAAc;AACpB,IAAA,QAAQ,EAAE,kBAAkB;AAC5B,IAAA,MAAM,EAAE,gBAAgB;AACxB,IAAA,OAAO,EAAE,iBAAiB;AAC1B,IAAA,KAAK,EAAE,eAAe;AACtB,IAAA,IAAI,EAAE,cAAc;AACpB,IAAA,IAAI,EAAE,cAAc;AACpB,IAAA,UAAU,EAAE,oBAAoB;AAChC,IAAA,cAAc,EAAE,wBAAwB;;AAG1C;;AAEG;AACU,MAAA,kBAAkB,GAAG;AAChC,IAAA,aAAa,CAAC,KAAK;AACnB,IAAA,aAAa,CAAC,IAAI;AAClB,IAAA,aAAa,CAAC,QAAQ;AACtB,IAAA,aAAa,CAAC,MAAM;AACpB,IAAA,aAAa,CAAC,OAAO;AACrB,IAAA,aAAa,CAAC,KAAK;AACnB,IAAA,aAAa,CAAC,IAAI;AAClB,IAAA,aAAa,CAAC,IAAI;AAClB,IAAA,aAAa,CAAC,UAAU;AACxB,IAAA,aAAa,CAAC,cAAc;;AAK9B;;AAEG;AACG,SAAU,iBAAiB,CAAC,QAAgB,EAAA;AAChD,IAAA,OAAO,kBAAkB,CAAC,QAAQ,CAAC,QAA2B,CAAC;AACjE;AAEA;;;;;;;;;AASG;AACG,SAAU,oBAAoB,CAAC,OAAsD,EAAA;AACzF,IAAA,MAAM,eAAe,GAAG,OAAO,CAAC,4BAA4B,CAAC;AAC7D,IAAA,MAAM,aAAa,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAEzD,QACE,eAAe,KAAK,MAAM;AAC1B,QAAA,aAAa,KAAK,MAAM;AACxB,SAAC,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACpE,SAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAEpE;;;;;;;;;;;;;;;;;;"}
package/dist/esm/main.mjs CHANGED
@@ -15,7 +15,7 @@ export { Calculator } from './tools/Calculator.mjs';
15
15
  export { createCodeExecutionTool, getCodeBaseURL, imageExtRegex } from './tools/CodeExecutor.mjs';
16
16
  export { createProgrammaticToolCallingTool, executeTools, extractUsedToolNames, fetchSessionFiles, filterToolsByUsage, formatCompletedResponse, makeRequest, normalizeToPythonIdentifier, unwrapToolResponse } from './tools/ProgrammaticToolCalling.mjs';
17
17
  export { countNestedGroups, createToolSearchRegexTool, escapeRegexSpecialChars, hasNestedQuantifiers, isDangerousPattern, sanitizeRegex } from './tools/ToolSearchRegex.mjs';
18
- export { BROWSER_TOOL_NAMES, EBrowserTools, createBrowserClickTool, createBrowserExtractTool, createBrowserGoBackTool, createBrowserHoverTool, createBrowserNavigateTool, createBrowserScreenshotTool, createBrowserScrollTool, createBrowserTools, createBrowserTypeTool, createBrowserWaitTool, hasBrowserCapability, isBrowserToolCall } from './tools/BrowserTools.mjs';
18
+ export { BROWSER_TOOL_NAMES, EBrowserTools, createBrowserClickTool, createBrowserExtractTool, createBrowserGetPageStateTool, createBrowserGoBackTool, createBrowserHoverTool, createBrowserNavigateTool, createBrowserScreenshotTool, createBrowserScrollTool, createBrowserTools, createBrowserTypeTool, createBrowserWaitTool, hasBrowserCapability, isBrowserToolCall } from './tools/BrowserTools.mjs';
19
19
  export { handleServerToolResult, handleToolCallChunks, handleToolCalls, toolResultTypes } from './tools/handlers.mjs';
20
20
  export { createSearchTool } from './tools/search/tool.mjs';
21
21
  export { Callback, CommonEvents, Constants, ContentTypes, EnvVar, GraphEvents, GraphNodeActions, GraphNodeKeys, MessageTypes, Providers, StepTypes, TitleMethod, ToolCallTypes } from './common/enum.mjs';
@@ -66,6 +66,9 @@ const BrowserScreenshotSchema = z.object({
66
66
  fullPage: z.boolean().optional().describe('Whether to capture the full page or just the viewport (default: viewport only)'),
67
67
  reason: z.string().optional().describe('Why you need a screenshot (e.g., "to identify visual elements", "to analyze page layout")'),
68
68
  });
69
+ const BrowserGetPageStateSchema = z.object({
70
+ reason: z.string().optional().describe('Why you need fresh page state (e.g., "after navigation", "to see updated elements")'),
71
+ });
69
72
  // ============================================
70
73
  // Tool Implementations
71
74
  // ============================================
@@ -178,8 +181,18 @@ Use this tool when you need to:
178
181
  - Navigate to a different page
179
182
  - Open a new URL
180
183
 
184
+ **IMPORTANT**: After calling browser_navigate, you MUST call browser_get_page_state
185
+ before using browser_click or browser_type. This is because navigation changes the page,
186
+ and you need to see the new page's elements before you can interact with them.
187
+
181
188
  Provide the full URL including the protocol (https://).
182
189
 
190
+ **Correct workflow**:
191
+ 1. browser_navigate({ url: "https://www.amazon.com" })
192
+ 2. browser_get_page_state({ reason: "see elements on Amazon" })
193
+ 3. Now find the search input's [index] in the returned state
194
+ 4. browser_type({ index: <search_input_index>, text: "query", pressEnter: true })
195
+
183
196
  Example: browser_navigate({ url: "https://www.google.com" })`,
184
197
  schema: BrowserNavigateSchema,
185
198
  });
@@ -355,6 +368,43 @@ Example: browser_screenshot({ fullPage: false })`,
355
368
  schema: BrowserScreenshotSchema,
356
369
  });
357
370
  }
371
+ /**
372
+ * Browser get page state tool - gets fresh page context after navigation or actions
373
+ * CRITICAL: Use this after browser_navigate or any action that changes the page
374
+ */
375
+ function createBrowserGetPageStateTool() {
376
+ return tool(async ({ reason }) => {
377
+ return JSON.stringify({
378
+ type: 'browser_action',
379
+ action: {
380
+ type: 'get_page_state',
381
+ reason,
382
+ },
383
+ requiresBrowserExecution: true,
384
+ // Special flag: extension should inject fresh context into the conversation
385
+ requiresContextRefresh: true,
386
+ });
387
+ }, {
388
+ name: EBrowserTools.GET_PAGE_STATE,
389
+ description: `Get fresh page state showing current interactive elements.
390
+
391
+ **CRITICAL**: You MUST call this tool after:
392
+ - browser_navigate (to see elements on the new page)
393
+ - browser_click (if it caused navigation or page changes)
394
+ - Any action that might have changed the visible elements
395
+
396
+ This tool returns the updated list of interactive elements with their [index] numbers.
397
+ Without calling this after navigation, you will NOT know what elements exist on the new page.
398
+
399
+ **Workflow example**:
400
+ 1. browser_navigate to amazon.com
401
+ 2. browser_get_page_state to see Amazon's elements
402
+ 3. Now you can see the search input's [index] and use browser_type
403
+
404
+ Example: browser_get_page_state({ reason: "to see elements after navigation" })`,
405
+ schema: BrowserGetPageStateSchema,
406
+ });
407
+ }
358
408
  /**
359
409
  * Create all browser automation tools
360
410
  *
@@ -379,7 +429,7 @@ Example: browser_screenshot({ fullPage: false })`,
379
429
  function createBrowserTools(config = {}) {
380
430
  const tools = [];
381
431
  // Enable all by default
382
- const { enableClick = true, enableType = true, enableNavigate = true, enableScroll = true, enableExtract = true, enableHover = true, enableWait = true, enableBack = true, enableScreenshot = true, } = config;
432
+ const { enableClick = true, enableType = true, enableNavigate = true, enableScroll = true, enableExtract = true, enableHover = true, enableWait = true, enableBack = true, enableScreenshot = true, enableGetPageState = true, } = config;
383
433
  if (enableClick)
384
434
  tools.push(createBrowserClickTool());
385
435
  if (enableType)
@@ -398,6 +448,8 @@ function createBrowserTools(config = {}) {
398
448
  tools.push(createBrowserGoBackTool());
399
449
  if (enableScreenshot)
400
450
  tools.push(createBrowserScreenshotTool());
451
+ if (enableGetPageState)
452
+ tools.push(createBrowserGetPageStateTool());
401
453
  return tools;
402
454
  }
403
455
  /**
@@ -414,6 +466,7 @@ const EBrowserTools = {
414
466
  WAIT: 'browser_wait',
415
467
  BACK: 'browser_back',
416
468
  SCREENSHOT: 'browser_screenshot',
469
+ GET_PAGE_STATE: 'browser_get_page_state',
417
470
  };
418
471
  /**
419
472
  * Get browser tool names for filtering/identification
@@ -428,6 +481,7 @@ const BROWSER_TOOL_NAMES = [
428
481
  EBrowserTools.WAIT,
429
482
  EBrowserTools.BACK,
430
483
  EBrowserTools.SCREENSHOT,
484
+ EBrowserTools.GET_PAGE_STATE,
431
485
  ];
432
486
  /**
433
487
  * Check if a tool call is a browser action
@@ -454,5 +508,5 @@ function hasBrowserCapability(headers) {
454
508
  (Array.isArray(capableHeader) && capableHeader.includes('true')));
455
509
  }
456
510
 
457
- export { BROWSER_TOOL_NAMES, EBrowserTools, createBrowserClickTool, createBrowserExtractTool, createBrowserGoBackTool, createBrowserHoverTool, createBrowserNavigateTool, createBrowserScreenshotTool, createBrowserScrollTool, createBrowserTools, createBrowserTypeTool, createBrowserWaitTool, hasBrowserCapability, isBrowserToolCall };
511
+ export { BROWSER_TOOL_NAMES, EBrowserTools, createBrowserClickTool, createBrowserExtractTool, createBrowserGetPageStateTool, createBrowserGoBackTool, createBrowserHoverTool, createBrowserNavigateTool, createBrowserScreenshotTool, createBrowserScrollTool, createBrowserTools, createBrowserTypeTool, createBrowserWaitTool, hasBrowserCapability, isBrowserToolCall };
458
512
  //# sourceMappingURL=BrowserTools.mjs.map
@@ -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\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\nProvide the full URL including the protocol (https://).\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// 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};\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 } = 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 \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} 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] 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 });\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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"}
@@ -127,6 +127,13 @@ declare const BrowserScreenshotSchema: z.ZodObject<{
127
127
  reason?: string | undefined;
128
128
  fullPage?: boolean | undefined;
129
129
  }>;
130
+ declare const BrowserGetPageStateSchema: z.ZodObject<{
131
+ reason: z.ZodOptional<z.ZodString>;
132
+ }, "strip", z.ZodTypeAny, {
133
+ reason?: string | undefined;
134
+ }, {
135
+ reason?: string | undefined;
136
+ }>;
130
137
  /**
131
138
  * Browser click tool - clicks an element by index or coordinates
132
139
  * Supports both semantic (index-based) and vision (coordinate-based) clicking
@@ -164,6 +171,11 @@ export declare function createBrowserGoBackTool(): DynamicStructuredTool<typeof
164
171
  * Browser screenshot tool - captures a screenshot
165
172
  */
166
173
  export declare function createBrowserScreenshotTool(): DynamicStructuredTool<typeof BrowserScreenshotSchema>;
174
+ /**
175
+ * Browser get page state tool - gets fresh page context after navigation or actions
176
+ * CRITICAL: Use this after browser_navigate or any action that changes the page
177
+ */
178
+ export declare function createBrowserGetPageStateTool(): DynamicStructuredTool<typeof BrowserGetPageStateSchema>;
167
179
  export type BrowserToolsConfig = {
168
180
  /** Enable click tool */
169
181
  enableClick?: boolean;
@@ -183,6 +195,8 @@ export type BrowserToolsConfig = {
183
195
  enableBack?: boolean;
184
196
  /** Enable screenshot tool */
185
197
  enableScreenshot?: boolean;
198
+ /** Enable get page state tool */
199
+ enableGetPageState?: boolean;
186
200
  };
187
201
  /**
188
202
  * Create all browser automation tools
@@ -220,11 +234,12 @@ export declare const EBrowserTools: {
220
234
  readonly WAIT: "browser_wait";
221
235
  readonly BACK: "browser_back";
222
236
  readonly SCREENSHOT: "browser_screenshot";
237
+ readonly GET_PAGE_STATE: "browser_get_page_state";
223
238
  };
224
239
  /**
225
240
  * Get browser tool names for filtering/identification
226
241
  */
227
- export declare const BROWSER_TOOL_NAMES: readonly ["browser_click", "browser_type", "browser_navigate", "browser_scroll", "browser_extract", "browser_hover", "browser_wait", "browser_back", "browser_screenshot"];
242
+ export declare const BROWSER_TOOL_NAMES: readonly ["browser_click", "browser_type", "browser_navigate", "browser_scroll", "browser_extract", "browser_hover", "browser_wait", "browser_back", "browser_screenshot", "browser_get_page_state"];
228
243
  export type BrowserToolName = typeof BROWSER_TOOL_NAMES[number];
229
244
  /**
230
245
  * Check if a tool call is a browser action
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "illuma-agents",
3
- "version": "1.0.19",
3
+ "version": "1.0.20",
4
4
  "main": "./dist/cjs/main.cjs",
5
5
  "module": "./dist/esm/main.mjs",
6
6
  "types": "./dist/types/index.d.ts",
@@ -117,6 +117,12 @@ const BrowserScreenshotSchema = z.object({
117
117
  ),
118
118
  });
119
119
 
120
+ const BrowserGetPageStateSchema = z.object({
121
+ reason: z.string().optional().describe(
122
+ 'Why you need fresh page state (e.g., "after navigation", "to see updated elements")'
123
+ ),
124
+ });
125
+
120
126
  // ============================================
121
127
  // Tool Implementations
122
128
  // ============================================
@@ -241,8 +247,18 @@ Use this tool when you need to:
241
247
  - Navigate to a different page
242
248
  - Open a new URL
243
249
 
250
+ **IMPORTANT**: After calling browser_navigate, you MUST call browser_get_page_state
251
+ before using browser_click or browser_type. This is because navigation changes the page,
252
+ and you need to see the new page's elements before you can interact with them.
253
+
244
254
  Provide the full URL including the protocol (https://).
245
255
 
256
+ **Correct workflow**:
257
+ 1. browser_navigate({ url: "https://www.amazon.com" })
258
+ 2. browser_get_page_state({ reason: "see elements on Amazon" })
259
+ 3. Now find the search input's [index] in the returned state
260
+ 4. browser_type({ index: <search_input_index>, text: "query", pressEnter: true })
261
+
246
262
  Example: browser_navigate({ url: "https://www.google.com" })`,
247
263
  schema: BrowserNavigateSchema,
248
264
  }
@@ -444,6 +460,47 @@ Example: browser_screenshot({ fullPage: false })`,
444
460
  );
445
461
  }
446
462
 
463
+ /**
464
+ * Browser get page state tool - gets fresh page context after navigation or actions
465
+ * CRITICAL: Use this after browser_navigate or any action that changes the page
466
+ */
467
+ export function createBrowserGetPageStateTool(): DynamicStructuredTool<typeof BrowserGetPageStateSchema> {
468
+ return tool<typeof BrowserGetPageStateSchema>(
469
+ async ({ reason }) => {
470
+ return JSON.stringify({
471
+ type: 'browser_action',
472
+ action: {
473
+ type: 'get_page_state',
474
+ reason,
475
+ },
476
+ requiresBrowserExecution: true,
477
+ // Special flag: extension should inject fresh context into the conversation
478
+ requiresContextRefresh: true,
479
+ });
480
+ },
481
+ {
482
+ name: EBrowserTools.GET_PAGE_STATE,
483
+ description: `Get fresh page state showing current interactive elements.
484
+
485
+ **CRITICAL**: You MUST call this tool after:
486
+ - browser_navigate (to see elements on the new page)
487
+ - browser_click (if it caused navigation or page changes)
488
+ - Any action that might have changed the visible elements
489
+
490
+ This tool returns the updated list of interactive elements with their [index] numbers.
491
+ Without calling this after navigation, you will NOT know what elements exist on the new page.
492
+
493
+ **Workflow example**:
494
+ 1. browser_navigate to amazon.com
495
+ 2. browser_get_page_state to see Amazon's elements
496
+ 3. Now you can see the search input's [index] and use browser_type
497
+
498
+ Example: browser_get_page_state({ reason: "to see elements after navigation" })`,
499
+ schema: BrowserGetPageStateSchema,
500
+ }
501
+ );
502
+ }
503
+
447
504
  // ============================================
448
505
  // Tool Collection
449
506
  // ============================================
@@ -467,6 +524,8 @@ export type BrowserToolsConfig = {
467
524
  enableBack?: boolean;
468
525
  /** Enable screenshot tool */
469
526
  enableScreenshot?: boolean;
527
+ /** Enable get page state tool */
528
+ enableGetPageState?: boolean;
470
529
  };
471
530
 
472
531
  /**
@@ -504,6 +563,7 @@ export function createBrowserTools(config: BrowserToolsConfig = {}): DynamicStru
504
563
  enableWait = true,
505
564
  enableBack = true,
506
565
  enableScreenshot = true,
566
+ enableGetPageState = true,
507
567
  } = config;
508
568
 
509
569
  if (enableClick) tools.push(createBrowserClickTool());
@@ -515,6 +575,7 @@ export function createBrowserTools(config: BrowserToolsConfig = {}): DynamicStru
515
575
  if (enableWait) tools.push(createBrowserWaitTool());
516
576
  if (enableBack) tools.push(createBrowserGoBackTool());
517
577
  if (enableScreenshot) tools.push(createBrowserScreenshotTool());
578
+ if (enableGetPageState) tools.push(createBrowserGetPageStateTool());
518
579
 
519
580
  return tools;
520
581
  }
@@ -533,6 +594,7 @@ export const EBrowserTools = {
533
594
  WAIT: 'browser_wait',
534
595
  BACK: 'browser_back',
535
596
  SCREENSHOT: 'browser_screenshot',
597
+ GET_PAGE_STATE: 'browser_get_page_state',
536
598
  } as const;
537
599
 
538
600
  /**
@@ -548,6 +610,7 @@ export const BROWSER_TOOL_NAMES = [
548
610
  EBrowserTools.WAIT,
549
611
  EBrowserTools.BACK,
550
612
  EBrowserTools.SCREENSHOT,
613
+ EBrowserTools.GET_PAGE_STATE,
551
614
  ] as const;
552
615
 
553
616
  export type BrowserToolName = typeof BROWSER_TOOL_NAMES[number];