@agentmark-ai/shared-utils 0.4.0 → 0.5.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
@@ -71,53 +71,24 @@ function hexToBytes(hex) {
71
71
  }
72
72
 
73
73
  // src/serialize.ts
74
+ import yaml from "js-yaml";
74
75
  function toFrontMatter(content) {
75
- function jsonToFrontMatter(json, indent = 0) {
76
- let frontMatter = "";
77
- const indentation = " ".repeat(indent);
78
- for (const key in json) {
79
- if (Object.prototype.hasOwnProperty.call(json, key)) {
80
- const value = json[key];
81
- if (typeof value === "object" && !Array.isArray(value)) {
82
- frontMatter += `${indentation}${key}:
83
- `;
84
- frontMatter += jsonToFrontMatter(value, indent + 1);
85
- } else if (Array.isArray(value)) {
86
- frontMatter += `${indentation}${key}:
87
- `;
88
- value.forEach((item) => {
89
- if (typeof item === "object") {
90
- frontMatter += `${indentation}-
91
- `;
92
- frontMatter += jsonToFrontMatter(item, indent + 2);
93
- } else {
94
- frontMatter += `${indentation}- ${item}
95
- `;
96
- }
97
- });
98
- } else {
99
- frontMatter += `${indentation}${key}: ${value}
100
- `;
101
- }
102
- }
103
- }
104
- return frontMatter;
105
- }
76
+ const body = Object.keys(content).length === 0 ? "" : yaml.dump(content, { lineWidth: -1, noRefs: true, skipInvalid: true });
106
77
  return `---
107
- ${jsonToFrontMatter(content)}---
78
+ ${body}---
108
79
  `;
109
80
  }
110
81
 
111
82
  // src/generate-types.ts
112
83
  import * as fs from "fs-extra";
113
84
  import path from "path";
114
- import yaml from "js-yaml";
85
+ import yaml2 from "js-yaml";
115
86
  function extractFrontmatter(content) {
116
87
  const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
117
88
  if (!match) {
118
89
  return { attributes: {} };
119
90
  }
120
- const attributes = yaml.load(match[1]);
91
+ const attributes = yaml2.load(match[1]);
121
92
  return { attributes: attributes || {} };
122
93
  }
123
94
  var _compile = null;
@@ -921,39 +892,50 @@ var AiSdkV4Strategy = class {
921
892
  return attributes["gen_ai.request.model"] || attributes["ai.model.id"];
922
893
  }
