@agentmark-ai/shared-utils 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -558,4 +558,43 @@ declare function normalizeSpan(resource: OtelResource, scope: OtelScope, span: O
558
558
  */
559
559
  declare function normalizeOtlpSpans(resourceSpans: OtlpResourceSpans[]): NormalizedSpan[];
560
560
 
561
- export { AGENTMARK_SCOPE_NAME, AgentMarkTransformer, type AgentmarkConfig, type AgentmarkModelConfig, type AgentmarkModelSchema, type AgentmarkModelSettingsConfig, type AgentmarkModelSettingsSchema, AiSdkTransformer, type AiSdkVersion, type AttributeExtractor, AgentMarkTransformer as ClaudeAgentTransformer, type GenerateTypesLanguage, MastraTransformer, type McpServerConfig, type McpServers, type McpStdioServerConfig, type McpUrlServerConfig, type Message, type ModelSettingsTypeAspectRatio, type ModelSettingsTypeImageSize, type ModelSettingsTypeSelect, type ModelSettingsTypeSlider, type NormalizedSpan, type OtelEvent, OtelGenAiTransformer, type OtelLink, type OtelResource, type OtelScope, type OtelSpan, type OtlpAttribute, type OtlpAttributeValue, type OtlpEvent, type OtlpLink, type OtlpResource, type OtlpResourceSpans, type OtlpScope, type OtlpScopeSpans, type OtlpSpan, SEMANTIC_KINDS, type ScopeTransformer, type SemanticKind, SpanType, type StandardMessageContent, type StandardTextContent, type StandardToolCallContent, type StandardToolResultContent, type ToolCall, TransformerRegistry, TypeClassifier, convertOtlpAttributes, createSignature, detectVersion, extractCustomMetadata, extractReasoningFromProviderMetadata, extractResourceScopeSpan, fetchPromptsFrontmatter, findPromptFiles, generateTypeDefinitions, generateUnique8CharString, normalizeOtlpSpans, normalizeSpan, parseAgentMarkAttributes, parseMetadata, parseTokens, registry, resolveSemanticKind, toFrontMatter, typeClassifier, verifySignature };
561
+ /**
562
+ * Compute a stable identifier for a dataset row, derived from its input.
563
+ *
564
+ * The identifier survives row reordering, additions, and deletions in the
565
+ * dataset — anything that doesn't change the row's *content* keeps the same
566
+ * id. This is the property regression-vs-baseline comparisons need: the
567
+ * same logical test case in two different runs must produce the same name
568
+ * so the baseline lookup can match them.
569
+ *
570
+ * Format: first 12 hex characters of the MD5 digest of the row's input,
571
+ * canonicalised with sorted keys at every level. This matches the Python
572
+ * runner's implementation byte-for-byte so cross-runtime comparisons
573
+ * (TS-emitted baseline vs. Python-emitted PR run, or vice versa) produce
574
+ * matching identifiers.
575
+ *
576
+ * Falls back to the positional index as a string when the row has no
577
+ * input — in that case there is nothing stable to hash, so positional is
578
+ * the best we can do.
579
+ *
580
+ * Note: we use MD5 here for compatibility with the existing Python
581
+ * implementation. MD5 is not used as a security primitive — it's used as a
582
+ * non-cryptographic content fingerprint, which is its appropriate role.
583
+ */
584
+ declare function computeDatasetItemName(input: unknown, fallbackIndex: number): string;
585
+ /**
586
+ * Stringify a value as canonical JSON with object keys sorted recursively.
587
+ *
588
+ * Differs from `JSON.stringify`:
589
+ * - Object keys are sorted lexicographically at every level of nesting, so
590
+ * `{a: 1, b: 2}` and `{b: 2, a: 1}` produce the same output.
591
+ * - Non-serializable values (functions, symbols, bigints, undefined) are
592
+ * coerced to strings via `String(value)`, matching Python's `default=str`
593
+ * behavior in `json.dumps`.
594
+ *
595
+ * Exported for testing and for callers that need the same canonicalisation
596
+ * for purposes other than item-name hashing.
597
+ */
598
+ declare function canonicalJsonStringify(value: unknown): string;
599
+
600
+ export { AGENTMARK_SCOPE_NAME, AgentMarkTransformer, type AgentmarkConfig, type AgentmarkModelConfig, type AgentmarkModelSchema, type AgentmarkModelSettingsConfig, type AgentmarkModelSettingsSchema, AiSdkTransformer, type AiSdkVersion, type AttributeExtractor, AgentMarkTransformer as ClaudeAgentTransformer, type GenerateTypesLanguage, MastraTransformer, type McpServerConfig, type McpServers, type McpStdioServerConfig, type McpUrlServerConfig, type Message, type ModelSettingsTypeAspectRatio, type ModelSettingsTypeImageSize, type ModelSettingsTypeSelect, type ModelSettingsTypeSlider, type NormalizedSpan, type OtelEvent, OtelGenAiTransformer, type OtelLink, type OtelResource, type OtelScope, type OtelSpan, type OtlpAttribute, type OtlpAttributeValue, type OtlpEvent, type OtlpLink, type OtlpResource, type OtlpResourceSpans, type OtlpScope, type OtlpScopeSpans, type OtlpSpan, SEMANTIC_KINDS, type ScopeTransformer, type SemanticKind, SpanType, type StandardMessageContent, type StandardTextContent, type StandardToolCallContent, type StandardToolResultContent, type ToolCall, TransformerRegistry, TypeClassifier, canonicalJsonStringify, computeDatasetItemName, convertOtlpAttributes, createSignature, detectVersion, extractCustomMetadata, extractReasoningFromProviderMetadata, extractResourceScopeSpan, fetchPromptsFrontmatter, findPromptFiles, generateTypeDefinitions, generateUnique8CharString, normalizeOtlpSpans, normalizeSpan, parseAgentMarkAttributes, parseMetadata, parseTokens, registry, resolveSemanticKind, toFrontMatter, typeClassifier, verifySignature };
package/dist/index.d.ts CHANGED
@@ -558,4 +558,43 @@ declare function normalizeSpan(resource: OtelResource, scope: OtelScope, span: O
558
558
  */
559
559
  declare function normalizeOtlpSpans(resourceSpans: OtlpResourceSpans[]): NormalizedSpan[];
560
560
 
561
- export { AGENTMARK_SCOPE_NAME, AgentMarkTransformer, type AgentmarkConfig, type AgentmarkModelConfig, type AgentmarkModelSchema, type AgentmarkModelSettingsConfig, type AgentmarkModelSettingsSchema, AiSdkTransformer, type AiSdkVersion, type AttributeExtractor, AgentMarkTransformer as ClaudeAgentTransformer, type GenerateTypesLanguage, MastraTransformer, type McpServerConfig, type McpServers, type McpStdioServerConfig, type McpUrlServerConfig, type Message, type ModelSettingsTypeAspectRatio, type ModelSettingsTypeImageSize, type ModelSettingsTypeSelect, type ModelSettingsTypeSlider, type NormalizedSpan, type OtelEvent, OtelGenAiTransformer, type OtelLink, type OtelResource, type OtelScope, type OtelSpan, type OtlpAttribute, type OtlpAttributeValue, type OtlpEvent, type OtlpLink, type OtlpResource, type OtlpResourceSpans, type OtlpScope, type OtlpScopeSpans, type OtlpSpan, SEMANTIC_KINDS, type ScopeTransformer, type SemanticKind, SpanType, type StandardMessageContent, type StandardTextContent, type StandardToolCallContent, type StandardToolResultContent, type ToolCall, TransformerRegistry, TypeClassifier, convertOtlpAttributes, createSignature, detectVersion, extractCustomMetadata, extractReasoningFromProviderMetadata, extractResourceScopeSpan, fetchPromptsFrontmatter, findPromptFiles, generateTypeDefinitions, generateUnique8CharString, normalizeOtlpSpans, normalizeSpan, parseAgentMarkAttributes, parseMetadata, parseTokens, registry, resolveSemanticKind, toFrontMatter, typeClassifier, verifySignature };
561
+ /**
562
+ * Compute a stable identifier for a dataset row, derived from its input.
563
+ *
564
+ * The identifier survives row reordering, additions, and deletions in the
565
+ * dataset — anything that doesn't change the row's *content* keeps the same
566
+ * id. This is the property regression-vs-baseline comparisons need: the
567
+ * same logical test case in two different runs must produce the same name
568
+ * so the baseline lookup can match them.
569
+ *
570
+ * Format: first 12 hex characters of the MD5 digest of the row's input,
571
+ * canonicalised with sorted keys at every level. This matches the Python
572
+ * runner's implementation byte-for-byte so cross-runtime comparisons
573
+ * (TS-emitted baseline vs. Python-emitted PR run, or vice versa) produce
574
+ * matching identifiers.
575
+ *
576
+ * Falls back to the positional index as a string when the row has no
577
+ * input — in that case there is nothing stable to hash, so positional is
578
+ * the best we can do.
579
+ *
580
+ * Note: we use MD5 here for compatibility with the existing Python
581
+ * implementation. MD5 is not used as a security primitive — it's used as a
582
+ * non-cryptographic content fingerprint, which is its appropriate role.
583
+ */
584
+ declare function computeDatasetItemName(input: unknown, fallbackIndex: number): string;
585
+ /**
586
+ * Stringify a value as canonical JSON with object keys sorted recursively.
587
+ *
588
+ * Differs from `JSON.stringify`:
589
+ * - Object keys are sorted lexicographically at every level of nesting, so
590
+ * `{a: 1, b: 2}` and `{b: 2, a: 1}` produce the same output.
591
+ * - Non-serializable values (functions, symbols, bigints, undefined) are
592
+ * coerced to strings via `String(value)`, matching Python's `default=str`
593
+ * behavior in `json.dumps`.
594
+ *
595
+ * Exported for testing and for callers that need the same canonicalisation
596
+ * for purposes other than item-name hashing.
597
+ */
598
+ declare function canonicalJsonStringify(value: unknown): string;
599
+
600
+ export { AGENTMARK_SCOPE_NAME, AgentMarkTransformer, type AgentmarkConfig, type AgentmarkModelConfig, type AgentmarkModelSchema, type AgentmarkModelSettingsConfig, type AgentmarkModelSettingsSchema, AiSdkTransformer, type AiSdkVersion, type AttributeExtractor, AgentMarkTransformer as ClaudeAgentTransformer, type GenerateTypesLanguage, MastraTransformer, type McpServerConfig, type McpServers, type McpStdioServerConfig, type McpUrlServerConfig, type Message, type ModelSettingsTypeAspectRatio, type ModelSettingsTypeImageSize, type ModelSettingsTypeSelect, type ModelSettingsTypeSlider, type NormalizedSpan, type OtelEvent, OtelGenAiTransformer, type OtelLink, type OtelResource, type OtelScope, type OtelSpan, type OtlpAttribute, type OtlpAttributeValue, type OtlpEvent, type OtlpLink, type OtlpResource, type OtlpResourceSpans, type OtlpScope, type OtlpScopeSpans, type OtlpSpan, SEMANTIC_KINDS, type ScopeTransformer, type SemanticKind, SpanType, type StandardMessageContent, type StandardTextContent, type StandardToolCallContent, type StandardToolResultContent, type ToolCall, TransformerRegistry, TypeClassifier, canonicalJsonStringify, computeDatasetItemName, convertOtlpAttributes, createSignature, detectVersion, extractCustomMetadata, extractReasoningFromProviderMetadata, extractResourceScopeSpan, fetchPromptsFrontmatter, findPromptFiles, generateTypeDefinitions, generateUnique8CharString, normalizeOtlpSpans, normalizeSpan, parseAgentMarkAttributes, parseMetadata, parseTokens, registry, resolveSemanticKind, toFrontMatter, typeClassifier, verifySignature };
package/dist/index.js CHANGED
@@ -40,6 +40,8 @@ __export(index_exports, {
40
40
  SpanType: () => SpanType,
41
41
  TransformerRegistry: () => TransformerRegistry,
42
42
  TypeClassifier: () => TypeClassifier,
43
+ canonicalJsonStringify: () => canonicalJsonStringify,
44
+ computeDatasetItemName: () => computeDatasetItemName,
43
45
  convertOtlpAttributes: () => convertOtlpAttributes,
44
46
  createSignature: () => createSignature,
45
47
  detectVersion: () => detectVersion,
@@ -228,27 +230,26 @@ async function generateTypeDefinitionsV1_0(prompts) {
228
230
  for (const prompt of prompts) {
229
231
  const { path: promptPath, input_schema } = prompt;
230
232
  const name = getInterfaceName(promptPath);
231
- let tools = {};
232
233
  try {
233
234
  let kind = "text";
234
235
  let output_schema = null;
236
+ let hasTools = false;
235
237
  if ("text_config" in prompt) {
236
238
  kind = "text";
237
- tools = prompt.text_config.tools || {};
239
+ hasTools = Array.isArray(prompt.text_config.tools) ? prompt.text_config.tools.length > 0 : !!prompt.text_config.tools;
238
240
  } else if ("object_config" in prompt) {
239
241
  kind = "object";
240
- tools = prompt.object_config.tools || {};
242
+ hasTools = Array.isArray(prompt.object_config.tools) ? prompt.object_config.tools.length > 0 : !!prompt.object_config.tools;
241
243
  output_schema = prompt.object_config.schema;
242
244
  } else if ("image_config" in prompt) {
243
245
  kind = "image";
244
- tools = prompt.image_config.tools || {};
246
+ hasTools = Array.isArray(prompt.image_config.tools) ? prompt.image_config.tools.length > 0 : !!prompt.image_config.tools;
245
247
  }
246
248
  const compile = await getCompile();
247
249
  const inputInterface = input_schema ? await compile(input_schema, `${name}In`, {
248
250
  bannerComment: "",
249
251
  additionalProperties: false
250
252
  }) : `interface ${name}In { [key: string]: any }`;
251
- const toolTypes = await generateToolTypes(tools);
252
253
  const outputInterface = output_schema ? await compile(output_schema, `${name}Out`, {
253
254
  bannerComment: "",
254
255
  additionalProperties: false
@@ -257,12 +258,11 @@ async function generateTypeDefinitionsV1_0(prompts) {
257
258
  inputInterface.replace("export interface", "interface"),
258
259
  outputInterface.replace("export type", "type").replace("export interface", "interface")
259
260
  );
260
- output += toolTypes || "";
261
261
  output += `type ${name} = {
262
262
  kind: '${kind}';
263
263
  input: ${name}In;
264
- output: ${name}Out;${toolTypes ? `
265
- tools?: Array<keyof Tools>;` : ""}
264
+ output: ${name}Out;${hasTools ? `
265
+ tools?: string[];` : ""}
266
266
  };
267
267
 
268
268
  `;
@@ -689,6 +689,7 @@ async function generateTypeDefinitions(prompts, language = "typescript") {
689
689
  return generateTypeDefinitionsV0(prompts);
690
690
  }
691
691
  async function fetchPromptsFrontmatter(options) {
692
+ var _a, _b, _c;
692
693
  if (options.local) {
693
694
  const baseUrl = `http://localhost:${options.local}`;
694
695
  try {
@@ -698,7 +699,8 @@ async function fetchPromptsFrontmatter(options) {
698
699
  `Failed to fetch prompt paths: ${pathsResponse.statusText}`
699
700
  );
700
701
  }
701
- const { paths } = await pathsResponse.json();
702
+ const body = await pathsResponse.json();
703
+ const paths = (_c = (_b = (_a = body == null ? void 0 : body.data) == null ? void 0 : _a.paths) != null ? _b : body == null ? void 0 : body.paths) != null ? _c : [];
702
704
  return Promise.all(
703
705
  paths.map(async (promptPath) => {
704
706
  const templateResponse = await fetch(
@@ -764,34 +766,6 @@ async function fetchPromptsFrontmatter(options) {
764
766
  }
765
767
  throw new Error("Either --local or --root-dir must be specified");
766
768
  }
767
- async function generateToolTypes(tools) {
768
- const toolArgTypes = [];
769
- for (const [toolName, schema] of Object.entries(tools)) {
770
- const typeName = `${getToolInterfaceName(toolName)}Args`;
771
- try {
772
- const compile = await getCompile();
773
- const argInterface = schema.parameters ? await compile(schema.parameters, typeName, {
774
- bannerComment: "",
775
- additionalProperties: false
776
- }) : `type ${typeName} = { ${Object.entries(schema.parameters || {}).map(([key]) => `${key}: any`).join("; ")} };`;
777
- toolArgTypes.push(
778
- argInterface.replace("export type", "type").replace("export interface", "interface")
779
- );
780
- } catch (error) {
781
- console.error(`Error processing tool ${toolName}:`, error);
782
- toolArgTypes.push(`type ${typeName} = { [key: string]: any };`);
783
- }
784
- }
785
- if (Object.keys(tools).length > 0) {
786
- const toolsInterface = `export interface Tools {
787
- ${Object.keys(tools).map(
788
- (toolName) => ` ${toolName}: { args: ${getToolInterfaceName(toolName)}Args };`
789
- ).join("\n")}
790
- }`;
791
- return toolArgTypes.join("\n\n") + "\n\n" + toolsInterface + "\n\n";
792
- }
793
- return null;
794
- }
795
769
 
796
770
  // src/normalizer/types.ts
797
771
  var SpanType = /* @__PURE__ */ ((SpanType2) => {
@@ -1778,6 +1752,7 @@ var AgentMarkTransformer = class {
1778
1752
  * Transform the span and extract normalized fields from GenAI attributes.
1779
1753
  */
1780
1754
  transform(_span, attributes) {
1755
+ var _a;
1781
1756
  const result = {};
1782
1757
  const responseModel = attributes[GenAIAttributes.RESPONSE_MODEL];
1783
1758
  const requestModel = attributes[GenAIAttributes.REQUEST_MODEL];
@@ -1851,7 +1826,7 @@ var AgentMarkTransformer = class {
1851
1826
  } catch {
1852
1827
  }
1853
1828
  }
1854
- const amInput = attributes["agentmark.input"];
1829
+ const amInput = (_a = attributes["agentmark.input"]) != null ? _a : attributes["agentmark.props"];
1855
1830
  if (amInput && typeof amInput === "string" && !result.input) {
1856
1831
  result.input = [{ role: "user", content: amInput }];
1857
1832
  }
@@ -1917,9 +1892,16 @@ var Attrs = {
1917
1892
  RESPONSE_FINISH_REASONS: "gen_ai.response.finish_reasons",
1918
1893
  USAGE_INPUT_TOKENS: "gen_ai.usage.input_tokens",
1919
1894
  USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens",
1920
- // v1.37.0+ content attributes
1895
+ // v1.37.0+ content attributes (canonical OTel GenAI semantic conventions).
1896
+ // SDKs that emit the AgentMark-scoped equivalents (`gen_ai.request.input`
1897
+ // / `gen_ai.response.output` — used by `claude-agent-sdk-v0-adapter`) are
1898
+ // also accepted here as fallbacks so an SDK picking either key set
1899
+ // doesn't silently lose IO data on ingest. The canonical pair always wins
1900
+ // when both are present.
1921
1901
  INPUT_MESSAGES: "gen_ai.input.messages",
1922
1902
  OUTPUT_MESSAGES: "gen_ai.output.messages",
1903
+ REQUEST_INPUT_FALLBACK: "gen_ai.request.input",
1904
+ RESPONSE_OUTPUT_FALLBACK: "gen_ai.response.output",
1923
1905
  SYSTEM_INSTRUCTIONS: "gen_ai.system_instructions",
1924
1906
  TOOL_DEFINITIONS: "gen_ai.tool.definitions",
1925
1907
  // Tool call attributes (v1.37.0+)
@@ -1984,6 +1966,7 @@ var OtelGenAiTransformer = class {
1984
1966
  return "SPAN" /* SPAN */;
1985
1967
  }
1986
1968
  transform(span, attributes) {
1969
+ var _a, _b;
1987
1970
  const result = {};
1988
1971
  const model = attributes[Attrs.RESPONSE_MODEL] || attributes[Attrs.REQUEST_MODEL];
1989
1972
  if (model && typeof model === "string") {
@@ -2004,12 +1987,12 @@ var OtelGenAiTransformer = class {
2004
1987
  if (typeof temperature === "number") {
2005
1988
  result.settings = { ...result.settings, temperature };
2006
1989
  }
2007
- const inputMessages = attributes[Attrs.INPUT_MESSAGES];
1990
+ const inputMessages = (_a = attributes[Attrs.INPUT_MESSAGES]) != null ? _a : attributes[Attrs.REQUEST_INPUT_FALLBACK];
2008
1991
  if (inputMessages && typeof inputMessages === "string") {
2009
1992
  const messages = normalizeMessages(inputMessages);
2010
1993
  if (messages) result.input = messages;
2011
1994
  }
2012
- const outputMessages = attributes[Attrs.OUTPUT_MESSAGES];
1995
+ const outputMessages = (_b = attributes[Attrs.OUTPUT_MESSAGES]) != null ? _b : attributes[Attrs.RESPONSE_OUTPUT_FALLBACK];
2013
1996
  if (outputMessages && typeof outputMessages === "string") {
2014
1997
  const extracted = extractStructuredOutput(outputMessages);
2015
1998
  if (extracted) {
@@ -2339,6 +2322,36 @@ function normalizeOtlpSpans(resourceSpans) {
2339
2322
  }
2340
2323
  return normalizedSpans;
2341
2324
  }
2325
+
2326
+ // src/dataset-item-name.ts
2327
+ var import_node_crypto = require("crypto");
2328
+ function computeDatasetItemName(input, fallbackIndex) {
2329
+ if (input === void 0 || input === null) {
2330
+ return String(fallbackIndex);
2331
+ }
2332
+ const canonical = canonicalJsonStringify(input);
2333
+ return (0, import_node_crypto.createHash)("md5").update(canonical).digest("hex").slice(0, 12);
2334
+ }
2335
+ function canonicalJsonStringify(value) {
2336
+ if (value === null) return "null";
2337
+ if (value === void 0) return JSON.stringify(String(void 0));
2338
+ const t = typeof value;
2339
+ if (t === "string" || t === "number" || t === "boolean") {
2340
+ return JSON.stringify(value);
2341
+ }
2342
+ if (t === "bigint" || t === "function" || t === "symbol") {
2343
+ return JSON.stringify(String(value));
2344
+ }
2345
+ if (Array.isArray(value)) {
2346
+ return "[" + value.map(canonicalJsonStringify).join(",") + "]";
2347
+ }
2348
+ const obj = value;
2349
+ const keys = Object.keys(obj).sort();
2350
+ const parts = keys.map((k) => {
2351
+ return JSON.stringify(k) + ":" + canonicalJsonStringify(obj[k]);
2352
+ });
2353
+ return "{" + parts.join(",") + "}";
2354
+ }
2342
2355
  // Annotate the CommonJS export names for ESM import in node:
2343
2356
  0 && (module.exports = {
2344
2357
  AGENTMARK_SCOPE_NAME,
@@ -2351,6 +2364,8 @@ function normalizeOtlpSpans(resourceSpans) {
2351
2364
  SpanType,
2352
2365
  TransformerRegistry,
2353
2366
  TypeClassifier,
2367
+ canonicalJsonStringify,
2368
+ computeDatasetItemName,
2354
2369
  convertOtlpAttributes,
2355
2370
  createSignature,
2356
2371
  detectVersion,