@agentmark-ai/shared-utils 0.7.0 → 0.8.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.mjs CHANGED
@@ -2367,13 +2367,38 @@ function extractGenericOutput(attributes) {
2367
2367
  }
2368
2368
  return { output: String(value) };
2369
2369
  }
2370
+ function parseDocumentMetadata(raw) {
2371
+ let parsed = raw;
2372
+ if (typeof raw === "string") {
2373
+ try {
2374
+ parsed = JSON.parse(raw);
2375
+ } catch {
2376
+ return void 0;
2377
+ }
2378
+ }
2379
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
2380
+ return void 0;
2381
+ }
2370
2382
  function extractRetrievalDocuments(attributes) {
2371
2383
  const docs = [];
2372
2384
  for (const i of collectIndices(attributes, RETRIEVAL_PREFIX)) {
2373
- const content = attributes[`${RETRIEVAL_PREFIX}.${i}.document.content`];
2374
- if (typeof content === "string" && content.length > 0) docs.push(content);
2375
- }
2376
- return docs.length > 0 ? docs.join("\n\n") : void 0;
2385
+ const base = `${RETRIEVAL_PREFIX}.${i}.document`;
2386
+ const doc = {};
2387
+ const id = attributes[`${base}.id`];
2388
+ if (id !== void 0 && id !== null && String(id).length > 0) doc.id = String(id);
2389
+ const content = attributes[`${base}.content`];
2390
+ if (typeof content === "string" && content.length > 0) doc.content = content;
2391
+ const score = toNumber(attributes[`${base}.score`]);
2392
+ if (score !== void 0) doc.score = score;
2393
+ const metadata = parseDocumentMetadata(attributes[`${base}.metadata`]);
2394
+ if (metadata !== void 0) doc.metadata = metadata;
2395
+ if (Object.keys(doc).length > 0) docs.push(doc);
2396
+ }
2397
+ return docs;
2398
+ }
2399
+ function retrievalDocumentsToText(documents) {
2400
+ const text = documents.map((d) => d.content).filter((c) => typeof c === "string" && c.length > 0).join("\n\n");
2401
+ return text.length > 0 ? text : void 0;
2377
2402
  }
