@agentmark-ai/shared-utils 0.6.0 → 0.7.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.d.mts +163 -1
- package/dist/index.d.ts +163 -1
- package/dist/index.js +530 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +523 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -34,27 +34,34 @@ __export(index_exports, {
|
|
|
34
34
|
AgentMarkTransformer: () => AgentMarkTransformer,
|
|
35
35
|
AiSdkTransformer: () => AiSdkTransformer,
|
|
36
36
|
ClaudeAgentTransformer: () => AgentMarkTransformer,
|
|
37
|
+
DispatchingTransformer: () => DispatchingTransformer,
|
|
37
38
|
MastraTransformer: () => MastraTransformer,
|
|
39
|
+
OpenInferenceTransformer: () => OpenInferenceTransformer,
|
|
40
|
+
OpenLLMetryTransformer: () => OpenLLMetryTransformer,
|
|
38
41
|
OtelGenAiTransformer: () => OtelGenAiTransformer,
|
|
39
42
|
SEMANTIC_KINDS: () => SEMANTIC_KINDS,
|
|
40
43
|
SpanType: () => SpanType,
|
|
41
44
|
TransformerRegistry: () => TransformerRegistry,
|
|
42
45
|
TypeClassifier: () => TypeClassifier,
|
|
46
|
+
collectIndices: () => collectIndices,
|
|
43
47
|
convertOtlpAttributes: () => convertOtlpAttributes,
|
|
44
48
|
createSignature: () => createSignature,
|
|
45
49
|
deriveTraceIO: () => deriveTraceIO,
|
|
46
50
|
detectVersion: () => detectVersion,
|
|
47
51
|
extractCustomMetadata: () => extractCustomMetadata,
|
|
52
|
+
extractIndexedToolCalls: () => extractIndexedToolCalls,
|
|
48
53
|
extractReasoningFromProviderMetadata: () => extractReasoningFromProviderMetadata,
|
|
49
54
|
extractResourceScopeSpan: () => extractResourceScopeSpan,
|
|
50
55
|
fetchPromptsFrontmatter: () => fetchPromptsFrontmatter,
|
|
51
56
|
findPromptFiles: () => findPromptFiles,
|
|
52
57
|
generateTypeDefinitions: () => generateTypeDefinitions,
|
|
53
58
|
generateUnique8CharString: () => generateUnique8CharString,
|
|
59
|
+
messagesToPlainText: () => messagesToPlainText,
|
|
54
60
|
normalizeOtlpSpans: () => normalizeOtlpSpans,
|
|
55
61
|
normalizeOtlpStatusCode: () => normalizeOtlpStatusCode,
|
|
56
62
|
normalizeSpan: () => normalizeSpan,
|
|
57
63
|
parseAgentMarkAttributes: () => parseAgentMarkAttributes,
|
|
64
|
+
parseIndexedMessages: () => parseIndexedMessages,
|
|
58
65
|
parseMetadata: () => parseMetadata,
|
|
59
66
|
parseTokens: () => parseTokens,
|
|
60
67
|
registry: () => registry,
|
|
@@ -1997,7 +2004,7 @@ var Attrs = {
|
|
|
1997
2004
|
USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens",
|
|
1998
2005
|
// v1.37.0+ content attributes (canonical OTel GenAI semantic conventions).
|
|
1999
2006
|
// SDKs that emit the AgentMark-scoped equivalents (`gen_ai.request.input`
|
|
2000
|
-
// / `gen_ai.response.output`
|
|
2007
|
+
// / `gen_ai.response.output`) are
|
|
2001
2008
|
// also accepted here as fallbacks so an SDK picking either key set
|
|
2002
2009
|
// doesn't silently lose IO data on ingest. The canonical pair always wins
|
|
2003
2010
|
// when both are present.
|
|
@@ -2203,6 +2210,520 @@ var OtelGenAiTransformer = class {
|
|
|
2203
2210
|
};
|
|
2204
2211
|
OtelGenAiTransformer.SCOPE_NAME = "pydantic-ai";
|
|
2205
2212
|
|
|
2213
|
+
// src/normalizer/extractors/indexed-message-parser.ts
|
|
2214
|
+
function escapeRegExp(value) {
|
|
2215
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2216
|
+
}
|
|
2217
|
+
function collectIndices(attributes, prefix) {
|
|
2218
|
+
const re = new RegExp(`^${escapeRegExp(prefix)}\\.(\\d+)\\.`);
|
|
2219
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2220
|
+
for (const key of Object.keys(attributes)) {
|
|
2221
|
+
const match = re.exec(key);
|
|
2222
|
+
if (match) seen.add(Number(match[1]));
|
|
2223
|
+
}
|
|
2224
|
+
return [...seen].sort((a, b) => a - b);
|
|
2225
|
+
}
|
|
2226
|
+
function parseArgs(raw) {
|
|
2227
|
+
if (raw === void 0 || raw === null) return {};
|
|
2228
|
+
if (typeof raw === "object") return raw;
|
|
2229
|
+
if (typeof raw === "string") {
|
|
2230
|
+
try {
|
|
2231
|
+
const parsed = JSON.parse(raw);
|
|
2232
|
+
return parsed && typeof parsed === "object" ? parsed : { raw };
|
|
2233
|
+
} catch {
|
|
2234
|
+
return { raw };
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
return { raw };
|
|
2238
|
+
}
|
|
2239
|
+
function readMessageToolCalls(attributes, messageBase, config) {
|
|
2240
|
+
const tc = config.toolCalls;
|
|
2241
|
+
if (!tc) return [];
|
|
2242
|
+
const arrayPrefix = `${messageBase}${tc.arrayKey}`;
|
|
2243
|
+
const indices = collectIndices(attributes, arrayPrefix);
|
|
2244
|
+
const calls = [];
|
|
2245
|
+
for (const j of indices) {
|
|
2246
|
+
const base = `${arrayPrefix}.${j}.${tc.infix}`;
|
|
2247
|
+
const name = attributes[`${base}${tc.nameKey}`];
|
|
2248
|
+
if (name === void 0) continue;
|
|
2249
|
+
const id = attributes[`${base}${tc.idKey}`];
|
|
2250
|
+
const args = parseArgs(attributes[`${base}${tc.argsKey}`]);
|
|
2251
|
+
calls.push({
|
|
2252
|
+
type: "tool-call",
|
|
2253
|
+
toolCallId: id !== void 0 ? String(id) : "",
|
|
2254
|
+
toolName: String(name),
|
|
2255
|
+
args
|
|
2256
|
+
});
|
|
2257
|
+
}
|
|
2258
|
+
return calls;
|
|
2259
|
+
}
|
|
2260
|
+
function readContentsText(attributes, messageBase, config) {
|
|
2261
|
+
var _a;
|
|
2262
|
+
if (!config.contentsKey) return void 0;
|
|
2263
|
+
const contentsPrefix = `${messageBase}${config.contentsKey}`;
|
|
2264
|
+
const indices = collectIndices(attributes, contentsPrefix);
|
|
2265
|
+
if (indices.length === 0) return void 0;
|
|
2266
|
+
const partInfix = (_a = config.contentsPartInfix) != null ? _a : "";
|
|
2267
|
+
const parts = [];
|
|
2268
|
+
for (const j of indices) {
|
|
2269
|
+
const text = attributes[`${contentsPrefix}.${j}.${partInfix}text`];
|
|
2270
|
+
if (typeof text === "string" && text.length > 0) parts.push(text);
|
|
2271
|
+
}
|
|
2272
|
+
return parts.length > 0 ? parts.join("\n") : void 0;
|
|
2273
|
+
}
|
|
2274
|
+
function parseIndexedMessages(attributes, config) {
|
|
2275
|
+
var _a, _b;
|
|
2276
|
+
const indices = collectIndices(attributes, config.prefix);
|
|
2277
|
+
if (indices.length === 0) return void 0;
|
|
2278
|
+
const roleKey = (_a = config.roleKey) != null ? _a : "role";
|
|
2279
|
+
const contentKey = (_b = config.contentKey) != null ? _b : "content";
|
|
2280
|
+
const messages = [];
|
|
2281
|
+
for (const i of indices) {
|
|
2282
|
+
const base = `${config.prefix}.${i}.${config.messageInfix}`;
|
|
2283
|
+
const role = attributes[`${base}${roleKey}`];
|
|
2284
|
+
const scalarContent = attributes[`${base}${contentKey}`];
|
|
2285
|
+
const text = typeof scalarContent === "string" ? scalarContent : scalarContent !== void 0 ? String(scalarContent) : readContentsText(attributes, base, config);
|
|
2286
|
+
const toolCalls = readMessageToolCalls(attributes, base, config);
|
|
2287
|
+
if (role === void 0 && text === void 0 && toolCalls.length === 0) continue;
|
|
2288
|
+
let content;
|
|
2289
|
+
if (toolCalls.length > 0) {
|
|
2290
|
+
const parts = [];
|
|
2291
|
+
if (text) parts.push({ type: "text", text });
|
|
2292
|
+
for (const call of toolCalls) {
|
|
2293
|
+
parts.push({
|
|
2294
|
+
type: "tool-call",
|
|
2295
|
+
toolCallId: call.toolCallId,
|
|
2296
|
+
toolName: call.toolName,
|
|
2297
|
+
args: call.args
|
|
2298
|
+
});
|
|
2299
|
+
}
|
|
2300
|
+
content = parts;
|
|
2301
|
+
} else {
|
|
2302
|
+
content = text != null ? text : "";
|
|
2303
|
+
}
|
|
2304
|
+
messages.push({ role: role !== void 0 ? String(role) : "user", content });
|
|
2305
|
+
}
|
|
2306
|
+
return messages.length > 0 ? messages : void 0;
|
|
2307
|
+
}
|
|
2308
|
+
function extractIndexedToolCalls(attributes, config) {
|
|
2309
|
+
if (!config.toolCalls) return void 0;
|
|
2310
|
+
const indices = collectIndices(attributes, config.prefix);
|
|
2311
|
+
const calls = [];
|
|
2312
|
+
for (const i of indices) {
|
|
2313
|
+
const base = `${config.prefix}.${i}.${config.messageInfix}`;
|
|
2314
|
+
calls.push(...readMessageToolCalls(attributes, base, config));
|
|
2315
|
+
}
|
|
2316
|
+
return calls.length > 0 ? calls : void 0;
|
|
2317
|
+
}
|
|
2318
|
+
function messagesToPlainText(messages) {
|
|
2319
|
+
if (!messages || messages.length === 0) return void 0;
|
|
2320
|
+
const chunks = [];
|
|
2321
|
+
for (const msg of messages) {
|
|
2322
|
+
if (typeof msg.content === "string") {
|
|
2323
|
+
if (msg.content.length > 0) chunks.push(msg.content);
|
|
2324
|
+
} else if (Array.isArray(msg.content)) {
|
|
2325
|
+
for (const part of msg.content) {
|
|
2326
|
+
if (typeof part === "string") {
|
|
2327
|
+
if (part.length > 0) chunks.push(part);
|
|
2328
|
+
} else if (part.type === "text" && part.text.length > 0) {
|
|
2329
|
+
chunks.push(part.text);
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
return chunks.length > 0 ? chunks.join("\n") : void 0;
|
|
2335
|
+
}
|
|
2336
|
+
|
|
2337
|
+
// src/normalizer/utils/coerce.ts
|
|
2338
|
+
function toNumber(value) {
|
|
2339
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : void 0;
|
|
2340
|
+
if (typeof value === "string") {
|
|
2341
|
+
const n = Number(value);
|
|
2342
|
+
return Number.isFinite(n) ? n : void 0;
|
|
2343
|
+
}
|
|
2344
|
+
return void 0;
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2347
|
+
// src/normalizer/transformers/openinference/index.ts
|
|
2348
|
+
var Attrs2 = {
|
|
2349
|
+
SPAN_KIND: "openinference.span.kind",
|
|
2350
|
+
MODEL: "llm.model_name",
|
|
2351
|
+
PROVIDER: "llm.provider",
|
|
2352
|
+
SYSTEM: "llm.system",
|
|
2353
|
+
INVOCATION_PARAMETERS: "llm.invocation_parameters",
|
|
2354
|
+
TOKEN_PROMPT: "llm.token_count.prompt",
|
|
2355
|
+
TOKEN_COMPLETION: "llm.token_count.completion",
|
|
2356
|
+
TOKEN_TOTAL: "llm.token_count.total",
|
|
2357
|
+
TOKEN_REASONING: "llm.token_count.completion_details.reasoning",
|
|
2358
|
+
INPUT_VALUE: "input.value",
|
|
2359
|
+
INPUT_MIME: "input.mime_type",
|
|
2360
|
+
OUTPUT_VALUE: "output.value",
|
|
2361
|
+
OUTPUT_MIME: "output.mime_type",
|
|
2362
|
+
TOOL_NAME: "tool.name",
|
|
2363
|
+
SESSION_ID: "session.id",
|
|
2364
|
+
USER_ID: "user.id",
|
|
2365
|
+
METADATA: "metadata"
|
|
2366
|
+
};
|
|
2367
|
+
var INPUT_MESSAGES = {
|
|
2368
|
+
prefix: "llm.input_messages",
|
|
2369
|
+
messageInfix: "message.",
|
|
2370
|
+
contentsKey: "contents",
|
|
2371
|
+
contentsPartInfix: "message_content.",
|
|
2372
|
+
toolCalls: {
|
|
2373
|
+
arrayKey: "tool_calls",
|
|
2374
|
+
infix: "tool_call.",
|
|
2375
|
+
idKey: "id",
|
|
2376
|
+
nameKey: "function.name",
|
|
2377
|
+
argsKey: "function.arguments"
|
|
2378
|
+
}
|
|
2379
|
+
};
|
|
2380
|
+
var OUTPUT_MESSAGES = {
|
|
2381
|
+
...INPUT_MESSAGES,
|
|
2382
|
+
prefix: "llm.output_messages"
|
|
2383
|
+
};
|
|
2384
|
+
var RETRIEVAL_PREFIX = "retrieval.documents";
|
|
2385
|
+
function extractSettings(attributes) {
|
|
2386
|
+
var _a, _b, _c, _d, _e;
|
|
2387
|
+
const raw = attributes[Attrs2.INVOCATION_PARAMETERS];
|
|
2388
|
+
if (raw === void 0) return void 0;
|
|
2389
|
+
let parsed;
|
|
2390
|
+
if (typeof raw === "string") {
|
|
2391
|
+
try {
|
|
2392
|
+
parsed = JSON.parse(raw);
|
|
2393
|
+
} catch {
|
|
2394
|
+
return void 0;
|
|
2395
|
+
}
|
|
2396
|
+
} else if (typeof raw === "object" && raw !== null) {
|
|
2397
|
+
parsed = raw;
|
|
2398
|
+
} else {
|
|
2399
|
+
return void 0;
|
|
2400
|
+
}
|
|
2401
|
+
if (!parsed || typeof parsed !== "object") return void 0;
|
|
2402
|
+
const settings = {};
|
|
2403
|
+
const temperature = toNumber(parsed.temperature);
|
|
2404
|
+
const maxTokens = toNumber((_b = (_a = parsed.max_tokens) != null ? _a : parsed.maxTokens) != null ? _b : parsed.max_completion_tokens);
|
|
2405
|
+
const topP = toNumber((_c = parsed.top_p) != null ? _c : parsed.topP);
|
|
2406
|
+
const presencePenalty = toNumber((_d = parsed.presence_penalty) != null ? _d : parsed.presencePenalty);
|
|
2407
|
+
const frequencyPenalty = toNumber((_e = parsed.frequency_penalty) != null ? _e : parsed.frequencyPenalty);
|
|
2408
|
+
if (temperature !== void 0) settings.temperature = temperature;
|
|
2409
|
+
if (maxTokens !== void 0) settings.maxTokens = maxTokens;
|
|
2410
|
+
if (topP !== void 0) settings.topP = topP;
|
|
2411
|
+
if (presencePenalty !== void 0) settings.presencePenalty = presencePenalty;
|
|
2412
|
+
if (frequencyPenalty !== void 0) settings.frequencyPenalty = frequencyPenalty;
|
|
2413
|
+
return Object.keys(settings).length > 0 ? settings : void 0;
|
|
2414
|
+
}
|
|
2415
|
+
function extractGenericInput(attributes) {
|
|
2416
|
+
const value = attributes[Attrs2.INPUT_VALUE];
|
|
2417
|
+
if (value === void 0) return {};
|
|
2418
|
+
const mime = attributes[Attrs2.INPUT_MIME];
|
|
2419
|
+
if (mime === "application/json" && typeof value === "string") {
|
|
2420
|
+
try {
|
|
2421
|
+
const parsed = JSON.parse(value);
|
|
2422
|
+
if (Array.isArray(parsed) && parsed.every((m) => m && typeof m === "object" && "role" in m)) {
|
|
2423
|
+
return { input: parsed };
|
|
2424
|
+
}
|
|
2425
|
+
return { input: [{ role: "user", content: JSON.stringify(parsed) }] };
|
|
2426
|
+
} catch {
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
return { input: [{ role: "user", content: String(value) }] };
|
|
2430
|
+
}
|
|
2431
|
+
function extractGenericOutput(attributes) {
|
|
2432
|
+
const value = attributes[Attrs2.OUTPUT_VALUE];
|
|
2433
|
+
if (value === void 0) return {};
|
|
2434
|
+
const mime = attributes[Attrs2.OUTPUT_MIME];
|
|
2435
|
+
if (mime === "application/json" && typeof value === "string") {
|
|
2436
|
+
try {
|
|
2437
|
+
const parsed = JSON.parse(value);
|
|
2438
|
+
return { output: JSON.stringify(parsed), outputObject: parsed };
|
|
2439
|
+
} catch {
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
return { output: String(value) };
|
|
2443
|
+
}
|
|
2444
|
+
function extractRetrievalDocuments(attributes) {
|
|
2445
|
+
const docs = [];
|
|
2446
|
+
for (const i of collectIndices(attributes, RETRIEVAL_PREFIX)) {
|
|
2447
|
+
const content = attributes[`${RETRIEVAL_PREFIX}.${i}.document.content`];
|
|
2448
|
+
if (typeof content === "string" && content.length > 0) docs.push(content);
|
|
2449
|
+
}
|
|
2450
|
+
return docs.length > 0 ? docs.join("\n\n") : void 0;
|
|
2451
|
+
}
|
|
2452
|
+
var OpenInferenceTransformer = class {
|
|
2453
|
+
classify(_span, attributes) {
|
|
2454
|
+
const kind = attributes[Attrs2.SPAN_KIND];
|
|
2455
|
+
if (typeof kind === "string" && kind.toUpperCase() === "LLM") return "GENERATION" /* GENERATION */;
|
|
2456
|
+
if (attributes[Attrs2.TOKEN_PROMPT] !== void 0 || attributes[Attrs2.TOKEN_COMPLETION] !== void 0) {
|
|
2457
|
+
return "GENERATION" /* GENERATION */;
|
|
2458
|
+
}
|
|
2459
|
+
return "SPAN" /* SPAN */;
|
|
2460
|
+
}
|
|
2461
|
+
transform(_span, attributes) {
|
|
2462
|
+
const result = {};
|
|
2463
|
+
const model = attributes[Attrs2.MODEL];
|
|
2464
|
+
if (typeof model === "string" && model.length > 0) result.model = model;
|
|
2465
|
+
const inputTokens = toNumber(attributes[Attrs2.TOKEN_PROMPT]);
|
|
2466
|
+
const outputTokens = toNumber(attributes[Attrs2.TOKEN_COMPLETION]);
|
|
2467
|
+
const totalTokens = toNumber(attributes[Attrs2.TOKEN_TOTAL]);
|
|
2468
|
+
const reasoningTokens = toNumber(attributes[Attrs2.TOKEN_REASONING]);
|
|
2469
|
+
if (inputTokens !== void 0) result.inputTokens = inputTokens;
|
|
2470
|
+
if (outputTokens !== void 0) result.outputTokens = outputTokens;
|
|
2471
|
+
if (totalTokens !== void 0) {
|
|
2472
|
+
result.totalTokens = totalTokens;
|
|
2473
|
+
} else if (inputTokens !== void 0 && outputTokens !== void 0) {
|
|
2474
|
+
result.totalTokens = inputTokens + outputTokens;
|
|
2475
|
+
}
|
|
2476
|
+
if (reasoningTokens !== void 0) result.reasoningTokens = reasoningTokens;
|
|
2477
|
+
const settings = extractSettings(attributes);
|
|
2478
|
+
if (settings) result.settings = settings;
|
|
2479
|
+
const inputMessages = parseIndexedMessages(attributes, INPUT_MESSAGES);
|
|
2480
|
+
if (inputMessages) {
|
|
2481
|
+
result.input = inputMessages;
|
|
2482
|
+
} else {
|
|
2483
|
+
Object.assign(result, extractGenericInput(attributes));
|
|
2484
|
+
}
|
|
2485
|
+
const outputMessages = parseIndexedMessages(attributes, OUTPUT_MESSAGES);
|
|
2486
|
+
const toolCalls = extractIndexedToolCalls(attributes, OUTPUT_MESSAGES);
|
|
2487
|
+
if (toolCalls) result.toolCalls = toolCalls;
|
|
2488
|
+
if (outputMessages) {
|
|
2489
|
+
const text = messagesToPlainText(outputMessages);
|
|
2490
|
+
if (text) result.output = text;
|
|
2491
|
+
} else {
|
|
2492
|
+
Object.assign(result, extractGenericOutput(attributes));
|
|
2493
|
+
}
|
|
2494
|
+
if (result.output === void 0) {
|
|
2495
|
+
const docs = extractRetrievalDocuments(attributes);
|
|
2496
|
+
if (docs) result.output = docs;
|
|
2497
|
+
}
|
|
2498
|
+
const toolName = attributes[Attrs2.TOOL_NAME];
|
|
2499
|
+
if (typeof toolName === "string" && toolName.length > 0) result.name = toolName;
|
|
2500
|
+
const sessionId = attributes[Attrs2.SESSION_ID];
|
|
2501
|
+
if (sessionId !== void 0) result.sessionId = String(sessionId);
|
|
2502
|
+
const userId = attributes[Attrs2.USER_ID];
|
|
2503
|
+
if (userId !== void 0) result.userId = String(userId);
|
|
2504
|
+
const metadataRaw = attributes[Attrs2.METADATA];
|
|
2505
|
+
if (metadataRaw !== void 0) {
|
|
2506
|
+
let parsed = metadataRaw;
|
|
2507
|
+
if (typeof metadataRaw === "string") {
|
|
2508
|
+
try {
|
|
2509
|
+
parsed = JSON.parse(metadataRaw);
|
|
2510
|
+
} catch {
|
|
2511
|
+
parsed = void 0;
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
2515
|
+
const metadata = {};
|
|
2516
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
2517
|
+
metadata[k] = typeof v === "string" ? v : JSON.stringify(v);
|
|
2518
|
+
}
|
|
2519
|
+
if (Object.keys(metadata).length > 0) result.metadata = metadata;
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
return result;
|
|
2523
|
+
}
|
|
2524
|
+
};
|
|
2525
|
+
|
|
2526
|
+
// src/normalizer/transformers/openllmetry/index.ts
|
|
2527
|
+
var Attrs3 = {
|
|
2528
|
+
SPAN_KIND: "traceloop.span.kind",
|
|
2529
|
+
REQUEST_MODEL: "gen_ai.request.model",
|
|
2530
|
+
RESPONSE_MODEL: "gen_ai.response.model",
|
|
2531
|
+
REQUEST_TEMPERATURE: "gen_ai.request.temperature",
|
|
2532
|
+
REQUEST_MAX_TOKENS: "gen_ai.request.max_tokens",
|
|
2533
|
+
REQUEST_TOP_P: "gen_ai.request.top_p",
|
|
2534
|
+
REQUEST_PRESENCE_PENALTY: "gen_ai.request.presence_penalty",
|
|
2535
|
+
REQUEST_FREQUENCY_PENALTY: "gen_ai.request.frequency_penalty",
|
|
2536
|
+
RESPONSE_FINISH_REASON: "gen_ai.response.finish_reason",
|
|
2537
|
+
TOTAL_TOKENS_ALT: "llm.usage.total_tokens",
|
|
2538
|
+
ENTITY_INPUT: "traceloop.entity.input",
|
|
2539
|
+
ENTITY_OUTPUT: "traceloop.entity.output",
|
|
2540
|
+
ENTITY_NAME: "traceloop.entity.name",
|
|
2541
|
+
ASSOCIATION_PREFIX: "traceloop.association.properties."
|
|
2542
|
+
};
|
|
2543
|
+
var PROMPT_MESSAGES = {
|
|
2544
|
+
prefix: "gen_ai.prompt",
|
|
2545
|
+
messageInfix: "",
|
|
2546
|
+
toolCalls: { arrayKey: "tool_calls", infix: "", idKey: "id", nameKey: "name", argsKey: "arguments" }
|
|
2547
|
+
};
|
|
2548
|
+
var COMPLETION_MESSAGES = {
|
|
2549
|
+
...PROMPT_MESSAGES,
|
|
2550
|
+
prefix: "gen_ai.completion"
|
|
2551
|
+
};
|
|
2552
|
+
function extractSettings2(attributes) {
|
|
2553
|
+
const settings = {};
|
|
2554
|
+
const temperature = toNumber(attributes[Attrs3.REQUEST_TEMPERATURE]);
|
|
2555
|
+
const maxTokens = toNumber(attributes[Attrs3.REQUEST_MAX_TOKENS]);
|
|
2556
|
+
const topP = toNumber(attributes[Attrs3.REQUEST_TOP_P]);
|
|
2557
|
+
const presencePenalty = toNumber(attributes[Attrs3.REQUEST_PRESENCE_PENALTY]);
|
|
2558
|
+
const frequencyPenalty = toNumber(attributes[Attrs3.REQUEST_FREQUENCY_PENALTY]);
|
|
2559
|
+
if (temperature !== void 0) settings.temperature = temperature;
|
|
2560
|
+
if (maxTokens !== void 0) settings.maxTokens = maxTokens;
|
|
2561
|
+
if (topP !== void 0) settings.topP = topP;
|
|
2562
|
+
if (presencePenalty !== void 0) settings.presencePenalty = presencePenalty;
|
|
2563
|
+
if (frequencyPenalty !== void 0) settings.frequencyPenalty = frequencyPenalty;
|
|
2564
|
+
return Object.keys(settings).length > 0 ? settings : void 0;
|
|
2565
|
+
}
|
|
2566
|
+
function extractEntityInput(attributes) {
|
|
2567
|
+
const raw = attributes[Attrs3.ENTITY_INPUT];
|
|
2568
|
+
if (raw === void 0) return void 0;
|
|
2569
|
+
const text = typeof raw === "string" ? raw : JSON.stringify(raw);
|
|
2570
|
+
return [{ role: "user", content: text }];
|
|
2571
|
+
}
|
|
2572
|
+
function extractEntityOutput(attributes) {
|
|
2573
|
+
const raw = attributes[Attrs3.ENTITY_OUTPUT];
|
|
2574
|
+
if (raw === void 0) return {};
|
|
2575
|
+
if (typeof raw === "string") {
|
|
2576
|
+
try {
|
|
2577
|
+
const parsed = JSON.parse(raw);
|
|
2578
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
2579
|
+
return { output: raw, outputObject: parsed };
|
|
2580
|
+
}
|
|
2581
|
+
} catch {
|
|
2582
|
+
}
|
|
2583
|
+
return { output: raw };
|
|
2584
|
+
}
|
|
2585
|
+
const result = { output: JSON.stringify(raw) };
|
|
2586
|
+
if (typeof raw === "object" && raw !== null) result.outputObject = raw;
|
|
2587
|
+
return result;
|
|
2588
|
+
}
|
|
2589
|
+
function extractFromEvents(events, attrKey) {
|
|
2590
|
+
var _a, _b, _c;
|
|
2591
|
+
if (!events) return void 0;
|
|
2592
|
+
for (const event of events) {
|
|
2593
|
+
const value = (_c = (_a = event.attributes) == null ? void 0 : _a[attrKey]) != null ? _c : (_b = event.attributes) == null ? void 0 : _b["content"];
|
|
2594
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
2595
|
+
}
|
|
2596
|
+
return void 0;
|
|
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;
|
|
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
|
+
const entityName = attributes[Attrs3.ENTITY_NAME];
|
|
2668
|
+
if (typeof entityName === "string" && entityName.length > 0) result.traceName = entityName;
|
|
2669
|
+
const metadata = {};
|
|
2670
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
2671
|
+
if (!key.startsWith(Attrs3.ASSOCIATION_PREFIX)) continue;
|
|
2672
|
+
const prop = key.slice(Attrs3.ASSOCIATION_PREFIX.length);
|
|
2673
|
+
if (prop === "session_id") {
|
|
2674
|
+
result.sessionId = String(value);
|
|
2675
|
+
} else if (prop === "user_id") {
|
|
2676
|
+
result.userId = String(value);
|
|
2677
|
+
} else if (prop) {
|
|
2678
|
+
metadata[prop] = typeof value === "string" ? value : JSON.stringify(value);
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
if (Object.keys(metadata).length > 0) result.metadata = metadata;
|
|
2682
|
+
return result;
|
|
2683
|
+
}
|
|
2684
|
+
};
|
|
2685
|
+
|
|
2686
|
+
// src/normalizer/transformers/dispatching/index.ts
|
|
2687
|
+
var OPENINFERENCE_INDEXED = /^llm\.(input_messages|output_messages|token_count)\./;
|
|
2688
|
+
var OPENLLMETRY_INDEXED = /^gen_ai\.(prompt|completion)\.\d+\./;
|
|
2689
|
+
function isOpenInference(attributes) {
|
|
2690
|
+
if (attributes["openinference.span.kind"] !== void 0) return true;
|
|
2691
|
+
if (attributes["llm.model_name"] !== void 0) return true;
|
|
2692
|
+
for (const key of Object.keys(attributes)) {
|
|
2693
|
+
if (OPENINFERENCE_INDEXED.test(key)) return true;
|
|
2694
|
+
}
|
|
2695
|
+
return false;
|
|
2696
|
+
}
|
|
2697
|
+
function isOpenLLMetry(attributes) {
|
|
2698
|
+
for (const key of Object.keys(attributes)) {
|
|
2699
|
+
if (key.startsWith("traceloop.")) return true;
|
|
2700
|
+
if (OPENLLMETRY_INDEXED.test(key)) return true;
|
|
2701
|
+
}
|
|
2702
|
+
return false;
|
|
2703
|
+
}
|
|
2704
|
+
var DispatchingTransformer = class {
|
|
2705
|
+
constructor() {
|
|
2706
|
+
this.openInference = new OpenInferenceTransformer();
|
|
2707
|
+
this.openLLMetry = new OpenLLMetryTransformer();
|
|
2708
|
+
this.otelGenAi = new OtelGenAiTransformer();
|
|
2709
|
+
}
|
|
2710
|
+
/** Choose the extractor for a span from its attribute signature. OpenInference
|
|
2711
|
+
* is checked before OpenLLMetry because its markers (`llm.*`,
|
|
2712
|
+
* `openinference.span.kind`) are more specific; the bare OTel GenAI
|
|
2713
|
+
* transformer is the catch-all. */
|
|
2714
|
+
select(attributes) {
|
|
2715
|
+
if (isOpenInference(attributes)) return this.openInference;
|
|
2716
|
+
if (isOpenLLMetry(attributes)) return this.openLLMetry;
|
|
2717
|
+
return this.otelGenAi;
|
|
2718
|
+
}
|
|
2719
|
+
classify(span, attributes) {
|
|
2720
|
+
return this.select(attributes).classify(span, attributes);
|
|
2721
|
+
}
|
|
2722
|
+
transform(span, attributes) {
|
|
2723
|
+
return this.select(attributes).transform(span, attributes);
|
|
2724
|
+
}
|
|
2725
|
+
};
|
|
2726
|
+
|
|
2206
2727
|
// src/normalizer/converters/otlp-converter.ts
|
|
2207
2728
|
function convertOtlpValue(value) {
|
|
2208
2729
|
var _a;
|
|
@@ -2392,7 +2913,7 @@ registry.register("ai", new AiSdkTransformer());
|
|
|
2392
2913
|
registry.register("default-tracer", new MastraTransformer());
|
|
2393
2914
|
registry.register("agentmark", new AgentMarkTransformer());
|
|
2394
2915
|
registry.register("pydantic-ai", new OtelGenAiTransformer());
|
|
2395
|
-
registry.setDefault(new
|
|
2916
|
+
registry.setDefault(new DispatchingTransformer());
|
|
2396
2917
|
var OTLP_STATUS_CODE_MAP = {
|
|
2397
2918
|
"0": "0",
|
|
2398
2919
|
STATUS_CODE_UNSET: "0",
|
|
@@ -2516,27 +3037,34 @@ function deriveTraceIO(spans) {
|
|
|
2516
3037
|
AgentMarkTransformer,
|
|
2517
3038
|
AiSdkTransformer,
|
|
2518
3039
|
ClaudeAgentTransformer,
|
|
3040
|
+
DispatchingTransformer,
|
|
2519
3041
|
MastraTransformer,
|
|
3042
|
+
OpenInferenceTransformer,
|
|
3043
|
+
OpenLLMetryTransformer,
|
|
2520
3044
|
OtelGenAiTransformer,
|
|
2521
3045
|
SEMANTIC_KINDS,
|
|
2522
3046
|
SpanType,
|
|
2523
3047
|
TransformerRegistry,
|
|
2524
3048
|
TypeClassifier,
|
|
3049
|
+
collectIndices,
|
|
2525
3050
|
convertOtlpAttributes,
|
|
2526
3051
|
createSignature,
|
|
2527
3052
|
deriveTraceIO,
|
|
2528
3053
|
detectVersion,
|
|
2529
3054
|
extractCustomMetadata,
|
|
3055
|
+
extractIndexedToolCalls,
|
|
2530
3056
|
extractReasoningFromProviderMetadata,
|
|
2531
3057
|
extractResourceScopeSpan,
|
|
2532
3058
|
fetchPromptsFrontmatter,
|
|
2533
3059
|
findPromptFiles,
|
|
2534
3060
|
generateTypeDefinitions,
|
|
2535
3061
|
generateUnique8CharString,
|
|
3062
|
+
messagesToPlainText,
|
|
2536
3063
|
normalizeOtlpSpans,
|
|
2537
3064
|
normalizeOtlpStatusCode,
|
|
2538
3065
|
normalizeSpan,
|
|
2539
3066
|
parseAgentMarkAttributes,
|
|
3067
|
+
parseIndexedMessages,
|
|
2540
3068
|
parseMetadata,
|
|
2541
3069
|
parseTokens,
|
|
2542
3070
|
registry,
|