/*
 * 文件定位：Agent 模型适配层 / Provider 接入层 / Provider Caller。
 * 核心目的：把 actualInvocationLayer 的 request envelope 安全地转成真实 transport 调用。
 * 能力要求1：通过闭包接收 private auth material，公共 request/result 只保留 redacted 形态。
 * 能力要求2：支持 timeout、abort、status/header/body 分离和 provider 错误分类。
 * 能力要求3：可适配现有 OpenAI endpoint 的 injected caller 形状。
 * 边界：不创建 PromptPack，不选择模型，不读取 credential source。
 * 对接：actualInvocationLayer 在 dryRun:false 时调用 providerCaller；live smoke 通过它替代直接 fetch。
 * 实现提示：transport 收到 raw headers，但 providerCaller 返回值必须先 redacted。
 */
import { redactHeaders, redactSecretRecord } from "../authProfileLayer/secretRedaction.js";
import { classifyProviderAccessError } from "./providerErrorClassifier.js";
function mergeHeaders(requestHeaders, authHeaders) {
    return {
        ...(requestHeaders ?? {}),
        ...(authHeaders ?? {}),
    };
}
function providerErrorSummary(body) {
    if (typeof body === "string") {
        return body.trim().slice(0, 500) || undefined;
    }
    if (body !== null && typeof body === "object" && !Array.isArray(body)) {
        const record = body;
        const error = record.error;
        if (error !== null && typeof error === "object" && !Array.isArray(error)) {
            const message = error.message;
            if (typeof message === "string" && message.trim().length > 0) {
                return message.trim().slice(0, 500);
            }
        }
        const message = record.message;
        if (typeof message === "string" && message.trim().length > 0) {
            return message.trim().slice(0, 500);
        }
    }
    return undefined;
}
function assertSuccess(response) {
    if (response.status >= 400) {
        throw {
            status: response.status,
            code: "provider_http_error",
            providerMessage: providerErrorSummary(response.body),
        };
    }
}
export function createProviderCaller(input) {
    return async (request) => {
        try {
            const response = await input.transport({
                method: request.method,
                url: request.url,
                headers: mergeHeaders(request.headers, input.authMaterial?.headers),
                query: {
                    ...(request.query ?? {}),
                    ...(input.authMaterial?.query ?? {}),
                },
                body: request.body,
                timeoutMs: input.timeoutMs,
                signal: input.signal,
            });
            assertSuccess(response);
            return {
                status: response.status,
                headers: redactHeaders(response.headers),
                body: redactSecretRecord(response.body),
                providerRawShapePromoted: false,
                publicSafe: true,
            };
        }
        catch (error) {
            throw classifyProviderAccessError(error);
        }
    };
}
export function unwrapProviderCallerBody(response) {
    if (response !== null &&
        typeof response === "object" &&
        !Array.isArray(response) &&
        "body" in response &&
        "providerRawShapePromoted" in response) {
        return response.body;
    }
    return response;
}
export function providerCallerErrorCode(error) {
    return classifyProviderAccessError(error).code;
}
