var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
    if (typeof path === "string" && /^\.\.?\//.test(path)) {
        return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
            return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
        });
    }
    return path;
};
import OpenAI, { APIError } from "openai";
import { createAssistantMessageEventStream, lazyApi, } from "@earendil-works/pi-ai";
import { shouldUseGpt56CodeMode } from "../adapter/activation/activation.js";
import { buildRequestBody } from "./openai-codex/request-body.js";
import { isResponsesLiteRequest, prepareResponsesLiteRequestImages, RESPONSES_LITE_HEADER } from "./openai-codex/responses-lite.js";
import { processCodexResponsesStream } from "./openai-codex/stream-events.js";
const BRIDGE_PROVIDER = "@howaboua/pi-codex-conversion:responses-proxy";
const OPENAI_RESPONSES_API_MODULE = "@earendil-works/pi-ai/api/openai-responses";
const standardResponsesStream = lazyApi(async () => await import(__rewriteRelativeImportExtension(OPENAI_RESPONSES_API_MODULE))).streamSimple;
function initialAssistantMessage(model) {
    return {
        role: "assistant",
        content: [],
        api: model.api,
        provider: model.provider,
        model: model.id,
        usage: {
            input: 0,
            output: 0,
            cacheRead: 0,
            cacheWrite: 0,
            totalTokens: 0,
            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
        },
        stopReason: "stop",
        timestamp: Date.now(),
    };
}
function mergeHeaders(...groups) {
    const headers = new Map();
    for (const group of groups) {
        for (const [name, value] of Object.entries(group ?? {})) {
            headers.set(name.toLowerCase(), { name, value });
        }
    }
    return Object.fromEntries([...headers.values()].map(({ name, value }) => [name, value]));
}
function hasHeader(headers, name) {
    const expected = name.toLowerCase();
    return Object.entries(headers ?? {}).some(([key, value]) => key.toLowerCase() === expected && value !== null && value.trim() !== "");
}
function clientAuth(provider, apiKey, headers) {
    if (apiKey)
        return { apiKey, headers };
    if (hasHeader(headers, "authorization"))
        return { apiKey: "unused", headers };
    if (hasHeader(headers, "cf-aig-authorization")) {
        return { apiKey: "unused", headers: mergeHeaders(headers, { Authorization: null }) };
    }
    throw new Error(`No API key for provider: ${provider}`);
}
async function reportErrorResponse(error, options, model) {
    if (!(error instanceof APIError) || error.status === undefined || !error.headers)
        return;
    await options?.onResponse?.({
        status: error.status,
        headers: Object.fromEntries(error.headers.entries()),
    }, model);
}
export function streamCodeModeResponsesProxy(model, context, options) {
    const stream = createAssistantMessageEventStream();
    const output = initialAssistantMessage(model);
    void (async () => {
        try {
            let headers = mergeHeaders(model.headers, options?.headers);
            let body = buildRequestBody(model, context, options);
            const rewritten = await options?.onPayload?.(body, model);
            if (rewritten !== undefined)
                body = rewritten;
            headers = mergeHeaders(headers, { [RESPONSES_LITE_HEADER]: null });
            if (isResponsesLiteRequest(body)) {
                body = await prepareResponsesLiteRequestImages(body);
                headers = mergeHeaders(headers, { [RESPONSES_LITE_HEADER]: "true" });
            }
            const auth = clientAuth(model.provider, options?.apiKey, headers);
            const client = new OpenAI({
                apiKey: auth.apiKey,
                baseURL: model.baseUrl,
                defaultHeaders: auth.headers,
            });
            let response;
            try {
                response = await client.responses.create(body, {
                    ...(options?.signal ? { signal: options.signal } : {}),
                    ...(options?.timeoutMs !== undefined ? { timeout: options.timeoutMs } : {}),
                    maxRetries: options?.maxRetries ?? 0,
                }).withResponse();
            }
            catch (error) {
                await reportErrorResponse(error, options, model);
                throw error;
            }
            await options?.onResponse?.({
                status: response.response.status,
                headers: Object.fromEntries(response.response.headers.entries()),
            }, model);
            stream.push({ type: "start", partial: output });
            await processCodexResponsesStream(response.data, output, stream, model, options);
            if (options?.signal?.aborted)
                throw new Error("Request was aborted");
            if (output.stopReason === "aborted" || output.stopReason === "error") {
                throw new Error("Responses stream ended without a successful result");
            }
            stream.push({ type: "done", reason: output.stopReason, message: output });
            stream.end();
        }
        catch (error) {
            for (const block of output.content) {
                if (typeof block === "object" && block !== null)
                    delete block.partialJson;
            }
            output.stopReason = options?.signal?.aborted ? "aborted" : "error";
            output.errorMessage = error instanceof Error ? error.message : String(error);
            stream.push({ type: "error", reason: output.stopReason, error: output });
            stream.end();
        }
    })();
    return stream;
}
export function registerCodeModeProxyProvider(pi, getConfig) {
    let registered = false;
    const shutdown = () => {
        if (!registered)
            return;
        pi.unregisterProvider(BRIDGE_PROVIDER);
        registered = false;
    };
    const applyConfig = (config) => {
        const needed = config.beta.codeMode && config.scope.additionalProviders.some((provider) => {
            const normalized = provider.trim().toLowerCase();
            return normalized !== "" && normalized !== "openai-codex";
        });
        if (needed === registered)
            return;
        if (!needed) {
            shutdown();
            return;
        }
        pi.registerProvider(BRIDGE_PROVIDER, {
            api: "openai-responses",
            streamSimple: (model, context, options) => shouldUseGpt56CodeMode({ model }, getConfig())
                ? streamCodeModeResponsesProxy(model, context, options)
                : standardResponsesStream(model, context, options),
        });
        registered = true;
    };
    return { applyConfig, shutdown };
}
