@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.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 import_front_matter = __toESM(require("front-matter"));
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
- 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
+ }
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 } = (0, import_front_matter.default)(content);
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.setDefault(new AiSdkTransformer());
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,