/** * OpenTelemetry GenAI spans, read as a usage log — the 1.71 arc's move. * * `from-claude-code` proved a pattern: a pure converter turns one tool's * export into Trazum's usage-log records, and every door prices it from * there. This generalises it to the standard the ecosystem is converging on * — OpenTelemetry's GenAI semantic conventions — so Trazum reads whatever * telemetry a team already emits rather than competing with the tool that * emits it. * * **What an LLM-call span carries** (OTLP/JSON, one `resourceSpans[]` → * `scopeSpans[]` → `spans[]`, each span an `attributes[]` of * `{ key, value: { stringValue | intValue | … } }`): * - `gen_ai.request.model` / `gen_ai.response.model` — the model. * - `gen_ai.usage.input_tokens` / `gen_ai.usage.output_tokens` — the counts. * - `gen_ai.operation.name`, or the resource's `service.name` — the label. * - the span's own `startTimeUnixNano` — the timestamp. * * **What it deliberately does not carry, and this does not invent.** OTel has * not standardised the cache-write TTL split, so an OTel-sourced record has * no `cache_creation` object and the cache verdicts read `cannot-tell` rather * than a fabricated one — the same refusal as inventing a price. Cache reads * are taken only where a `gen_ai.usage.cache_read_input_tokens`-shaped key is * actually present. * * **Nothing but the numbers crosses.** Prompt and completion content, trace * ids, and every other span attribute stay in the span; the record carries * model, timestamp, label and the token counts, held by a fixture that * plants a secret in a span attribute and greps the whole output for it. */ /** One converted record, shaped exactly as `parseUsageLine` reads it. */ export interface OtelRecord { model: string; ts: string; label?: string; usage: { input_tokens: number; output_tokens: number; cache_read_input_tokens?: number; }; } export interface OtelConversion { records: OtelRecord[]; /** Spans that were LLM calls and converted. */ llmSpans: number; /** Spans that were not LLM calls (no gen_ai usage): counted, not converted. */ otherSpans: number; /** Converted records that carried no cache-read data — the OTel norm today. */ noCacheData: number; /** Lines/documents that did not parse as JSON at all. */ unparseable: number; } /** * Convert an OTLP/JSON payload. Accepts a single document or newline-delimited * documents (one `{ resourceSpans: … }` per line), so both an exporter's file * dump and a streamed capture work. Pure over its input. */ export declare function otelRecords(text: string): OtelConversion; /** * Does this text look like an OpenTelemetry span export rather than a usage * log or a Claude Code transcript? The presence of `resourceSpans` (the OTLP * envelope) or a `gen_ai.` attribute key — a signature, not a filename, so * the web tab can route a dropped file with no help from the reader. Reads a * bounded prefix: an export announces itself early. */ export declare function looksLikeOtel(text: string, prefixBytes?: number): boolean; //# sourceMappingURL=otel.d.ts.map