/**
 * Per-tool contract for `web_crawl` — host-mediated server call.
 * No citations; the renderer reads markdown content + `params.url` only.
 */
import { Type } from '@sinclair/typebox';
import { HostToolResultStatus, buildRendererArtifact } from '../../../contracts/host-tool.js';
import { withAbort } from '../../../utils/abort.js';
import { WEB_CRAWL } from '../tool-names.js';
export const WEB_CRAWL_KIND = 'webCrawl';
/** Listing one-liner used by `get_tool_info`. */
export const WEB_CRAWL_TOOL_SUMMARY = 'Fetch and extract content from a specific URL (fall back to bash curl if unsatisfactory)';
export const WEB_CRAWL_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.`;
export const WEB_CRAWL_DESCRIPTION_DESCRIPTION = "A short one-sentence summary starting with 'Fetching content from...'";
export const WEB_CRAWL_URL_DESCRIPTION = 'The URL to crawl. Must include protocol (http:// or https://)';
export const WEB_CRAWL_QUERY_DESCRIPTION = 'Optional query for highlighting relevant content';
const webCrawlLlmSchema = Type.Object({
    description: Type.String({
        description: WEB_CRAWL_DESCRIPTION_DESCRIPTION,
        minLength: 1
    }),
    url: Type.String({
        description: WEB_CRAWL_URL_DESCRIPTION,
        minLength: 1
    }),
    query: Type.Optional(Type.String({
        description: WEB_CRAWL_QUERY_DESCRIPTION
    }))
});
function validateParams(value) {
    if (!value || typeof value !== 'object')
        return false;
    const candidate = value;
    return (typeof candidate.description === 'string' &&
        typeof candidate.url === 'string' &&
        (candidate.query === undefined || typeof candidate.query === 'string'));
}
function validateResultDetails(value) {
    if (value === undefined)
        return true;
    if (!value || typeof value !== 'object')
        return false;
    const candidate = value;
    return ((candidate.url === undefined || typeof candidate.url === 'string') &&
        (candidate.title === undefined || typeof candidate.title === 'string') &&
        (candidate.text === undefined || typeof candidate.text === 'string'));
}
function normalizeResultDetails(value) {
    return value === undefined ? undefined : { ...value };
}
function getResultObservabilityFields(details) {
    if (!validateResultDetails(details) || details === undefined)
        return undefined;
    return {
        has_title: typeof details.title === 'string' && details.title.length > 0,
        has_text: typeof details.text === 'string' && details.text.length > 0
    };
}
function evaluateApproval() {
    return { required: false };
}
function formatResult(details, isError, userMessage) {
    const trimmed = details?.text?.trim();
    const cleanError = userMessage?.trim();
    const text = trimmed && trimmed.length > 0
        ? trimmed
        : cleanError && cleanError.length > 0
            ? cleanError
            : isError
                ? 'Web crawl failed.'
                : 'No content returned.';
    return {
        content: [{ type: 'text', text }],
        details: buildRendererArtifact(details, userMessage),
        isError
    };
}
function createLlmTool(options) {
    return {
        name: WEB_CRAWL,
        label: 'Web Crawl',
        isReadOnly: true,
        description: WEB_CRAWL_TOOL_DESCRIPTION,
        parameters: webCrawlLlmSchema,
        async execute(toolCallId, llmArgs, signal) {
            const args = llmArgs;
            const params = {
                description: args.description,
                url: args.url,
                ...(args.query !== undefined ? { query: args.query } : {})
            };
            void options.sessionPolicy;
            const request = {
                approval: evaluateApproval(),
                heartbeat: {
                    label: 'Fetching web page...',
                    toolName: WEB_CRAWL
                },
                kind: WEB_CRAWL_KIND,
                params,
                requestId: toolCallId
            };
            const result = await withAbort(signal, async () => options.pendingHostToolRequests.request(request));
            const details = result.details;
            const isError = result.status === HostToolResultStatus.Failed ||
                result.status === HostToolResultStatus.Cancelled;
            return formatResult(details, isError, result.userMessage);
        }
    };
}
export const webCrawlContract = {
    kind: WEB_CRAWL_KIND,
    createLlmTool,
    evaluateApproval,
    getResultObservabilityFields,
    validateParams,
    validateResultDetails,
    normalizeResultDetails
};
//# sourceMappingURL=contract.js.map