/**
 * Web crawl tool -- fetch and extract content from a specific URL using Exa API.
 *
 * Lives behind the meta-tool wall (get_tool_info + execute_tool).
 * Never appears in the system prompt directly.
 *
 * Uses Exa API for clean text extraction (strips ads/nav/scripts) and
 * can render JavaScript-heavy pages. If content is incomplete or raw
 * HTML is needed, the agent can fall back to curl/wget via bash.
 */
import { Type } from '@sinclair/typebox';
import { SHORTCUT_PROVIDER_ID } from '../../model-ids.js';
import { WEB_CRAWL } from '../../tool-names.js';
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const EXA_CONTENTS_API_URL = 'https://api.exa.ai/contents';
const TIMEOUT_MS = 30_000;
const TOOL_DESCRIPTION = `\
Fetch content from a specific URL. Use when the user provides a direct link.

Uses Exa API for clean text extraction (strips ads/nav/scripts) and can render JavaScript-heavy pages. If content is incomplete or you need raw HTML, fall back to curl/wget via bash.

IMPORTANT: Only use this tool when a specific URL is provided. For general searches or finding URLs, use web_search instead.`;
// ---------------------------------------------------------------------------
// Schema
// ---------------------------------------------------------------------------
const schema = Type.Object({
    description: Type.String({
        description: "A short one-sentence summary starting with 'Fetching content from...'",
        minLength: 1
    }),
    url: Type.String({
        description: 'The URL to crawl. Must include protocol (http:// or https://)',
        minLength: 1
    }),
    query: Type.Optional(Type.String({
        description: 'Optional query for highlighting relevant content'
    }))
});
const defaultOperations = {
    fetch: globalThis.fetch.bind(globalThis)
};
// ---------------------------------------------------------------------------
// Factory
// ---------------------------------------------------------------------------
export function createWebCrawlTool(options) {
    const ops = options?.operations ?? defaultOperations;
    return {
        name: WEB_CRAWL,
        label: 'Web Crawl',
        description: TOOL_DESCRIPTION,
        parameters: schema,
        async execute(_toolCallId, { description: _description, url, query }, signal, _onUpdate, ctx) {
            // Validate URL protocol
            if (!url.startsWith('http://') && !url.startsWith('https://')) {
                return {
                    content: [{ type: 'text', text: 'Error: URL must start with http:// or https://' }],
                    details: { url, title: '' }
                };
            }
            // Resolve API key -- Exa API key is fetched from the Shortcut provider
            // (the proxy backend stores the EXA_API_KEY and exposes it via the auth layer)
            const extCtx = ctx;
            const apiKey = extCtx?.modelRegistry
                ? await extCtx.modelRegistry.getApiKeyForProvider(SHORTCUT_PROVIDER_ID)
                : undefined;
            // Also check for a direct EXA_API_KEY env var as fallback
            const exaApiKey = process.env.EXA_API_KEY ?? apiKey;
            if (!exaApiKey) {
                throw new Error('Not authenticated. Please log in first (or set EXA_API_KEY).');
            }
            // Build request payload
            const payload = { urls: [url], text: true };
            if (query) {
                payload.highlights = { query };
            }
            // Make request to Exa API
            let response;
            try {
                response = await ops.fetch(EXA_CONTENTS_API_URL, {
                    method: 'POST',
                    headers: {
                        'x-api-key': exaApiKey,
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(payload),
                    signal: signal
                        ? AbortSignal.any([signal, AbortSignal.timeout(TIMEOUT_MS)])
                        : AbortSignal.timeout(TIMEOUT_MS)
                });
            }
            catch (e) {
                const msg = e instanceof Error ? e.message : String(e);
                throw new Error(`Web crawl failed to connect: ${msg}`);
            }
            if (!response.ok) {
                const raw = await response.text();
                const text = raw.split('\n').slice(0, 10).join('\n');
                throw new Error(`Exa API error ${response.status}: ${text}`);
            }
            // Parse response
            let data;
            try {
                data = (await response.json());
            }
            catch {
                throw new Error('Exa API returned invalid JSON');
            }
            const results = data.results ?? [];
            if (results.length === 0) {
                return {
                    content: [{ type: 'text', text: `No content returned for URL: ${url}` }],
                    details: { url, title: '' }
                };
            }
            const result = results[0];
            const title = result.title ?? 'Untitled';
            const text = result.text ?? '';
            const formattedContent = `# ${title}\n\nURL: ${result.url ?? url}\n\n${text}`;
            return {
                content: [{ type: 'text', text: formattedContent }],
                details: { url: result.url ?? url, title }
            };
        }
    };
}
//# sourceMappingURL=web-crawl.js.map