@agentmark-ai/shared-utils 0.1.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 ADDED
@@ -0,0 +1,1486 @@
1
+ // src/generate-unique-8-char-string.ts
2
+ var generateUnique8CharString = () => {
3
+ const timestamp = Date.now().toString(36);
4
+ const randomChars = Math.random().toString(36).substr(2, 6);
5
+ return timestamp + randomChars;
6
+ };
7
+
8
+ // src/hmac-256-signature.ts
9
+ var encoder = new TextEncoder();
10
+ async function createSignature(secret = "", payload) {
11
+ if (!secret) {
12
+ secret = "DEFAULT";
13
+ }
14
+ const algorithm = { name: "HMAC", hash: { name: "SHA-256" } };
15
+ const keyBytes = encoder.encode(secret);
16
+ const extractable = false;
17
+ const key = await crypto.subtle.importKey(
18
+ "raw",
19
+ keyBytes,
20
+ algorithm,
21
+ extractable,
22
+ ["sign", "verify"]
23
+ );
24
+ const signature = await crypto.subtle.sign(
25
+ algorithm,
26
+ key,
27
+ encoder.encode(payload)
28
+ );
29
+ return `sha256=${toHexString(signature)}`;
30
+ }
31
+ function toHexString(signature) {
32
+ return Array.from(new Uint8Array(signature)).map((b) => b.toString(16).padStart(2, "0")).join("");
33
+ }
34
+ async function verifySignature(secret, header, payload) {
35
+ if (!secret) {
36
+ secret = "DEFAULT";
37
+ }
38
+ const parts = header.split("=");
39
+ const sigHex = parts[1];
40
+ const algorithm = { name: "HMAC", hash: { name: "SHA-256" } };
41
+ const keyBytes = encoder.encode(secret);
42
+ const extractable = false;
43
+ const key = await crypto.subtle.importKey(
44
+ "raw",
45
+ keyBytes,
46
+ algorithm,
47
+ extractable,
48
+ ["sign", "verify"]
49
+ );
50
+ const sigBytes = hexToBytes(sigHex);
51
+ const dataBytes = encoder.encode(payload);
52
+ const equal = await crypto.subtle.verify(
53
+ algorithm.name,
54
+ key,
55
+ sigBytes,
56
+ dataBytes
57
+ );
58
+ return equal;
59
+ }
60
+ function hexToBytes(hex) {
61
+ const len = hex.length / 2;
62
+ const bytes = new Uint8Array(len);
63
+ let index = 0;
64
+ for (let i = 0; i < hex.length; i += 2) {
65
+ const c = hex.slice(i, i + 2);
66
+ const b = parseInt(c, 16);
67
+ bytes[index] = b;
68
+ index += 1;
69
+ }
70
+ return bytes;
71
+ }
72
+
73
+ // src/serialize.ts
74
+ function toFrontMatter(content) {
75
+ function jsonToFrontMatter(json, indent = 0) {
76
+ let frontMatter = "";
77
+ const indentation = " ".repeat(indent);
78
+ for (const key in json) {
79
+ if (Object.prototype.hasOwnProperty.call(json, key)) {
80
+ const value = json[key];
81
+ if (typeof value === "object" && !Array.isArray(value)) {
82
+ frontMatter += `${indentation}${key}:
83
+ `;
84
+ frontMatter += jsonToFrontMatter(value, indent + 1);
85
+ } else if (Array.isArray(value)) {
86
+ frontMatter += `${indentation}${key}:
87
+ `;
88
+ value.forEach((item) => {
89
+ if (typeof item === "object") {
90
+ frontMatter += `${indentation}-
91
+ `;
92
+ frontMatter += jsonToFrontMatter(item, indent + 2);
93
+ } else {
94
+ frontMatter += `${indentation}- ${item}
95
+ `;
96
+ }
97
+ });
98
+ } else {
99
+ frontMatter += `${indentation}${key}: ${value}
100
+ `;
101
+ }
102
+ }
103
+ }
104
+ return frontMatter;
105
+ }
106
+ return `---
107
+ ${jsonToFrontMatter(content)}---
108
+ `;
109
+ }
110
+
111
+ // src/generate-types.ts
112
+ import * as fs from "fs-extra";
113
+ import path from "path";
114
+ import fm from "front-matter";
115
+ var _compile = null;
116
+ async function getCompile() {
117
+ var _a;
118
+ if (_compile) return _compile;
119
+ const mod = await import("json-schema-to-typescript");
120
+ const c = mod.compile || ((_a = mod.default) == null ? void 0 : _a.compile);
121
+ _compile = c.bind(mod);
122
+ return _compile;
123
+ }
124
+ function getInterfaceName(filePath) {
125
+ return filePath.replace(/\.prompt\.mdx$/, "").split("/").map((part) => {
126
+ return part.split(/[-_]|(?=[A-Z])/).map(
127
+ (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
128
+ ).join("").replace(/[^a-zA-Z0-9]/g, "");
129
+ }).join("$");
130
+ }
131
+ function getToolInterfaceName(toolName) {
132
+ return toolName.split(/[-_]|(?=[A-Z])/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
133
+ }
134
+ async function findPromptFiles(dir) {
135
+ const files = await fs.readdir(dir, { withFileTypes: true });
136
+ let promptFiles = [];
137
+ for (const file of files) {
138
+ const fullPath = path.join(dir, file.name);
139
+ if (file.isDirectory()) {
140
+ promptFiles = promptFiles.concat(await findPromptFiles(fullPath));
141
+ } else if (file.name.endsWith(".prompt.mdx")) {
142
+ promptFiles.push(fullPath);
143
+ }
144
+ }
145
+ return promptFiles;
146
+ }
147
+ async function generateTypeDefinitionsV1_0(prompts) {
148
+ const interfaces = [];
149
+ const headerComment = `// Auto-generated types from AgentMark
150
+ // Do not edit this file directly
151
+
152
+ `;
153
+ let output = "";
154
+ const typeMapping = [];
155
+ for (const prompt of prompts) {
156
+ const { path: promptPath, input_schema } = prompt;
157
+ const name = getInterfaceName(promptPath);
158
+ let tools = {};
159
+ try {
160
+ let kind = "text";
161
+ let output_schema = null;
162
+ if ("text_config" in prompt) {
163
+ kind = "text";
164
+ tools = prompt.text_config.tools || {};
165
+ } else if ("object_config" in prompt) {
166
+ kind = "object";
167
+ tools = prompt.object_config.tools || {};
168
+ output_schema = prompt.object_config.schema;
169
+ } else if ("image_config" in prompt) {
170
+ kind = "image";
171
+ tools = prompt.image_config.tools || {};
172
+ }
173
+ const compile = await getCompile();
174
+ const inputInterface = input_schema ? await compile(input_schema, `${name}In`, {
175
+ bannerComment: "",
176
+ additionalProperties: false
177
+ }) : `interface ${name}In { [key: string]: any }`;
178
+ const toolTypes = await generateToolTypes(tools);
179
+ const outputInterface = output_schema ? await compile(output_schema, `${name}Out`, {
180
+ bannerComment: "",
181
+ additionalProperties: false
182
+ }) : `type ${name}Out = string`;
183
+ interfaces.push(
184
+ inputInterface.replace("export interface", "interface"),
185
+ outputInterface.replace("export type", "type").replace("export interface", "interface")
186
+ );
187
+ output += toolTypes || "";
188
+ output += `type ${name} = {
189
+ kind: '${kind}';
190
+ input: ${name}In;
191
+ output: ${name}Out;${toolTypes ? `
192
+ tools?: Array<keyof Tools>;` : ""}
193
+ };
194
+
195
+ `;
196
+ typeMapping.push(` "${promptPath}": ${name}`);
197
+ const withoutMdx = promptPath.replace(/\.mdx$/, "");
198
+ if (withoutMdx !== promptPath) {
199
+ typeMapping.push(` "${withoutMdx}": ${name}`);
200
+ }
201
+ const shortName = promptPath.replace(/\.prompt\.mdx$/, "");
202
+ if (shortName !== promptPath && shortName !== withoutMdx) {
203
+ typeMapping.push(` "${shortName}": ${name}`);
204
+ }
205
+ } catch (error) {
206
+ console.error(`Error processing ${promptPath}:`, error);
207
+ interfaces.push(
208
+ `interface ${name}In { [key: string]: any }
209
+ type ${name}Out = string`
210
+ );
211
+ }
212
+ }
213
+ output += `export default interface AgentmarkTypes {
214
+ ${typeMapping.join(",\n")}
215
+ }
216
+ `;
217
+ return headerComment + interfaces.join("\n\n") + "\n\n" + output;
218
+ }
219
+ async function generateTypeDefinitionsV0(prompts) {
220
+ var _a, _b;
221
+ const interfaces = [];
222
+ const headerComment = `// Auto-generated types from AgentMark
223
+ // Do not edit this file directly
224
+
225
+ `;
226
+ let output = "";
227
+ const typeMapping = [];
228
+ for (const prompt of prompts) {
229
+ const { path: promptPath, metadata, input_schema } = prompt;
230
+ const name = getInterfaceName(promptPath);
231
+ try {
232
+ const compile = await getCompile();
233
+ const inputInterface = input_schema ? await compile(input_schema, `${name}In`, {
234
+ bannerComment: "",
235
+ additionalProperties: false
236
+ }) : `interface ${name}In { [key: string]: any }`;
237
+ const outputSchema = (_b = (_a = metadata == null ? void 0 : metadata.model) == null ? void 0 : _a.settings) == null ? void 0 : _b.schema;
238
+ const outputInterface = outputSchema ? await compile(outputSchema, `${name}Out`, {
239
+ bannerComment: "",
240
+ additionalProperties: false
241
+ }) : `type ${name}Out = string`;
242
+ interfaces.push(
243
+ inputInterface.replace("export interface", "interface"),
244
+ outputInterface.replace("export type", "type").replace("export interface", "interface")
245
+ );
246
+ output += `interface ${name} {
247
+ input: ${name}In;
248
+ output: ${name}Out;
249
+ }
250
+
251
+ `;
252
+ typeMapping.push(` "${promptPath}": ${name}`);
253
+ const withoutMdx = promptPath.replace(/\.mdx$/, "");
254
+ if (withoutMdx !== promptPath) {
255
+ typeMapping.push(` "${withoutMdx}": ${name}`);
256
+ }
257
+ const shortName = promptPath.replace(/\.prompt\.mdx$/, "");
258
+ if (shortName !== promptPath && shortName !== withoutMdx) {
259
+ typeMapping.push(` "${shortName}": ${name}`);
260
+ }
261
+ } catch (error) {
262
+ console.error(`Error processing ${promptPath}:`, error);
263
+ interfaces.push(
264
+ `interface ${name}In { [key: string]: any }
265
+ type ${name}Out = string`
266
+ );
267
+ output += `interface ${name} {
268
+ input: ${name}In;
269
+ output: ${name}Out;
270
+ }
271
+
272
+ `;
273
+ typeMapping.push(` "${promptPath}": ${name}`);
274
+ const withoutMdx = promptPath.replace(/\.mdx$/, "");
275
+ if (withoutMdx !== promptPath) {
276
+ typeMapping.push(` "${withoutMdx}": ${name}`);
277
+ }
278
+ const shortName = promptPath.replace(/\.prompt\.mdx$/, "");
279
+ if (shortName !== promptPath && shortName !== withoutMdx) {
280
+ typeMapping.push(` "${shortName}": ${name}`);
281
+ }
282
+ }
283
+ }
284
+ output += `export default interface AgentmarkTypes {
285
+ ${typeMapping.join(",\n")}
286
+ }
287
+ `;
288
+ return headerComment + interfaces.join("\n\n") + "\n\n" + output;
289
+ }
290
+ var isNewFormat = (frontmatter) => {
291
+ return frontmatter["text_config"] || frontmatter["object_config"] || frontmatter["image_config"];
292
+ };
293
+ async function generateTypeDefinitions(prompts) {
294
+ if (prompts[0].version === "1.0") {
295
+ return generateTypeDefinitionsV1_0(prompts);
296
+ }
297
+ return generateTypeDefinitionsV0(prompts);
298
+ }
299
+ async function fetchPromptsFrontmatter(options) {
300
+ if (options.local) {
301
+ const baseUrl = `http://localhost:${options.local}`;
302
+ try {
303
+ const pathsResponse = await fetch(`${baseUrl}/v1/prompts`);
304
+ if (!pathsResponse.ok) {
305
+ throw new Error(
306
+ `Failed to fetch prompt paths: ${pathsResponse.statusText}`
307
+ );
308
+ }
309
+ const { paths } = await pathsResponse.json();
310
+ return Promise.all(
311
+ paths.map(async (promptPath) => {
312
+ const templateResponse = await fetch(
313
+ `${baseUrl}/v1/templates?path=${promptPath}`
314
+ );
315
+ if (!templateResponse.ok) {
316
+ throw new Error(
317
+ `Failed to fetch template ${promptPath}: ${templateResponse.statusText}`
318
+ );
319
+ }
320
+ const { data: ast } = await templateResponse.json();
321
+ const yamlNode = ast.children.find(
322
+ (node) => node.type === "yaml"
323
+ );
324
+ if (!yamlNode) {
325
+ throw new Error(`No YAML frontmatter found in ${promptPath}`);
326
+ }
327
+ const { parse: parseYaml } = await import("yaml");
328
+ const frontmatter = parseYaml(yamlNode.value);
329
+ if (isNewFormat(frontmatter)) {
330
+ return {
331
+ path: promptPath,
332
+ ...frontmatter,
333
+ version: "1.0"
334
+ };
335
+ }
336
+ return {
337
+ path: promptPath,
338
+ ...frontmatter
339
+ };
340
+ })
341
+ );
342
+ } catch (error) {
343
+ if (error instanceof TypeError && error.message.includes("fetch failed")) {
344
+ console.error(`Connection failed to ${baseUrl}.`);
345
+ }
346
+ console.error("\nError details:", error);
347
+ throw error;
348
+ }
349
+ }
350
+ if (options.rootDir) {
351
+ if (!fs.existsSync(options.rootDir)) {
352
+ throw new Error(`Directory not found at: ${options.rootDir}`);
353
+ }
354
+ const promptFiles = await findPromptFiles(options.rootDir);
355
+ return Promise.all(
356
+ promptFiles.map(async (file) => {
357
+ const content = await fs.readFile(file, "utf-8");
358
+ const { attributes } = fm(content);
359
+ if (isNewFormat(attributes)) {
360
+ return {
361
+ path: path.relative(options.rootDir, file),
362
+ ...attributes,
363
+ version: "1.0"
364
+ };
365
+ }
366
+ return {
367
+ path: path.relative(options.rootDir, file),
368
+ ...attributes
369
+ };
370
+ })
371
+ );
372
+ }
373
+ throw new Error("Either --local or --root-dir must be specified");
374
+ }
375
+ async function generateToolTypes(tools) {
376
+ const toolArgTypes = [];
377
+ for (const [toolName, schema] of Object.entries(tools)) {
378
+ const typeName = `${getToolInterfaceName(toolName)}Args`;
379
+ try {
380
+ const compile = await getCompile();
381
+ const argInterface = schema.parameters ? await compile(schema.parameters, typeName, {
382
+ bannerComment: "",
383
+ additionalProperties: false
384
+ }) : `type ${typeName} = { ${Object.entries(schema.parameters || {}).map(([key]) => `${key}: any`).join("; ")} };`;
385
+ toolArgTypes.push(
386
+ argInterface.replace("export type", "type").replace("export interface", "interface")
387
+ );
388
+ } catch (error) {
389
+ console.error(`Error processing tool ${toolName}:`, error);
390
+ toolArgTypes.push(`type ${typeName} = { [key: string]: any };`);
391
+ }
392
+ }
393
+ if (Object.keys(tools).length > 0) {
394
+ const toolsInterface = `export interface Tools {
395
+ ${Object.keys(tools).map(
396
+ (toolName) => ` ${toolName}: { args: ${getToolInterfaceName(toolName)}Args };`
397
+ ).join("\n")}
398
+ }`;
399
+ return toolArgTypes.join("\n\n") + "\n\n" + toolsInterface + "\n\n";
400
+ }
401
+ return null;
402
+ }
403
+
404
+ // src/normalizer/types.ts
405
+ var SpanType = /* @__PURE__ */ ((SpanType2) => {
406
+ SpanType2["SPAN"] = "SPAN";
407
+ SpanType2["GENERATION"] = "GENERATION";
408
+ SpanType2["EVENT"] = "EVENT";
409
+ return SpanType2;
410
+ })(SpanType || {});
411
+
412
+ // src/normalizer/registry.ts
413
+ var TransformerRegistry = class {
414
+ constructor() {
415
+ this.transformers = /* @__PURE__ */ new Map();
416
+ this.defaultTransformer = null;
417
+ }
418
+ register(scope, transformer) {
419
+ this.transformers.set(scope, transformer);
420
+ }
421
+ setDefault(transformer) {
422
+ this.defaultTransformer = transformer;
423
+ }
424
+ getTransformer(scope) {
425
+ return this.transformers.get(scope) || this.defaultTransformer;
426
+ }
427
+ };
428
+ var registry = new TransformerRegistry();
429
+
430
+ // src/normalizer/transformers/ai-sdk/version-detector.ts
431
+ function detectVersion(attributes) {
432
+ if (attributes["ai.response.text"] !== void 0 && attributes["ai.response.text"] !== null || attributes["ai.response.toolCalls"] !== void 0 && attributes["ai.response.toolCalls"] !== null || attributes["ai.response.object"] !== void 0 && attributes["ai.response.object"] !== null) {
433
+ return "v5";
434
+ }
435
+ if (attributes["ai.result.text"] !== void 0 && attributes["ai.result.text"] !== null || attributes["ai.result.toolCalls"] !== void 0 && attributes["ai.result.toolCalls"] !== null || attributes["ai.result.object"] !== void 0 && attributes["ai.result.object"] !== null) {
436
+ return "v4";
437
+ }
438
+ if (attributes["ai.prompt.messages"] !== void 0 && attributes["ai.prompt.messages"] !== null || attributes["ai.prompt"] !== void 0 && attributes["ai.prompt"] !== null) {
439
+ return "v4";
440
+ }
441
+ return "unknown";
442
+ }
443
+
444
+ // src/normalizer/extractors/token-parser.ts
445
+ function parseTokens(attributes, keys) {
446
+ const result = {};
447
+ const parseIntSafe = (val) => {
448
+ if (typeof val === "number") return Math.floor(val);
449
+ if (typeof val === "string") {
450
+ try {
451
+ const parsed2 = JSON.parse(val);
452
+ if (typeof parsed2 === "number") return Math.floor(parsed2);
453
+ if (parsed2 && typeof parsed2.intValue === "number") return Math.floor(parsed2.intValue);
454
+ } catch {
455
+ }
456
+ const parsed = parseInt(val, 10);
457
+ return isNaN(parsed) ? void 0 : parsed;
458
+ }
459
+ return void 0;
460
+ };
461
+ if (keys.inputKey && attributes[keys.inputKey] !== void 0) {
462
+ result.inputTokens = parseIntSafe(attributes[keys.inputKey]);
463
+ } else if (keys.promptKey && attributes[keys.promptKey] !== void 0) {
464
+ result.inputTokens = parseIntSafe(attributes[keys.promptKey]);
465
+ }
466
+ if (keys.outputKey && attributes[keys.outputKey] !== void 0) {
467
+ result.outputTokens = parseIntSafe(attributes[keys.outputKey]);
468
+ } else if (keys.completionKey && attributes[keys.completionKey] !== void 0) {
469
+ result.outputTokens = parseIntSafe(attributes[keys.completionKey]);
470
+ }
471
+ if (keys.totalKey && attributes[keys.totalKey] !== void 0) {
472
+ result.totalTokens = parseIntSafe(attributes[keys.totalKey]);
473
+ }
474
+ if (result.totalTokens === void 0 && result.inputTokens !== void 0 && result.outputTokens !== void 0) {
475
+ result.totalTokens = result.inputTokens + result.outputTokens;
476
+ }
477
+ if (keys.reasoningKey && attributes[keys.reasoningKey] !== void 0) {
478
+ result.reasoningTokens = parseIntSafe(attributes[keys.reasoningKey]);
479
+ }
480
+ return result;
481
+ }
482
+
483
+ // src/normalizer/utils/key-sanitizer.ts
484
+ var DANGEROUS_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
485
+ function isSafeKey(key) {
486
+ return !DANGEROUS_KEYS.has(key);
487
+ }
488
+
489
+ // src/normalizer/extractors/metadata-parser.ts
490
+ var KNOWN_METADATA_FIELDS = /* @__PURE__ */ new Set([
491
+ "session_id",
492
+ "session_name",
493
+ "user_id",
494
+ "trace_name",
495
+ "dataset_run_id",
496
+ "dataset_run_name",
497
+ "dataset_path",
498
+ "dataset_item_name",
499
+ "dataset_expected_output",
500
+ "prompt_name",
501
+ "props",
502
+ "commit_sha"
503
+ ]);
504
+ function parseMetadata(attributes, prefix = "agentmark.metadata.") {
505
+ const result = {};
506
+ const get = (key) => attributes[`${prefix}${key}`];
507
+ if (get("session_id")) result.sessionId = String(get("session_id"));
508
+ if (get("session_name")) result.sessionName = String(get("session_name"));
509
+ if (get("user_id")) result.userId = String(get("user_id"));
510
+ if (get("trace_name")) result.traceName = String(get("trace_name"));
511
+ if (get("dataset_run_id")) result.datasetRunId = String(get("dataset_run_id"));
512
+ if (get("dataset_run_name")) result.datasetRunName = String(get("dataset_run_name"));
513
+ if (get("dataset_path")) result.datasetPath = String(get("dataset_path"));
514
+ if (get("dataset_item_name")) result.datasetItemName = String(get("dataset_item_name"));
515
+ if (get("dataset_expected_output")) result.datasetExpectedOutput = String(get("dataset_expected_output"));
516
+ if (get("prompt_name")) result.promptName = String(get("prompt_name"));
517
+ if (get("props")) result.props = String(get("props"));
518
+ if (get("commit_sha")) result.commitSha = String(get("commit_sha"));
519
+ return result;
520
+ }
521
+ function extractCustomMetadata(attributes, prefix = "agentmark.metadata.") {
522
+ const customMetadata = {};
523
+ for (const [key, value] of Object.entries(attributes)) {
524
+ if (key.startsWith(prefix)) {
525
+ const metadataKey = key.slice(prefix.length);
526
+ if (metadataKey && !KNOWN_METADATA_FIELDS.has(metadataKey) && isSafeKey(metadataKey)) {
527
+ customMetadata[metadataKey] = String(value);
528
+ }
529
+ }
530
+ }
531
+ return customMetadata;
532
+ }
533
+
534
+ // src/normalizer/transformers/ai-sdk/token-helpers.ts
535
+ function extractReasoningFromProviderMetadata(attributes) {
536
+ var _a;
537
+ const providerMetadata = attributes["ai.response.providerMetadata"];
538
+ if (!providerMetadata) return void 0;
539
+ try {
540
+ const parsed = typeof providerMetadata === "string" ? JSON.parse(providerMetadata) : providerMetadata;
541
+ if (((_a = parsed == null ? void 0 : parsed.openai) == null ? void 0 : _a.reasoningTokens) !== void 0) {
542
+ return typeof parsed.openai.reasoningTokens === "number" ? parsed.openai.reasoningTokens : void 0;
543
+ }
544
+ } catch {
545
+ }
546
+ return void 0;
547
+ }
548
+
549
+ // src/normalizer/transformers/ai-sdk/strategies/v4.ts
550
+ var AiSdkV4Strategy = class {
551
+ /**
552
+ * Normalize a content part from V4 format to standard format
553
+ */
554
+ normalizeContentPart(part) {
555
+ if (typeof part === "string") {
556
+ return part;
557
+ }
558
+ if (!part || typeof part !== "object") {
559
+ return part;
560
+ }
561
+ const type = part.type;
562
+ if (type === "text") {
563
+ return {
564
+ type: "text",
565
+ text: part.text || ""
566
+ };
567
+ }
568
+ if (type === "tool-call") {
569
+ return {
570
+ type: "tool-call",
571
+ toolCallId: part.toolCallId || "",
572
+ toolName: part.toolName || "",
573
+ args: part.args || {}
574
+ // V4 uses 'args' directly
575
+ };
576
+ }
577
+ if (type === "tool-result") {
578
+ return {
579
+ type: "tool-result",
580
+ toolCallId: part.toolCallId || "",
581
+ toolName: part.toolName || "",
582
+ result: part.result
583
+ // V4 uses 'result' directly
584
+ };
585
+ }
586
+ return part;
587
+ }
588
+ /**
589
+ * Normalize a single message from V4 format to standard format
590
+ */
591
+ normalizeMessage(message) {
592
+ if (!message || typeof message !== "object") {
593
+ return message;
594
+ }
595
+ const { role, content, ...rest } = message;
596
+ let normalizedContent;
597
+ if (typeof content === "string") {
598
+ normalizedContent = content;
599
+ } else if (Array.isArray(content)) {
600
+ normalizedContent = content.map((part) => this.normalizeContentPart(part));
601
+ } else if (content && typeof content === "object") {
602
+ normalizedContent = this.normalizeContentPart(content);
603
+ } else {
604
+ normalizedContent = content;
605
+ }
606
+ return {
607
+ role: role || "",
608
+ content: normalizedContent,
609
+ ...rest
610
+ };
611
+ }
612
+ /**
613
+ * Normalize messages array from V4 format to standard format
614
+ */
615
+ normalizeMessages(messages) {
616
+ if (!Array.isArray(messages)) {
617
+ return messages;
618
+ }
619
+ return messages.map((msg) => this.normalizeMessage(msg));
620
+ }
621
+ extractModel(attributes) {
622
+ return attributes["gen_ai.request.model"] || attributes["ai.model.id"];
623
+ }
624
+ extractInput(attributes) {
625
+ let messagesValue;
626
+ if (attributes["ai.prompt.messages"] !== void 0) {
627
+ messagesValue = attributes["ai.prompt.messages"];
628
+ } else if (attributes["ai.prompt"] !== void 0) {
629
+ const promptValue = attributes["ai.prompt"];
630
+ if (typeof promptValue === "string") {
631
+ try {
632
+ const parsed = JSON.parse(promptValue);
633
+ messagesValue = parsed.messages || parsed;
634
+ } catch {
635
+ return void 0;
636
+ }
637
+ } else {
638
+ messagesValue = promptValue.messages || promptValue;
639
+ }
640
+ } else {
641
+ return void 0;
642
+ }
643
+ let messages;
644
+ if (typeof messagesValue === "string") {
645
+ try {
646
+ messages = JSON.parse(messagesValue);
647
+ } catch {
648
+ return void 0;
649
+ }
650
+ } else {
651
+ messages = messagesValue;
652
+ }
653
+ if (!Array.isArray(messages)) {
654
+ return void 0;
655
+ }
656
+ return this.normalizeMessages(messages);
657
+ }
658
+ extractOutput(attributes) {
659
+ if (attributes["ai.result.text"] !== void 0) return attributes["ai.result.text"];
660
+ if (attributes["ai.response.text"] !== void 0) return attributes["ai.response.text"];
661
+ return void 0;
662
+ }
663
+ extractOutputObject(attributes) {
664
+ let objValue;
665
+ if (attributes["ai.result.object"] !== void 0) {
666
+ objValue = attributes["ai.result.object"];
667
+ } else if (attributes["ai.response.object"] !== void 0) {
668
+ objValue = attributes["ai.response.object"];
669
+ } else {
670
+ return void 0;
671
+ }
672
+ if (typeof objValue === "string") {
673
+ try {
674
+ return JSON.parse(objValue);
675
+ } catch {
676
+ return void 0;
677
+ }
678
+ }
679
+ return objValue;
680
+ }
681
+ extractToolCalls(attributes) {
682
+ let toolCallsValue;
683
+ if (attributes["ai.result.toolCalls"] !== void 0) {
684
+ toolCallsValue = attributes["ai.result.toolCalls"];
685
+ } else if (attributes["ai.response.toolCalls"] !== void 0) {
686
+ toolCallsValue = attributes["ai.response.toolCalls"];
687
+ } else {
688
+ if (attributes["ai.toolCall.name"] !== void 0) {
689
+ const toolCallId = attributes["ai.toolCall.id"];
690
+ const toolName = attributes["ai.toolCall.name"];
691
+ const argsValue = attributes["ai.toolCall.args"];
692
+ const resultValue = attributes["ai.toolCall.result"];
693
+ if (toolCallId && toolName) {
694
+ let args = {};
695
+ if (argsValue !== void 0) {
696
+ if (typeof argsValue === "string") {
697
+ try {
698
+ args = JSON.parse(argsValue);
699
+ } catch {
700
+ args = {};
701
+ }
702
+ } else if (typeof argsValue === "object" && argsValue !== null) {
703
+ args = argsValue;
704
+ }
705
+ }
706
+ let result;
707
+ if (resultValue !== void 0) {
708
+ if (typeof resultValue === "string") {
709
+ result = resultValue;
710
+ } else {
711
+ try {
712
+ result = JSON.stringify(resultValue);
713
+ } catch {
714
+ result = String(resultValue);
715
+ }
716
+ }
717
+ }
718
+ return [{
719
+ type: "tool-call",
720
+ toolCallId: String(toolCallId),
721
+ toolName: String(toolName),
722
+ args,
723
+ result
724
+ }];
725
+ }
726
+ }
727
+ return void 0;
728
+ }
729
+ let toolCalls;
730
+ if (typeof toolCallsValue === "string") {
731
+ try {
732
+ toolCalls = JSON.parse(toolCallsValue);
733
+ } catch {
734
+ return void 0;
735
+ }
736
+ } else {
737
+ toolCalls = toolCallsValue;
738
+ }
739
+ if (!Array.isArray(toolCalls)) {
740
+ return void 0;
741
+ }
742
+ return toolCalls.map((tc) => ({
743
+ type: tc.type || "tool-call",
744
+ toolCallId: tc.toolCallId,
745
+ toolName: tc.toolName,
746
+ args: tc.args || tc.input || {}
747
+ // v4 uses 'args', normalize to 'args'
748
+ }));
749
+ }
750
+ extractFinishReason(attributes) {
751
+ if (attributes["ai.result.finishReason"] !== void 0) {
752
+ return String(attributes["ai.result.finishReason"]);
753
+ }
754
+ if (attributes["ai.response.finishReason"] !== void 0) {
755
+ return String(attributes["ai.response.finishReason"]);
756
+ }
757
+ if (attributes["gen_ai.response.finish_reasons"] !== void 0) {
758
+ const reasons = attributes["gen_ai.response.finish_reasons"];
759
+ if (Array.isArray(reasons) && reasons.length > 0) {
760
+ return String(reasons[0]);
761
+ }
762
+ return String(reasons);
763
+ }
764
+ return void 0;
765
+ }
766
+ extractSettings(attributes) {
767
+ var _a, _b, _c, _d, _e;
768
+ const settings = {};
769
+ if (attributes["gen_ai.request.temperature"] !== void 0 || attributes["ai.settings.temperature"] !== void 0) {
770
+ const value = (_a = attributes["gen_ai.request.temperature"]) != null ? _a : attributes["ai.settings.temperature"];
771
+ settings.temperature = typeof value === "number" ? value : parseFloat(String(value));
772
+ }
773
+ if (attributes["gen_ai.request.max_tokens"] !== void 0 || attributes["ai.settings.maxTokens"] !== void 0) {
774
+ const value = (_b = attributes["gen_ai.request.max_tokens"]) != null ? _b : attributes["ai.settings.maxTokens"];
775
+ settings.maxTokens = typeof value === "number" ? value : parseInt(String(value), 10);
776
+ }
777
+ if (attributes["gen_ai.request.top_p"] !== void 0 || attributes["ai.settings.topP"] !== void 0) {
778
+ const value = (_c = attributes["gen_ai.request.top_p"]) != null ? _c : attributes["ai.settings.topP"];
779
+ settings.topP = typeof value === "number" ? value : parseFloat(String(value));
780
+ }
781
+ if (attributes["gen_ai.request.presence_penalty"] !== void 0 || attributes["ai.settings.presencePenalty"] !== void 0) {
782
+ const value = (_d = attributes["gen_ai.request.presence_penalty"]) != null ? _d : attributes["ai.settings.presencePenalty"];
783
+ settings.presencePenalty = typeof value === "number" ? value : parseFloat(String(value));
784
+ }
785
+ if (attributes["gen_ai.request.frequency_penalty"] !== void 0 || attributes["ai.settings.frequencyPenalty"] !== void 0) {
786
+ const value = (_e = attributes["gen_ai.request.frequency_penalty"]) != null ? _e : attributes["ai.settings.frequencyPenalty"];
787
+ settings.frequencyPenalty = typeof value === "number" ? value : parseFloat(String(value));
788
+ }
789
+ return Object.keys(settings).length > 0 ? settings : void 0;
790
+ }
791
+ extractTokens(attributes) {
792
+ const tokens = parseTokens(attributes, {
793
+ inputKey: "gen_ai.usage.prompt_tokens",
794
+ outputKey: "gen_ai.usage.completion_tokens",
795
+ totalKey: "gen_ai.usage.total_tokens",
796
+ promptKey: "ai.usage.promptTokens",
797
+ // SDK specific fallback
798
+ completionKey: "ai.usage.completionTokens"
799
+ // SDK specific fallback
800
+ });
801
+ tokens.reasoningTokens = extractReasoningFromProviderMetadata(attributes);
802
+ if (!tokens.reasoningTokens) {
803
+ tokens.reasoningTokens = 0;
804
+ }
805
+ return {
806
+ input: tokens.inputTokens,
807
+ output: tokens.outputTokens,
808
+ total: tokens.totalTokens,
809
+ reasoning: tokens.reasoningTokens
810
+ };
811
+ }
812
+ extractMetadata(attributes) {
813
+ const result = parseMetadata(attributes);
814
+ const aiTelemetryResult = parseMetadata(attributes, "ai.telemetry.metadata.");
815
+ const agentmarkCustomMetadata = extractCustomMetadata(attributes, "agentmark.metadata.");
816
+ const aiTelemetryCustomMetadata = extractCustomMetadata(attributes, "ai.telemetry.metadata.");
817
+ const mergedCustomMetadata = {
818
+ ...agentmarkCustomMetadata,
819
+ ...aiTelemetryCustomMetadata
820
+ };
821
+ return {
822
+ ...result,
823
+ ...aiTelemetryResult,
824
+ // Only include metadata field if there are custom metadata keys
825
+ ...Object.keys(mergedCustomMetadata).length > 0 ? { metadata: mergedCustomMetadata } : {}
826
+ };
827
+ }
828
+ };
829
+
830
+ // src/normalizer/transformers/ai-sdk/strategies/v5.ts
831
+ var AiSdkV5Strategy = class {
832
+ /**
833
+ * Normalize a content part from V5 format to standard format
834
+ */
835
+ normalizeContentPart(part) {
836
+ if (typeof part === "string") {
837
+ return part;
838
+ }
839
+ if (!part || typeof part !== "object") {
840
+ return part;
841
+ }
842
+ const type = part.type;
843
+ if (type === "text") {
844
+ return {
845
+ type: "text",
846
+ text: part.text || ""
847
+ };
848
+ }
849
+ if (type === "tool-call") {
850
+ return {
851
+ type: "tool-call",
852
+ toolCallId: part.toolCallId || "",
853
+ toolName: part.toolName || "",
854
+ args: part.input || part.args || {}
855
+ // V5 uses 'input', normalize to 'args'
856
+ };
857
+ }
858
+ if (type === "tool-result") {
859
+ let normalizedResult;
860
+ if (part.output !== void 0) {
861
+ if (typeof part.output === "object" && part.output !== null) {
862
+ if ("value" in part.output) {
863
+ normalizedResult = part.output.value;
864
+ } else {
865
+ normalizedResult = part.output;
866
+ }
867
+ } else {
868
+ normalizedResult = part.output;
869
+ }
870
+ } else if (part.result !== void 0) {
871
+ normalizedResult = part.result;
872
+ } else {
873
+ normalizedResult = void 0;
874
+ }
875
+ return {
876
+ type: "tool-result",
877
+ toolCallId: part.toolCallId || "",
878
+ toolName: part.toolName || "",
879
+ result: normalizedResult
880
+ };
881
+ }
882
+ return part;
883
+ }
884
+ /**
885
+ * Normalize a single message from V5 format to standard format
886
+ */
887
+ normalizeMessage(message) {
888
+ if (!message || typeof message !== "object") {
889
+ return message;
890
+ }
891
+ const { role, content, ...rest } = message;
892
+ let normalizedContent;
893
+ if (typeof content === "string") {
894
+ normalizedContent = content;
895
+ } else if (Array.isArray(content)) {
896
+ normalizedContent = content.map((part) => this.normalizeContentPart(part));
897
+ } else if (content && typeof content === "object") {
898
+ normalizedContent = this.normalizeContentPart(content);
899
+ } else {
900
+ normalizedContent = content;
901
+ }
902
+ return {
903
+ role: role || "",
904
+ content: normalizedContent,
905
+ ...rest
906
+ };
907
+ }
908
+ /**
909
+ * Normalize messages array from V5 format to standard format
910
+ */
911
+ normalizeMessages(messages) {
912
+ if (!Array.isArray(messages)) {
913
+ return messages;
914
+ }
915
+ return messages.map((msg) => this.normalizeMessage(msg));
916
+ }
917
+ extractModel(attributes) {
918
+ return attributes["gen_ai.request.model"] || attributes["ai.model.id"];
919
+ }
920
+ extractInput(attributes) {
921
+ let messagesValue;
922
+ if (attributes["ai.prompt.messages"] !== void 0) {
923
+ messagesValue = attributes["ai.prompt.messages"];
924
+ } else if (attributes["ai.prompt"] !== void 0) {
925
+ const promptValue = attributes["ai.prompt"];
926
+ if (typeof promptValue === "string") {
927
+ try {
928
+ const parsed = JSON.parse(promptValue);
929
+ messagesValue = parsed.messages || parsed;
930
+ } catch {
931
+ return void 0;
932
+ }
933
+ } else {
934
+ messagesValue = promptValue.messages || promptValue;
935
+ }
936
+ } else {
937
+ return void 0;
938
+ }
939
+ let messages;
940
+ if (typeof messagesValue === "string") {
941
+ try {
942
+ messages = JSON.parse(messagesValue);
943
+ } catch {
944
+ return void 0;
945
+ }
946
+ } else {
947
+ messages = messagesValue;
948
+ }
949
+ if (!Array.isArray(messages)) {
950
+ return void 0;
951
+ }
952
+ return this.normalizeMessages(messages);
953
+ }
954
+ extractOutput(attributes) {
955
+ if (attributes["ai.response.text"] !== void 0) return attributes["ai.response.text"];
956
+ return void 0;
957
+ }
958
+ extractOutputObject(attributes) {
959
+ if (attributes["ai.response.object"] === void 0) {
960
+ return void 0;
961
+ }
962
+ const objValue = attributes["ai.response.object"];
963
+ if (typeof objValue === "string") {
964
+ try {
965
+ return JSON.parse(objValue);
966
+ } catch {
967
+ return void 0;
968
+ }
969
+ }
970
+ if (typeof objValue === "object" && objValue !== null) {
971
+ return objValue;
972
+ }
973
+ return void 0;
974
+ }
975
+ extractToolCalls(attributes) {
976
+ if (attributes["ai.response.toolCalls"] !== void 0) {
977
+ const toolCallsValue = attributes["ai.response.toolCalls"];
978
+ let toolCalls;
979
+ if (typeof toolCallsValue === "string") {
980
+ try {
981
+ toolCalls = JSON.parse(toolCallsValue);
982
+ } catch {
983
+ return void 0;
984
+ }
985
+ } else {
986
+ toolCalls = toolCallsValue;
987
+ }
988
+ if (!Array.isArray(toolCalls)) {
989
+ return void 0;
990
+ }
991
+ return toolCalls.map((tc) => ({
992
+ type: tc.type || "tool-call",
993
+ toolCallId: tc.toolCallId,
994
+ toolName: tc.toolName,
995
+ args: tc.input || tc.args || {},
996
+ // v5 uses 'input', normalize to 'args'
997
+ providerMetadata: tc.providerMetadata || tc.providerOptions
998
+ }));
999
+ }
1000
+ if (attributes["ai.toolCall.name"] !== void 0) {
1001
+ const toolCallId = attributes["ai.toolCall.id"];
1002
+ const toolName = attributes["ai.toolCall.name"];
1003
+ const argsValue = attributes["ai.toolCall.args"];
1004
+ const resultValue = attributes["ai.toolCall.result"];
1005
+ if (toolCallId && toolName) {
1006
+ let args = {};
1007
+ if (argsValue !== void 0) {
1008
+ if (typeof argsValue === "string") {
1009
+ try {
1010
+ args = JSON.parse(argsValue);
1011
+ } catch {
1012
+ args = {};
1013
+ }
1014
+ } else if (typeof argsValue === "object" && argsValue !== null) {
1015
+ args = argsValue;
1016
+ }
1017
+ }
1018
+ let result;
1019
+ if (resultValue !== void 0) {
1020
+ if (typeof resultValue === "string") {
1021
+ result = resultValue;
1022
+ } else {
1023
+ try {
1024
+ result = JSON.stringify(resultValue);
1025
+ } catch {
1026
+ result = String(resultValue);
1027
+ }
1028
+ }
1029
+ }
1030
+ return [{
1031
+ type: "tool-call",
1032
+ toolCallId: String(toolCallId),
1033
+ toolName: String(toolName),
1034
+ args,
1035
+ result
1036
+ }];
1037
+ }
1038
+ }
1039
+ return void 0;
1040
+ }
1041
+ extractFinishReason(attributes) {
1042
+ if (attributes["ai.response.finishReason"] !== void 0) {
1043
+ return String(attributes["ai.response.finishReason"]);
1044
+ }
1045
+ if (attributes["gen_ai.response.finish_reasons"] !== void 0) {
1046
+ const reasons = attributes["gen_ai.response.finish_reasons"];
1047
+ if (Array.isArray(reasons) && reasons.length > 0) {
1048
+ return String(reasons[0]);
1049
+ }
1050
+ return String(reasons);
1051
+ }
1052
+ return void 0;
1053
+ }
1054
+ extractSettings(attributes) {
1055
+ var _a, _b, _c, _d, _e;
1056
+ const settings = {};
1057
+ if (attributes["gen_ai.request.temperature"] !== void 0 || attributes["ai.settings.temperature"] !== void 0) {
1058
+ const value = (_a = attributes["gen_ai.request.temperature"]) != null ? _a : attributes["ai.settings.temperature"];
1059
+ settings.temperature = typeof value === "number" ? value : parseFloat(String(value));
1060
+ }
1061
+ if (attributes["gen_ai.request.max_tokens"] !== void 0 || attributes["ai.settings.maxTokens"] !== void 0) {
1062
+ const value = (_b = attributes["gen_ai.request.max_tokens"]) != null ? _b : attributes["ai.settings.maxTokens"];
1063
+ settings.maxTokens = typeof value === "number" ? value : parseInt(String(value), 10);
1064
+ }
1065
+ if (attributes["gen_ai.request.top_p"] !== void 0 || attributes["ai.settings.topP"] !== void 0) {
1066
+ const value = (_c = attributes["gen_ai.request.top_p"]) != null ? _c : attributes["ai.settings.topP"];
1067
+ settings.topP = typeof value === "number" ? value : parseFloat(String(value));
1068
+ }
1069
+ if (attributes["gen_ai.request.presence_penalty"] !== void 0 || attributes["ai.settings.presencePenalty"] !== void 0) {
1070
+ const value = (_d = attributes["gen_ai.request.presence_penalty"]) != null ? _d : attributes["ai.settings.presencePenalty"];
1071
+ settings.presencePenalty = typeof value === "number" ? value : parseFloat(String(value));
1072
+ }
1073
+ if (attributes["gen_ai.request.frequency_penalty"] !== void 0 || attributes["ai.settings.frequencyPenalty"] !== void 0) {
1074
+ const value = (_e = attributes["gen_ai.request.frequency_penalty"]) != null ? _e : attributes["ai.settings.frequencyPenalty"];
1075
+ settings.frequencyPenalty = typeof value === "number" ? value : parseFloat(String(value));
1076
+ }
1077
+ return Object.keys(settings).length > 0 ? settings : void 0;
1078
+ }
1079
+ extractTokens(attributes) {
1080
+ const tokens = parseTokens(attributes, {
1081
+ inputKey: "gen_ai.usage.input_tokens",
1082
+ outputKey: "gen_ai.usage.output_tokens",
1083
+ totalKey: "gen_ai.usage.total_tokens",
1084
+ promptKey: "ai.usage.promptTokens",
1085
+ // SDK specific fallback
1086
+ completionKey: "ai.usage.completionTokens",
1087
+ // SDK specific fallback
1088
+ reasoningKey: "ai.usage.reasoningTokens"
1089
+ // AI SDK v5 uses this
1090
+ });
1091
+ if (tokens.reasoningTokens === void 0) {
1092
+ tokens.reasoningTokens = extractReasoningFromProviderMetadata(attributes);
1093
+ }
1094
+ if (!tokens.reasoningTokens) {
1095
+ tokens.reasoningTokens = 0;
1096
+ }
1097
+ return {
1098
+ input: tokens.inputTokens,
1099
+ output: tokens.outputTokens,
1100
+ total: tokens.totalTokens,
1101
+ reasoning: tokens.reasoningTokens
1102
+ };
1103
+ }
1104
+ extractMetadata(attributes) {
1105
+ const result = parseMetadata(attributes);
1106
+ const aiTelemetryResult = parseMetadata(attributes, "ai.telemetry.metadata.");
1107
+ const agentmarkCustomMetadata = extractCustomMetadata(attributes, "agentmark.metadata.");
1108
+ const aiTelemetryCustomMetadata = extractCustomMetadata(attributes, "ai.telemetry.metadata.");
1109
+ const mergedCustomMetadata = {
1110
+ ...agentmarkCustomMetadata,
1111
+ ...aiTelemetryCustomMetadata
1112
+ };
1113
+ return {
1114
+ ...result,
1115
+ ...aiTelemetryResult,
1116
+ // Only include metadata field if there are custom metadata keys
1117
+ ...Object.keys(mergedCustomMetadata).length > 0 ? { metadata: mergedCustomMetadata } : {}
1118
+ };
1119
+ }
1120
+ };
1121
+
1122
+ // src/normalizer/transformers/ai-sdk/index.ts
1123
+ var AiSdkTransformer = class {
1124
+ constructor() {
1125
+ this.strategies = {
1126
+ v4: new AiSdkV4Strategy(),
1127
+ v5: new AiSdkV5Strategy()
1128
+ };
1129
+ }
1130
+ classify(span, _attributes) {
1131
+ const isGenerationSpan = span.name === "ai.generateText.doGenerate" || span.name === "ai.streamText.doStream" || span.name === "ai.generateObject.doGenerate" || span.name === "ai.streamObject.doStream";
1132
+ return isGenerationSpan ? "GENERATION" /* GENERATION */ : "SPAN" /* SPAN */;
1133
+ }
1134
+ transform(_span, attributes) {
1135
+ const version = detectVersion(attributes);
1136
+ const strategy = version === "v5" ? this.strategies.v5 : this.strategies.v4;
1137
+ const tokens = strategy.extractTokens(attributes);
1138
+ const toolCalls = strategy.extractToolCalls(attributes);
1139
+ const result = {
1140
+ model: strategy.extractModel(attributes),
1141
+ input: strategy.extractInput(attributes),
1142
+ output: strategy.extractOutput(attributes),
1143
+ outputObject: strategy.extractOutputObject(attributes),
1144
+ toolCalls,
1145
+ finishReason: strategy.extractFinishReason(attributes),
1146
+ settings: strategy.extractSettings(attributes),
1147
+ inputTokens: tokens.input,
1148
+ outputTokens: tokens.output,
1149
+ totalTokens: tokens.total,
1150
+ reasoningTokens: tokens.reasoning,
1151
+ ...strategy.extractMetadata(attributes)
1152
+ };
1153
+ const toolName = attributes["ai.toolCall.name"];
1154
+ if (toolName && typeof toolName === "string") {
1155
+ result.name = toolName;
1156
+ }
1157
+ return result;
1158
+ }
1159
+ };
1160
+
1161
+ // src/normalizer/transformers/mastra/index.ts
1162
+ var MastraTransformer = class {
1163
+ classify(span, _attributes) {
1164
+ const isGenerationSpan = span.name === "agent.streamLegacy" || span.name === "agent.stream" || span.name === "agent.streamObject" || span.name === "agent.generate" || span.name === "agent.generateObject";
1165
+ return isGenerationSpan ? "GENERATION" /* GENERATION */ : "SPAN" /* SPAN */;
1166
+ }
1167
+ transform(span, attributes) {
1168
+ const result = {};
1169
+ const modelConfig = this.extractModelConfig(attributes, span);
1170
+ if (modelConfig == null ? void 0 : modelConfig.modelId) {
1171
+ result.model = modelConfig.modelId;
1172
+ }
1173
+ const input = this.extractInput(span, attributes);
1174
+ if (input) {
1175
+ result.input = input;
1176
+ }
1177
+ const streamResult = this.extractStreamResult(span, attributes);
1178
+ if (streamResult) {
1179
+ if (streamResult.output) {
1180
+ result.output = streamResult.output;
1181
+ }
1182
+ if (streamResult.outputObject) {
1183
+ result.outputObject = streamResult.outputObject;
1184
+ }
1185
+ if (streamResult.usage) {
1186
+ result.inputTokens = streamResult.usage.promptTokens;
1187
+ result.outputTokens = streamResult.usage.completionTokens;
1188
+ result.totalTokens = streamResult.usage.totalTokens;
1189
+ }
1190
+ }
1191
+ if (attributes["agentmark.trace_name"]) {
1192
+ result.traceName = attributes["agentmark.trace_name"];
1193
+ } else if (attributes["componentName"]) {
1194
+ result.traceName = attributes["componentName"];
1195
+ }
1196
+ if (modelConfig == null ? void 0 : modelConfig.settings) {
1197
+ result.settings = modelConfig.settings;
1198
+ }
1199
+ return result;
1200
+ }
1201
+ extractModelConfig(attributes, _span) {
1202
+ var _a, _b;
1203
+ const resolveModelConfigResult = attributes["agent.resolveModelConfig.result"];
1204
+ if (resolveModelConfigResult) {
1205
+ try {
1206
+ const config = typeof resolveModelConfigResult === "string" ? JSON.parse(resolveModelConfigResult) : resolveModelConfigResult;
1207
+ if (config.modelId) {
1208
+ return {
1209
+ modelId: config.modelId,
1210
+ provider: (_a = config.config) == null ? void 0 : _a.provider,
1211
+ settings: config.settings
1212
+ };
1213
+ }
1214
+ } catch {
1215
+ }
1216
+ }
1217
+ const prepareLLMOptionsResult = attributes["agent.prepareLLMOptions.result"];
1218
+ if (prepareLLMOptionsResult) {
1219
+ try {
1220
+ const result = typeof prepareLLMOptionsResult === "string" ? JSON.parse(prepareLLMOptionsResult) : prepareLLMOptionsResult;
1221
+ if ((_b = result.llm) == null ? void 0 : _b.name) {
1222
+ }
1223
+ } catch {
1224
+ }
1225
+ }
1226
+ return null;
1227
+ }
1228
+ extractInput(span, attributes) {
1229
+ const spanName = span.name;
1230
+ const argument0 = attributes[`${spanName}.argument.0`] || attributes["agent.prepareLLMOptions.argument.0"] || attributes["agent.stream.argument.0"] || attributes["agent.streamLegacy.argument.0"];
1231
+ if (argument0) {
1232
+ try {
1233
+ const messages = typeof argument0 === "string" ? JSON.parse(argument0) : argument0;
1234
+ if (Array.isArray(messages)) {
1235
+ return messages;
1236
+ }
1237
+ } catch {
1238
+ }
1239
+ }
1240
+ return void 0;
1241
+ }
1242
+ extractStreamResult(span, attributes) {
1243
+ const spanName = span.name;
1244
+ const resultAttr = attributes[`${spanName}.result`] || attributes["agent.stream.result"] || attributes["agent.streamLegacy.result"] || attributes["agent.streamObject.result"];
1245
+ if (resultAttr) {
1246
+ try {
1247
+ const result = typeof resultAttr === "string" ? JSON.parse(resultAttr) : resultAttr;
1248
+ const extracted = {};
1249
+ if (result.usage) {
1250
+ extracted.usage = {
1251
+ promptTokens: result.usage.promptTokens,
1252
+ completionTokens: result.usage.completionTokens,
1253
+ totalTokens: result.usage.totalTokens
1254
+ };
1255
+ }
1256
+ if (result.object) {
1257
+ extracted.outputObject = result.object;
1258
+ extracted.output = JSON.stringify(result.object);
1259
+ } else if (result.text) {
1260
+ extracted.output = result.text;
1261
+ } else if (result.response) {
1262
+ if (typeof result.response === "string") {
1263
+ extracted.output = result.response;
1264
+ } else {
1265
+ extracted.output = JSON.stringify(result.response);
1266
+ extracted.outputObject = result.response;
1267
+ }
1268
+ }
1269
+ return extracted;
1270
+ } catch {
1271
+ }
1272
+ }
1273
+ return null;
1274
+ }
1275
+ };
1276
+
1277
+ // src/normalizer/converters/otlp-converter.ts
1278
+ function convertOtlpValue(value) {
1279
+ var _a;
1280
+ if (value.stringValue !== void 0) {
1281
+ return value.stringValue;
1282
+ }
1283
+ if (value.intValue !== void 0) {
1284
+ return typeof value.intValue === "string" ? parseInt(value.intValue, 10) : value.intValue;
1285
+ }
1286
+ if (value.doubleValue !== void 0) {
1287
+ return value.doubleValue;
1288
+ }
1289
+ if (value.boolValue !== void 0) {
1290
+ return value.boolValue;
1291
+ }
1292
+ if ((_a = value.arrayValue) == null ? void 0 : _a.values) {
1293
+ return value.arrayValue.values.map(convertOtlpValue);
1294
+ }
1295
+ if (value.bytesValue !== void 0) {
1296
+ return value.bytesValue;
1297
+ }
1298
+ return void 0;
1299
+ }
1300
+ function convertOtlpAttributes(attributes) {
1301
+ if (!attributes || attributes.length === 0) {
1302
+ return {};
1303
+ }
1304
+ const result = {};
1305
+ for (const attr of attributes) {
1306
+ if (attr.key && isSafeKey(attr.key)) {
1307
+ result[attr.key] = convertOtlpValue(attr.value);
1308
+ }
1309
+ }
1310
+ return result;
1311
+ }
1312
+ function extractResourceScopeSpan(resourceSpans) {
1313
+ var _a, _b, _c;
1314
+ const result = [];
1315
+ const resourceAttributes = convertOtlpAttributes((_a = resourceSpans.resource) == null ? void 0 : _a.attributes);
1316
+ for (const scopeSpans of resourceSpans.scopeSpans || []) {
1317
+ const scope = {
1318
+ name: (_b = scopeSpans.scope) == null ? void 0 : _b.name,
1319
+ version: (_c = scopeSpans.scope) == null ? void 0 : _c.version
1320
+ };
1321
+ for (const otlpSpan of scopeSpans.spans || []) {
1322
+ const spanAttributes = convertOtlpAttributes(otlpSpan.attributes);
1323
+ const events = (otlpSpan.events || []).map((otlpEvent) => ({
1324
+ timeUnixNano: otlpEvent.timeUnixNano,
1325
+ name: otlpEvent.name,
1326
+ attributes: convertOtlpAttributes(otlpEvent.attributes)
1327
+ }));
1328
+ const links = (otlpSpan.links || []).map((otlpLink) => ({
1329
+ traceId: otlpLink.traceId,
1330
+ spanId: otlpLink.spanId,
1331
+ traceState: otlpLink.traceState,
1332
+ attributes: convertOtlpAttributes(otlpLink.attributes)
1333
+ }));
1334
+ const span = {
1335
+ traceId: otlpSpan.traceId,
1336
+ spanId: otlpSpan.spanId,
1337
+ parentSpanId: otlpSpan.parentSpanId,
1338
+ traceState: otlpSpan.traceState,
1339
+ name: otlpSpan.name,
1340
+ kind: otlpSpan.kind,
1341
+ startTimeUnixNano: otlpSpan.startTimeUnixNano,
1342
+ endTimeUnixNano: otlpSpan.endTimeUnixNano,
1343
+ attributes: spanAttributes,
1344
+ events,
1345
+ links,
1346
+ status: otlpSpan.status
1347
+ };
1348
+ const resource = {
1349
+ attributes: resourceAttributes
1350
+ };
1351
+ result.push({ resource, scope, span });
1352
+ }
1353
+ }
1354
+ return result;
1355
+ }
1356
+
1357
+ // src/normalizer/extractors/agentmark-parser.ts
1358
+ function parseAgentMarkAttributes(attributes, prefix = "agentmark.") {
1359
+ const result = {};
1360
+ const get = (key) => attributes[`${prefix}${key}`];
1361
+ if (get("session_id")) result.sessionId = String(get("session_id"));
1362
+ if (get("session_name")) result.sessionName = String(get("session_name"));
1363
+ if (get("user_id")) result.userId = String(get("user_id"));
1364
+ if (get("trace_name")) result.traceName = String(get("trace_name"));
1365
+ if (get("dataset_run_id")) result.datasetRunId = String(get("dataset_run_id"));
1366
+ if (get("dataset_run_name")) result.datasetRunName = String(get("dataset_run_name"));
1367
+ if (get("dataset_item_name")) result.datasetItemName = String(get("dataset_item_name"));
1368
+ if (get("dataset_expected_output")) result.datasetExpectedOutput = String(get("dataset_expected_output"));
1369
+ return result;
1370
+ }
1371
+
1372
+ // src/normalizer/type-classifier.ts
1373
+ var TypeClassifier = class {
1374
+ classify(span, attributes) {
1375
+ if (attributes["gen_ai.system"] || attributes["gen_ai.request.model"] || attributes["gen_ai.operation.name"]) {
1376
+ return "GENERATION" /* GENERATION */;
1377
+ }
1378
+ if (attributes["ai.response.text"] || attributes["ai.result.text"] || attributes["ai.response.toolCalls"] || attributes["ai.result.toolCalls"]) {
1379
+ return "GENERATION" /* GENERATION */;
1380
+ }
1381
+ if (span.name.startsWith("ai.generate") || span.name.startsWith("ai.stream")) {
1382
+ return "GENERATION" /* GENERATION */;
1383
+ }
1384
+ return "SPAN" /* SPAN */;
1385
+ }
1386
+ };
1387
+ var typeClassifier = new TypeClassifier();
1388
+
1389
+ // src/normalizer/index.ts
1390
+ registry.register("ai", new AiSdkTransformer());
1391
+ registry.register("default-tracer", new MastraTransformer());
1392
+ registry.setDefault(new AiSdkTransformer());
1393
+ function normalizeSpan(resource, scope, span) {
1394
+ var _a, _b, _c;
1395
+ const allAttributes = {
1396
+ ...resource.attributes || {},
1397
+ ...span.attributes || {}
1398
+ };
1399
+ const transformer = registry.getTransformer(scope.name || "");
1400
+ const type = transformer ? transformer.classify(span, allAttributes) : "SPAN" /* SPAN */;
1401
+ const startNs = BigInt(span.startTimeUnixNano);
1402
+ const endNs = BigInt(span.endTimeUnixNano);
1403
+ const startMsInt = startNs / BigInt(1e6);
1404
+ const startMsRemainder = Number(startNs % BigInt(1e6)) / 1e6;
1405
+ const endMsInt = endNs / BigInt(1e6);
1406
+ const endMsRemainder = Number(endNs % BigInt(1e6)) / 1e6;
1407
+ const startMs = Number(startMsInt) + startMsRemainder;
1408
+ const endMs = Number(endMsInt) + endMsRemainder;
1409
+ const normalized = {
1410
+ // Identity
1411
+ traceId: span.traceId,
1412
+ spanId: span.spanId,
1413
+ parentSpanId: span.parentSpanId,
1414
+ traceState: span.traceState,
1415
+ // Type
1416
+ type,
1417
+ // Timing (convert nanoseconds to milliseconds: divide by 1,000,000)
1418
+ startTime: startMs,
1419
+ endTime: endMs,
1420
+ duration: endMs - startMs,
1421
+ // Metadata
1422
+ name: span.name,
1423
+ kind: span.kind.toString(),
1424
+ serviceName: (_a = resource.attributes) == null ? void 0 : _a["service.name"],
1425
+ statusCode: ((_b = span.status) == null ? void 0 : _b.code.toString()) || "0",
1426
+ statusMessage: (_c = span.status) == null ? void 0 : _c.message,
1427
+ // Raw Data
1428
+ resourceAttributes: resource.attributes || {},
1429
+ spanAttributes: span.attributes || {},
1430
+ events: (span.events || []).map((e) => ({
1431
+ timestamp: Number(BigInt(e.timeUnixNano)) / 1e6,
1432
+ name: e.name,
1433
+ attributes: e.attributes || {}
1434
+ })),
1435
+ links: (span.links || []).map((l) => ({
1436
+ traceId: l.traceId,
1437
+ spanId: l.spanId,
1438
+ traceState: l.traceState,
1439
+ attributes: l.attributes
1440
+ }))
1441
+ };
1442
+ if (transformer) {
1443
+ const transformed = transformer.transform(span, allAttributes);
1444
+ Object.assign(normalized, transformed);
1445
+ }
1446
+ const agentMarkAttributes = parseAgentMarkAttributes(allAttributes);
1447
+ Object.assign(normalized, agentMarkAttributes);
1448
+ return normalized;
1449
+ }
1450
+ function normalizeOtlpSpans(resourceSpans) {
1451
+ const normalizedSpans = [];
1452
+ for (const resourceSpan of resourceSpans) {
1453
+ const extracted = extractResourceScopeSpan(resourceSpan);
1454
+ for (const { resource, scope, span } of extracted) {
1455
+ normalizedSpans.push(normalizeSpan(resource, scope, span));
1456
+ }
1457
+ }
1458
+ return normalizedSpans;
1459
+ }
1460
+ export {
1461
+ AiSdkTransformer,
1462
+ MastraTransformer,
1463
+ SpanType,
1464
+ TransformerRegistry,
1465
+ TypeClassifier,
1466
+ convertOtlpAttributes,
1467
+ createSignature,
1468
+ detectVersion,
1469
+ extractCustomMetadata,
1470
+ extractReasoningFromProviderMetadata,
1471
+ extractResourceScopeSpan,
1472
+ fetchPromptsFrontmatter,
1473
+ findPromptFiles,
1474
+ generateTypeDefinitions,
1475
+ generateUnique8CharString,
1476
+ normalizeOtlpSpans,
1477
+ normalizeSpan,
1478
+ parseAgentMarkAttributes,
1479
+ parseMetadata,
1480
+ parseTokens,
1481
+ registry,
1482
+ toFrontMatter,
1483
+ typeClassifier,
1484
+ verifySignature
1485
+ };
1486
+ //# sourceMappingURL=index.mjs.map