923
894
  extractInput(attributes) {
924
- let messagesValue;
925
- if (attributes["ai.prompt.messages"] !== void 0) {
926
- messagesValue = attributes["ai.prompt.messages"];
927
- } else if (attributes["ai.prompt"] !== void 0) {
928
- const promptValue = attributes["ai.prompt"];
929
- if (typeof promptValue === "string") {
930
- try {
931
- const parsed = JSON.parse(promptValue);
932
- messagesValue = parsed.messages || parsed;
933
- } catch {
934
- return void 0;
935
- }
936
- } else {
937
- messagesValue = promptValue.messages || promptValue;
938
- }
939
- } else {
895
+ const raw = attributes["ai.prompt.messages"] !== void 0 ? attributes["ai.prompt.messages"] : attributes["ai.prompt"];
896
+ if (raw === void 0) {
940
897
  return void 0;
941
898
  }
942
- let messages;
943
- if (typeof messagesValue === "string") {
899
+ let value = raw;
900
+ if (typeof value === "string") {
944
901
  try {
945
- messages = JSON.parse(messagesValue);
902
+ value = JSON.parse(value);
946
903
  } catch {
947
- return void 0;
948
904
  }
949
- } else {
950
- messages = messagesValue;
951
905
  }
952
- if (!Array.isArray(messages)) {
906
+ const messages = this.coerceToMessages(value);
907
+ if (!messages) {
953
908
  return void 0;
954
909
  }
955
910
  return this.normalizeMessages(messages);
956
911
  }
912
+ /**
913
+ * Coerce the shapes `ai.prompt` / `ai.prompt.messages` can take into a
914
+ * messages array: a raw array, `{ messages, system? }`,
915
+ * `{ prompt, system? }` (string prompt), or a bare string.
916
+ */
917
+ coerceToMessages(value) {
918
+ if (typeof value === "string") {
919
+ return [{ role: "user", content: value }];
920
+ }
921
+ if (Array.isArray(value)) {
922
+ return value;
923
+ }
924
+ if (value && typeof value === "object") {
925
+ if (Array.isArray(value.messages)) {
926
+ return typeof value.system === "string" ? [{ role: "system", content: value.system }, ...value.messages] : value.messages;
927
+ }
928
+ if (typeof value.prompt === "string") {
929
+ const messages = [];
930
+ if (typeof value.system === "string") {
931
+ messages.push({ role: "system", content: value.system });
932
+ }
933
+ messages.push({ role: "user", content: value.prompt });
934
+ return messages;
935
+ }
936
+ }
937
+ return void 0;
938
+ }
957
939
  extractOutput(attributes) {
958
940
  if (attributes["ai.result.text"] !== void 0) return attributes["ai.result.text"];
959
941
  if (attributes["ai.response.text"] !== void 0) return attributes["ai.response.text"];
@@ -1217,39 +1199,54 @@ var AiSdkV5Strategy = class {
1217
1199
  return attributes["gen_ai.request.model"] || attributes["ai.model.id"];
1218
1200
  }
1219
1201
  extractInput(attributes) {
1220
- let messagesValue;
1221
- if (attributes["ai.prompt.messages"] !== void 0) {
1222
- messagesValue = attributes["ai.prompt.messages"];
1223
- } else if (attributes["ai.prompt"] !== void 0) {
1224
- const promptValue = attributes["ai.prompt"];
1225
- if (typeof promptValue === "string") {
1226
- try {
1227
- const parsed = JSON.parse(promptValue);
1228
- messagesValue = parsed.messages || parsed;
1229
- } catch {
1230
- return void 0;
1231
- }
1232
- } else {
1233
- messagesValue = promptValue.messages || promptValue;
1234
- }
1235
- } else {
1202
+ const raw = attributes["ai.prompt.messages"] !== void 0 ? attributes["ai.prompt.messages"] : attributes["ai.prompt"];
1203
+ if (raw === void 0) {
1236
1204
  return void 0;
1237
1205
  }
1238
- let messages;
1239
- if (typeof messagesValue === "string") {
1206
+ let value = raw;
1207
+ if (typeof value === "string") {
1240
1208
  try {
1241
- messages = JSON.parse(messagesValue);
1209
+ value = JSON.parse(value);
1242
1210
  } catch {
1243
- return void 0;
1244
1211
  }
1245
- } else {
1246
- messages = messagesValue;
1247
1212
  }
1248
- if (!Array.isArray(messages)) {
1213
+ const messages = this.coerceToMessages(value);
1214
+ if (!messages) {
1249
1215
  return void 0;
1250
1216
  }
1251
1217
  return this.normalizeMessages(messages);
1252
1218
  }
1219
+ /**
1220
+ * Coerce the shapes `ai.prompt` / `ai.prompt.messages` can take into a
1221
+ * messages array:
1222
+ * - `[ ...messages ]` — ai.prompt.messages (leaf spans)
1223
+ * - `{ messages: [...], system? }` — ai.prompt with messages
1224
+ * - `{ prompt: "text", system? }` — ai.prompt for a string prompt
1225
+ * (the parent wrapper spans)
1226
+ * - `"text"` — a bare (non-JSON) prompt string
1227
+ */
1228
+ coerceToMessages(value) {
1229
+ if (typeof value === "string") {
1230
+ return [{ role: "user", content: value }];
1231
+ }
1232
+ if (Array.isArray(value)) {
1233
+ return value;
1234
+ }
1235
+ if (value && typeof value === "object") {
1236
+ if (Array.isArray(value.messages)) {
1237
+ return typeof value.system === "string" ? [{ role: "system", content: value.system }, ...value.messages] : value.messages;
1238
+ }
1239
+ if (typeof value.prompt === "string") {
1240
+ const messages = [];
1241
+ if (typeof value.system === "string") {
1242
+ messages.push({ role: "system", content: value.system });
1243
+ }
1244
+ messages.push({ role: "user", content: value.prompt });
1245
+ return messages;
1246
+ }
1247
+ }
1248
+ return void 0;
1249
+ }
1253
1250
  extractOutput(attributes) {
1254
1251
  if (attributes["ai.response.text"] !== void 0) return attributes["ai.response.text"];
1255
1252
  return void 0;
@@ -1590,6 +1587,8 @@ function parseAgentMarkAttributes(attributes, prefix = "agentmark.") {
1590
1587
  if (get("dataset_expected_output")) result.datasetExpectedOutput = String(get("dataset_expected_output"));
1591
1588
  if (get("dataset_input")) result.datasetInput = String(get("dataset_input"));
1592
1589
  if (get("dataset_path")) result.datasetPath = String(get("dataset_path"));
1590
+ if (get("experiment_key")) result.experimentKey = String(get("experiment_key"));
1591
+ if (get("source_tree_hash")) result.sourceTreeHash = String(get("source_tree_hash"));
1593
1592
  return result;
1594
1593
  }
1595
1594
 
@@ -2104,13 +2103,20 @@ var FRAMEWORK_MAPPINGS = [
2104
2103
  {
2105
2104
  key: "ai.operationId",
2106
2105
  // Vercel AI SDK
2106
+ // The AI SDK emits ai.operationId WITH the "ai." prefix (e.g.
2107
+ // "ai.generateText"); accept both prefixed and unprefixed so generation
2108
+ // wrappers resolve to "llm" instead of falling through to "function".
2107
2109
  map: {
2108
2110
  "embed": "embedding",
2109
2111
  "ai.embed": "embedding",
2110
2112
  "generateText": "llm",
2113
+ "ai.generateText": "llm",
2111
2114
  "streamText": "llm",
2115
+ "ai.streamText": "llm",
2112
2116
  "generateObject": "llm",
2113
- "streamObject": "llm"
2117
+ "ai.generateObject": "llm",
2118
+ "streamObject": "llm",
2119
+ "ai.streamObject": "llm"
2114
2120
  }
2115
2121
  },
2116
2122
  {
@@ -2154,6 +2160,9 @@ function resolveSemanticKind(normalized, allAttributes) {
2154
2160
  if (normalized.type === "GENERATION" /* GENERATION */) {
2155
2161
  return "llm";
2156
2162
  }
2163
+ if (normalized.model) {
2164
+ return "llm";
2165
+ }
2157
2166
  if (normalized.toolCalls && normalized.toolCalls.length > 0) {
2158
2167
  return "tool";
2159
2168
  }
@@ -2255,36 +2264,6 @@ function normalizeOtlpSpans(resourceSpans) {
2255
2264
  }
2256
2265
  return normalizedSpans;
2257
2266
  }
2258
-
2259
- // src/dataset-item-name.ts
2260
- import { createHash } from "crypto";
2261
- function computeDatasetItemName(input, fallbackIndex) {
2262
- if (input === void 0 || input === null) {
2263
- return String(fallbackIndex);
2264
- }
2265
- const canonical = canonicalJsonStringify(input);
2266
- return createHash("md5").update(canonical).digest("hex").slice(0, 12);
2267
- }
2268
- function canonicalJsonStringify(value) {
2269
- if (value === null) return "null";
2270
- if (value === void 0) return JSON.stringify(String(void 0));
2271
- const t = typeof value;
2272
- if (t === "string" || t === "number" || t === "boolean") {
2273
- return JSON.stringify(value);
2274
- }
2275
- if (t === "bigint" || t === "function" || t === "symbol") {
2276
- return JSON.stringify(String(value));
2277
- }
2278
- if (Array.isArray(value)) {
2279
- return "[" + value.map(canonicalJsonStringify).join(",") + "]";
2280
- }
2281
- const obj = value;
2282
- const keys = Object.keys(obj).sort();
2283
- const parts = keys.map((k) => {
2284
- return JSON.stringify(k) + ":" + canonicalJsonStringify(obj[k]);
2285
- });
2286
- return "{" + parts.join(",") + "}";
2287
- }
2288
2267
  export {
2289
2268
  AGENTMARK_SCOPE_NAME,
2290
2269
  AgentMarkTransformer,
@@ -2296,8 +2275,6 @@ export {
2296
2275
  SpanType,
2297
2276
  TransformerRegistry,
2298
2277
  TypeClassifier,
2299
- canonicalJsonStringify,
2300
- computeDatasetItemName,
2301
2278
  convertOtlpAttributes,
2302
2279
  createSignature,
2303
2280
  detectVersion,