const BROWSER_ACTIONS = ['navigate', 'snapshot', 'click', 'type', 'press', 'scroll', 'wait']; export function createBrowserTools({ browser } = {}) { return [{ name: 'browser', permission: 'read', description: 'The only web tool. Drive the headed Jarvis Chromium window. Not computer-use and not web_search or web_fetch; those are removed. To search, navigate to https://duckduckgo.com/?q=QUERY or https://www.google.com/search?q=QUERY, then snapshot and click a result ref. action: navigate (url, returns page text), snapshot, click (ref from the last snapshot), type (ref + text, optional submit), press (key), scroll (dy), wait (ms). Always snapshot or navigate before click or type; refs change after every action. Read the text field, then think. Cookie banners: snapshot, then click Accept by ref. If challenge is true, ask the user to finish the visible Jarvis browser window, then snapshot again. Public IP: navigate to https://ifconfig.me/ip. Private and localhost urls are blocked. Do not speak refs or JSON. Do not use curl, wget, cu_observe, or cu_click for websites.', parameters: { type: 'object', properties: { action: { type: 'string', enum: BROWSER_ACTIONS, description: 'navigate opens url. snapshot lists numbered refs. click/type need ref from that snapshot. press needs key. scroll uses dy. wait uses ms.', }, url: { type: 'string', description: 'Public http or https url for navigate.' }, ref: { type: 'string', description: 'Numbered control from the last snapshot, for click or type.' }, text: { type: 'string', description: 'Text to type into ref, or a click-by-label fallback, or wait-for text.' }, key: { type: 'string', description: 'Key or chord for press, such as Enter, Tab, Escape, Control+l.' }, selector: { type: 'string', description: 'Optional CSS selector when a snapshot ref is missing.' }, dy: { type: 'number', description: 'Vertical scroll pixels. Positive scrolls down.' }, dx: { type: 'number', description: 'Horizontal scroll pixels.' }, ms: { type: 'number', description: 'Milliseconds to wait, cap 20000.' }, submit: { type: 'boolean', description: 'After type, press Enter.' }, }, required: ['action'], }, execute: async (input = {}) => { if (!browser || typeof browser.call !== 'function') throw new Error('Jarvis browser helper unavailable'); const action = String(input.action || '').trim(); if (!action) throw new Error('action required'); const { action: _ignored, ...payload } = input; return browser.call(action, payload); }, }]; } export { BROWSER_ACTIONS };