import type { AdapterContext, WebFetchProvider, WebSearchProvider } from "@rakazo/adapter-kit"; import { clampMaxChars, clampMaxResults, MAX_WEB_FETCH_URLS } from "./web-limits.js"; import { normalizeSearchCategory, normalizeSearchDomains, resolveSearchQueries, } from "./web-research.js"; export async function webSearchFromTool( search: WebSearchProvider, context: AdapterContext, args: Record, ) { const rawQuery = typeof args.query === "string" ? args.query.trim() : ""; const rawQueries = Array.isArray(args.queries) ? args.queries.filter((q): q is string => typeof q === "string" && q.trim().length > 0) : undefined; const queries = resolveSearchQueries({ query: rawQuery, queries: rawQueries, }); if (queries.length === 0) return { error: "query is required" }; const category = normalizeSearchCategory(args.category); const domains = normalizeSearchDomains(args.domains); try { const results = await search.search( { query: rawQuery || queries[0]!, ...(rawQueries && rawQueries.length > 0 ? { queries } : {}), ...(category ? { category } : {}), ...(domains ? { domains } : {}), maxResults: clampMaxResults(args.maxResults), signal: context.signal, }, context, ); return { results }; } catch (error) { return { error: error instanceof Error ? error.message : String(error) }; } } export async function webFetchFromTool( fetchProvider: WebFetchProvider, context: AdapterContext, args: Record, ) { const singleUrl = typeof args.url === "string" ? args.url.trim() : ""; const batchUrls = Array.isArray(args.urls) ? args.urls .filter((u): u is string => typeof u === "string") .map((u) => u.trim()) .filter((u) => u.length > 0) .slice(0, MAX_WEB_FETCH_URLS) : undefined; const query = typeof args.query === "string" && args.query.trim() ? args.query.trim() : undefined; const maxChars = clampMaxChars(args.maxChars); if (batchUrls && batchUrls.length > 0) { const uniqueUrls = [...new Set(singleUrl ? [singleUrl, ...batchUrls] : batchUrls)].slice( 0, MAX_WEB_FETCH_URLS, ); const pages = await Promise.all( uniqueUrls.map(async (targetUrl) => { try { return await fetchProvider.fetch( { url: targetUrl, ...(query ? { query } : {}), maxChars, signal: context.signal, }, context, ); } catch (error) { return { url: targetUrl, error: error instanceof Error ? error.message : String(error), }; } }), ); return { pages }; } if (!singleUrl) return { error: "url is required" }; try { const result = await fetchProvider.fetch( { url: singleUrl, ...(query ? { query } : {}), maxChars, signal: context.signal, }, context, ); return result; } catch (error) { return { error: error instanceof Error ? error.message : String(error) }; } }