/**
 * OTel SDK initialization for external agents.
 *
 * Phase 2 — sprint-564 hotfix
 *
 * initVaubanSDK() now instantiates a BasicTracerProvider with an OTLP HTTP
 * exporter and a BatchSpanProcessor. No host-side OTel setup is required.
 * The collectorUrl defaults to the Alloy gateway that fans out to Tempo,
 * Langfuse, and CC ingest.
 *
 * @see https://opentelemetry.io/docs/languages/js/instrumentation/
 */
import { trace } from "@opentelemetry/api";
import { BasicTracerProvider, BatchSpanProcessor, ConsoleSpanExporter, } from "@opentelemetry/sdk-trace-base";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { resourceFromAttributes } from "@opentelemetry/resources";
import { registerW3CPropagator } from "./trace-context.js";
import { GEN_AI_AGENT_ID } from "./attributes.js";
export function createOtelClient(opts) {
    const base = opts.baseUrl.replace(/\/$/, "");
    return {
        async ingestSpans(spans, ingestOpts) {
            const token = await opts.getToken();
            const headers = {
                "Content-Type": "application/json",
                Authorization: `Bearer ${token}`,
            };
            if (ingestOpts?.origin)
                headers["X-Origin"] = ingestOpts.origin;
            const response = await fetch(`${base}/api/otel/ingest`, {
                method: "POST",
                headers,
                body: JSON.stringify(spans),
            });
            if (!response.ok) {
                let message = `HTTP ${response.status}`;
                try {
                    const body = (await response.json());
                    message = body.error ?? body.message ?? message;
                }
                catch {
                    /* ignore */
                }
                throw new Error(`OtelClient.ingestSpans: ${message}`);
            }
            return response.json();
        },
    };
}
let _sdkProvider = null;
/**
 * Initialize the Vauban OTel SDK. Call once at process startup.
 *
 * Instantiates a BasicTracerProvider with an OTLP HTTP exporter on the
 * configured collector endpoint, registers process-level resource attributes,
 * and installs a shutdown hook. No host-side OTel setup is required.
 *
 * Returns the tracer provider for introspection.
 */
export function initVaubanSDK(opts) {
    const collectorUrl = opts.collectorUrl ?? "http://alloy.observability.svc.cluster.local:4318";
    const resource = resourceFromAttributes({
        "service.name": opts.agentId,
        "service.version": opts.agentVersion,
        [GEN_AI_AGENT_ID]: opts.agentId,
        "vauban.org.id": opts.orgId,
    });
    // OTLP HTTP exporter
    const otlpExporter = new OTLPTraceExporter({
        url: `${collectorUrl.replace(/\/$/, "")}/v1/traces`,
        headers: { Authorization: `Bearer ${opts.apiKey}` },
    });
    const spanProcessors = [new BatchSpanProcessor(otlpExporter)];
    if (opts.debug) {
        spanProcessors.push(new BatchSpanProcessor(new ConsoleSpanExporter()));
    }
    const provider = new BasicTracerProvider({ resource, spanProcessors });
    trace.setGlobalTracerProvider(provider);
    // Register W3C Trace Context propagator so traceparent/tracestate headers
    // are injected/extracted automatically on delegation boundaries.
    registerW3CPropagator();
    // Graceful shutdown
    const shutdown = () => {
        provider.forceFlush().finally(() => provider.shutdown());
    };
    process.on("SIGTERM", shutdown);
    process.on("SIGINT", shutdown);
    _sdkProvider = provider;
    console.log(`[vauban-sdk] OTel enabled → ${collectorUrl} | agent=${opts.agentId} v${opts.agentVersion}`);
    // ── Auto-registration (fire-and-forget) ─────────────────────────────────
    if (opts.registryUrl) {
        const registryUrl = opts.registryUrl.replace(/\/$/, "");
        _registryBaseUrl = registryUrl;
        _apiKey = opts.apiKey;
        fetch(`${registryUrl}/api/registry/agents`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${opts.apiKey}`,
            },
            body: JSON.stringify({
                agentId: opts.agentId,
                orgId: opts.orgId,
                name: opts.agentName ?? opts.agentId,
                version: opts.agentVersion,
                capabilities: opts.capabilities ?? [],
                repoUrl: opts.repoUrl,
                sdkVersion: "0.14.3",
                metadata: { collectorUrl },
            }),
        })
            .then((res) => {
            if (res.ok) {
                console.log(`[vauban-sdk] agent registered → ${registryUrl}`);
            }
            else {
                console.warn(`[vauban-sdk] registry returned ${res.status} — agent not registered`);
            }
        })
            .catch((err) => {
            console.warn(`[vauban-sdk] registry unreachable — agent not auto-registered: ${err.message}`);
        });
    }
    return provider;
}
export function getSDKProvider() {
    return _sdkProvider;
}
// ── Run reporting ────────────────────────────────────────────────────────
let _registryBaseUrl;
let _apiKey;
/**
 * Report a run start to the CC registry.
 * Called automatically by initVaubanSDK when registryUrl is set,
 * and manually by agents that want their cycles to appear in /runs.
 */
export async function reportRunStart(opts) {
    const base = _registryBaseUrl;
    const key = _apiKey;
    if (!base || !key)
        return null;
    try {
        const res = await fetch(`${base}/api/runs`, {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${key}`,
            },
            body: JSON.stringify({
                agentId: opts.agentId,
                runId: opts.runId,
                model: opts.model,
                provider: opts.provider,
            }),
        });
        if (!res.ok)
            return null;
        return (await res.json());
    }
    catch {
        return null;
    }
}
/**
 * Report a run finish to the CC registry.
 */
export async function reportRunFinish(opts) {
    const base = _registryBaseUrl;
    const key = _apiKey;
    if (!base || !key)
        return;
    try {
        await fetch(`${base}/api/runs/${encodeURIComponent(opts.runId)}`, {
            method: "PATCH",
            headers: {
                "Content-Type": "application/json",
                Authorization: `Bearer ${key}`,
            },
            body: JSON.stringify({
                status: opts.status,
                input_tokens: opts.inputTokens,
                output_tokens: opts.outputTokens,
                cost_usd: opts.costUsd,
                error_message: opts.errorMessage,
            }),
        });
    }
    catch {
        // fire-and-forget
    }
}
//# sourceMappingURL=ingest.js.map