import { SearchProviderRegistry } from "./search/registry.js";
import { resolveWebSearchConfig } from "./search/resolve-config.js";
import { checkUrlSafety, checkWebsiteBlocklist } from "./url-safety.js";
import { Type } from "@sinclair/typebox";
//#region src/agent/tools/web.ts
const WebSearchSchema = Type.Object({
	query: Type.String({ description: "The search query" }),
	count: Type.Optional(Type.Number({ description: "Number of results (default: from config, usually 5)" }))
});
function formatSearchResults(results) {
	return results.map((r, i) => `${i + 1}. ${r.title}\n   ${r.url}\n   ${r.description ? `${r.description}` : ""}`).join("\n\n");
}
function createWebSearchTool(getConfig) {
	return {
		name: "web_search",
		description: "Search the web. Uses configured search APIs when set; otherwise falls back to a built-in HTML search (region-aware).",
		parameters: WebSearchSchema,
		label: "🔍 Web Search",
		async execute(_toolCallId, params, signal) {
			const p = params;
			const cfg = resolveWebSearchConfig(getConfig()?.tools?.web);
			const registry = new SearchProviderRegistry(cfg);
			const count = p.count ?? cfg.maxResults ?? 5;
			try {
				const { results, provider } = await registry.search(p.query, count, signal);
				if (results.length === 0) return {
					content: [{
						type: "text",
						text: "No results found."
					}],
					details: {
						results: [],
						provider
					}
				};
				return {
					content: [{
						type: "text",
						text: formatSearchResults(results)
					}],
					details: {
						results,
						provider
					}
				};
			} catch (error) {
				return {
					content: [{
						type: "text",
						text: `Search error: ${error instanceof Error ? error.message : String(error)}`
					}],
					details: { results: [] }
				};
			}
		}
	};
}
const MAX_FETCH_CHARS = 6e6;
const WebFetchSchema = Type.Object({
	url: Type.String({ description: "The URL to fetch" }),
	maxChars: Type.Optional(Type.Number({ description: "Maximum characters to return (default: 10000)" }))
});
function stripHtmlFallback(html) {
	return html.replace(/<script[^\u003e]*\u003e[\s\S]*?\u003c\/script\u003e/gi, "").replace(/<style[^\u003e]*\u003e[\s\S]*?\u003c\/style\u003e/gi, "").replace(/\u003c[^\u003e]+\u003e/g, " ").replace(/\n\s*\n+/g, "\n").replace(/\s+/g, " ").trim();
}
async function extractReadableText(html, pageUrl) {
	const { JSDOM } = await import("jsdom");
	const { Readability } = await import("@mozilla/readability");
	return new Readability(new JSDOM(html, { url: pageUrl }).window.document).parse()?.textContent?.trim() ?? "";
}
function createWebFetchTool(getConfig) {
	return {
		name: "web_fetch",
		description: "Fetch and extract readable content from a URL (HTML via Readability; plain text as-is).",
		parameters: WebFetchSchema,
		label: "🌐 Web Fetch",
		async execute(_toolCallId, params, signal) {
			try {
				const p = params;
				const safety = checkUrlSafety(p.url);
				if (!safety.safe) return {
					content: [{
						type: "text",
						text: `Blocked: ${safety.reason}`
					}],
					details: {}
				};
				const blocked = checkWebsiteBlocklist(p.url, getConfig()?.tools?.web?.blocklist);
				if (blocked) return {
					content: [{
						type: "text",
						text: `Blocked: ${blocked.message}`
					}],
					details: {}
				};
				const response = await fetch(p.url, { signal });
				if (!response.ok) throw new Error(`HTTP ${response.status}`);
				const html = await response.text();
				if (html.length > MAX_FETCH_CHARS) throw new Error("Response too large");
				const maxChars = p.maxChars || 1e4;
				const contentType = response.headers.get("content-type") ?? "";
				const looksHtml = /html|xml/i.test(contentType) || /^[\s\n]*</.test(html.slice(0, Math.min(500, html.length)));
				let text;
				if (looksHtml) try {
					text = await extractReadableText(html, p.url);
					if (!text || text.length < 40) text = stripHtmlFallback(html);
				} catch {
					text = stripHtmlFallback(html);
				}
				else text = html.trim();
				if (text.length > maxChars) text = text.substring(0, maxChars) + "\n\n[truncated...]";
				return {
					content: [{
						type: "text",
						text
					}],
					details: {}
				};
			} catch (error) {
				return {
					content: [{
						type: "text",
						text: `Fetch error: ${error instanceof Error ? error.message : String(error)}`
					}],
					details: {}
				};
			}
		}
	};
}
//#endregion
export { createWebFetchTool, createWebSearchTool };

//# sourceMappingURL=web.js.map