@agentmark-ai/shared-utils 0.2.0 → 0.3.1
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 +26 -3
- package/dist/index.d.ts +26 -3
- package/dist/index.js +545 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +544 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -35,6 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
AiSdkTransformer: () => AiSdkTransformer,
|
|
36
36
|
ClaudeAgentTransformer: () => AgentMarkTransformer,
|
|
37
37
|
MastraTransformer: () => MastraTransformer,
|
|
38
|
+
OtelGenAiTransformer: () => OtelGenAiTransformer,
|
|
38
39
|
SpanType: () => SpanType,
|
|
39
40
|
TransformerRegistry: () => TransformerRegistry,
|
|
40
41
|
TypeClassifier: () => TypeClassifier,
|
|
@@ -173,7 +174,15 @@ ${jsonToFrontMatter(content)}---
|
|
|
173
174
|
// src/generate-types.ts
|
|
174
175
|
var fs = __toESM(require("fs-extra"));
|
|
175
176
|
var import_path = __toESM(require("path"));
|
|
176
|
-
var
|
|
177
|
+
var import_js_yaml = __toESM(require("js-yaml"));
|
|
178
|
+
function extractFrontmatter(content) {
|
|
179
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
180
|
+
if (!match) {
|
|
181
|
+
return { attributes: {} };
|
|
182
|
+
}
|
|
183
|
+
const attributes = import_js_yaml.default.load(match[1]);
|
|
184
|
+
return { attributes: attributes || {} };
|
|
185
|
+
}
|
|
177
186
|
var _compile = null;
|
|
178
187
|
async function getCompile() {
|
|
179
188
|
var _a;
|
|
@@ -352,7 +361,326 @@ ${typeMapping.join(",\n")}
|
|
|
352
361
|
var isNewFormat = (frontmatter) => {
|
|
353
362
|
return frontmatter["text_config"] || frontmatter["object_config"] || frontmatter["image_config"];
|
|
354
363
|
};
|
|
355
|
-
|
|
364
|
+
function pythonPrimitiveType(schemaType) {
|
|
365
|
+
const map = {
|
|
366
|
+
string: "str",
|
|
367
|
+
number: "float",
|
|
368
|
+
integer: "int",
|
|
369
|
+
boolean: "bool",
|
|
370
|
+
null: "None"
|
|
371
|
+
};
|
|
372
|
+
return map[schemaType] || "Any";
|
|
373
|
+
}
|
|
374
|
+
function propToPascal(prop) {
|
|
375
|
+
return prop.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
|
|
376
|
+
}
|
|
377
|
+
function schemaToPythonType(schema, parentClass, propKey, collected) {
|
|
378
|
+
if (!schema) return "Any";
|
|
379
|
+
const union = schema.anyOf || schema.oneOf;
|
|
380
|
+
if (union) {
|
|
381
|
+
const nullIdx = union.findIndex((v) => v.type === "null");
|
|
382
|
+
const hasNull = nullIdx >= 0;
|
|
383
|
+
const others = union.filter((_, i) => i !== nullIdx);
|
|
384
|
+
if (hasNull && others.length === 1) {
|
|
385
|
+
return `${schemaToPythonType(others[0], parentClass, propKey, collected)} | None`;
|
|
386
|
+
}
|
|
387
|
+
const parts = others.map(
|
|
388
|
+
(v, i) => schemaToPythonType(v, parentClass, `${propKey}${i}`, collected)
|
|
389
|
+
);
|
|
390
|
+
if (hasNull) parts.push("None");
|
|
391
|
+
return parts.join(" | ");
|
|
392
|
+
}
|
|
393
|
+
if (Array.isArray(schema.type)) {
|
|
394
|
+
const hasNull = schema.type.includes("null");
|
|
395
|
+
const nonNull = schema.type.filter((t) => t !== "null");
|
|
396
|
+
if (nonNull.length === 1 && nonNull[0] === "object" && schema.properties) {
|
|
397
|
+
const clsName = `${parentClass}${propToPascal(propKey)}`;
|
|
398
|
+
collected.push(buildTypedDict(clsName, schema, collected));
|
|
399
|
+
return hasNull ? `${clsName} | None` : clsName;
|
|
400
|
+
}
|
|
401
|
+
if (nonNull.length === 1 && nonNull[0] === "array" && schema.items) {
|
|
402
|
+
const item = schemaToPythonType(
|
|
403
|
+
schema.items,
|
|
404
|
+
parentClass,
|
|
405
|
+
propKey,
|
|
406
|
+
collected
|
|
407
|
+
);
|
|
408
|
+
return hasNull ? `list[${item}] | None` : `list[${item}]`;
|
|
409
|
+
}
|
|
410
|
+
const base = nonNull.length === 1 ? pythonPrimitiveType(nonNull[0]) : nonNull.map(pythonPrimitiveType).join(" | ");
|
|
411
|
+
return hasNull ? `${base} | None` : base;
|
|
412
|
+
}
|
|
413
|
+
switch (schema.type) {
|
|
414
|
+
case "string":
|
|
415
|
+
case "number":
|
|
416
|
+
case "integer":
|
|
417
|
+
case "boolean":
|
|
418
|
+
case "null":
|
|
419
|
+
return pythonPrimitiveType(schema.type);
|
|
420
|
+
case "array": {
|
|
421
|
+
const item = schema.items ? schemaToPythonType(schema.items, parentClass, propKey, collected) : "Any";
|
|
422
|
+
return `list[${item}]`;
|
|
423
|
+
}
|
|
424
|
+
case "object": {
|
|
425
|
+
if (!schema.properties || Object.keys(schema.properties).length === 0) {
|
|
426
|
+
return "dict[str, Any]";
|
|
427
|
+
}
|
|
428
|
+
const clsName = `${parentClass}${propToPascal(propKey)}`;
|
|
429
|
+
collected.push(buildTypedDict(clsName, schema, collected));
|
|
430
|
+
return clsName;
|
|
431
|
+
}
|
|
432
|
+
default:
|
|
433
|
+
if (schema.properties) {
|
|
434
|
+
const clsName = `${parentClass}${propToPascal(propKey)}`;
|
|
435
|
+
collected.push(buildTypedDict(clsName, schema, collected));
|
|
436
|
+
return clsName;
|
|
437
|
+
}
|
|
438
|
+
return "Any";
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function buildTypedDict(className, schema, collected) {
|
|
442
|
+
const props = schema.properties || {};
|
|
443
|
+
const requiredSet = new Set(schema.required || []);
|
|
444
|
+
const lines = [];
|
|
445
|
+
const desc = schema.description;
|
|
446
|
+
if (desc) {
|
|
447
|
+
lines.push(`class ${className}(TypedDict):`);
|
|
448
|
+
lines.push(` """${desc}"""`);
|
|
449
|
+
} else {
|
|
450
|
+
lines.push(`class ${className}(TypedDict):`);
|
|
451
|
+
}
|
|
452
|
+
const entries = Object.entries(props);
|
|
453
|
+
if (entries.length === 0) {
|
|
454
|
+
lines.push(" pass");
|
|
455
|
+
return lines.join("\n");
|
|
456
|
+
}
|
|
457
|
+
for (const [key, propSchema] of entries) {
|
|
458
|
+
const pyType = schemaToPythonType(
|
|
459
|
+
propSchema,
|
|
460
|
+
className,
|
|
461
|
+
key,
|
|
462
|
+
collected
|
|
463
|
+
);
|
|
464
|
+
const isRequired = requiredSet.has(key);
|
|
465
|
+
const annotation = isRequired ? pyType : `NotRequired[${pyType}]`;
|
|
466
|
+
const propDesc = propSchema.description;
|
|
467
|
+
if (propDesc) {
|
|
468
|
+
const prefix = ` ${key}: ${annotation} # `;
|
|
469
|
+
const maxDesc = 99 - prefix.length;
|
|
470
|
+
if (maxDesc > 10) {
|
|
471
|
+
const shortDesc = propDesc.length > maxDesc ? propDesc.substring(0, maxDesc - 3) + "..." : propDesc;
|
|
472
|
+
lines.push(`${prefix}${shortDesc}`);
|
|
473
|
+
} else {
|
|
474
|
+
lines.push(` ${key}: ${annotation}`);
|
|
475
|
+
}
|
|
476
|
+
} else {
|
|
477
|
+
lines.push(` ${key}: ${annotation}`);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return lines.join("\n");
|
|
481
|
+
}
|
|
482
|
+
function generatePythonToolTypes(tools) {
|
|
483
|
+
if (Object.keys(tools).length === 0) return null;
|
|
484
|
+
const collected = [];
|
|
485
|
+
for (const [toolName, schema] of Object.entries(tools)) {
|
|
486
|
+
const argsName = `${getToolInterfaceName(toolName)}Args`;
|
|
487
|
+
if (schema.parameters && schema.parameters.properties) {
|
|
488
|
+
collected.push(buildTypedDict(argsName, schema.parameters, collected));
|
|
489
|
+
} else {
|
|
490
|
+
collected.push(`class ${argsName}(TypedDict):
|
|
491
|
+
pass`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const toolLines = Object.keys(tools).map((name) => ` ${name}: ${getToolInterfaceName(name)}Args`).join("\n");
|
|
495
|
+
collected.push(`class Tools(TypedDict):
|
|
496
|
+
${toolLines}`);
|
|
497
|
+
return collected.join("\n\n\n");
|
|
498
|
+
}
|
|
499
|
+
function buildPythonHeader(body) {
|
|
500
|
+
const imports = ["TypedDict"];
|
|
501
|
+
if (body.includes("NotRequired[")) imports.push("NotRequired");
|
|
502
|
+
if (body.includes("Literal[")) imports.push("Literal");
|
|
503
|
+
if (/\bAny\b/.test(body)) imports.push("Any");
|
|
504
|
+
imports.sort();
|
|
505
|
+
return `# Auto-generated types from AgentMark
|
|
506
|
+
# Do not edit this file directly
|
|
507
|
+
|
|
508
|
+
from __future__ import annotations
|
|
509
|
+
|
|
510
|
+
from typing import ${imports.join(", ")}
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
`;
|
|
514
|
+
}
|
|
515
|
+
async function generatePythonTypeDefinitionsV1_0(prompts) {
|
|
516
|
+
const allClasses = [];
|
|
517
|
+
const typeMapping = [];
|
|
518
|
+
for (const prompt of prompts) {
|
|
519
|
+
const { path: promptPath, input_schema } = prompt;
|
|
520
|
+
const name = getInterfaceName(promptPath);
|
|
521
|
+
try {
|
|
522
|
+
let kind = "text";
|
|
523
|
+
let outputSchema = null;
|
|
524
|
+
let tools = {};
|
|
525
|
+
if ("text_config" in prompt) {
|
|
526
|
+
kind = "text";
|
|
527
|
+
tools = prompt.text_config.tools || {};
|
|
528
|
+
} else if ("object_config" in prompt) {
|
|
529
|
+
kind = "object";
|
|
530
|
+
tools = prompt.object_config.tools || {};
|
|
531
|
+
outputSchema = prompt.object_config.schema;
|
|
532
|
+
} else if ("image_config" in prompt) {
|
|
533
|
+
kind = "image";
|
|
534
|
+
tools = prompt.image_config.tools || {};
|
|
535
|
+
}
|
|
536
|
+
const inputCollected = [];
|
|
537
|
+
if (input_schema && input_schema.properties) {
|
|
538
|
+
inputCollected.push(
|
|
539
|
+
buildTypedDict(`${name}In`, input_schema, inputCollected)
|
|
540
|
+
);
|
|
541
|
+
} else {
|
|
542
|
+
inputCollected.push(`class ${name}In(TypedDict):
|
|
543
|
+
pass`);
|
|
544
|
+
}
|
|
545
|
+
allClasses.push(...inputCollected);
|
|
546
|
+
const outputCollected = [];
|
|
547
|
+
if (outputSchema && outputSchema.properties) {
|
|
548
|
+
outputCollected.push(
|
|
549
|
+
buildTypedDict(`${name}Out`, outputSchema, outputCollected)
|
|
550
|
+
);
|
|
551
|
+
} else if (kind === "object") {
|
|
552
|
+
outputCollected.push(`class ${name}Out(TypedDict):
|
|
553
|
+
pass`);
|
|
554
|
+
} else {
|
|
555
|
+
outputCollected.push(`${name}Out = str`);
|
|
556
|
+
}
|
|
557
|
+
allClasses.push(...outputCollected);
|
|
558
|
+
if (Object.keys(tools).length > 0) {
|
|
559
|
+
const toolOutput = generatePythonToolTypes(tools);
|
|
560
|
+
if (toolOutput) allClasses.push(toolOutput);
|
|
561
|
+
}
|
|
562
|
+
const toolsLine = Object.keys(tools).length > 0 ? "\n tools: NotRequired[list[str]]" : "";
|
|
563
|
+
allClasses.push(
|
|
564
|
+
`class ${name}(TypedDict):
|
|
565
|
+
kind: Literal['${kind}']
|
|
566
|
+
input: ${name}In
|
|
567
|
+
output: ${name}Out${toolsLine}`
|
|
568
|
+
);
|
|
569
|
+
typeMapping.push({ path: promptPath, name });
|
|
570
|
+
const withoutMdx = promptPath.replace(/\.mdx$/, "");
|
|
571
|
+
if (withoutMdx !== promptPath)
|
|
572
|
+
typeMapping.push({ path: withoutMdx, name });
|
|
573
|
+
const shortName = promptPath.replace(/\.prompt\.mdx$/, "");
|
|
574
|
+
if (shortName !== promptPath && shortName !== withoutMdx) {
|
|
575
|
+
typeMapping.push({ path: shortName, name });
|
|
576
|
+
}
|
|
577
|
+
} catch (error) {
|
|
578
|
+
console.error(`Error processing ${promptPath}:`, error);
|
|
579
|
+
allClasses.push(`class ${name}In(TypedDict):
|
|
580
|
+
pass`);
|
|
581
|
+
allClasses.push(`${name}Out = str`);
|
|
582
|
+
allClasses.push(
|
|
583
|
+
`class ${name}(TypedDict):
|
|
584
|
+
kind: Literal['text']
|
|
585
|
+
input: ${name}In
|
|
586
|
+
output: ${name}Out`
|
|
587
|
+
);
|
|
588
|
+
typeMapping.push({ path: promptPath, name });
|
|
589
|
+
const withoutMdx = promptPath.replace(/\.mdx$/, "");
|
|
590
|
+
if (withoutMdx !== promptPath)
|
|
591
|
+
typeMapping.push({ path: withoutMdx, name });
|
|
592
|
+
const shortName = promptPath.replace(/\.prompt\.mdx$/, "");
|
|
593
|
+
if (shortName !== promptPath && shortName !== withoutMdx) {
|
|
594
|
+
typeMapping.push({ path: shortName, name });
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
const mappingLines = typeMapping.map(({ path: path2, name }) => ` '${path2}': ${name}`).join(",\n");
|
|
599
|
+
allClasses.push(
|
|
600
|
+
`AgentmarkTypes = TypedDict('AgentmarkTypes', {
|
|
601
|
+
${mappingLines},
|
|
602
|
+
})`
|
|
603
|
+
);
|
|
604
|
+
const body = allClasses.join("\n\n\n") + "\n";
|
|
605
|
+
return buildPythonHeader(body) + body;
|
|
606
|
+
}
|
|
607
|
+
async function generatePythonTypeDefinitionsV0(prompts) {
|
|
608
|
+
var _a, _b;
|
|
609
|
+
const allClasses = [];
|
|
610
|
+
const typeMapping = [];
|
|
611
|
+
for (const prompt of prompts) {
|
|
612
|
+
const { path: promptPath, metadata, input_schema } = prompt;
|
|
613
|
+
const name = getInterfaceName(promptPath);
|
|
614
|
+
try {
|
|
615
|
+
const inputCollected = [];
|
|
616
|
+
if (input_schema && input_schema.properties) {
|
|
617
|
+
inputCollected.push(
|
|
618
|
+
buildTypedDict(`${name}In`, input_schema, inputCollected)
|
|
619
|
+
);
|
|
620
|
+
} else {
|
|
621
|
+
inputCollected.push(`class ${name}In(TypedDict):
|
|
622
|
+
pass`);
|
|
623
|
+
}
|
|
624
|
+
allClasses.push(...inputCollected);
|
|
625
|
+
const outputSchema = (_b = (_a = metadata == null ? void 0 : metadata.model) == null ? void 0 : _a.settings) == null ? void 0 : _b.schema;
|
|
626
|
+
const outputCollected = [];
|
|
627
|
+
if (outputSchema && outputSchema.properties) {
|
|
628
|
+
outputCollected.push(
|
|
629
|
+
buildTypedDict(`${name}Out`, outputSchema, outputCollected)
|
|
630
|
+
);
|
|
631
|
+
} else {
|
|
632
|
+
outputCollected.push(`${name}Out = str`);
|
|
633
|
+
}
|
|
634
|
+
allClasses.push(...outputCollected);
|
|
635
|
+
allClasses.push(
|
|
636
|
+
`class ${name}(TypedDict):
|
|
637
|
+
input: ${name}In
|
|
638
|
+
output: ${name}Out`
|
|
639
|
+
);
|
|
640
|
+
typeMapping.push({ path: promptPath, name });
|
|
641
|
+
const withoutMdx = promptPath.replace(/\.mdx$/, "");
|
|
642
|
+
if (withoutMdx !== promptPath)
|
|
643
|
+
typeMapping.push({ path: withoutMdx, name });
|
|
644
|
+
const shortName = promptPath.replace(/\.prompt\.mdx$/, "");
|
|
645
|
+
if (shortName !== promptPath && shortName !== withoutMdx) {
|
|
646
|
+
typeMapping.push({ path: shortName, name });
|
|
647
|
+
}
|
|
648
|
+
} catch (error) {
|
|
649
|
+
console.error(`Error processing ${promptPath}:`, error);
|
|
650
|
+
allClasses.push(`class ${name}In(TypedDict):
|
|
651
|
+
pass`);
|
|
652
|
+
allClasses.push(`${name}Out = str`);
|
|
653
|
+
allClasses.push(
|
|
654
|
+
`class ${name}(TypedDict):
|
|
655
|
+
input: ${name}In
|
|
656
|
+
output: ${name}Out`
|
|
657
|
+
);
|
|
658
|
+
typeMapping.push({ path: promptPath, name });
|
|
659
|
+
const withoutMdx = promptPath.replace(/\.mdx$/, "");
|
|
660
|
+
if (withoutMdx !== promptPath)
|
|
661
|
+
typeMapping.push({ path: withoutMdx, name });
|
|
662
|
+
const shortName = promptPath.replace(/\.prompt\.mdx$/, "");
|
|
663
|
+
if (shortName !== promptPath && shortName !== withoutMdx) {
|
|
664
|
+
typeMapping.push({ path: shortName, name });
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
const mappingLines = typeMapping.map(({ path: path2, name }) => ` '${path2}': ${name}`).join(",\n");
|
|
669
|
+
allClasses.push(
|
|
670
|
+
`AgentmarkTypes = TypedDict('AgentmarkTypes', {
|
|
671
|
+
${mappingLines},
|
|
672
|
+
})`
|
|
673
|
+
);
|
|
674
|
+
const body = allClasses.join("\n\n\n") + "\n";
|
|
675
|
+
return buildPythonHeader(body) + body;
|
|
676
|
+
}
|
|
677
|
+
async function generateTypeDefinitions(prompts, language = "typescript") {
|
|
678
|
+
if (language === "python") {
|
|
679
|
+
if (prompts[0].version === "1.0") {
|
|
680
|
+
return generatePythonTypeDefinitionsV1_0(prompts);
|
|
681
|
+
}
|
|
682
|
+
return generatePythonTypeDefinitionsV0(prompts);
|
|
683
|
+
}
|
|
356
684
|
if (prompts[0].version === "1.0") {
|
|
357
685
|
return generateTypeDefinitionsV1_0(prompts);
|
|
358
686
|
}
|
|
@@ -417,7 +745,7 @@ async function fetchPromptsFrontmatter(options) {
|
|
|
417
745
|
return Promise.all(
|
|
418
746
|
promptFiles.map(async (file) => {
|
|
419
747
|
const content = await fs.readFile(file, "utf-8");
|
|
420
|
-
const { attributes } = (
|
|
748
|
+
const { attributes } = extractFrontmatter(content);
|
|
421
749
|
if (isNewFormat(attributes)) {
|
|
422
750
|
return {
|
|
423
751
|
path: import_path.default.relative(options.rootDir, file),
|
|
@@ -559,6 +887,7 @@ var KNOWN_METADATA_FIELDS = /* @__PURE__ */ new Set([
|
|
|
559
887
|
"dataset_path",
|
|
560
888
|
"dataset_item_name",
|
|
561
889
|
"dataset_expected_output",
|
|
890
|
+
"dataset_input",
|
|
562
891
|
"prompt_name",
|
|
563
892
|
"props",
|
|
564
893
|
"commit_sha"
|
|
@@ -1346,10 +1675,12 @@ function parseAgentMarkAttributes(attributes, prefix = "agentmark.") {
|
|
|
1346
1675
|
if (get("trace_name")) result.traceName = String(get("trace_name"));
|
|
1347
1676
|
if (get("prompt_name")) result.promptName = String(get("prompt_name"));
|
|
1348
1677
|
if (get("props")) result.props = String(get("props"));
|
|
1678
|
+
if (get("span.kind")) result.kind = String(get("span.kind"));
|
|
1349
1679
|
if (get("dataset_run_id")) result.datasetRunId = String(get("dataset_run_id"));
|
|
1350
1680
|
if (get("dataset_run_name")) result.datasetRunName = String(get("dataset_run_name"));
|
|
1351
1681
|
if (get("dataset_item_name")) result.datasetItemName = String(get("dataset_item_name"));
|
|
1352
1682
|
if (get("dataset_expected_output")) result.datasetExpectedOutput = String(get("dataset_expected_output"));
|
|
1683
|
+
if (get("dataset_input")) result.datasetInput = String(get("dataset_input"));
|
|
1353
1684
|
if (get("dataset_path")) result.datasetPath = String(get("dataset_path"));
|
|
1354
1685
|
return result;
|
|
1355
1686
|
}
|
|
@@ -1462,6 +1793,10 @@ var AgentMarkTransformer = class {
|
|
|
1462
1793
|
if (result.inputTokens !== void 0 && result.outputTokens !== void 0) {
|
|
1463
1794
|
result.totalTokens = result.inputTokens + result.outputTokens;
|
|
1464
1795
|
}
|
|
1796
|
+
const costUsd = attributes["agentmark.usage.cost_usd"];
|
|
1797
|
+
if (typeof costUsd === "number" && costUsd > 0) {
|
|
1798
|
+
result.cost = costUsd;
|
|
1799
|
+
}
|
|
1465
1800
|
const finishReasons = attributes[GenAIAttributes.RESPONSE_FINISH_REASONS];
|
|
1466
1801
|
if (finishReasons) {
|
|
1467
1802
|
try {
|
|
@@ -1507,6 +1842,22 @@ var AgentMarkTransformer = class {
|
|
|
1507
1842
|
const responseOutput = attributes[GenAIAttributes.RESPONSE_OUTPUT];
|
|
1508
1843
|
if (responseOutput && typeof responseOutput === "string") {
|
|
1509
1844
|
result.output = responseOutput;
|
|
1845
|
+
try {
|
|
1846
|
+
result.outputObject = JSON.parse(responseOutput);
|
|
1847
|
+
} catch {
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1850
|
+
const amInput = attributes["agentmark.input"];
|
|
1851
|
+
if (amInput && typeof amInput === "string" && !result.input) {
|
|
1852
|
+
result.input = [{ role: "user", content: amInput }];
|
|
1853
|
+
}
|
|
1854
|
+
const amOutput = attributes["agentmark.output"];
|
|
1855
|
+
if (amOutput && typeof amOutput === "string" && !result.output) {
|
|
1856
|
+
result.output = amOutput;
|
|
1857
|
+
try {
|
|
1858
|
+
result.outputObject = JSON.parse(amOutput);
|
|
1859
|
+
} catch {
|
|
1860
|
+
}
|
|
1510
1861
|
}
|
|
1511
1862
|
const toolName = attributes[GenAIAttributes.TOOL_NAME];
|
|
1512
1863
|
const toolCallId = attributes[GenAIAttributes.TOOL_CALL_ID];
|
|
@@ -1548,6 +1899,194 @@ var AgentMarkTransformer = class {
|
|
|
1548
1899
|
};
|
|
1549
1900
|
var AGENTMARK_SCOPE_NAME = "agentmark";
|
|
1550
1901
|
|
|
1902
|
+
// src/normalizer/transformers/otel-genai/index.ts
|
|
1903
|
+
var Attrs = {
|
|
1904
|
+
// Standard OTel GenAI attributes
|
|
1905
|
+
SYSTEM: "gen_ai.system",
|
|
1906
|
+
PROVIDER_NAME: "gen_ai.provider.name",
|
|
1907
|
+
OPERATION_NAME: "gen_ai.operation.name",
|
|
1908
|
+
REQUEST_MODEL: "gen_ai.request.model",
|
|
1909
|
+
REQUEST_MAX_TOKENS: "gen_ai.request.max_tokens",
|
|
1910
|
+
REQUEST_TEMPERATURE: "gen_ai.request.temperature",
|
|
1911
|
+
RESPONSE_ID: "gen_ai.response.id",
|
|
1912
|
+
RESPONSE_MODEL: "gen_ai.response.model",
|
|
1913
|
+
RESPONSE_FINISH_REASONS: "gen_ai.response.finish_reasons",
|
|
1914
|
+
USAGE_INPUT_TOKENS: "gen_ai.usage.input_tokens",
|
|
1915
|
+
USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens",
|
|
1916
|
+
// v1.37.0+ content attributes
|
|
1917
|
+
INPUT_MESSAGES: "gen_ai.input.messages",
|
|
1918
|
+
OUTPUT_MESSAGES: "gen_ai.output.messages",
|
|
1919
|
+
SYSTEM_INSTRUCTIONS: "gen_ai.system_instructions",
|
|
1920
|
+
TOOL_DEFINITIONS: "gen_ai.tool.definitions",
|
|
1921
|
+
// Tool call attributes (v1.37.0+)
|
|
1922
|
+
TOOL_NAME: "gen_ai.tool.name",
|
|
1923
|
+
TOOL_CALL_ID: "gen_ai.tool.call.id",
|
|
1924
|
+
TOOL_CALL_ARGS: "gen_ai.tool.call.arguments",
|
|
1925
|
+
TOOL_CALL_RESULT: "gen_ai.tool.call.result"
|
|
1926
|
+
};
|
|
1927
|
+
function partsToText(parts) {
|
|
1928
|
+
return parts.filter((p) => p.type === "text" && p.content).map((p) => p.content).join("\n");
|
|
1929
|
+
}
|
|
1930
|
+
function normalizeMessages(raw) {
|
|
1931
|
+
try {
|
|
1932
|
+
const parsed = JSON.parse(raw);
|
|
1933
|
+
if (!Array.isArray(parsed) || parsed.length === 0) return null;
|
|
1934
|
+
const messages = [];
|
|
1935
|
+
for (const msg of parsed) {
|
|
1936
|
+
if (!msg.role) continue;
|
|
1937
|
+
if (msg.content && typeof msg.content === "string") {
|
|
1938
|
+
messages.push(msg);
|
|
1939
|
+
} else if (msg.parts && Array.isArray(msg.parts)) {
|
|
1940
|
+
const text = partsToText(msg.parts);
|
|
1941
|
+
if (text) {
|
|
1942
|
+
messages.push({ role: msg.role, content: text });
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
return messages.length > 0 ? messages : null;
|
|
1947
|
+
} catch {
|
|
1948
|
+
return null;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
function extractStructuredOutput(raw) {
|
|
1952
|
+
try {
|
|
1953
|
+
const parsed = JSON.parse(raw);
|
|
1954
|
+
if (!Array.isArray(parsed)) return null;
|
|
1955
|
+
for (const msg of parsed) {
|
|
1956
|
+
for (const part of msg.parts || []) {
|
|
1957
|
+
if (part.type === "tool_call" && part.arguments) {
|
|
1958
|
+
return {
|
|
1959
|
+
output: JSON.stringify(part.arguments),
|
|
1960
|
+
outputObject: part.arguments
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
for (const msg of parsed) {
|
|
1966
|
+
const text = partsToText(msg.parts || []);
|
|
1967
|
+
if (text) return { output: text };
|
|
1968
|
+
}
|
|
1969
|
+
return null;
|
|
1970
|
+
} catch {
|
|
1971
|
+
return null;
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
var OtelGenAiTransformer = class {
|
|
1975
|
+
classify(span, attributes) {
|
|
1976
|
+
if (span.name.startsWith("chat ")) return "GENERATION" /* GENERATION */;
|
|
1977
|
+
if (span.name.startsWith("invoke_agent") || span.name === "agent run") return "SPAN" /* SPAN */;
|
|
1978
|
+
if (span.name.startsWith("execute_tool") || span.name.startsWith("running ")) return "SPAN" /* SPAN */;
|
|
1979
|
+
if (attributes[Attrs.USAGE_INPUT_TOKENS] !== void 0) return "GENERATION" /* GENERATION */;
|
|
1980
|
+
return "SPAN" /* SPAN */;
|
|
1981
|
+
}
|
|
1982
|
+
transform(span, attributes) {
|
|
1983
|
+
const result = {};
|
|
1984
|
+
const model = attributes[Attrs.RESPONSE_MODEL] || attributes[Attrs.REQUEST_MODEL];
|
|
1985
|
+
if (model && typeof model === "string") {
|
|
1986
|
+
result.model = model;
|
|
1987
|
+
}
|
|
1988
|
+
const inputTokens = attributes[Attrs.USAGE_INPUT_TOKENS];
|
|
1989
|
+
const outputTokens = attributes[Attrs.USAGE_OUTPUT_TOKENS];
|
|
1990
|
+
if (typeof inputTokens === "number") result.inputTokens = inputTokens;
|
|
1991
|
+
if (typeof outputTokens === "number") result.outputTokens = outputTokens;
|
|
1992
|
+
if (result.inputTokens !== void 0 && result.outputTokens !== void 0) {
|
|
1993
|
+
result.totalTokens = result.inputTokens + result.outputTokens;
|
|
1994
|
+
}
|
|
1995
|
+
const finishReasons = attributes[Attrs.RESPONSE_FINISH_REASONS];
|
|
1996
|
+
if (Array.isArray(finishReasons) && finishReasons.length > 0) {
|
|
1997
|
+
result.finishReason = finishReasons[0];
|
|
1998
|
+
}
|
|
1999
|
+
const temperature = attributes[Attrs.REQUEST_TEMPERATURE];
|
|
2000
|
+
if (typeof temperature === "number") {
|
|
2001
|
+
result.settings = { ...result.settings, temperature };
|
|
2002
|
+
}
|
|
2003
|
+
const inputMessages = attributes[Attrs.INPUT_MESSAGES];
|
|
2004
|
+
if (inputMessages && typeof inputMessages === "string") {
|
|
2005
|
+
const messages = normalizeMessages(inputMessages);
|
|
2006
|
+
if (messages) result.input = messages;
|
|
2007
|
+
}
|
|
2008
|
+
const outputMessages = attributes[Attrs.OUTPUT_MESSAGES];
|
|
2009
|
+
if (outputMessages && typeof outputMessages === "string") {
|
|
2010
|
+
const extracted = extractStructuredOutput(outputMessages);
|
|
2011
|
+
if (extracted) {
|
|
2012
|
+
result.output = extracted.output;
|
|
2013
|
+
if (extracted.outputObject) {
|
|
2014
|
+
result.outputObject = extracted.outputObject;
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
const allMessages = attributes["pydantic_ai.all_messages"];
|
|
2019
|
+
if (allMessages && typeof allMessages === "string" && !result.input) {
|
|
2020
|
+
const messages = normalizeMessages(allMessages);
|
|
2021
|
+
if (messages) {
|
|
2022
|
+
const userMessages = messages.filter((m) => m.role === "user");
|
|
2023
|
+
if (userMessages.length > 0) {
|
|
2024
|
+
result.input = userMessages;
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
const finalResult = attributes["final_result"];
|
|
2029
|
+
if (finalResult && typeof finalResult === "string" && !result.output) {
|
|
2030
|
+
result.output = finalResult;
|
|
2031
|
+
try {
|
|
2032
|
+
result.outputObject = JSON.parse(finalResult);
|
|
2033
|
+
} catch {
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
const propsStr = attributes["agentmark.props"];
|
|
2037
|
+
if (propsStr && typeof propsStr === "string" && !result.input) {
|
|
2038
|
+
try {
|
|
2039
|
+
const props = JSON.parse(propsStr);
|
|
2040
|
+
result.input = [{ role: "user", content: JSON.stringify(props) }];
|
|
2041
|
+
} catch {
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
const outputStr = attributes["agentmark.output"];
|
|
2045
|
+
if (outputStr && typeof outputStr === "string" && !result.output) {
|
|
2046
|
+
result.output = outputStr;
|
|
2047
|
+
try {
|
|
2048
|
+
result.outputObject = JSON.parse(outputStr);
|
|
2049
|
+
} catch {
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
const toolName = attributes[Attrs.TOOL_NAME];
|
|
2053
|
+
if (toolName && typeof toolName === "string") {
|
|
2054
|
+
result.name = toolName;
|
|
2055
|
+
const toolCall = {
|
|
2056
|
+
type: "tool-call",
|
|
2057
|
+
toolCallId: attributes[Attrs.TOOL_CALL_ID] || "",
|
|
2058
|
+
toolName,
|
|
2059
|
+
args: {}
|
|
2060
|
+
};
|
|
2061
|
+
const toolArgs = attributes[Attrs.TOOL_CALL_ARGS];
|
|
2062
|
+
if (toolArgs && typeof toolArgs === "string") {
|
|
2063
|
+
try {
|
|
2064
|
+
toolCall.args = JSON.parse(toolArgs);
|
|
2065
|
+
} catch {
|
|
2066
|
+
toolCall.args = { raw: toolArgs };
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
const toolResult = attributes[Attrs.TOOL_CALL_RESULT];
|
|
2070
|
+
if (toolResult && typeof toolResult === "string") {
|
|
2071
|
+
toolCall.result = toolResult;
|
|
2072
|
+
}
|
|
2073
|
+
result.toolCalls = [toolCall];
|
|
2074
|
+
}
|
|
2075
|
+
const agentmarkAttrs = parseAgentMarkAttributes(attributes);
|
|
2076
|
+
Object.assign(result, agentmarkAttrs);
|
|
2077
|
+
const parsedMeta = parseMetadata(attributes);
|
|
2078
|
+
if (parsedMeta.metadata && Object.keys(parsedMeta.metadata).length > 0) {
|
|
2079
|
+
result.metadata = { ...result.metadata, ...parsedMeta.metadata };
|
|
2080
|
+
}
|
|
2081
|
+
const customMeta = extractCustomMetadata(attributes);
|
|
2082
|
+
if (Object.keys(customMeta).length > 0) {
|
|
2083
|
+
result.metadata = { ...result.metadata, ...customMeta };
|
|
2084
|
+
}
|
|
2085
|
+
return result;
|
|
2086
|
+
}
|
|
2087
|
+
};
|
|
2088
|
+
OtelGenAiTransformer.SCOPE_NAME = "pydantic-ai";
|
|
2089
|
+
|
|
1551
2090
|
// src/normalizer/converters/otlp-converter.ts
|
|
1552
2091
|
function convertOtlpValue(value) {
|
|
1553
2092
|
var _a;
|
|
@@ -1649,7 +2188,8 @@ var typeClassifier = new TypeClassifier();
|
|
|
1649
2188
|
registry.register("ai", new AiSdkTransformer());
|
|
1650
2189
|
registry.register("default-tracer", new MastraTransformer());
|
|
1651
2190
|
registry.register("agentmark", new AgentMarkTransformer());
|
|
1652
|
-
registry.
|
|
2191
|
+
registry.register("pydantic-ai", new OtelGenAiTransformer());
|
|
2192
|
+
registry.setDefault(new OtelGenAiTransformer());
|
|
1653
2193
|
function normalizeSpan(resource, scope, span) {
|
|
1654
2194
|
var _a, _b, _c;
|
|
1655
2195
|
const allAttributes = {
|
|
@@ -1724,6 +2264,7 @@ function normalizeOtlpSpans(resourceSpans) {
|
|
|
1724
2264
|
AiSdkTransformer,
|
|
1725
2265
|
ClaudeAgentTransformer,
|
|
1726
2266
|
MastraTransformer,
|
|
2267
|
+
OtelGenAiTransformer,
|
|
1727
2268
|
SpanType,
|
|
1728
2269
|
TransformerRegistry,
|
|
1729
2270
|
TypeClassifier,
|