import type { ToolDef } from './provider-base.js'; import type { ToolDispatcher } from './tool-dispatcher.js'; export declare function isWebToolName(name: string): boolean; export declare function getWebTools(): ToolDef[]; export declare function buildWebDispatcher(): ToolDispatcher; interface SearchHit { title: string; url: string; snippet: string; } /** * v1.2.118 — pluggable search-provider interface. Each provider: * - `name` is the env-config token (e.g. 'tavily') * - `available()` short-circuits the chain when required keys are * missing (so a fresh agim install without TAVILY_API_KEY skips * Tavily without logging an error every search) * - `search()` returns ≥0 SearchHit; an empty array means "no hits" * and triggers fallback to the next provider, while a throw means * "transient error" and is also followed by fallback (logged at * warn). Either way, the chain continues until exhaustion. */ interface SearchProvider { name: string; available(): boolean; search(query: string, n: number, signal: AbortSignal): Promise; } /** * Read `AGIM_WEB_SEARCH_PROVIDERS` (CSV) and return the active chain. * Unknown names are dropped with a one-shot warn (so a typo doesn't * silently disable the entire chain). Providers whose `available()` * returns false are also dropped — these are NOT logged because the * common case is "key not set, skip", not a misconfig. */ export declare function resolveSearchProviderChain(): SearchProvider[]; /** * v1.2.126 — descriptor used by the SPA search settings page. Lists * every registered provider (whether in the env chain or not), with * its key-requirement flag and current availability so the operator * can see "Tavily ✓ configured / Brave ⚠ missing key" at a glance. */ export interface SearchProviderInfo { name: string; envKey: string | null; available: boolean; } /** All known providers + each provider's env requirement & current * availability. Order matches DEFAULT_PROVIDER_ORDER so the SPA can * render a stable list when no env chain is configured. */ export declare function listAllSearchProviders(): SearchProviderInfo[]; /** Look up a single provider by name. Returns null if unknown — the * caller (e.g. /api/search/test) is expected to surface that as a * 400 with the supported names. */ export declare function getSearchProviderByName(name: string): SearchProvider | null; export declare function parseBraveResults(data: unknown, max: number): SearchHit[]; export declare function parseSerperResults(data: unknown, max: number): SearchHit[]; export declare function parseExaResults(data: unknown, max: number): SearchHit[]; /** Parse Tavily's `{results: [{title, url, content, score}]}` shape. * Tolerant of missing fields: a hit needs title + url to be usable. */ export declare function parseTavilyResults(data: unknown, max: number): SearchHit[]; /** Tiny extractor for the DuckDuckGo HTML SERP. The DDG HTML page wraps * each result in `
` with `title` * + `snippet`. We don't use a DOM parser * (no dep), just regex — robust enough for SERPs (DDG is stable about * these classes). */ export declare function parseDdgHtml(html: string, max: number): SearchHit[]; /** Best-effort metaso response normaliser. Field names from metaso vary * with API version; we look at common shapes. Adjust here if metaso * changes their schema. * * As of 2026-06-01 the public POST /api/v1/search returns * `{ webpages: [{ title, link, snippet, score, position, date }], total }`. * Older endpoints used `data.list[]` / `results[]` / `items[]` — kept * for compatibility so a transparent rollback in metaso doesn't break * us. v1.2.128 hotfix: previously we missed `webpages` and parsed 0 * hits on every call, which surfaced as "测试 ✓ 0 hits" in the admin * UI's per-provider test button (#agim-issue 2026-06-01). */ export declare function parseMetasoResults(data: unknown, max: number): SearchHit[]; interface SafetyResult { ok: boolean; reason?: string; } export declare function checkUrlSafety(raw: string): SafetyResult; /** Lookup signature — injectable so tests can simulate DNS rebinding. */ export type DnsLookupAll = (host: string) => Promise>; /** * v1.3.7 (F3) — DNS-aware SSRF check. Closes CR-2: a hostname whose A/AAAA * record points at a private/link-local address (classic DNS-rebinding to * 169.254.169.254 / 10.x / ::1) was previously allowed because the sync * check only inspects IP *literals*. Here we resolve the name and run every * returned address through the same checkIpv4Safety / checkIpv6Safety used * for literals. * * Residual risk: this validates at check time, but fetch() re-resolves at * connect time, so a TTL-0 rebind between the two could still slip through * (true TOCTOU closure needs a connection-level lookup pin via a custom * undici dispatcher — a heavier follow-up). This still removes the trivial * "point your DNS at the metadata endpoint" bypass. */ export declare function checkUrlSafetyAsync(raw: string, lookupAll?: DnsLookupAll): Promise; /** * v1.2.70 — IPv4 parser that accepts every form Node's URL parser * also accepts: * - dotted quad "127.0.0.1" * - 3-part "127.1" (rare but valid per RFC 3986) * - decimal integer "2130706433" * - hex integer "0x7f000001" / "0x7f.0.0.1" * - octal "0177.0.0.1" * Returns the 4-octet form or null if the input isn't a valid IPv4 * representation. Validates each octet's range, closing CR-3 * (999.999.999.999 overflow) — any out-of-range part → null. */ export declare function tryParseIPv4Variants(host: string): [number, number, number, number] | null; /** Expand `addr` (already validated by net.isIPv6) into 8 × 16-bit * groups. Returns null only if the form somehow can't be normalized * (shouldn't happen post-net.isIPv6). */ export declare function expandIpv6(addr: string): number[] | null; interface Cidr4 { network: number; mask: number; } export declare function parseSsrfWhitelist(raw: string | undefined): Cidr4[]; export {}; //# sourceMappingURL=web-dispatcher.d.ts.map