/**
 * Canonical OTLP-flat-line readers shared by every consumer of the
 * OTLP-JSONL wire shape (one OTLP span per line; the form
 * `flattenOtlpExportToNdjson` produces and the form AppWorld / HALO
 * emit via their OpenInference OTLP exporter).
 *
 * `OtlpFileTraceStore` indexes spans with these; `otlpToRunRecords`
 * aggregates spans into `RunRecord`s with the same readers. One parser,
 * one vocabulary — a divergence between the analyst's view of a trace and
 * the RunRecord projected from it is a class of bug this consolidation
 * removes by construction.
 *
 * Vocabulary. The readers understand BOTH dialects that appear in the
 * wild:
 *   - the substrate's own `llm.*` / `tool.*` / `span.kind` attributes
 *     (`flattenSpanAttributes` in `trace/otel.ts`), and
 *   - the OpenInference / inference-export attributes AppWorld / HALO
 *     emit (`openinference.span.kind`, `inference.observation_kind`,
 *     `inference.llm.input_tokens`, `llm.token_count.prompt`, …).
 *
 * Pure, no I/O.
 */
import type { TraceAnalystSpanKind, TraceAnalystSpanStatus } from './types';
/**
 * The structural fields a flat OTLP-JSONL line projects to. `attributes`
 * is the merged resource+span attribute map (span overrides resource);
 * the named fields are the pivots every reader of a trace needs without
 * paying the full attribute materialisation.
 */
export interface ProjectedOtlpSpan {
    trace_id: string;
    span_id: string;
    parent_span_id: string | null;
    name: string;
    kind: TraceAnalystSpanKind;
    start_time: string;
    end_time: string;
    duration_ms: number;
    status: TraceAnalystSpanStatus;
    status_message: string | undefined;
    service_name: string | null;
    agent_name: string | null;
    model_name: string | null;
    tool_name: string | null;
    /** Merged resource + span attributes, span winning on overlap. */
    attributes: Record<string, unknown>;
}
/**
 * Project one parsed OTLP-JSONL object to `ProjectedOtlpSpan`, or `null`
 * when the line is missing the mandatory `trace_id` + `span_id`.
 */
export declare function projectOtlpFlatLine(raw: Record<string, unknown>): ProjectedOtlpSpan | null;
export declare function readOtlpStatus(raw: Record<string, unknown>): {
    code: TraceAnalystSpanStatus;
    message: string | undefined;
};
export declare function inferOtlpKind(attrs: Record<string, unknown>): TraceAnalystSpanKind;
/**
 * Flatten OTLP `attributes` + `resource.attributes` into a single
 * dotted-key map. Span attributes override resource attributes when keys
 * overlap. Nested objects/arrays are preserved as-is.
 */
export declare function extractOtlpAttributes(raw: Record<string, unknown>): Record<string, unknown>;
export declare function stringField(raw: Record<string, unknown>, key: string): string | undefined;
export declare function asString(v: unknown): string | null;
/** Read a numeric attribute, tolerating numeric strings; `null` if absent/NaN. */
export declare function asNumber(v: unknown): number | null;
/** First finite numeric value across a list of candidate attribute keys. */
export declare function firstNumberAttr(attrs: Record<string, unknown>, keys: readonly string[]): number | null;
/** First non-empty string value across a list of candidate attribute keys. */
export declare function firstStringAttr(attrs: Record<string, unknown>, keys: readonly string[]): string | null;
/**
 * Parse a span timestamp to epoch millis, or null when empty/unparseable. The
 * OTLP readers accept BOTH ISO-8601 and epoch-millis-string dialects, so raw
 * string comparison (`<`, `localeCompare`) mis-orders across dialects and
 * `Date.parse` returns NaN for a bare epoch-millis string.
 */
export declare function spanEpochMillis(ts: string | undefined | null): number | null;
/**
 * Order comparator for span timestamps across mixed ISO/epoch dialects.
 * Unparseable timestamps sort as epoch 0 (earliest), never NaN (which would
 * make the sort non-deterministic).
 */
export declare function compareSpanTime(a: string, b: string): number;
//# sourceMappingURL=otlp-span.d.ts.map