@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.mjs CHANGED
@@ -298,7 +298,326 @@ ${typeMapping.join(",\n")}
298
298
  var isNewFormat = (frontmatter) => {
299
299
  return frontmatter["text_config"] || frontmatter["object_config"] || frontmatter["image_config"];
300
300
  };
301
- 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
+ }
302
621
  if (prompts[0].version === "1.0") {
303
622
  return generateTypeDefinitionsV1_0(prompts);
304
623
  }
@@ -505,6 +824,7 @@ var KNOWN_METADATA_FIELDS = /* @__PURE__ */ new Set([
505
824
  "dataset_path",
506
825
  "dataset_item_name",
507
826
  "dataset_expected_output",
827
+ "dataset_input",
508
828
  "prompt_name",
509
829
  "props",
510
830
  "commit_sha"
@@ -1292,10 +1612,12 @@ function parseAgentMarkAttributes(attributes, prefix = "agentmark.") {
1292
1612
  if (get("trace_name")) result.traceName = String(get("trace_name"));
1293
1613
  if (get("prompt_name")) result.promptName = String(get("prompt_name"));
1294
1614
  if (get("props")) result.props = String(get("props"));
1615
+ if (get("span.kind")) result.kind = String(get("span.kind"));
1295
1616
  if (get("dataset_run_id")) result.datasetRunId = String(get("dataset_run_id"));
1296
1617
  if (get("dataset_run_name")) result.datasetRunName = String(get("dataset_run_name"));
1297
1618
  if (get("dataset_item_name")) result.datasetItemName = String(get("dataset_item_name"));
1298
1619
  if (get("dataset_expected_output")) result.datasetExpectedOutput = String(get("dataset_expected_output"));
1620
+ if (get("dataset_input")) result.datasetInput = String(get("dataset_input"));
1299
1621
  if (get("dataset_path")) result.datasetPath = String(get("dataset_path"));
1300
1622
  return result;
1301
1623
  }
@@ -1408,6 +1730,10 @@ var AgentMarkTransformer = class {
1408
1730
  if (result.inputTokens !== void 0 && result.outputTokens !== void 0) {
1409
1731
  result.totalTokens = result.inputTokens + result.outputTokens;
1410
1732
  }
1733
+ const costUsd = attributes["agentmark.usage.cost_usd"];
1734
+ if (typeof costUsd === "number" && costUsd > 0) {
1735
+ result.cost = costUsd;
1736
+ }
1411
1737
  const finishReasons = attributes[GenAIAttributes.RESPONSE_FINISH_REASONS];
1412
1738
  if (finishReasons) {
1413
1739
  try {
@@ -1453,6 +1779,22 @@ var AgentMarkTransformer = class {
1453
1779
  const responseOutput = attributes[GenAIAttributes.RESPONSE_OUTPUT];
1454
1780
  if (responseOutput && typeof responseOutput === "string") {
1455
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
+ }
1456
1798
  }
1457
1799
  const toolName = attributes[GenAIAttributes.TOOL_NAME];
1458
1800
  const toolCallId = attributes[GenAIAttributes.TOOL_CALL_ID];
@@ -1494,6 +1836,194 @@ var AgentMarkTransformer = class {
1494
1836
  };
1495
1837
  var AGENTMARK_SCOPE_NAME = "agentmark";
1496
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
+
1497
2027
  // src/normalizer/converters/otlp-converter.ts
1498
2028
  function convertOtlpValue(value) {
1499
2029
  var _a;
@@ -1595,7 +2125,8 @@ var typeClassifier = new TypeClassifier();
1595
2125
  registry.register("ai", new AiSdkTransformer());
1596
2126
  registry.register("default-tracer", new MastraTransformer());
1597
2127
  registry.register("agentmark", new AgentMarkTransformer());
1598
- registry.setDefault(new AiSdkTransformer());
2128
+ registry.register("pydantic-ai", new OtelGenAiTransformer());
2129
+ registry.setDefault(new OtelGenAiTransformer());
1599
2130
  function normalizeSpan(resource, scope, span) {
1600
2131
  var _a, _b, _c;
1601
2132
  const allAttributes = {
@@ -1669,6 +2200,7 @@ export {
1669
2200
  AiSdkTransformer,
1670
2201
  AgentMarkTransformer as ClaudeAgentTransformer,
1671
2202
  MastraTransformer,
2203
+ OtelGenAiTransformer,
1672
2204
  SpanType,
1673
2205
  TransformerRegistry,
1674
2206
  TypeClassifier,