@agentmark-ai/shared-utils 0.3.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.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,
@@ -360,7 +361,326 @@ ${typeMapping.join(",\n")}
360
361
  var isNewFormat = (frontmatter) => {
361
362
  return frontmatter["text_config"] || frontmatter["object_config"] || frontmatter["image_config"];
362
363
  };
363
- async function generateTypeDefinitions(prompts) {
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
+ }
364
684
  if (prompts[0].version === "1.0") {
365
685
  return generateTypeDefinitionsV1_0(prompts);
366
686
  }
@@ -567,6 +887,7 @@ var KNOWN_METADATA_FIELDS = /* @__PURE__ */ new Set([
567
887
  "dataset_path",
568
888
  "dataset_item_name",
569
889
  "dataset_expected_output",
890
+ "dataset_input",
570
891
  "prompt_name",
571
892
  "props",
572
893
  "commit_sha"
@@ -1354,10 +1675,12 @@ function parseAgentMarkAttributes(attributes, prefix = "agentmark.") {
1354
1675
  if (get("trace_name")) result.traceName = String(get("trace_name"));
1355
1676
  if (get("prompt_name")) result.promptName = String(get("prompt_name"));
1356
1677
  if (get("props")) result.props = String(get("props"));
1678
+ if (get("span.kind")) result.kind = String(get("span.kind"));
1357
1679
  if (get("dataset_run_id")) result.datasetRunId = String(get("dataset_run_id"));
1358
1680
  if (get("dataset_run_name")) result.datasetRunName = String(get("dataset_run_name"));
1359
1681
  if (get("dataset_item_name")) result.datasetItemName = String(get("dataset_item_name"));
1360
1682
  if (get("dataset_expected_output")) result.datasetExpectedOutput = String(get("dataset_expected_output"));
1683
+ if (get("dataset_input")) result.datasetInput = String(get("dataset_input"));
1361
1684
  if (get("dataset_path")) result.datasetPath = String(get("dataset_path"));
1362
1685
  return result;
1363
1686
  }
@@ -1470,6 +1793,10 @@ var AgentMarkTransformer = class {
1470
1793
  if (result.inputTokens !== void 0 && result.outputTokens !== void 0) {
1471
1794
  result.totalTokens = result.inputTokens + result.outputTokens;
1472
1795
  }
1796
+ const costUsd = attributes["agentmark.usage.cost_usd"];
1797
+ if (typeof costUsd === "number" && costUsd > 0) {
1798
+ result.cost = costUsd;
1799
+ }
1473
1800
  const finishReasons = attributes[GenAIAttributes.RESPONSE_FINISH_REASONS];
1474
1801
  if (finishReasons) {
1475
1802
  try {
@@ -1515,6 +1842,22 @@ var AgentMarkTransformer = class {
1515
1842
  const responseOutput = attributes[GenAIAttributes.RESPONSE_OUTPUT];
1516
1843
  if (responseOutput && typeof responseOutput === "string") {
1517
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
+ }
1518
1861
  }
1519
1862
  const toolName = attributes[GenAIAttributes.TOOL_NAME];
1520
1863
  const toolCallId = attributes[GenAIAttributes.TOOL_CALL_ID];
@@ -1556,6 +1899,194 @@ var AgentMarkTransformer = class {
1556
1899
  };
1557
1900
  var AGENTMARK_SCOPE_NAME = "agentmark";
1558
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
+
1559
2090
  // src/normalizer/converters/otlp-converter.ts
1560
2091
  function convertOtlpValue(value) {
1561
2092
  var _a;
@@ -1657,7 +2188,8 @@ var typeClassifier = new TypeClassifier();
1657
2188
  registry.register("ai", new AiSdkTransformer());
1658
2189
  registry.register("default-tracer", new MastraTransformer());
1659
2190
  registry.register("agentmark", new AgentMarkTransformer());
1660
- registry.setDefault(new AiSdkTransformer());
2191
+ registry.register("pydantic-ai", new OtelGenAiTransformer());
2192
+ registry.setDefault(new OtelGenAiTransformer());
1661
2193
  function normalizeSpan(resource, scope, span) {
1662
2194
  var _a, _b, _c;
1663
2195
  const allAttributes = {
@@ -1732,6 +2264,7 @@ function normalizeOtlpSpans(resourceSpans) {
1732
2264
  AiSdkTransformer,
1733
2265
  ClaudeAgentTransformer,
1734
2266
  MastraTransformer,
2267
+ OtelGenAiTransformer,
1735
2268
  SpanType,
1736
2269
  TransformerRegistry,
1737
2270
  TypeClassifier,