@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.mjs CHANGED
@@ -111,7 +111,15 @@ ${jsonToFrontMatter(content)}---
111
111
  // src/generate-types.ts
112
112
  import * as fs from "fs-extra";
113
113
  import path from "path";
114
- import fm from "front-matter";
114
+ import yaml from "js-yaml";
115
+ function extractFrontmatter(content) {
116
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
117
+ if (!match) {
118
+ return { attributes: {} };
119
+ }
120
+ const attributes = yaml.load(match[1]);
121
+ return { attributes: attributes || {} };
122
+ }
115
123
  var _compile = null;
116
124
  async function getCompile() {
117
125
  var _a;
@@ -290,7 +298,326 @@ ${typeMapping.join(",\n")}
290
298
  var isNewFormat = (frontmatter) => {
291
299
  return frontmatter["text_config"] || frontmatter["object_config"] || frontmatter["image_config"];
292
300
  };
293
- async function generateTypeDefinitions(prompts) {
301
+ function pythonPrimitiveType(schemaType) {
302
+ const map = {
303
+ string: "str",
304
+ number: "float",
305
+ integer: "int",
306
+ boolean: "bool",
307
+ null: "None"
308
+ };
309
+ return map[schemaType] || "Any";
310
+ }
311
+ function propToPascal(prop) {
312
+ return prop.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
313
+ }
314
+ function schemaToPythonType(schema, parentClass, propKey, collected) {
315
+ if (!schema) return "Any";
316
+ const union = schema.anyOf || schema.oneOf;
317
+ if (union) {
318
+ const nullIdx = union.findIndex((v) => v.type === "null");
319
+ const hasNull = nullIdx >= 0;
320
+ const others = union.filter((_, i) => i !== nullIdx);
321
+ if (hasNull && others.length === 1) {
322
+ return `${schemaToPythonType(others[0], parentClass, propKey, collected)} | None`;
323
+ }
324
+ const parts = others.map(
325
+ (v, i) => schemaToPythonType(v, parentClass, `${propKey}${i}`, collected)
326
+ );
327
+ if (hasNull) parts.push("None");
328
+ return parts.join(" | ");
329
+ }
330
+ if (Array.isArray(schema.type)) {
331
+ const hasNull = schema.type.includes("null");
332
+ const nonNull = schema.type.filter((t) => t !== "null");
333
+ if (nonNull.length === 1 && nonNull[0] === "object" && schema.properties) {
334
+ const clsName = `${parentClass}${propToPascal(propKey)}`;
335
+ collected.push(buildTypedDict(clsName, schema, collected));
336
+ return hasNull ? `${clsName} | None` : clsName;
337
+ }
338
+ if (nonNull.length === 1 && nonNull[0] === "array" && schema.items) {
339
+ const item = schemaToPythonType(
340
+ schema.items,
341
+ parentClass,
342
+ propKey,
343
+ collected
344
+ );
345
+ return hasNull ? `list[${item}] | None` : `list[${item}]`;
346
+ }
347
+ const base = nonNull.length === 1 ? pythonPrimitiveType(nonNull[0]) : nonNull.map(pythonPrimitiveType).join(" | ");
348
+ return hasNull ? `${base} | None` : base;
349
+ }
350
+ switch (schema.type) {
351
+ case "string":
352
+ case "number":
353
+ case "integer":
354
+ case "boolean":
355
+ case "null":
356
+ return pythonPrimitiveType(schema.type);
357
+ case "array": {
358
+ const item = schema.items ? schemaToPythonType(schema.items, parentClass, propKey, collected) : "Any";
359
+ return `list[${item}]`;
360
+ }
361
+ case "object": {
362
+ if (!schema.properties || Object.keys(schema.properties).length === 0) {
363
+ return "dict[str, Any]";
364
+ }
365
+ const clsName = `${parentClass}${propToPascal(propKey)}`;
366
+ collected.push(buildTypedDict(clsName, schema, collected));
367
+ return clsName;
368
+ }
369
+ default:
370
+ if (schema.properties) {
371
+ const clsName = `${parentClass}${propToPascal(propKey)}`;
372
+ collected.push(buildTypedDict(clsName, schema, collected));
373
+ return clsName;
374
+ }
375
+ return "Any";
376
+ }
377
+ }
378
+ function buildTypedDict(className, schema, collected) {
379
+ const props = schema.properties || {};
380
+ const requiredSet = new Set(schema.required || []);
381
+ const lines = [];
382
+ const desc = schema.description;
383
+ if (desc) {
384
+ lines.push(`class ${className}(TypedDict):`);
385
+ lines.push(` """${desc}"""`);
386
+ } else {
387
+ lines.push(`class ${className}(TypedDict):`);
388
+ }
389
+ const entries = Object.entries(props);
390
+ if (entries.length === 0) {
391
+ lines.push(" pass");
392
+ return lines.join("\n");
393
+ }
394
+ for (const [key, propSchema] of entries) {
395
+ const pyType = schemaToPythonType(
396
+ propSchema,
397
+ className,
398
+ key,
399
+ collected
400
+ );
401
+ const isRequired = requiredSet.has(key);
402
+ const annotation = isRequired ? pyType : `NotRequired[${pyType}]`;
403
+ const propDesc = propSchema.description;
404
+ if (propDesc) {
405
+ const prefix = ` ${key}: ${annotation} # `;
406
+ const maxDesc = 99 - prefix.length;
407
+ if (maxDesc > 10) {
408
+ const shortDesc = propDesc.length > maxDesc ? propDesc.substring(0, maxDesc - 3) + "..." : propDesc;
409
+ lines.push(`${prefix}${shortDesc}`);
410
+ } else {
411
+ lines.push(` ${key}: ${annotation}`);
412
+ }
413
+ } else {
414
+ lines.push(` ${key}: ${annotation}`);
415
+ }
416
+ }
417
+ return lines.join("\n");
418
+ }
419
+ function generatePythonToolTypes(tools) {
420
+ if (Object.keys(tools).length === 0) return null;
421
+ const collected = [];
422
+ for (const [toolName, schema] of Object.entries(tools)) {
423
+ const argsName = `${getToolInterfaceName(toolName)}Args`;
424
+ if (schema.parameters && schema.parameters.properties) {
425
+ collected.push(buildTypedDict(argsName, schema.parameters, collected));
426
+ } else {
427
+ collected.push(`class ${argsName}(TypedDict):
428
+ pass`);
429
+ }
430
+ }
431
+ const toolLines = Object.keys(tools).map((name) => ` ${name}: ${getToolInterfaceName(name)}Args`).join("\n");
432
+ collected.push(`class Tools(TypedDict):
433
+ ${toolLines}`);
434
+ return collected.join("\n\n\n");
435
+ }
436
+ function buildPythonHeader(body) {
437
+ const imports = ["TypedDict"];
438
+ if (body.includes("NotRequired[")) imports.push("NotRequired");
439
+ if (body.includes("Literal[")) imports.push("Literal");
440
+ if (/\bAny\b/.test(body)) imports.push("Any");
441
+ imports.sort();
442
+ return `# Auto-generated types from AgentMark
443
+ # Do not edit this file directly
444
+
445
+ from __future__ import annotations
446
+
447
+ from typing import ${imports.join(", ")}
448
+
449
+
450
+ `;
451
+ }
452
+ async function generatePythonTypeDefinitionsV1_0(prompts) {
453
+ const allClasses = [];
454
+ const typeMapping = [];
455
+ for (const prompt of prompts) {
456
+ const { path: promptPath, input_schema } = prompt;
457
+ const name = getInterfaceName(promptPath);
458
+ try {
459
+ let kind = "text";
460
+ let outputSchema = null;
461
+ let tools = {};
462
+ if ("text_config" in prompt) {
463
+ kind = "text";
464
+ tools = prompt.text_config.tools || {};
465
+ } else if ("object_config" in prompt) {
466
+ kind = "object";
467
+ tools = prompt.object_config.tools || {};
468
+ outputSchema = prompt.object_config.schema;
469
+ } else if ("image_config" in prompt) {
470
+ kind = "image";
471
+ tools = prompt.image_config.tools || {};
472
+ }
473
+ const inputCollected = [];
474
+ if (input_schema && input_schema.properties) {
475
+ inputCollected.push(
476
+ buildTypedDict(`${name}In`, input_schema, inputCollected)
477
+ );
478
+ } else {
479
+ inputCollected.push(`class ${name}In(TypedDict):
480
+ pass`);
481
+ }
482
+ allClasses.push(...inputCollected);
483
+ const outputCollected = [];
484
+ if (outputSchema && outputSchema.properties) {
485
+ outputCollected.push(
486
+ buildTypedDict(`${name}Out`, outputSchema, outputCollected)
487
+ );
488
+ } else if (kind === "object") {
489
+ outputCollected.push(`class ${name}Out(TypedDict):
490
+ pass`);
491
+ } else {
492
+ outputCollected.push(`${name}Out = str`);
493
+ }
494
+ allClasses.push(...outputCollected);
495
+ if (Object.keys(tools).length > 0) {
496
+ const toolOutput = generatePythonToolTypes(tools);
497
+ if (toolOutput) allClasses.push(toolOutput);
498
+ }
499
+ const toolsLine = Object.keys(tools).length > 0 ? "\n tools: NotRequired[list[str]]" : "";
500
+ allClasses.push(
501
+ `class ${name}(TypedDict):
502
+ kind: Literal['${kind}']
503
+ input: ${name}In
504
+ output: ${name}Out${toolsLine}`
505
+ );
506
+ typeMapping.push({ path: promptPath, name });
507
+ const withoutMdx = promptPath.replace(/\.mdx$/, "");
508
+ if (withoutMdx !== promptPath)
509
+ typeMapping.push({ path: withoutMdx, name });
510
+ const shortName = promptPath.replace(/\.prompt\.mdx$/, "");
511
+ if (shortName !== promptPath && shortName !== withoutMdx) {
512
+ typeMapping.push({ path: shortName, name });
513
+ }
514
+ } catch (error) {
515
+ console.error(`Error processing ${promptPath}:`, error);
516
+ allClasses.push(`class ${name}In(TypedDict):
517
+ pass`);
518
+ allClasses.push(`${name}Out = str`);
519
+ allClasses.push(
520
+ `class ${name}(TypedDict):
521
+ kind: Literal['text']
522
+ input: ${name}In
523
+ output: ${name}Out`
524
+ );
525
+ typeMapping.push({ path: promptPath, name });
526
+ const withoutMdx = promptPath.replace(/\.mdx$/, "");
527
+ if (withoutMdx !== promptPath)
528
+ typeMapping.push({ path: withoutMdx, name });
529
+ const shortName = promptPath.replace(/\.prompt\.mdx$/, "");
530
+ if (shortName !== promptPath && shortName !== withoutMdx) {
531
+ typeMapping.push({ path: shortName, name });
532
+ }
533
+ }
534
+ }
535
+ const mappingLines = typeMapping.map(({ path: path2, name }) => ` '${path2}': ${name}`).join(",\n");
536
+ allClasses.push(
537
+ `AgentmarkTypes = TypedDict('AgentmarkTypes', {
538
+ ${mappingLines},
539
+ })`
540
+ );
541
+ const body = allClasses.join("\n\n\n") + "\n";
542
+ return buildPythonHeader(body) + body;
543
+ }
544
+ async function generatePythonTypeDefinitionsV0(prompts) {
545
+ var _a, _b;
546
+ const allClasses = [];
547
+ const typeMapping = [];
548
+ for (const prompt of prompts) {
549
+ const { path: promptPath, metadata, input_schema } = prompt;
550
+ const name = getInterfaceName(promptPath);
551
+ try {
552
+ const inputCollected = [];
553
+ if (input_schema && input_schema.properties) {
554
+ inputCollected.push(
555
+ buildTypedDict(`${name}In`, input_schema, inputCollected)
556
+ );
557
+ } else {
558
+ inputCollected.push(`class ${name}In(TypedDict):
559
+ pass`);
560
+ }
561
+ allClasses.push(...inputCollected);
562
+ const outputSchema = (_b = (_a = metadata == null ? void 0 : metadata.model) == null ? void 0 : _a.settings) == null ? void 0 : _b.schema;
563
+ const outputCollected = [];
564
+ if (outputSchema && outputSchema.properties) {
565
+ outputCollected.push(
566
+ buildTypedDict(`${name}Out`, outputSchema, outputCollected)
567
+ );
568
+ } else {
569
+ outputCollected.push(`${name}Out = str`);
570
+ }
571
+ allClasses.push(...outputCollected);
572
+ allClasses.push(
573
+ `class ${name}(TypedDict):
574
+ input: ${name}In
575
+ output: ${name}Out`
576
+ );
577
+ typeMapping.push({ path: promptPath, name });
578
+ const withoutMdx = promptPath.replace(/\.mdx$/, "");
579
+ if (withoutMdx !== promptPath)
580
+ typeMapping.push({ path: withoutMdx, name });
581
+ const shortName = promptPath.replace(/\.prompt\.mdx$/, "");
582
+ if (shortName !== promptPath && shortName !== withoutMdx) {
583
+ typeMapping.push({ path: shortName, name });
584
+ }
585
+ } catch (error) {
586
+ console.error(`Error processing ${promptPath}:`, error);
587
+ allClasses.push(`class ${name}In(TypedDict):
588
+ pass`);
589
+ allClasses.push(`${name}Out = str`);
590
+ allClasses.push(
591
+ `class ${name}(TypedDict):
592
+ input: ${name}In
593
+ output: ${name}Out`
594
+ );
595
+ typeMapping.push({ path: promptPath, name });
596
+ const withoutMdx = promptPath.replace(/\.mdx$/, "");
597
+ if (withoutMdx !== promptPath)
598
+ typeMapping.push({ path: withoutMdx, name });
599
+ const shortName = promptPath.replace(/\.prompt\.mdx$/, "");
600
+ if (shortName !== promptPath && shortName !== withoutMdx) {
601
+ typeMapping.push({ path: shortName, name });
602
+ }
603
+ }
604
+ }
605
+ const mappingLines = typeMapping.map(({ path: path2, name }) => ` '${path2}': ${name}`).join(",\n");
606
+ allClasses.push(
607
+ `AgentmarkTypes = TypedDict('AgentmarkTypes', {
608
+ ${mappingLines},
609
+ })`
610
+ );
611
+ const body = allClasses.join("\n\n\n") + "\n";
612
+ return buildPythonHeader(body) + body;
613
+ }
614
+ async function generateTypeDefinitions(prompts, language = "typescript") {
615
+ if (language === "python") {
616
+ if (prompts[0].version === "1.0") {
617
+ return generatePythonTypeDefinitionsV1_0(prompts);
618
+ }
619
+ return generatePythonTypeDefinitionsV0(prompts);
620
+ }
294
621
  if (prompts[0].version === "1.0") {
295
622
  return generateTypeDefinitionsV1_0(prompts);
296
623
  }
@@ -355,7 +682,7 @@ async function fetchPromptsFrontmatter(options) {
355
682
  return Promise.all(
356
683
  promptFiles.map(async (file) => {
357
684
  const content = await fs.readFile(file, "utf-8");
358
- const { attributes } = fm(content);
685
+ const { attributes } = extractFrontmatter(content);
359
686
  if (isNewFormat(attributes)) {
360
687
  return {
361
688
  path: path.relative(options.rootDir, file),
@@ -497,6 +824,7 @@ var KNOWN_METADATA_FIELDS = /* @__PURE__ */ new Set([
497
824
  "dataset_path",
498
825
  "dataset_item_name",
499
826
  "dataset_expected_output",
827
+ "dataset_input",
500
828
  "prompt_name",
501
829
  "props",
502
830
  "commit_sha"
@@ -1284,10 +1612,12 @@ function parseAgentMarkAttributes(attributes, prefix = "agentmark.") {
1284
1612
  if (get("trace_name")) result.traceName = String(get("trace_name"));
1285
1613
  if (get("prompt_name")) result.promptName = String(get("prompt_name"));
1286
1614
  if (get("props")) result.props = String(get("props"));
1615
+ if (get("span.kind")) result.kind = String(get("span.kind"));
1287
1616
  if (get("dataset_run_id")) result.datasetRunId = String(get("dataset_run_id"));
1288
1617
  if (get("dataset_run_name")) result.datasetRunName = String(get("dataset_run_name"));
1289
1618
  if (get("dataset_item_name")) result.datasetItemName = String(get("dataset_item_name"));
1290
1619
  if (get("dataset_expected_output")) result.datasetExpectedOutput = String(get("dataset_expected_output"));
1620
+ if (get("dataset_input")) result.datasetInput = String(get("dataset_input"));
1291
1621
  if (get("dataset_path")) result.datasetPath = String(get("dataset_path"));
1292
1622
  return result;
1293
1623
  }
@@ -1400,6 +1730,10 @@ var AgentMarkTransformer = class {
1400
1730
  if (result.inputTokens !== void 0 && result.outputTokens !== void 0) {
1401
1731
  result.totalTokens = result.inputTokens + result.outputTokens;
1402
1732
  }
1733
+ const costUsd = attributes["agentmark.usage.cost_usd"];
1734
+ if (typeof costUsd === "number" && costUsd > 0) {
1735
+ result.cost = costUsd;
1736
+ }
1403
1737
  const finishReasons = attributes[GenAIAttributes.RESPONSE_FINISH_REASONS];
1404
1738
  if (finishReasons) {
1405
1739
  try {
@@ -1445,6 +1779,22 @@ var AgentMarkTransformer = class {
1445
1779
  const responseOutput = attributes[GenAIAttributes.RESPONSE_OUTPUT];
1446
1780
  if (responseOutput && typeof responseOutput === "string") {
1447
1781
  result.output = responseOutput;
1782
+ try {
1783
+ result.outputObject = JSON.parse(responseOutput);
1784
+ } catch {
1785
+ }
1786
+ }
1787
+ const amInput = attributes["agentmark.input"];
1788
+ if (amInput && typeof amInput === "string" && !result.input) {
1789
+ result.input = [{ role: "user", content: amInput }];
1790
+ }
1791
+ const amOutput = attributes["agentmark.output"];
1792
+ if (amOutput && typeof amOutput === "string" && !result.output) {
1793
+ result.output = amOutput;
1794
+ try {
1795
+ result.outputObject = JSON.parse(amOutput);
1796
+ } catch {
1797
+ }
1448
1798
  }
1449
1799
  const toolName = attributes[GenAIAttributes.TOOL_NAME];
1450
1800
  const toolCallId = attributes[GenAIAttributes.TOOL_CALL_ID];
@@ -1486,6 +1836,194 @@ var AgentMarkTransformer = class {
1486
1836
  };
1487
1837
  var AGENTMARK_SCOPE_NAME = "agentmark";
1488
1838
 
1839
+ // src/normalizer/transformers/otel-genai/index.ts
1840
+ var Attrs = {
1841
+ // Standard OTel GenAI attributes
1842
+ SYSTEM: "gen_ai.system",
1843
+ PROVIDER_NAME: "gen_ai.provider.name",
1844
+ OPERATION_NAME: "gen_ai.operation.name",
1845
+ REQUEST_MODEL: "gen_ai.request.model",
1846
+ REQUEST_MAX_TOKENS: "gen_ai.request.max_tokens",
1847
+ REQUEST_TEMPERATURE: "gen_ai.request.temperature",
1848
+ RESPONSE_ID: "gen_ai.response.id",
1849
+ RESPONSE_MODEL: "gen_ai.response.model",
1850
+ RESPONSE_FINISH_REASONS: "gen_ai.response.finish_reasons",
1851
+ USAGE_INPUT_TOKENS: "gen_ai.usage.input_tokens",
1852
+ USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens",
1853
+ // v1.37.0+ content attributes
1854
+ INPUT_MESSAGES: "gen_ai.input.messages",
1855
+ OUTPUT_MESSAGES: "gen_ai.output.messages",
1856
+ SYSTEM_INSTRUCTIONS: "gen_ai.system_instructions",
1857
+ TOOL_DEFINITIONS: "gen_ai.tool.definitions",
1858
+ // Tool call attributes (v1.37.0+)
1859
+ TOOL_NAME: "gen_ai.tool.name",
1860
+ TOOL_CALL_ID: "gen_ai.tool.call.id",
1861
+ TOOL_CALL_ARGS: "gen_ai.tool.call.arguments",
1862
+ TOOL_CALL_RESULT: "gen_ai.tool.call.result"
1863
+ };
1864
+ function partsToText(parts) {
1865
+ return parts.filter((p) => p.type === "text" && p.content).map((p) => p.content).join("\n");
1866
+ }
1867
+ function normalizeMessages(raw) {
1868
+ try {
1869
+ const parsed = JSON.parse(raw);
1870
+ if (!Array.isArray(parsed) || parsed.length === 0) return null;
1871
+ const messages = [];
1872
+ for (const msg of parsed) {
1873
+ if (!msg.role) continue;
1874
+ if (msg.content && typeof msg.content === "string") {
1875
+ messages.push(msg);
1876
+ } else if (msg.parts && Array.isArray(msg.parts)) {
1877
+ const text = partsToText(msg.parts);
1878
+ if (text) {
1879
+ messages.push({ role: msg.role, content: text });
1880
+ }
1881
+ }
1882
+ }
1883
+ return messages.length > 0 ? messages : null;
1884
+ } catch {
1885
+ return null;
1886
+ }
1887
+ }
1888
+ function extractStructuredOutput(raw) {
1889
+ try {
1890
+ const parsed = JSON.parse(raw);
1891
+ if (!Array.isArray(parsed)) return null;
1892
+ for (const msg of parsed) {
1893
+ for (const part of msg.parts || []) {
1894
+ if (part.type === "tool_call" && part.arguments) {
1895
+ return {
1896
+ output: JSON.stringify(part.arguments),
1897
+ outputObject: part.arguments
1898
+ };
1899
+ }
1900
+ }
1901
+ }
1902
+ for (const msg of parsed) {
1903
+ const text = partsToText(msg.parts || []);
1904
+ if (text) return { output: text };
1905
+ }
1906
+ return null;
1907
+ } catch {
1908
+ return null;
1909
+ }
1910
+ }
1911
+ var OtelGenAiTransformer = class {
1912
+ classify(span, attributes) {
1913
+ if (span.name.startsWith("chat ")) return "GENERATION" /* GENERATION */;
1914
+ if (span.name.startsWith("invoke_agent") || span.name === "agent run") return "SPAN" /* SPAN */;
1915
+ if (span.name.startsWith("execute_tool") || span.name.startsWith("running ")) return "SPAN" /* SPAN */;
1916
+ if (attributes[Attrs.USAGE_INPUT_TOKENS] !== void 0) return "GENERATION" /* GENERATION */;
1917
+ return "SPAN" /* SPAN */;
1918
+ }
1919
+ transform(span, attributes) {
1920
+ const result = {};
1921
+ const model = attributes[Attrs.RESPONSE_MODEL] || attributes[Attrs.REQUEST_MODEL];
1922
+ if (model && typeof model === "string") {
1923
+ result.model = model;
1924
+ }
1925
+ const inputTokens = attributes[Attrs.USAGE_INPUT_TOKENS];
1926
+ const outputTokens = attributes[Attrs.USAGE_OUTPUT_TOKENS];
1927
+ if (typeof inputTokens === "number") result.inputTokens = inputTokens;
1928
+ if (typeof outputTokens === "number") result.outputTokens = outputTokens;
1929
+ if (result.inputTokens !== void 0 && result.outputTokens !== void 0) {
1930
+ result.totalTokens = result.inputTokens + result.outputTokens;
1931
+ }
1932
+ const finishReasons = attributes[Attrs.RESPONSE_FINISH_REASONS];
1933
+ if (Array.isArray(finishReasons) && finishReasons.length > 0) {
1934
+ result.finishReason = finishReasons[0];
1935
+ }
1936
+ const temperature = attributes[Attrs.REQUEST_TEMPERATURE];
1937
+ if (typeof temperature === "number") {
1938
+ result.settings = { ...result.settings, temperature };
1939
+ }
1940
+ const inputMessages = attributes[Attrs.INPUT_MESSAGES];
1941
+ if (inputMessages && typeof inputMessages === "string") {
1942
+ const messages = normalizeMessages(inputMessages);
1943
+ if (messages) result.input = messages;
1944
+ }
1945
+ const outputMessages = attributes[Attrs.OUTPUT_MESSAGES];
1946
+ if (outputMessages && typeof outputMessages === "string") {
1947
+ const extracted = extractStructuredOutput(outputMessages);
1948
+ if (extracted) {
1949
+ result.output = extracted.output;
1950
+ if (extracted.outputObject) {
1951
+ result.outputObject = extracted.outputObject;
1952
+ }
1953
+ }
1954
+ }
1955
+ const allMessages = attributes["pydantic_ai.all_messages"];
1956
+ if (allMessages && typeof allMessages === "string" && !result.input) {
1957
+ const messages = normalizeMessages(allMessages);
1958
+ if (messages) {
1959
+ const userMessages = messages.filter((m) => m.role === "user");
1960
+ if (userMessages.length > 0) {
1961
+ result.input = userMessages;
1962
+ }
1963
+ }
1964
+ }
1965
+ const finalResult = attributes["final_result"];
1966
+ if (finalResult && typeof finalResult === "string" && !result.output) {
1967
+ result.output = finalResult;
1968
+ try {
1969
+ result.outputObject = JSON.parse(finalResult);
1970
+ } catch {
1971
+ }
1972
+ }
1973
+ const propsStr = attributes["agentmark.props"];
1974
+ if (propsStr && typeof propsStr === "string" && !result.input) {
1975
+ try {
1976
+ const props = JSON.parse(propsStr);
1977
+ result.input = [{ role: "user", content: JSON.stringify(props) }];
1978
+ } catch {
1979
+ }
1980
+ }
1981
+ const outputStr = attributes["agentmark.output"];
1982
+ if (outputStr && typeof outputStr === "string" && !result.output) {
1983
+ result.output = outputStr;
1984
+ try {
1985
+ result.outputObject = JSON.parse(outputStr);
1986
+ } catch {
1987
+ }
1988
+ }
1989
+ const toolName = attributes[Attrs.TOOL_NAME];
1990
+ if (toolName && typeof toolName === "string") {
1991
+ result.name = toolName;
1992
+ const toolCall = {
1993
+ type: "tool-call",
1994
+ toolCallId: attributes[Attrs.TOOL_CALL_ID] || "",
1995
+ toolName,
1996
+ args: {}
1997
+ };
1998
+ const toolArgs = attributes[Attrs.TOOL_CALL_ARGS];
1999
+ if (toolArgs && typeof toolArgs === "string") {
2000
+ try {
2001
+ toolCall.args = JSON.parse(toolArgs);
2002
+ } catch {
2003
+ toolCall.args = { raw: toolArgs };
2004
+ }
2005
+ }
2006
+ const toolResult = attributes[Attrs.TOOL_CALL_RESULT];
2007
+ if (toolResult && typeof toolResult === "string") {
2008
+ toolCall.result = toolResult;
2009
+ }
2010
+ result.toolCalls = [toolCall];
2011
+ }
2012
+ const agentmarkAttrs = parseAgentMarkAttributes(attributes);
2013
+ Object.assign(result, agentmarkAttrs);
2014
+ const parsedMeta = parseMetadata(attributes);
2015
+ if (parsedMeta.metadata && Object.keys(parsedMeta.metadata).length > 0) {
2016
+ result.metadata = { ...result.metadata, ...parsedMeta.metadata };
2017
+ }
2018
+ const customMeta = extractCustomMetadata(attributes);
2019
+ if (Object.keys(customMeta).length > 0) {
2020
+ result.metadata = { ...result.metadata, ...customMeta };
2021
+ }
2022
+ return result;
2023
+ }
2024
+ };
2025
+ OtelGenAiTransformer.SCOPE_NAME = "pydantic-ai";
2026
+
1489
2027
  // src/normalizer/converters/otlp-converter.ts
1490
2028
  function convertOtlpValue(value) {
1491
2029
  var _a;
@@ -1587,7 +2125,8 @@ var typeClassifier = new TypeClassifier();
1587
2125
  registry.register("ai", new AiSdkTransformer());
1588
2126
  registry.register("default-tracer", new MastraTransformer());
1589
2127
  registry.register("agentmark", new AgentMarkTransformer());
1590
- registry.setDefault(new AiSdkTransformer());
2128
+ registry.register("pydantic-ai", new OtelGenAiTransformer());
2129
+ registry.setDefault(new OtelGenAiTransformer());
1591
2130
  function normalizeSpan(resource, scope, span) {
1592
2131
  var _a, _b, _c;
1593
2132
  const allAttributes = {
@@ -1661,6 +2200,7 @@ export {
1661
2200
  AiSdkTransformer,
1662
2201
  AgentMarkTransformer as ClaudeAgentTransformer,
1663
2202
  MastraTransformer,
2203
+ OtelGenAiTransformer,
1664
2204
  SpanType,
1665
2205
  TransformerRegistry,
1666
2206
  TypeClassifier,