@agentmark-ai/shared-utils 0.6.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2136,85 +2136,562 @@ var OtelGenAiTransformer = class {
2136
2136
  };
2137
2137
  OtelGenAiTransformer.SCOPE_NAME = "pydantic-ai";
2138
2138
 
2139
- // src/normalizer/converters/otlp-converter.ts
2140
- function convertOtlpValue(value) {
2139
+ // src/normalizer/extractors/indexed-message-parser.ts
2140
+ function escapeRegExp(value) {
2141
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2142
+ }
2143
+ function collectIndices(attributes, prefix) {
2144
+ const re = new RegExp(`^${escapeRegExp(prefix)}\\.(\\d+)\\.`);
2145
+ const seen = /* @__PURE__ */ new Set();
2146
+ for (const key of Object.keys(attributes)) {
2147
+ const match = re.exec(key);
2148
+ if (match) seen.add(Number(match[1]));
2149
+ }
2150
+ return [...seen].sort((a, b) => a - b);
2151
+ }
2152
+ function parseArgs(raw) {
2153
+ if (raw === void 0 || raw === null) return {};
2154
+ if (typeof raw === "object") return raw;
2155
+ if (typeof raw === "string") {
2156
+ try {
2157
+ const parsed = JSON.parse(raw);
2158
+ return parsed && typeof parsed === "object" ? parsed : { raw };
2159
+ } catch {
2160
+ return { raw };
2161
+ }
2162
+ }
2163
+ return { raw };
2164
+ }
2165
+ function readMessageToolCalls(attributes, messageBase, config) {
2166
+ const tc = config.toolCalls;
2167
+ if (!tc) return [];
2168
+ const arrayPrefix = `${messageBase}${tc.arrayKey}`;
2169
+ const indices = collectIndices(attributes, arrayPrefix);
2170
+ const calls = [];
2171
+ for (const j of indices) {
2172
+ const base = `${arrayPrefix}.${j}.${tc.infix}`;
2173
+ const name = attributes[`${base}${tc.nameKey}`];
2174
+ if (name === void 0) continue;
2175
+ const id = attributes[`${base}${tc.idKey}`];
2176
+ const args = parseArgs(attributes[`${base}${tc.argsKey}`]);
2177
+ calls.push({
2178
+ type: "tool-call",
2179
+ toolCallId: id !== void 0 ? String(id) : "",
2180
+ toolName: String(name),
2181
+ args
2182
+ });
2183
+ }
2184
+ return calls;
2185
+ }
2186
+ function readContentsText(attributes, messageBase, config) {
2141
2187
  var _a;
2142
- if (value.stringValue !== void 0) {
2143
- return value.stringValue;
2188
+ if (!config.contentsKey) return void 0;
2189
+ const contentsPrefix = `${messageBase}${config.contentsKey}`;
2190
+ const indices = collectIndices(attributes, contentsPrefix);
2191
+ if (indices.length === 0) return void 0;
2192
+ const partInfix = (_a = config.contentsPartInfix) != null ? _a : "";
2193
+ const parts = [];
2194
+ for (const j of indices) {
2195
+ const text = attributes[`${contentsPrefix}.${j}.${partInfix}text`];
2196
+ if (typeof text === "string" && text.length > 0) parts.push(text);
2197
+ }
2198
+ return parts.length > 0 ? parts.join("\n") : void 0;
2199
+ }
2200
+ function parseIndexedMessages(attributes, config) {
2201
+ var _a, _b;
2202
+ const indices = collectIndices(attributes, config.prefix);
2203
+ if (indices.length === 0) return void 0;
2204
+ const roleKey = (_a = config.roleKey) != null ? _a : "role";
2205
+ const contentKey = (_b = config.contentKey) != null ? _b : "content";
2206
+ const messages = [];
2207
+ for (const i of indices) {
2208
+ const base = `${config.prefix}.${i}.${config.messageInfix}`;
2209
+ const role = attributes[`${base}${roleKey}`];
2210
+ const scalarContent = attributes[`${base}${contentKey}`];
2211
+ const text = typeof scalarContent === "string" ? scalarContent : scalarContent !== void 0 ? String(scalarContent) : readContentsText(attributes, base, config);
2212
+ const toolCalls = readMessageToolCalls(attributes, base, config);
2213
+ if (role === void 0 && text === void 0 && toolCalls.length === 0) continue;
2214
+ let content;
2215
+ if (toolCalls.length > 0) {
2216
+ const parts = [];
2217
+ if (text) parts.push({ type: "text", text });
2218
+ for (const call of toolCalls) {
2219
+ parts.push({
2220
+ type: "tool-call",
2221
+ toolCallId: call.toolCallId,
2222
+ toolName: call.toolName,
2223
+ args: call.args
2224
+ });
2225
+ }
2226
+ content = parts;
2227
+ } else {
2228
+ content = text != null ? text : "";
2229
+ }
2230
+ messages.push({ role: role !== void 0 ? String(role) : "user", content });
2144
2231
  }
2145
- if (value.intValue !== void 0) {
2146
- return typeof value.intValue === "string" ? parseInt(value.intValue, 10) : value.intValue;
2232
+ return messages.length > 0 ? messages : void 0;
2233
+ }
2234
+ function extractIndexedToolCalls(attributes, config) {
2235
+ if (!config.toolCalls) return void 0;
2236
+ const indices = collectIndices(attributes, config.prefix);
2237
+ const calls = [];
2238
+ for (const i of indices) {
2239
+ const base = `${config.prefix}.${i}.${config.messageInfix}`;
2240
+ calls.push(...readMessageToolCalls(attributes, base, config));
2241
+ }
2242
+ return calls.length > 0 ? calls : void 0;
2243
+ }
2244
+ function messagesToPlainText(messages) {
2245
+ if (!messages || messages.length === 0) return void 0;
2246
+ const chunks = [];
2247
+ for (const msg of messages) {
2248
+ if (typeof msg.content === "string") {
2249
+ if (msg.content.length > 0) chunks.push(msg.content);
2250
+ } else if (Array.isArray(msg.content)) {
2251
+ for (const part of msg.content) {
2252
+ if (typeof part === "string") {
2253
+ if (part.length > 0) chunks.push(part);
2254
+ } else if (part.type === "text" && part.text.length > 0) {
2255
+ chunks.push(part.text);
2256
+ }
2257
+ }
2258
+ }
2147
2259
  }
2148
- if (value.doubleValue !== void 0) {
2149
- return value.doubleValue;
2260
+ return chunks.length > 0 ? chunks.join("\n") : void 0;
2261
+ }
2262
+
2263
+ // src/normalizer/utils/coerce.ts
2264
+ function toNumber(value) {
2265
+ if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
2266
+ if (typeof value === "string") {
2267
+ const n = Number(value);
2268
+ return Number.isFinite(n) ? n : void 0;
2150
2269
  }
2151
- if (value.boolValue !== void 0) {
2152
- return value.boolValue;
2270
+ return void 0;
2271
+ }
2272
+
2273
+ // src/normalizer/transformers/openinference/index.ts
2274
+ var Attrs2 = {
2275
+ SPAN_KIND: "openinference.span.kind",
2276
+ MODEL: "llm.model_name",
2277
+ PROVIDER: "llm.provider",
2278
+ SYSTEM: "llm.system",
2279
+ INVOCATION_PARAMETERS: "llm.invocation_parameters",
2280
+ TOKEN_PROMPT: "llm.token_count.prompt",
2281
+ TOKEN_COMPLETION: "llm.token_count.completion",
2282
+ TOKEN_TOTAL: "llm.token_count.total",
2283
+ TOKEN_REASONING: "llm.token_count.completion_details.reasoning",
2284
+ INPUT_VALUE: "input.value",
2285
+ INPUT_MIME: "input.mime_type",
2286
+ OUTPUT_VALUE: "output.value",
2287
+ OUTPUT_MIME: "output.mime_type",
2288
+ TOOL_NAME: "tool.name",
2289
+ SESSION_ID: "session.id",
2290
+ USER_ID: "user.id",
2291
+ METADATA: "metadata"
2292
+ };
2293
+ var INPUT_MESSAGES = {
2294
+ prefix: "llm.input_messages",
2295
+ messageInfix: "message.",
2296
+ contentsKey: "contents",
2297
+ contentsPartInfix: "message_content.",
2298
+ toolCalls: {
2299
+ arrayKey: "tool_calls",
2300
+ infix: "tool_call.",
2301
+ idKey: "id",
2302
+ nameKey: "function.name",
2303
+ argsKey: "function.arguments"
2153
2304
  }
2154
- if ((_a = value.arrayValue) == null ? void 0 : _a.values) {
2155
- return value.arrayValue.values.map(convertOtlpValue);
2305
+ };
2306
+ var OUTPUT_MESSAGES = {
2307
+ ...INPUT_MESSAGES,
2308
+ prefix: "llm.output_messages"
2309
+ };
2310
+ var RETRIEVAL_PREFIX = "retrieval.documents";
2311
+ function extractSettings(attributes) {
2312
+ var _a, _b, _c, _d, _e;
2313
+ const raw = attributes[Attrs2.INVOCATION_PARAMETERS];
2314
+ if (raw === void 0) return void 0;
2315
+ let parsed;
2316
+ if (typeof raw === "string") {
2317
+ try {
2318
+ parsed = JSON.parse(raw);
2319
+ } catch {
2320
+ return void 0;
2321
+ }
2322
+ } else if (typeof raw === "object" && raw !== null) {
2323
+ parsed = raw;
2324
+ } else {
2325
+ return void 0;
2156
2326
  }
2157
- if (value.bytesValue !== void 0) {
2158
- return value.bytesValue;
2327
+ if (!parsed || typeof parsed !== "object") return void 0;
2328
+ const settings = {};
2329
+ const temperature = toNumber(parsed.temperature);
2330
+ const maxTokens = toNumber((_b = (_a = parsed.max_tokens) != null ? _a : parsed.maxTokens) != null ? _b : parsed.max_completion_tokens);
2331
+ const topP = toNumber((_c = parsed.top_p) != null ? _c : parsed.topP);
2332
+ const presencePenalty = toNumber((_d = parsed.presence_penalty) != null ? _d : parsed.presencePenalty);
2333
+ const frequencyPenalty = toNumber((_e = parsed.frequency_penalty) != null ? _e : parsed.frequencyPenalty);
2334
+ if (temperature !== void 0) settings.temperature = temperature;
2335
+ if (maxTokens !== void 0) settings.maxTokens = maxTokens;
2336
+ if (topP !== void 0) settings.topP = topP;
2337
+ if (presencePenalty !== void 0) settings.presencePenalty = presencePenalty;
2338
+ if (frequencyPenalty !== void 0) settings.frequencyPenalty = frequencyPenalty;
2339
+ return Object.keys(settings).length > 0 ? settings : void 0;
2340
+ }
2341
+ function extractGenericInput(attributes) {
2342
+ const value = attributes[Attrs2.INPUT_VALUE];
2343
+ if (value === void 0) return {};
2344
+ const mime = attributes[Attrs2.INPUT_MIME];
2345
+ if (mime === "application/json" && typeof value === "string") {
2346
+ try {
2347
+ const parsed = JSON.parse(value);
2348
+ if (Array.isArray(parsed) && parsed.every((m) => m && typeof m === "object" && "role" in m)) {
2349
+ return { input: parsed };
2350
+ }
2351
+ return { input: [{ role: "user", content: JSON.stringify(parsed) }] };
2352
+ } catch {
2353
+ }
2354
+ }
2355
+ return { input: [{ role: "user", content: String(value) }] };
2356
+ }
2357
+ function extractGenericOutput(attributes) {
2358
+ const value = attributes[Attrs2.OUTPUT_VALUE];
2359
+ if (value === void 0) return {};
2360
+ const mime = attributes[Attrs2.OUTPUT_MIME];
2361
+ if (mime === "application/json" && typeof value === "string") {
2362
+ try {
2363
+ const parsed = JSON.parse(value);
2364
+ return { output: JSON.stringify(parsed), outputObject: parsed };
2365
+ } catch {
2366
+ }
2159
2367
  }
2368
+ return { output: String(value) };
2369
+ }
2370
+ function parseDocumentMetadata(raw) {
2371
+ let parsed = raw;
2372
+ if (typeof raw === "string") {
2373
+ try {
2374
+ parsed = JSON.parse(raw);
2375
+ } catch {
2376
+ return void 0;
2377
+ }
2378
+ }
2379
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
2160
2380
  return void 0;
2161
2381
  }
2162
- function convertOtlpAttributes(attributes) {
2163
- if (!attributes || attributes.length === 0) {
2164
- return {};
2382
+ function extractRetrievalDocuments(attributes) {
2383
+ const docs = [];
2384
+ for (const i of collectIndices(attributes, RETRIEVAL_PREFIX)) {
2385
+ const base = `${RETRIEVAL_PREFIX}.${i}.document`;
2386
+ const doc = {};
2387
+ const id = attributes[`${base}.id`];
2388
+ if (id !== void 0 && id !== null && String(id).length > 0) doc.id = String(id);
2389
+ const content = attributes[`${base}.content`];
2390
+ if (typeof content === "string" && content.length > 0) doc.content = content;
2391
+ const score = toNumber(attributes[`${base}.score`]);
2392
+ if (score !== void 0) doc.score = score;
2393
+ const metadata = parseDocumentMetadata(attributes[`${base}.metadata`]);
2394
+ if (metadata !== void 0) doc.metadata = metadata;
2395
+ if (Object.keys(doc).length > 0) docs.push(doc);
2396
+ }
2397
+ return docs;
2398
+ }
2399
+ function retrievalDocumentsToText(documents) {
2400
+ const text = documents.map((d) => d.content).filter((c) => typeof c === "string" && c.length > 0).join("\n\n");
2401
+ return text.length > 0 ? text : void 0;
2402
+ }
2403
+ var OpenInferenceTransformer = class {
2404
+ classify(_span, attributes) {
2405
+ const kind = attributes[Attrs2.SPAN_KIND];
2406
+ if (typeof kind === "string" && kind.toUpperCase() === "LLM") return "GENERATION" /* GENERATION */;
2407
+ if (attributes[Attrs2.TOKEN_PROMPT] !== void 0 || attributes[Attrs2.TOKEN_COMPLETION] !== void 0) {
2408
+ return "GENERATION" /* GENERATION */;
2409
+ }
2410
+ return "SPAN" /* SPAN */;
2165
2411
  }
2166
- const result = {};
2167
- for (const attr of attributes) {
2168
- if (attr.key && isSafeKey(attr.key)) {
2169
- result[attr.key] = convertOtlpValue(attr.value);
2412
+ transform(_span, attributes) {
2413
+ const result = {};
2414
+ const model = attributes[Attrs2.MODEL];
2415
+ if (typeof model === "string" && model.length > 0) result.model = model;
2416
+ const inputTokens = toNumber(attributes[Attrs2.TOKEN_PROMPT]);
2417
+ const outputTokens = toNumber(attributes[Attrs2.TOKEN_COMPLETION]);
2418
+ const totalTokens = toNumber(attributes[Attrs2.TOKEN_TOTAL]);
2419
+ const reasoningTokens = toNumber(attributes[Attrs2.TOKEN_REASONING]);
2420
+ if (inputTokens !== void 0) result.inputTokens = inputTokens;
2421
+ if (outputTokens !== void 0) result.outputTokens = outputTokens;
2422
+ if (totalTokens !== void 0) {
2423
+ result.totalTokens = totalTokens;
2424
+ } else if (inputTokens !== void 0 && outputTokens !== void 0) {
2425
+ result.totalTokens = inputTokens + outputTokens;
2426
+ }
2427
+ if (reasoningTokens !== void 0) result.reasoningTokens = reasoningTokens;
2428
+ const settings = extractSettings(attributes);
2429
+ if (settings) result.settings = settings;
2430
+ const inputMessages = parseIndexedMessages(attributes, INPUT_MESSAGES);
2431
+ if (inputMessages) {
2432
+ result.input = inputMessages;
2433
+ } else {
2434
+ Object.assign(result, extractGenericInput(attributes));
2435
+ }
2436
+ const outputMessages = parseIndexedMessages(attributes, OUTPUT_MESSAGES);
2437
+ const toolCalls = extractIndexedToolCalls(attributes, OUTPUT_MESSAGES);
2438
+ if (toolCalls) result.toolCalls = toolCalls;
2439
+ if (outputMessages) {
2440
+ const text = messagesToPlainText(outputMessages);
2441
+ if (text) result.output = text;
2442
+ } else {
2443
+ Object.assign(result, extractGenericOutput(attributes));
2444
+ }
2445
+ const documents = extractRetrievalDocuments(attributes);
2446
+ if (documents.length > 0) {
2447
+ if (result.outputObject === void 0) result.outputObject = { documents };
2448
+ if (result.output === void 0) {
2449
+ const text = retrievalDocumentsToText(documents);
2450
+ if (text) result.output = text;
2451
+ }
2452
+ }
2453
+ const toolName = attributes[Attrs2.TOOL_NAME];
2454
+ if (typeof toolName === "string" && toolName.length > 0) result.name = toolName;
2455
+ const sessionId = attributes[Attrs2.SESSION_ID];
2456
+ if (sessionId !== void 0) result.sessionId = String(sessionId);
2457
+ const userId = attributes[Attrs2.USER_ID];
2458
+ if (userId !== void 0) result.userId = String(userId);
2459
+ const metadataRaw = attributes[Attrs2.METADATA];
2460
+ if (metadataRaw !== void 0) {
2461
+ let parsed = metadataRaw;
2462
+ if (typeof metadataRaw === "string") {
2463
+ try {
2464
+ parsed = JSON.parse(metadataRaw);
2465
+ } catch {
2466
+ parsed = void 0;
2467
+ }
2468
+ }
2469
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
2470
+ const metadata = {};
2471
+ for (const [k, v] of Object.entries(parsed)) {
2472
+ metadata[k] = typeof v === "string" ? v : JSON.stringify(v);
2473
+ }
2474
+ if (Object.keys(metadata).length > 0) result.metadata = metadata;
2475
+ }
2170
2476
  }
2477
+ return result;
2171
2478
  }
2479
+ };
2480
+
2481
+ // src/normalizer/transformers/openllmetry/index.ts
2482
+ var Attrs3 = {
2483
+ SPAN_KIND: "traceloop.span.kind",
2484
+ REQUEST_MODEL: "gen_ai.request.model",
2485
+ RESPONSE_MODEL: "gen_ai.response.model",
2486
+ REQUEST_TEMPERATURE: "gen_ai.request.temperature",
2487
+ REQUEST_MAX_TOKENS: "gen_ai.request.max_tokens",
2488
+ REQUEST_TOP_P: "gen_ai.request.top_p",
2489
+ REQUEST_PRESENCE_PENALTY: "gen_ai.request.presence_penalty",
2490
+ REQUEST_FREQUENCY_PENALTY: "gen_ai.request.frequency_penalty",
2491
+ RESPONSE_FINISH_REASON: "gen_ai.response.finish_reason",
2492
+ TOTAL_TOKENS_ALT: "llm.usage.total_tokens",
2493
+ ENTITY_INPUT: "traceloop.entity.input",
2494
+ ENTITY_OUTPUT: "traceloop.entity.output",
2495
+ ENTITY_NAME: "traceloop.entity.name",
2496
+ ASSOCIATION_PREFIX: "traceloop.association.properties."
2497
+ };
2498
+ var PROMPT_MESSAGES = {
2499
+ prefix: "gen_ai.prompt",
2500
+ messageInfix: "",
2501
+ toolCalls: { arrayKey: "tool_calls", infix: "", idKey: "id", nameKey: "name", argsKey: "arguments" }
2502
+ };
2503
+ var COMPLETION_MESSAGES = {
2504
+ ...PROMPT_MESSAGES,
2505
+ prefix: "gen_ai.completion"
2506
+ };
2507
+ function extractSettings2(attributes) {
2508
+ const settings = {};
2509
+ const temperature = toNumber(attributes[Attrs3.REQUEST_TEMPERATURE]);
2510
+ const maxTokens = toNumber(attributes[Attrs3.REQUEST_MAX_TOKENS]);
2511
+ const topP = toNumber(attributes[Attrs3.REQUEST_TOP_P]);
2512
+ const presencePenalty = toNumber(attributes[Attrs3.REQUEST_PRESENCE_PENALTY]);
2513
+ const frequencyPenalty = toNumber(attributes[Attrs3.REQUEST_FREQUENCY_PENALTY]);
2514
+ if (temperature !== void 0) settings.temperature = temperature;
2515
+ if (maxTokens !== void 0) settings.maxTokens = maxTokens;
2516
+ if (topP !== void 0) settings.topP = topP;
2517
+ if (presencePenalty !== void 0) settings.presencePenalty = presencePenalty;
2518
+ if (frequencyPenalty !== void 0) settings.frequencyPenalty = frequencyPenalty;
2519
+ return Object.keys(settings).length > 0 ? settings : void 0;
2520
+ }
2521
+ function extractEntityInput(attributes) {
2522
+ const raw = attributes[Attrs3.ENTITY_INPUT];
2523
+ if (raw === void 0) return void 0;
2524
+ const text = typeof raw === "string" ? raw : JSON.stringify(raw);
2525
+ return [{ role: "user", content: text }];
2526
+ }
2527
+ function extractEntityOutput(attributes) {
2528
+ const raw = attributes[Attrs3.ENTITY_OUTPUT];
2529
+ if (raw === void 0) return {};
2530
+ if (typeof raw === "string") {
2531
+ try {
2532
+ const parsed = JSON.parse(raw);
2533
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
2534
+ return { output: raw, outputObject: parsed };
2535
+ }
2536
+ } catch {
2537
+ }
2538
+ return { output: raw };
2539
+ }
2540
+ const result = { output: JSON.stringify(raw) };
2541
+ if (typeof raw === "object" && raw !== null) result.outputObject = raw;
2172
2542
  return result;
2173
2543
  }
2174
- function extractResourceScopeSpan(resourceSpans) {
2544
+ function extractFromEvents(events, attrKey) {
2175
2545
  var _a, _b, _c;
2176
- const result = [];
2177
- const resourceAttributes = convertOtlpAttributes((_a = resourceSpans.resource) == null ? void 0 : _a.attributes);
2178
- for (const scopeSpans of resourceSpans.scopeSpans || []) {
2179
- const scope = {
2180
- name: (_b = scopeSpans.scope) == null ? void 0 : _b.name,
2181
- version: (_c = scopeSpans.scope) == null ? void 0 : _c.version
2182
- };
2183
- for (const otlpSpan of scopeSpans.spans || []) {
2184
- const spanAttributes = convertOtlpAttributes(otlpSpan.attributes);
2185
- const events = (otlpSpan.events || []).map((otlpEvent) => ({
2186
- timeUnixNano: otlpEvent.timeUnixNano,
2187
- name: otlpEvent.name,
2188
- attributes: convertOtlpAttributes(otlpEvent.attributes)
2189
- }));
2190
- const links = (otlpSpan.links || []).map((otlpLink) => ({
2191
- traceId: otlpLink.traceId,
2192
- spanId: otlpLink.spanId,
2193
- traceState: otlpLink.traceState,
2194
- attributes: convertOtlpAttributes(otlpLink.attributes)
2195
- }));
2196
- const span = {
2197
- traceId: otlpSpan.traceId,
2198
- spanId: otlpSpan.spanId,
2199
- parentSpanId: otlpSpan.parentSpanId,
2200
- traceState: otlpSpan.traceState,
2201
- name: otlpSpan.name,
2202
- kind: otlpSpan.kind,
2203
- startTimeUnixNano: otlpSpan.startTimeUnixNano,
2204
- endTimeUnixNano: otlpSpan.endTimeUnixNano,
2205
- attributes: spanAttributes,
2206
- events,
2207
- links,
2208
- status: otlpSpan.status
2209
- };
2210
- const resource = {
2211
- attributes: resourceAttributes
2212
- };
2213
- result.push({ resource, scope, span });
2546
+ if (!events) return void 0;
2547
+ for (const event of events) {
2548
+ const value = (_c = (_a = event.attributes) == null ? void 0 : _a[attrKey]) != null ? _c : (_b = event.attributes) == null ? void 0 : _b["content"];
2549
+ if (typeof value === "string" && value.length > 0) return value;
2550
+ }
2551
+ return void 0;
2552
+ }
2553
+ function parseResultMetadata(raw) {
2554
+ let parsed = raw;
2555
+ if (typeof raw === "string") {
2556
+ try {
2557
+ parsed = JSON.parse(raw);
2558
+ } catch {
2559
+ return void 0;
2214
2560
  }
2215
2561
  }
2216
- return result;
2562
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
2563
+ return void 0;
2564
+ }
2565
+ var VECTOR_RESULT_EVENT_NAMES = /* @__PURE__ */ new Set(["db.query.result", "db.search.result"]);
2566
+ function extractVectorResultDocuments(events) {
2567
+ var _a, _b;
2568
+ if (!events) return [];
2569
+ const docs = [];
2570
+ for (const event of events) {
2571
+ if (!VECTOR_RESULT_EVENT_NAMES.has(event.name)) continue;
2572
+ const a = (_a = event.attributes) != null ? _a : {};
2573
+ const get = (field) => {
2574
+ var _a2;
2575
+ return (_a2 = a[`db.query.result.${field}`]) != null ? _a2 : a[`db.search.result.${field}`];
2576
+ };
2577
+ const doc = {};
2578
+ const id = get("id");
2579
+ if (id !== void 0 && id !== null && String(id).length > 0) doc.id = String(id);
2580
+ const content = get("document");
2581
+ if (typeof content === "string" && content.length > 0) doc.content = content;
2582
+ const score = toNumber(get("score"));
2583
+ if (score !== void 0) doc.score = score;
2584
+ const distance = toNumber(get("distance"));
2585
+ if (distance !== void 0) doc.distance = distance;
2586
+ let metadata = parseResultMetadata(get("metadata"));
2587
+ if (metadata === void 0) {
2588
+ const entity = get("entity");
2589
+ if (entity !== void 0 && entity !== null && String(entity).length > 0) {
2590
+ metadata = (_b = parseResultMetadata(entity)) != null ? _b : { entity: String(entity) };
2591
+ }
2592
+ }
2593
+ if (metadata !== void 0) doc.metadata = metadata;
2594
+ if (Object.keys(doc).length > 0) docs.push(doc);
2595
+ }
2596
+ return docs;
2597
+ }
2598
+ function extractFinishReason(attributes) {
2599
+ const direct = attributes[Attrs3.RESPONSE_FINISH_REASON];
2600
+ if (direct !== void 0) {
2601
+ return Array.isArray(direct) ? String(direct[0]) : String(direct);
2602
+ }
2603
+ const indexed = attributes["gen_ai.completion.0.finish_reason"];
2604
+ if (indexed !== void 0) return String(indexed);
2605
+ return void 0;
2217
2606
  }
2607
+ var OpenLLMetryTransformer = class {
2608
+ classify(_span, attributes) {
2609
+ const kind = attributes[Attrs3.SPAN_KIND];
2610
+ if (typeof kind === "string" && kind.toUpperCase() === "LLM") return "GENERATION" /* GENERATION */;
2611
+ if (attributes["gen_ai.usage.prompt_tokens"] !== void 0 || attributes["gen_ai.usage.completion_tokens"] !== void 0 || attributes["gen_ai.usage.input_tokens"] !== void 0) {
2612
+ return "GENERATION" /* GENERATION */;
2613
+ }
2614
+ return "SPAN" /* SPAN */;
2615
+ }
2616
+ transform(span, attributes) {
2617
+ var _a;
2618
+ const result = {};
2619
+ const model = (_a = attributes[Attrs3.RESPONSE_MODEL]) != null ? _a : attributes[Attrs3.REQUEST_MODEL];
2620
+ if (typeof model === "string" && model.length > 0) result.model = model;
2621
+ const tokens = parseTokens(attributes, {
2622
+ inputKey: "gen_ai.usage.input_tokens",
2623
+ outputKey: "gen_ai.usage.output_tokens",
2624
+ totalKey: "gen_ai.usage.total_tokens",
2625
+ promptKey: "gen_ai.usage.prompt_tokens",
2626
+ completionKey: "gen_ai.usage.completion_tokens"
2627
+ });
2628
+ if (tokens.inputTokens !== void 0) result.inputTokens = tokens.inputTokens;
2629
+ if (tokens.outputTokens !== void 0) result.outputTokens = tokens.outputTokens;
2630
+ if (tokens.totalTokens !== void 0) {
2631
+ result.totalTokens = tokens.totalTokens;
2632
+ } else {
2633
+ const altTotal = toNumber(attributes[Attrs3.TOTAL_TOKENS_ALT]);
2634
+ if (altTotal !== void 0) result.totalTokens = altTotal;
2635
+ }
2636
+ const settings = extractSettings2(attributes);
2637
+ if (settings) result.settings = settings;
2638
+ const finishReason = extractFinishReason(attributes);
2639
+ if (finishReason) result.finishReason = finishReason;
2640
+ const promptMessages = parseIndexedMessages(attributes, PROMPT_MESSAGES);
2641
+ if (promptMessages) {
2642
+ result.input = promptMessages;
2643
+ } else {
2644
+ const entityInput = extractEntityInput(attributes);
2645
+ if (entityInput) {
2646
+ result.input = entityInput;
2647
+ } else {
2648
+ const eventPrompt = extractFromEvents(span.events, "gen_ai.prompt");
2649
+ if (eventPrompt) result.input = [{ role: "user", content: eventPrompt }];
2650
+ }
2651
+ }
2652
+ const completionMessages = parseIndexedMessages(attributes, COMPLETION_MESSAGES);
2653
+ const toolCalls = extractIndexedToolCalls(attributes, COMPLETION_MESSAGES);
2654
+ if (toolCalls) result.toolCalls = toolCalls;
2655
+ if (completionMessages) {
2656
+ const text = messagesToPlainText(completionMessages);
2657
+ if (text) result.output = text;
2658
+ } else {
2659
+ const entityOutput = extractEntityOutput(attributes);
2660
+ if (entityOutput.output !== void 0) {
2661
+ Object.assign(result, entityOutput);
2662
+ } else {
2663
+ const eventCompletion = extractFromEvents(span.events, "gen_ai.completion");
2664
+ if (eventCompletion) result.output = eventCompletion;
2665
+ }
2666
+ }
2667
+ if (result.outputObject === void 0) {
2668
+ const documents = extractVectorResultDocuments(span.events);
2669
+ if (documents.length > 0) {
2670
+ result.outputObject = { documents };
2671
+ if (result.output === void 0) {
2672
+ const text = documents.map((d) => d.content).filter((c) => typeof c === "string" && c.length > 0).join("\n\n");
2673
+ if (text) result.output = text;
2674
+ }
2675
+ }
2676
+ }
2677
+ const entityName = attributes[Attrs3.ENTITY_NAME];
2678
+ if (typeof entityName === "string" && entityName.length > 0) result.traceName = entityName;
2679
+ const metadata = {};
2680
+ for (const [key, value] of Object.entries(attributes)) {
2681
+ if (!key.startsWith(Attrs3.ASSOCIATION_PREFIX)) continue;
2682
+ const prop = key.slice(Attrs3.ASSOCIATION_PREFIX.length);
2683
+ if (prop === "session_id") {
2684
+ result.sessionId = String(value);
2685
+ } else if (prop === "user_id") {
2686
+ result.userId = String(value);
2687
+ } else if (prop) {
2688
+ metadata[prop] = typeof value === "string" ? value : JSON.stringify(value);
2689
+ }
2690
+ }
2691
+ if (Object.keys(metadata).length > 0) result.metadata = metadata;
2692
+ return result;
2693
+ }
2694
+ };
2218
2695
 
2219
2696
  // src/normalizer/resolvers/semantic-kind-resolver.ts
2220
2697
  var SEMANTIC_KINDS = ["function", "llm", "tool", "agent", "retrieval", "embedding", "guardrail"];
@@ -2229,6 +2706,25 @@ var OPENINFERENCE_MAP = {
2229
2706
  "GUARDRAIL": "guardrail",
2230
2707
  "RERANKER": "retrieval"
2231
2708
  };
2709
+ var VECTOR_DB_SYSTEMS = /* @__PURE__ */ new Set([
2710
+ "pinecone",
2711
+ "qdrant",
2712
+ "weaviate",
2713
+ "milvus",
2714
+ "chroma",
2715
+ "chromadb",
2716
+ "marqo",
2717
+ "lancedb"
2718
+ ]);
2719
+ var VECTOR_RESULT_EVENT_NAMES2 = /* @__PURE__ */ new Set(["db.query.result", "db.search.result"]);
2720
+ function hasVectorStoreSignature(attributes, events) {
2721
+ var _a;
2722
+ const dbSystem = (_a = attributes["db.system"]) != null ? _a : attributes["db.system.name"];
2723
+ if (typeof dbSystem === "string" && VECTOR_DB_SYSTEMS.has(dbSystem.toLowerCase())) return true;
2724
+ if (Object.keys(attributes).some((k) => k.startsWith("db.vector.query."))) return true;
2725
+ if (events == null ? void 0 : events.some((e) => VECTOR_RESULT_EVENT_NAMES2.has(e.name))) return true;
2726
+ return false;
2727
+ }
2232
2728
  var FRAMEWORK_MAPPINGS = [
2233
2729
  {
2234
2730
  key: "ai.operationId",
@@ -2281,6 +2777,9 @@ function resolveSemanticKind(normalized, allAttributes) {
2281
2777
  if (mapped) return mapped;
2282
2778
  }
2283
2779
  }
2780
+ if (hasVectorStoreSignature(allAttributes, normalized.events)) {
2781
+ return "retrieval";
2782
+ }
2284
2783
  const opName = allAttributes["gen_ai.operation.name"];
2285
2784
  if (opName) {
2286
2785
  const op = String(opName).toLowerCase();
@@ -2303,6 +2802,132 @@ function resolveSemanticKind(normalized, allAttributes) {
2303
2802
  return "function";
2304
2803
  }
2305
2804
 
2805
+ // src/normalizer/transformers/dispatching/index.ts
2806
+ var OPENINFERENCE_INDEXED = /^llm\.(input_messages|output_messages|token_count)\./;
2807
+ var OPENLLMETRY_INDEXED = /^gen_ai\.(prompt|completion)\.\d+\./;
2808
+ function isOpenInference(attributes) {
2809
+ if (attributes["openinference.span.kind"] !== void 0) return true;
2810
+ if (attributes["llm.model_name"] !== void 0) return true;
2811
+ for (const key of Object.keys(attributes)) {
2812
+ if (OPENINFERENCE_INDEXED.test(key)) return true;
2813
+ }
2814
+ return false;
2815
+ }
2816
+ function isOpenLLMetry(attributes) {
2817
+ for (const key of Object.keys(attributes)) {
2818
+ if (key.startsWith("traceloop.")) return true;
2819
+ if (OPENLLMETRY_INDEXED.test(key)) return true;
2820
+ }
2821
+ return false;
2822
+ }
2823
+ var DispatchingTransformer = class {
2824
+ constructor() {
2825
+ this.openInference = new OpenInferenceTransformer();
2826
+ this.openLLMetry = new OpenLLMetryTransformer();
2827
+ this.otelGenAi = new OtelGenAiTransformer();
2828
+ }
2829
+ /** Choose the extractor for a span from its attribute/event signature.
2830
+ * OpenInference is checked before OpenLLMetry because its markers (`llm.*`,
2831
+ * `openinference.span.kind`) are more specific. Vector-store query spans
2832
+ * route to the OpenLLMetry extractor — they may carry no `traceloop.*`
2833
+ * marker (a bare Pinecone span is just `db.system` + `db.query.result`
2834
+ * events), so without this they'd fall through to the OTel-GenAI catch-all
2835
+ * and their result documents would be dropped. The bare OTel GenAI
2836
+ * transformer is the final catch-all. */
2837
+ select(attributes, span) {
2838
+ if (isOpenInference(attributes)) return this.openInference;
2839
+ if (isOpenLLMetry(attributes)) return this.openLLMetry;
2840
+ if (hasVectorStoreSignature(attributes, span == null ? void 0 : span.events)) return this.openLLMetry;
2841
+ return this.otelGenAi;
2842
+ }
2843
+ classify(span, attributes) {
2844
+ return this.select(attributes, span).classify(span, attributes);
2845
+ }
2846
+ transform(span, attributes) {
2847
+ return this.select(attributes, span).transform(span, attributes);
2848
+ }
2849
+ };
2850
+
2851
+ // src/normalizer/converters/otlp-converter.ts
2852
+ function convertOtlpValue(value) {
2853
+ var _a;
2854
+ if (value.stringValue !== void 0) {
2855
+ return value.stringValue;
2856
+ }
2857
+ if (value.intValue !== void 0) {
2858
+ return typeof value.intValue === "string" ? parseInt(value.intValue, 10) : value.intValue;
2859
+ }
2860
+ if (value.doubleValue !== void 0) {
2861
+ return value.doubleValue;
2862
+ }
2863
+ if (value.boolValue !== void 0) {
2864
+ return value.boolValue;
2865
+ }
2866
+ if ((_a = value.arrayValue) == null ? void 0 : _a.values) {
2867
+ return value.arrayValue.values.map(convertOtlpValue);
2868
+ }
2869
+ if (value.bytesValue !== void 0) {
2870
+ return value.bytesValue;
2871
+ }
2872
+ return void 0;
2873
+ }
2874
+ function convertOtlpAttributes(attributes) {
2875
+ if (!attributes || attributes.length === 0) {
2876
+ return {};
2877
+ }
2878
+ const result = {};
2879
+ for (const attr of attributes) {
2880
+ if (attr.key && isSafeKey(attr.key)) {
2881
+ result[attr.key] = convertOtlpValue(attr.value);
2882
+ }
2883
+ }
2884
+ return result;
2885
+ }
2886
+ function extractResourceScopeSpan(resourceSpans) {
2887
+ var _a, _b, _c;
2888
+ const result = [];
2889
+ const resourceAttributes = convertOtlpAttributes((_a = resourceSpans.resource) == null ? void 0 : _a.attributes);
2890
+ for (const scopeSpans of resourceSpans.scopeSpans || []) {
2891
+ const scope = {
2892
+ name: (_b = scopeSpans.scope) == null ? void 0 : _b.name,
2893
+ version: (_c = scopeSpans.scope) == null ? void 0 : _c.version
2894
+ };
2895
+ for (const otlpSpan of scopeSpans.spans || []) {
2896
+ const spanAttributes = convertOtlpAttributes(otlpSpan.attributes);
2897
+ const events = (otlpSpan.events || []).map((otlpEvent) => ({
2898
+ timeUnixNano: otlpEvent.timeUnixNano,
2899
+ name: otlpEvent.name,
2900
+ attributes: convertOtlpAttributes(otlpEvent.attributes)
2901
+ }));
2902
+ const links = (otlpSpan.links || []).map((otlpLink) => ({
2903
+ traceId: otlpLink.traceId,
2904
+ spanId: otlpLink.spanId,
2905
+ traceState: otlpLink.traceState,
2906
+ attributes: convertOtlpAttributes(otlpLink.attributes)
2907
+ }));
2908
+ const span = {
2909
+ traceId: otlpSpan.traceId,
2910
+ spanId: otlpSpan.spanId,
2911
+ parentSpanId: otlpSpan.parentSpanId,
2912
+ traceState: otlpSpan.traceState,
2913
+ name: otlpSpan.name,
2914
+ kind: otlpSpan.kind,
2915
+ startTimeUnixNano: otlpSpan.startTimeUnixNano,
2916
+ endTimeUnixNano: otlpSpan.endTimeUnixNano,
2917
+ attributes: spanAttributes,
2918
+ events,
2919
+ links,
2920
+ status: otlpSpan.status
2921
+ };
2922
+ const resource = {
2923
+ attributes: resourceAttributes
2924
+ };
2925
+ result.push({ resource, scope, span });
2926
+ }
2927
+ }
2928
+ return result;
2929
+ }
2930
+
2306
2931
  // src/normalizer/type-classifier.ts
2307
2932
  var TypeClassifier = class {
2308
2933
  classify(span, attributes) {
@@ -2325,7 +2950,7 @@ registry.register("ai", new AiSdkTransformer());
2325
2950
  registry.register("default-tracer", new MastraTransformer());
2326
2951
  registry.register("agentmark", new AgentMarkTransformer());
2327
2952
  registry.register("pydantic-ai", new OtelGenAiTransformer());
2328
- registry.setDefault(new OtelGenAiTransformer());
2953
+ registry.setDefault(new DispatchingTransformer());
2329
2954
  var OTLP_STATUS_CODE_MAP = {
2330
2955
  "0": "0",
2331
2956
  STATUS_CODE_UNSET: "0",
@@ -2448,31 +3073,40 @@ export {
2448
3073
  AgentMarkTransformer,
2449
3074
  AiSdkTransformer,
2450
3075
  AgentMarkTransformer as ClaudeAgentTransformer,
3076
+ DispatchingTransformer,
2451
3077
  MastraTransformer,
3078
+ OpenInferenceTransformer,
3079
+ OpenLLMetryTransformer,
2452
3080
  OtelGenAiTransformer,
2453
3081
  SEMANTIC_KINDS,
2454
3082
  SpanType,
2455
3083
  TransformerRegistry,
2456
3084
  TypeClassifier,
3085
+ collectIndices,
2457
3086
  convertOtlpAttributes,
2458
3087
  createSignature,
2459
3088
  deriveTraceIO,
2460
3089
  detectVersion,
2461
3090
  extractCustomMetadata,
3091
+ extractIndexedToolCalls,
2462
3092
  extractReasoningFromProviderMetadata,
2463
3093
  extractResourceScopeSpan,
2464
3094
  fetchPromptsFrontmatter,
2465
3095
  findPromptFiles,
2466
3096
  generateTypeDefinitions,
2467
3097
  generateUnique8CharString,
3098
+ hasVectorStoreSignature,
3099
+ messagesToPlainText,
2468
3100
  normalizeOtlpSpans,
2469
3101
  normalizeOtlpStatusCode,
2470
3102
  normalizeSpan,
2471
3103
  parseAgentMarkAttributes,
3104
+ parseIndexedMessages,
2472
3105
  parseMetadata,
2473
3106
  parseTokens,
2474
3107
  registry,
2475
3108
  resolveSemanticKind,
3109
+ retrievalDocumentsToText,
2476
3110
  toFrontMatter,
2477
3111
  typeClassifier,
2478
3112
  verifySignature