import { BaseBrowserToolExecutor } from '../base-browser'; import { createErrorResponse, createSuccessResponse } from '../../../../common/tool-handler'; import { ERROR_MESSAGES } from '../../../../common/constants'; export class EnhancedSearchTool extends BaseBrowserToolExecutor { async chromeSearchGoogle(args: { query: string; openGoogle?: boolean; extractResults?: boolean; maxResults?: number; }) { const { query, openGoogle = true, extractResults = true, maxResults = 10 } = args; try { // Step 1: Navigate to Google if requested if (openGoogle) { await this.navigateToGoogle(); await this.sleep(3000); // Wait for page to load } // Step 2: Find and fill search box const searchSuccess = await this.performGoogleSearch(query); if (!searchSuccess) { return createErrorResponse( 'Failed to perform Google search - could not find or interact with search box', ); } // Step 3: Wait for results to load await this.sleep(3000); // Step 4: Extract results if requested if (extractResults) { const results = await this.extractSearchResults(maxResults); return createSuccessResponse({ query, searchCompleted: true, resultsExtracted: true, results, }); } return createSuccessResponse({ query, searchCompleted: true, resultsExtracted: false, message: 'Google search completed successfully', }); } catch (error) { return createErrorResponse( `Error performing Google search: ${error instanceof Error ? error.message : 'Unknown error'}`, ); } } async chromeSubmitForm(args: { formSelector?: string; inputSelector?: string; submitMethod?: 'enter' | 'button' | 'auto'; }) { const { formSelector = 'form', inputSelector, submitMethod = 'auto' } = args; try { const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); if (!tabs[0]?.id) { return createErrorResponse(ERROR_MESSAGES.TAB_NOT_FOUND); } const tabId = tabs[0].id; // Inject form submission script await this.injectContentScript(tabId, ['inject-scripts/form-submit-helper.js']); const result = await this.sendMessageToTab(tabId, { action: 'submitForm', formSelector, inputSelector, submitMethod, }); if (result.error) { return createErrorResponse(result.error); } return createSuccessResponse(result); } catch (error) { return createErrorResponse( `Error submitting form: ${error instanceof Error ? error.message : 'Unknown error'}`, ); } } private async navigateToGoogle(): Promise { const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); if (!tabs[0]?.id) { throw new Error('No active tab found'); } await chrome.tabs.update(tabs[0].id, { url: 'https://www.google.com' }); } private async performGoogleSearch(query: string): Promise { const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); if (!tabs[0]?.id) { throw new Error('No active tab found'); } const tabId = tabs[0].id; // Enhanced search box selectors const searchSelectors = [ '#APjFqb', // Main Google search box ID 'textarea[name="q"]', // Google search textarea 'input[name="q"]', // Google search input (fallback) '[role="combobox"]', // Role-based selector '.gLFyf', // Google search box class 'textarea[aria-label*="Search"]', // Aria-label based '[title*="Search"]', // Title attribute '.gsfi', // Google search field input class '#lst-ib', // Alternative Google search ID 'input[type="search"]', // Generic search input 'textarea[role="combobox"]', // Textarea with combobox role ]; // Inject search helper script await this.injectContentScript(tabId, ['inject-scripts/enhanced-search-helper.js']); for (const selector of searchSelectors) { try { const result = await this.sendMessageToTab(tabId, { action: 'performGoogleSearch', selector, query, }); if (result.success) { return true; } } catch (error) { console.debug(`Search selector ${selector} failed:`, error); continue; } } return false; } private async extractSearchResults(maxResults: number): Promise { const tabs = await chrome.tabs.query({ active: true, currentWindow: true }); if (!tabs[0]?.id) { throw new Error('No active tab found'); } const tabId = tabs[0].id; const result = await this.sendMessageToTab(tabId, { action: 'extractSearchResults', maxResults, }); return result.results || []; } private sleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } } // Export tool instances export const searchGoogleTool = new (class extends EnhancedSearchTool { name = 'chrome_search_google'; async execute(args: any) { return await this.chromeSearchGoogle(args); } })(); export const submitFormTool = new (class extends EnhancedSearchTool { name = 'chrome_submit_form'; async execute(args: any) { return await this.chromeSubmitForm(args); } })();