@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.d.mts +478 -0
- package/dist/index.d.ts +478 -0
- package/dist/index.js +1546 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1486 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +31 -0
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
|