UNPKG

browser-use-typescript

Version:

A TypeScript-based browser automation framework

199 lines 8.04 kB
/** * TypeScript implementation of the Registry service */ import { ActionModel, ActionRegistry, } from './types'; import { ActionResult } from "../../agent/types"; /** * Registry for browser actions * Manages the registration and execution of browser actions */ export class Registry { registry; excludeActions; /** * Create a new Registry * @param excludeActions List of action names to exclude from registration */ constructor(excludeActions = []) { this.registry = new ActionRegistry(); this.excludeActions = excludeActions; } /** * Creates a parameter model from a function * Similar to Pydantic's create_model in Python * @param func Function to create a model from * @returns A constructor function for creating parameter objects */ /** * Creates an action model with specified actions to include/exclude * @param options Options for creating the action model * @returns An action model constructor */ create_action_model(options) { const { include_actions } = options; const actions = []; // Filter actions based on include/exclude lists for (const name in this.registry.actions) { if (include_actions && !include_actions.includes(name)) { continue; } actions.push(this.registry.actions[name]); } // Create schema and descriptions objects const schemas = {}; const descriptions = {}; // Populate both objects from the registered actions actions.forEach(action => { schemas[action.name] = action.paramModel; descriptions[action.name] = action.description; }); // Create ActionModel with both schemas and descriptions return new ActionModel(schemas, undefined, descriptions); } /** * Register an action with the registry * @param description Description of the action * @param paramModel Model for the action parameters * @returns Decorator function that registers the action */ registerAction(name, description, paramModel, func) { // Register the action with its description and parameter model const action = { name, description, function: func, paramModel, promptDescription: () => `${name}: ${description}` }; // Assume we have an action registry to store actions this.registry.actions[name] = action; } _replaceSensitiveData(params, sensitiveData) { if (!params || !sensitiveData) { return params; } const processValue = (value) => { if (typeof value === 'string') { // Replace <secret>placeholder</secret> with actual sensitive data return value.replace(/<secret>(.*?)<\/secret>/g, (_, placeholder) => { return sensitiveData[placeholder] || placeholder; }); } else if (Array.isArray(value)) { return value.map(processValue); } else if (value && typeof value === 'object') { return this._replaceSensitiveData(value, sensitiveData); } return value; }; const result = { ...params }; for (const key in result) { result[key] = processValue(result[key]); } return result; } /** * Execute an action by name with parameters * @param actionName Name of the action to execute * @param params Parameters for the action * @param context Context for the action * @param sensitiveData Optional sensitive data to replace in parameters * @param pageExtractionLlm Optional LLM for page extraction * @returns Result of the action */ async executeAction(actionName, params, context, sensitiveData) { // Check if action exists if (!(actionName in this.registry.actions)) { return new ActionResult({ error: `Action ${actionName} not found in registry`, success: false }); } const action = this.registry.actions[actionName]; try { // Process sensitive data if provided const processedParams = sensitiveData ? this._replaceSensitiveData(params, sensitiveData) : params; // Create a combined object with all parameters const allParams = { ...processedParams }; // Add context-specific parameters if available try { if (context) { // Instead of inspecting the function arguments directly (which triggers strict mode errors), // we'll just conditionally add context properties if they exist if (context.browser) allParams.browser = context.browser; if (context.pageExtractionLlm) allParams.pageExtractionLlm = context.pageExtractionLlm; if (context.sensitiveData) allParams.sensitiveData = context.sensitiveData; if (context.availableFilePaths) allParams.availableFilePaths = context.availableFilePaths; } } catch (error) { return new ActionResult({ error: `Error preparing parameters for action ${actionName}: ${error}`, success: false }); } // Call the function with appropriate parameters based on function signature try { // Check function parameter count to determine how to pass arguments if (action.function.length === 1) { // Function expects just params (where browser will be extracted from context) return await action.function(allParams); } else if (action.function.length === 2) { // Function expects params and browser as separate arguments return await action.function(allParams, context.browser); } else if (action.function.length === 3) { // Function expects params, browser, and pageExtractionLlm return await action.function(allParams, context.browser, context.pageExtractionLlm); } else { console.warn(`Function ${actionName} has unexpected parameter count: ${action.function.length}`); // Default to passing all possible parameters return await action.function(allParams, context.browser, context.pageExtractionLlm); } } catch (error) { console.error(`Error executing action ${actionName}:`, error); return new ActionResult({ error: `Error executing action ${actionName}: ${error}`, success: false }); } } catch (error) { return new ActionResult({ error: `Error executing action ${actionName}: ${error}`, success: false }); } } /** * Get a description of all registered actions for the prompt * @returns Description of all actions */ getPromptDescription() { return this.registry.getPromptDescription(); } /** * Get all registered actions * @returns Map of action names to registered actions */ getActions() { return this.registry.actions; } /** * Check if an action is registered * @param actionName Name of the action to check * @returns True if the action is registered */ hasAction(actionName) { return actionName in this.registry.actions; } } //# sourceMappingURL=service.js.map