import { SpanKind, SpanStatusCode } from '../types.js';
/**
 * Start an LLM provider call span as a child of the turn span.
 *
 * @param tracer - RuntimeTracer instance.
 * @param ctx - LLM span context.
 */
export function startLlmSpan(tracer, ctx) {
    const attrs = {
        'llm.provider': ctx.provider,
        'llm.model': ctx.model,
        'turn.id': ctx.turnId,
        'llm.streaming': ctx.streaming ?? false,
    };
    if (ctx.messageCount !== undefined) {
        attrs['llm.message_count'] = ctx.messageCount;
    }
    return tracer.startSpan('llm.call', {
        traceId: ctx.traceId,
        parentSpanId: ctx.parentSpanId,
        // LLM calls are modelled as CLIENT spans (calling an external service)
        kind: SpanKind.CLIENT,
        attributes: attrs,
    });
}
/**
 * Record that the LLM stream has started (first token received).
 *
 * @param span - The active LLM span.
 * @param firstTokenMs - Epoch ms when the first token arrived (optional override).
 */
export function recordLlmStreamStart(span, firstTokenMs) {
    if (span.ended)
        return;
    span.addEvent('llm.stream_start', {
        'llm.time_to_first_token_ms': firstTokenMs ?? Date.now(),
    });
}
/**
 * End an LLM provider call span.
 *
 * @param span - The span returned by `startLlmSpan`.
 * @param ctx - LLM end context.
 */
export function endLlmSpan(span, ctx) {
    if (span.ended)
        return;
    if (ctx.stopReason) {
        span.setAttribute('llm.stop_reason', ctx.stopReason);
    }
    if (ctx.httpStatus !== undefined) {
        span.setAttribute('llm.http_status', ctx.httpStatus);
    }
    if (ctx.tokens) {
        span.setAttributes({
            'llm.tokens.input': ctx.tokens.inputTokens,
            'llm.tokens.output': ctx.tokens.outputTokens,
            'llm.tokens.cache_read': ctx.tokens.cacheReadTokens ?? 0,
            'llm.tokens.cache_write': ctx.tokens.cacheWriteTokens ?? 0,
        });
    }
    if (ctx.success) {
        span.setStatus({ code: SpanStatusCode.OK });
        span.addEvent('llm.call_completed');
    }
    else {
        const msg = ctx.error ?? 'LLM call failed';
        span.setStatus({ code: SpanStatusCode.ERROR, message: msg });
        span.setAttribute('llm.error', msg);
        span.addEvent('llm.call_failed', { 'llm.error': msg });
    }
    span.end();
}