2378
2403
  var OpenInferenceTransformer = class {
2379
2404
  classify(_span, attributes) {
@@ -2417,9 +2442,13 @@ var OpenInferenceTransformer = class {
2417
2442
  } else {
2418
2443
  Object.assign(result, extractGenericOutput(attributes));
2419
2444
  }
2420
- if (result.output === void 0) {
2421
- const docs = extractRetrievalDocuments(attributes);
2422
- if (docs) result.output = docs;
2445
+ const documents = extractRetrievalDocuments(attributes);
2446
+ if (documents.length > 0) {
2447
+ if (result.outputObject === void 0) result.outputObject = { documents };
2448
+ if (result.output === void 0) {
2449
+ const text = retrievalDocumentsToText(documents);
2450
+ if (text) result.output = text;
2451
+ }
2423
2452
  }
2424
2453
  const toolName = attributes[Attrs2.TOOL_NAME];
2425
2454
  if (typeof toolName === "string" && toolName.length > 0) result.name = toolName;
@@ -2521,6 +2550,51 @@ function extractFromEvents(events, attrKey) {
2521
2550
  }
2522
2551
  return void 0;
2523
2552
  }
2553
+ function parseResultMetadata(raw) {
2554
+ let parsed = raw;
2555
+ if (typeof raw === "string") {
2556
+ try {
2557
+ parsed = JSON.parse(raw);
2558
+ } catch {
2559
+ return void 0;
2560
+ }
2561
+ }
2562
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
2563
+ return void 0;
2564
+ }
2565
+ var VECTOR_RESULT_EVENT_NAMES = /* @__PURE__ */ new Set(["db.query.result", "db.search.result"]);
2566
+ function extractVectorResultDocuments(events) {
2567
+ var _a, _b;
2568
+ if (!events) return [];
2569
+ const docs = [];
2570
+ for (const event of events) {
2571
+ if (!VECTOR_RESULT_EVENT_NAMES.has(event.name)) continue;
2572
+ const a = (_a = event.attributes) != null ? _a : {};
2573
+ const get = (field) => {
2574
+ var _a2;
2575
+ return (_a2 = a[`db.query.result.${field}`]) != null ? _a2 : a[`db.search.result.${field}`];
2576
+ };
2577
+ const doc = {};
2578
+ const id = get("id");
2579
+ if (id !== void 0 && id !== null && String(id).length > 0) doc.id = String(id);
2580
+ const content = get("document");
2581
+ if (typeof content === "string" && content.length > 0) doc.content = content;
2582
+ const score = toNumber(get("score"));
2583
+ if (score !== void 0) doc.score = score;
2584
+ const distance = toNumber(get("distance"));
2585
+ if (distance !== void 0) doc.distance = distance;
2586
+ let metadata = parseResultMetadata(get("metadata"));
2587
+ if (metadata === void 0) {
2588
+ const entity = get("entity");
2589
+ if (entity !== void 0 && entity !== null && String(entity).length > 0) {
2590
+ metadata = (_b = parseResultMetadata(entity)) != null ? _b : { entity: String(entity) };
2591
+ }
2592
+ }
2593
+ if (metadata !== void 0) doc.metadata = metadata;
2594
+ if (Object.keys(doc).length > 0) docs.push(doc);
2595
+ }
2596
+ return docs;
2597
+ }
2524
2598
  function extractFinishReason(attributes) {
2525
2599
  const direct = attributes[Attrs3.RESPONSE_FINISH_REASON];
2526
2600
  if (direct !== void 0) {
@@ -2590,6 +2664,16 @@ var OpenLLMetryTransformer = class {
2590
2664
  if (eventCompletion) result.output = eventCompletion;
2591
2665
  }
2592
2666
  }
2667
+ if (result.outputObject === void 0) {
2668
+ const documents = extractVectorResultDocuments(span.events);
2669
+ if (documents.length > 0) {
2670
+ result.outputObject = { documents };
2671
+ if (result.output === void 0) {
2672
+ const text = documents.map((d) => d.content).filter((c) => typeof c === "string" && c.length > 0).join("\n\n");
2673
+ if (text) result.output = text;
2674
+ }
2675
+ }
2676
+ }
2593
2677
  const entityName = attributes[Attrs3.ENTITY_NAME];
2594
2678
  if (typeof entityName === "string" && entityName.length > 0) result.traceName = entityName;
2595
2679
  const metadata = {};
@@ -2609,6 +2693,115 @@ var OpenLLMetryTransformer = class {
2609
2693
  }
2610
2694
  };
2611
2695
 
2696
+ // src/normalizer/resolvers/semantic-kind-resolver.ts
2697
+ var SEMANTIC_KINDS = ["function", "llm", "tool", "agent", "retrieval", "embedding", "guardrail"];
2698
+ var VALID_KINDS = new Set(SEMANTIC_KINDS);
2699
+ var OPENINFERENCE_MAP = {
2700
+ "CHAIN": "function",
2701
+ "LLM": "llm",
2702
+ "TOOL": "tool",
2703
+ "AGENT": "agent",
2704
+ "RETRIEVER": "retrieval",
2705
+ "EMBEDDING": "embedding",
2706
+ "GUARDRAIL": "guardrail",
2707
+ "RERANKER": "retrieval"
2708
+ };
2709
+ var VECTOR_DB_SYSTEMS = /* @__PURE__ */ new Set([
2710
+ "pinecone",
2711
+ "qdrant",
2712
+ "weaviate",
2713
+ "milvus",
2714
+ "chroma",
2715
+ "chromadb",
2716
+ "marqo",
2717
+ "lancedb"
2718
+ ]);
2719
+ var VECTOR_RESULT_EVENT_NAMES2 = /* @__PURE__ */ new Set(["db.query.result", "db.search.result"]);
2720
+ function hasVectorStoreSignature(attributes, events) {
2721
+ var _a;
2722
+ const dbSystem = (_a = attributes["db.system"]) != null ? _a : attributes["db.system.name"];
2723
+ if (typeof dbSystem === "string" && VECTOR_DB_SYSTEMS.has(dbSystem.toLowerCase())) return true;
2724
+ if (Object.keys(attributes).some((k) => k.startsWith("db.vector.query."))) return true;
2725
+ if (events == null ? void 0 : events.some((e) => VECTOR_RESULT_EVENT_NAMES2.has(e.name))) return true;
2726
+ return false;
2727
+ }
2728
+ var FRAMEWORK_MAPPINGS = [
2729
+ {
2730
+ key: "ai.operationId",
2731
+ // Vercel AI SDK
2732
+ // The AI SDK emits ai.operationId WITH the "ai." prefix (e.g.
2733
+ // "ai.generateText"); accept both prefixed and unprefixed so generation
2734
+ // wrappers resolve to "llm" instead of falling through to "function".
2735
+ map: {
2736
+ "embed": "embedding",
2737
+ "ai.embed": "embedding",
2738
+ "generateText": "llm",
2739
+ "ai.generateText": "llm",
2740
+ "streamText": "llm",
2741
+ "ai.streamText": "llm",
2742
+ "generateObject": "llm",
2743
+ "ai.generateObject": "llm",
2744
+ "streamObject": "llm",
2745
+ "ai.streamObject": "llm"
2746
+ }
2747
+ },
2748
+ {
2749
+ key: "traceloop.span.kind",
2750
+ // Traceloop / OpenLLMetry
2751
+ map: { "LLM": "llm", "TOOL": "tool", "AGENT": "agent", "WORKFLOW": "function", "TASK": "function" }
2752
+ },
2753
+ {
2754
+ key: "langchain.run_type",
2755
+ // LangChain via OTLP
2756
+ map: { "llm": "llm", "chat_model": "llm", "retriever": "retrieval", "tool": "tool", "chain": "function", "embedding": "embedding" }
2757
+ },
2758
+ {
2759
+ key: "genkit:type",
2760
+ // Firebase Genkit
2761
+ map: { "model": "llm", "tool": "tool", "flow": "function", "retriever": "retrieval", "embedder": "embedding" }
2762
+ }
2763
+ ];
2764
+ function resolveSemanticKind(normalized, allAttributes) {
2765
+ if (normalized.semanticKind && VALID_KINDS.has(normalized.semanticKind)) {
2766
+ return normalized.semanticKind;
2767
+ }
2768
+ const oiKind = allAttributes["openinference.span.kind"];
2769
+ if (oiKind) {
2770
+ const mapped = OPENINFERENCE_MAP[String(oiKind).toUpperCase()];
2771
+ if (mapped) return mapped;
2772
+ }
2773
+ for (const { key, map } of FRAMEWORK_MAPPINGS) {
2774
+ const val = allAttributes[key];
2775
+ if (val) {
2776
+ const mapped = map[String(val)];
2777
+ if (mapped) return mapped;
2778
+ }
2779
+ }
2780
+ if (hasVectorStoreSignature(allAttributes, normalized.events)) {
2781
+ return "retrieval";
2782
+ }
2783
+ const opName = allAttributes["gen_ai.operation.name"];
2784
+ if (opName) {
2785
+ const op = String(opName).toLowerCase();
2786
+ if (op === "chat" || op === "text_completion" || op === "generate_content") return "llm";
2787
+ if (op === "embeddings") return "embedding";
2788
+ }
2789
+ if (normalized.type === "GENERATION" /* GENERATION */) {
2790
+ return "llm";
2791
+ }
2792
+ if (normalized.model) {
2793
+ return "llm";
2794
+ }
2795
+ if (normalized.toolCalls && normalized.toolCalls.length > 0) {
2796
+ return "tool";
2797
+ }
2798
+ const name = (normalized.name || "").toLowerCase();
2799
+ if (/retriev|search|rag/i.test(name)) return "retrieval";
2800
+ if (/embed/i.test(name)) return "embedding";
2801
+ if (/guard|safety/i.test(name)) return "guardrail";
2802
+ return "function";
2803
+ }
2804
+
2612
2805
  // src/normalizer/transformers/dispatching/index.ts
2613
2806
  var OPENINFERENCE_INDEXED = /^llm\.(input_messages|output_messages|token_count)\./;
2614
2807
  var OPENLLMETRY_INDEXED = /^gen_ai\.(prompt|completion)\.\d+\./;
@@ -2633,20 +2826,25 @@ var DispatchingTransformer = class {
2633
2826
  this.openLLMetry = new OpenLLMetryTransformer();
2634
2827
  this.otelGenAi = new OtelGenAiTransformer();
2635
2828
  }
2636
- /** Choose the extractor for a span from its attribute signature. OpenInference
2637
- * is checked before OpenLLMetry because its markers (`llm.*`,
2638
- * `openinference.span.kind`) are more specific; the bare OTel GenAI
2639
- * transformer is the catch-all. */
2640
- select(attributes) {
2829
+ /** Choose the extractor for a span from its attribute/event signature.
2830
+ * OpenInference is checked before OpenLLMetry because its markers (`llm.*`,
2831
+ * `openinference.span.kind`) are more specific. Vector-store query spans
2832
+ * route to the OpenLLMetry extractor — they may carry no `traceloop.*`
2833
+ * marker (a bare Pinecone span is just `db.system` + `db.query.result`
2834
+ * events), so without this they'd fall through to the OTel-GenAI catch-all
2835
+ * and their result documents would be dropped. The bare OTel GenAI
2836
+ * transformer is the final catch-all. */
2837
+ select(attributes, span) {
2641
2838
  if (isOpenInference(attributes)) return this.openInference;
2642
2839
  if (isOpenLLMetry(attributes)) return this.openLLMetry;
2840
+ if (hasVectorStoreSignature(attributes, span == null ? void 0 : span.events)) return this.openLLMetry;
2643
2841
  return this.otelGenAi;
2644
2842
  }
2645
2843
  classify(span, attributes) {
2646
- return this.select(attributes).classify(span, attributes);
2844
+ return this.select(attributes, span).classify(span, attributes);
2647
2845
  }
2648
2846
  transform(span, attributes) {
2649
- return this.select(attributes).transform(span, attributes);
2847
+ return this.select(attributes, span).transform(span, attributes);
2650
2848
  }
2651
2849
  };
2652
2850
 
@@ -2730,93 +2928,6 @@ function extractResourceScopeSpan(resourceSpans) {
2730
2928
  return result;
2731
2929
  }
2732
2930
 
2733
- // src/normalizer/resolvers/semantic-kind-resolver.ts
2734
- var SEMANTIC_KINDS = ["function", "llm", "tool", "agent", "retrieval", "embedding", "guardrail"];
2735
- var VALID_KINDS = new Set(SEMANTIC_KINDS);
2736
- var OPENINFERENCE_MAP = {
2737
- "CHAIN": "function",
2738
- "LLM": "llm",
2739
- "TOOL": "tool",
2740
- "AGENT": "agent",
2741
- "RETRIEVER": "retrieval",
2742
- "EMBEDDING": "embedding",
2743
- "GUARDRAIL": "guardrail",
2744
- "RERANKER": "retrieval"
2745
- };
2746
- var FRAMEWORK_MAPPINGS = [
2747
- {
2748
- key: "ai.operationId",
2749
- // Vercel AI SDK
2750
- // The AI SDK emits ai.operationId WITH the "ai." prefix (e.g.
2751
- // "ai.generateText"); accept both prefixed and unprefixed so generation
2752
- // wrappers resolve to "llm" instead of falling through to "function".
2753
- map: {
2754
- "embed": "embedding",
2755
- "ai.embed": "embedding",
2756
- "generateText": "llm",
2757
- "ai.generateText": "llm",
2758
- "streamText": "llm",
2759
- "ai.streamText": "llm",
2760
- "generateObject": "llm",
2761
- "ai.generateObject": "llm",
2762
- "streamObject": "llm",
2763
- "ai.streamObject": "llm"
2764
- }
2765
- },
2766
- {
2767
- key: "traceloop.span.kind",
2768
- // Traceloop / OpenLLMetry
2769
- map: { "LLM": "llm", "TOOL": "tool", "AGENT": "agent", "WORKFLOW": "function", "TASK": "function" }
2770
- },
2771
- {
2772
- key: "langchain.run_type",
2773
- // LangChain via OTLP
2774
- map: { "llm": "llm", "chat_model": "llm", "retriever": "retrieval", "tool": "tool", "chain": "function", "embedding": "embedding" }
2775
- },
2776
- {
2777
- key: "genkit:type",
2778
- // Firebase Genkit
2779
- map: { "model": "llm", "tool": "tool", "flow": "function", "retriever": "retrieval", "embedder": "embedding" }
2780
- }
2781
- ];
2782
- function resolveSemanticKind(normalized, allAttributes) {
2783
- if (normalized.semanticKind && VALID_KINDS.has(normalized.semanticKind)) {
2784
- return normalized.semanticKind;
2785
- }
2786
- const oiKind = allAttributes["openinference.span.kind"];
2787
- if (oiKind) {
2788
- const mapped = OPENINFERENCE_MAP[String(oiKind).toUpperCase()];
2789
- if (mapped) return mapped;
2790
- }
2791
- for (const { key, map } of FRAMEWORK_MAPPINGS) {
2792
- const val = allAttributes[key];
2793
- if (val) {
2794
- const mapped = map[String(val)];
2795
- if (mapped) return mapped;
2796
- }
2797
- }
2798
- const opName = allAttributes["gen_ai.operation.name"];
2799
- if (opName) {
2800
- const op = String(opName).toLowerCase();
2801
- if (op === "chat" || op === "text_completion" || op === "generate_content") return "llm";
2802
- if (op === "embeddings") return "embedding";
2803
- }
2804
- if (normalized.type === "GENERATION" /* GENERATION */) {
2805
- return "llm";
2806
- }
2807
- if (normalized.model) {
2808
- return "llm";
2809
- }
2810
- if (normalized.toolCalls && normalized.toolCalls.length > 0) {
2811
- return "tool";
2812
- }
2813
- const name = (normalized.name || "").toLowerCase();
2814
- if (/retriev|search|rag/i.test(name)) return "retrieval";
2815
- if (/embed/i.test(name)) return "embedding";
2816
- if (/guard|safety/i.test(name)) return "guardrail";
2817
- return "function";
2818
- }
2819
-
2820
2931
  // src/normalizer/type-classifier.ts
2821
2932
  var TypeClassifier = class {
2822
2933
  classify(span, attributes) {
@@ -2984,6 +3095,7 @@ export {
2984
3095
  findPromptFiles,
2985
3096
  generateTypeDefinitions,
2986
3097
  generateUnique8CharString,
3098
+ hasVectorStoreSignature,
2987
3099
  messagesToPlainText,
2988
3100
  normalizeOtlpSpans,
2989
3101
  normalizeOtlpStatusCode,
@@ -2994,6 +3106,7 @@ export {
2994
3106
  parseTokens,
2995
3107
  registry,
2996
3108
  resolveSemanticKind,
3109
+ retrievalDocumentsToText,
2997
3110
  toFrontMatter,
2998
3111
  typeClassifier,
2999
3112
  verifySignature