UNPKG

crewai-ts

Version:

TypeScript port of crewAI for agent-based workflows

107 lines (106 loc) 3.9 kB
/** * WebSearchTool implementation * Provides search capabilities for agents to gather information from the web * Optimized for performance and error handling */ import { z } from 'zod'; import { createStructuredTool } from '../StructuredTool.js'; // Input schema for web search const searchInputSchema = z.object({ query: z.string().min(1, "Search query cannot be empty"), numResults: z.number().int().positive().default(5).optional(), includeUrls: z.boolean().default(true).optional(), includeDomains: z.array(z.string()).optional(), excludeDomains: z.array(z.string()).optional(), }); /** * LRU Cache implementation for search results */ class LRUCache { cache = new Map(); maxSize; expiration; // Time in milliseconds constructor(maxSize = 100, expiration = 3600000) { this.maxSize = maxSize; this.expiration = expiration; } get(key) { const item = this.cache.get(key); if (!item) return undefined; // Check if item has expired if (Date.now() - item.timestamp > this.expiration) { this.cache.delete(key); return undefined; } // Refresh item position in cache (most recently used) this.cache.delete(key); this.cache.set(key, item); return item.value; } set(key, value) { // If cache is at capacity, remove least recently used item with optimized type safety if (this.cache.size >= this.maxSize) { // Handle potential undefined value with explicit type checks for memory optimization const iterator = this.cache.keys(); const next = iterator.next(); // Verify that the iterator has a value before attempting to delete if (!next.done && next.value !== undefined) { const lruKey = next.value; this.cache.delete(lruKey); } } this.cache.set(key, { value, timestamp: Date.now() }); } clear() { this.cache.clear(); } } /** * Default search implementation with fallback strategy * This is a placeholder that would be replaced with actual API calls */ async function defaultSearch(input) { // This would be implemented with actual search API calls // For now just return a fallback result return [{ title: "Search API not configured", snippet: "Please configure a search API or provide a custom search function", position: 1 }]; } /** * Creates a web search tool with the specified configuration */ export function createWebSearchTool(options = {}) { // Configure search function const searchFunction = options.customSearchFunction || defaultSearch; // Set up caching if enabled const resultCache = options.cacheResults ? new LRUCache(100, options.cacheExpiration) : undefined; // Tool implementation const toolOptions = { name: "web_search", description: "Search the web for information on a specific topic or query", inputSchema: searchInputSchema, cacheResults: !!options.cacheResults, timeout: options.timeoutMs, maxRetries: options.maxRetries, func: async (input, runOptions) => { // Use custom cache implementation if provided if (resultCache) { const cacheKey = JSON.stringify(input); const cachedResult = resultCache.get(cacheKey); if (cachedResult) return cachedResult; const results = await searchFunction(input); resultCache.set(cacheKey, results); return results; } // Without custom cache, rely on the tool's built-in caching return await searchFunction(input); } }; return createStructuredTool(toolOptions); }