"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const registry_1 = require("./registry"); /** * Web search via DuckDuckGo HTML endpoint. * No API key required. Scrapes result snippets and titles. * Atlas uses this for competitor research, market context, pricing models, etc. */ (0, registry_1.registerTool)({ name: 'web_search', description: 'Search the web for current information. Use this to research competitors, market trends, pricing models, existing solutions, technology choices, or any topic the user mentions that would benefit from real-world context. Returns a summary of top search results.', parameters: { type: 'object', properties: { query: { type: 'string', description: 'The search query. Be specific — e.g. "SaaS project management tools pricing 2024" rather than just "project management".' } }, required: ['query'] }, async handler(args) { const query = String(args.query).trim(); if (!query) return { error: 'No query provided' }; const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`; try { const res = await fetch(url, { headers: { 'User-Agent': 'Mozilla/5.0 (compatible; VIBN-Atlas/1.0)', 'Accept': 'text/html', }, signal: AbortSignal.timeout(15000), }); if (!res.ok) { return { error: `Search failed with status ${res.status}` }; } const html = await res.text(); // Extract result titles and snippets from DuckDuckGo HTML const results = []; // Match result titles const titleMatches = html.matchAll(/class="result__a"[^>]*href="[^"]*"[^>]*>(.*?)<\/a>/gs); const titles = []; for (const m of titleMatches) { const title = m[1].replace(/<[^>]+>/g, '').trim(); if (title) titles.push(title); } // Match result snippets const snippetMatches = html.matchAll(/class="result__snippet"[^>]*>(.*?)<\/a>/gs); const snippets = []; for (const m of snippetMatches) { const snippet = m[1].replace(/<[^>]+>/g, '').trim(); if (snippet) snippets.push(snippet); } // Combine up to 6 results const count = Math.min(6, Math.max(titles.length, snippets.length)); for (let i = 0; i < count; i++) { const title = titles[i] || ''; const snippet = snippets[i] || ''; if (title || snippet) { results.push(`**${title}**\n${snippet}`); } } if (results.length === 0) { return { error: 'No results found' }; } const text = results.join('\n\n'); const truncated = text.length > 5000 ? text.slice(0, 5000) + '\n\n[...results truncated]' : text; return { query, results: truncated }; } catch (err) { const message = err instanceof Error ? err.message : String(err); return { error: `Search request failed: ${message}` }; } } });