const WEB_SEARCH_SOURCES_INCLUDE = "web_search_call.action.sources";
function hasProviderResponsesShape(payload) {
    return Boolean(payload && typeof payload === "object" && "input" in payload);
}
function hasWebSearchTool(tools) {
    return tools.some((tool) => {
        if (!tool || typeof tool !== "object")
            return false;
        const type = tool.type;
        return type === "web_search_preview" || type === "web_search";
    });
}
function isValidDomainFilter(value) {
    const domain = value.trim();
    return domain.length > 0 && !domain.includes("://") && !/[/?#\s]/.test(domain);
}
function normalizedDomainFilters(values) {
    const domains = values?.map((value) => value.trim()).filter(isValidDomainFilter) ?? [];
    return domains.length > 0 ? domains : undefined;
}
function normalizedLocation(location) {
    if (!location)
        return undefined;
    const country = location.country?.trim();
    const region = location.region?.trim();
    const city = location.city?.trim();
    const timezone = location.timezone?.trim();
    if (!country && !region && !city && !timezone)
        return undefined;
    return {
        type: "approximate",
        ...(country ? { country } : {}),
        ...(region ? { region } : {}),
        ...(city ? { city } : {}),
        ...(timezone ? { timezone } : {}),
    };
}
export function normalizeOpenAiWebSearchConfig(options) {
    const allowedDomains = normalizedDomainFilters(options?.allowedDomains);
    const blockedDomains = normalizedDomainFilters(options?.blockedDomains);
    const userLocation = normalizedLocation(options?.userLocation);
    return {
        external_web_access: options?.externalWebAccess ?? true,
        search_context_size: options?.searchContextSize ?? "medium",
        include_sources: options?.includeSources ?? true,
        ...(allowedDomains || blockedDomains
            ? {
                filters: {
                    ...(allowedDomains ? { allowed_domains: allowedDomains } : {}),
                    ...(blockedDomains ? { blocked_domains: blockedDomains } : {}),
                },
            }
            : {}),
        ...(userLocation ? { user_location: userLocation } : {}),
    };
}
function buildOpenAiWebSearchProviderTool(config) {
    const tool = {
        type: "web_search",
        external_web_access: config.external_web_access,
    };
    if (config.search_context_size)
        tool.search_context_size = config.search_context_size;
    if (config.user_location)
        tool.user_location = config.user_location;
    if (config.filters?.allowed_domains?.length || config.filters?.blocked_domains?.length) {
        tool.filters = {
            ...(config.filters.allowed_domains?.length ? { allowed_domains: config.filters.allowed_domains } : {}),
            ...(config.filters.blocked_domains?.length ? { blocked_domains: config.filters.blocked_domains } : {}),
        };
    }
    return tool;
}
function addOpenAiWebSearchSourcesInclude(payload, config) {
    if (!config.include_sources)
        return {};
    const include = Array.isArray(payload.include) ? [...payload.include] : [];
    if (!include.includes(WEB_SEARCH_SOURCES_INCLUDE))
        include.push(WEB_SEARCH_SOURCES_INCLUDE);
    return { include };
}
export function addOpenAiWebSearchProviderTool(payload, config) {
    if (!hasProviderResponsesShape(payload))
        return payload;
    const tools = Array.isArray(payload.tools) ? [...payload.tools] : [];
    if (hasWebSearchTool(tools))
        return payload;
    return {
        ...payload,
        ...addOpenAiWebSearchSourcesInclude(payload, config),
        tools: [...tools, buildOpenAiWebSearchProviderTool(config)],
    };
}
const openAiWebSearchAdapter = {
    provider: "openai",
    createExtension(options) {
        const config = normalizeOpenAiWebSearchConfig(options);
        return (pi) => {
            pi.on("before_agent_start", (event) => ({
                systemPrompt: [
                    event.systemPrompt,
                    "# Native Web Search",
                    "web_search is available as a Pibo native tool through the OpenAI provider adapter. Use it when current or externally sourced information is needed.",
                ].join("\n\n"),
            }));
            pi.on("before_provider_request", (event) => addOpenAiWebSearchProviderTool(event.payload, config));
        };
    },
};
const WEB_SEARCH_PROVIDER_ADAPTERS = {
    openai: openAiWebSearchAdapter,
};
export function getWebSearchProviderAdapter(provider) {
    return WEB_SEARCH_PROVIDER_ADAPTERS[provider];
}
export function createWebSearchProviderExtension(providerTool) {
    return getWebSearchProviderAdapter(providerTool.provider).createExtension(providerTool.options);
}
export function isWebSearchProviderTool(tool) {
    return tool.providerTool?.kind === "web_search";
}
export function createWebSearchToolProfile(options = {}) {
    return {
        name: "web_search",
        description: "Searches the web through the configured provider adapter.",
        providerTool: {
            kind: "web_search",
            provider: "openai",
            options: {
                externalWebAccess: true,
                searchContextSize: "medium",
                includeSources: true,
                ...options,
            },
        },
    };
}
