@cloudbase/agent-observability 0.0.16 → 0.0.18

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/langchain.js CHANGED
@@ -21,39 +21,41 @@ var __copyProps = (to, from, except, desc) => {
21
21
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
22
 
23
23
  // src/core/constants.ts
24
- var import_openinference_semantic_conventions, OtelSpanAttributes;
24
+ var import_openinference_semantic_conventions, OBSERVABILITY_SDK_NAME, OBSERVABILITY_SDK_VERSION, OtelSpanAttributes;
25
25
  var init_constants = __esm({
26
26
  "src/core/constants.ts"() {
27
27
  "use strict";
28
28
  import_openinference_semantic_conventions = require("@arizeai/openinference-semantic-conventions");
29
+ OBSERVABILITY_SDK_NAME = "observability";
30
+ OBSERVABILITY_SDK_VERSION = "0.1.0";
29
31
  OtelSpanAttributes = {
30
32
  // OpenInference - re-export all standard conventions
31
33
  ...import_openinference_semantic_conventions.SemanticConventions,
32
- // AG-Kit Trace attributes (non-standard)
34
+ // Trace attributes (non-standard)
33
35
  TRACE_NAME: "trace.name",
34
36
  TRACE_TAGS: "trace.tags",
35
37
  TRACE_PUBLIC: "trace.public",
36
38
  TRACE_METADATA: "trace.metadata",
37
39
  TRACE_INPUT: "trace.input",
38
40
  TRACE_OUTPUT: "trace.output",
39
- // AG-Kit Observation attributes (non-standard)
41
+ // Observation attributes (non-standard)
40
42
  OBSERVATION_TYPE: "observation.type",
41
43
  OBSERVATION_LEVEL: "observation.level",
42
44
  OBSERVATION_STATUS_MESSAGE: "observation.status_message",
43
45
  OBSERVATION_INPUT: "observation.input",
44
46
  OBSERVATION_OUTPUT: "observation.output",
45
47
  OBSERVATION_METADATA: "observation.metadata",
46
- // AG-Kit LLM-specific (non-standard)
48
+ // LLM-specific (non-standard)
47
49
  LLM_COMPLETION_START_TIME: "llm.completion_start_time",
48
50
  LLM_MODEL_PARAMETERS: "llm.model_parameters",
49
51
  LLM_USAGE_DETAILS: "llm.usage_details",
50
52
  LLM_COST_DETAILS: "llm.cost_details",
51
- // AG-Kit Retriever-specific (non-standard)
53
+ // Retriever-specific (non-standard)
52
54
  RETRIEVER_NAME: "retriever.name",
53
55
  RETRIEVER_QUERY: "retriever.query",
54
56
  RETRIEVER_INDEX_ID: "retriever.index_id",
55
57
  RETRIEVER_TOP_K: "retriever.top_k",
56
- // AG-Kit General (non-standard)
58
+ // General (non-standard)
57
59
  ENVIRONMENT: "environment",
58
60
  RELEASE: "release",
59
61
  VERSION: "version"
@@ -106,25 +108,38 @@ function createObservationAttributes(type, attributes) {
106
108
  modelParameters,
107
109
  usageDetails
108
110
  } = attributes;
111
+ const spanKind = import_openinference_semantic_conventions.OpenInferenceSpanKind[type.toUpperCase()] || "CHAIN";
109
112
  const otelAttributes = {
110
- [import_openinference_semantic_conventions2.SemanticConventions.OPENINFERENCE_SPAN_KIND]: type.toUpperCase(),
113
+ [import_openinference_semantic_conventions2.SemanticConventions.OPENINFERENCE_SPAN_KIND]: spanKind,
111
114
  [OtelSpanAttributes.OBSERVATION_TYPE]: type,
112
115
  [OtelSpanAttributes.OBSERVATION_LEVEL]: level,
113
116
  [OtelSpanAttributes.OBSERVATION_STATUS_MESSAGE]: statusMessage,
114
117
  [OtelSpanAttributes.VERSION]: version,
115
118
  // Use OpenInference input.value convention
116
119
  [import_openinference_semantic_conventions2.SemanticConventions.INPUT_VALUE]: _serialize(input),
117
- // Also set legacy agkit.observation.input for compatibility
120
+ // Also set observation.input for compatibility
118
121
  [OtelSpanAttributes.OBSERVATION_INPUT]: _serialize(input),
119
122
  // Use OpenInference output.value convention
120
123
  [import_openinference_semantic_conventions2.SemanticConventions.OUTPUT_VALUE]: _serialize(output),
121
- // Also set legacy agkit.observation.output for compatibility
124
+ // Also set observation.output for compatibility
122
125
  [OtelSpanAttributes.OBSERVATION_OUTPUT]: _serialize(output)
123
126
  };
124
127
  if (type === "llm") {
125
128
  if (model) {
126
129
  otelAttributes[import_openinference_semantic_conventions2.SemanticConventions.LLM_MODEL_NAME] = model;
127
130
  }
131
+ const system = attributes?.system;
132
+ const provider = attributes?.provider;
133
+ const inputMessages = attributes?.inputMessages;
134
+ const outputMessages = attributes?.outputMessages;
135
+ const inputMimeType = attributes?.inputMimeType;
136
+ const outputMimeType = attributes?.outputMimeType;
137
+ if (system !== void 0) {
138
+ otelAttributes[import_openinference_semantic_conventions2.SemanticConventions.LLM_SYSTEM] = String(system);
139
+ }
140
+ if (provider !== void 0) {
141
+ otelAttributes[import_openinference_semantic_conventions2.SemanticConventions.LLM_PROVIDER] = String(provider);
142
+ }
128
143
  if (modelParameters) {
129
144
  otelAttributes[import_openinference_semantic_conventions2.SemanticConventions.LLM_INVOCATION_PARAMETERS] = _serialize(modelParameters);
130
145
  otelAttributes[OtelSpanAttributes.LLM_MODEL_PARAMETERS] = _serialize(modelParameters);
@@ -147,6 +162,20 @@ function createObservationAttributes(type, attributes) {
147
162
  if (completionStartTime) {
148
163
  otelAttributes[OtelSpanAttributes.LLM_COMPLETION_START_TIME] = _serialize(completionStartTime);
149
164
  }
165
+ if (inputMessages !== void 0 && Array.isArray(inputMessages)) {
166
+ const messageAttrs = _flattenLLMMessages(inputMessages, "llm.input_messages");
167
+ Object.assign(otelAttributes, messageAttrs);
168
+ }
169
+ if (outputMessages !== void 0 && Array.isArray(outputMessages)) {
170
+ const messageAttrs = _flattenLLMMessages(outputMessages, "llm.output_messages");
171
+ Object.assign(otelAttributes, messageAttrs);
172
+ }
173
+ if (inputMimeType !== void 0) {
174
+ otelAttributes[import_openinference_semantic_conventions2.SemanticConventions.INPUT_MIME_TYPE] = String(inputMimeType);
175
+ }
176
+ if (outputMimeType !== void 0) {
177
+ otelAttributes[import_openinference_semantic_conventions2.SemanticConventions.OUTPUT_MIME_TYPE] = String(outputMimeType);
178
+ }
150
179
  }
151
180
  if (type === "embedding") {
152
181
  if (model) {
@@ -156,6 +185,42 @@ function createObservationAttributes(type, attributes) {
156
185
  otelAttributes[import_openinference_semantic_conventions2.SemanticConventions.LLM_INVOCATION_PARAMETERS] = _serialize(modelParameters);
157
186
  }
158
187
  }
188
+ if (type === "tool") {
189
+ const toolName = attributes?.toolName ?? attributes?.tool_name;
190
+ const toolDescription = attributes?.toolDescription;
191
+ const toolParameters = attributes?.toolParameters;
192
+ const toolCall = attributes?.toolCall;
193
+ if (toolName !== void 0) {
194
+ otelAttributes[import_openinference_semantic_conventions2.SemanticConventions.TOOL_NAME] = String(toolName);
195
+ }
196
+ if (toolDescription !== void 0) {
197
+ otelAttributes[import_openinference_semantic_conventions2.SemanticConventions.TOOL_DESCRIPTION] = String(toolDescription);
198
+ }
199
+ if (toolParameters !== void 0) {
200
+ otelAttributes[import_openinference_semantic_conventions2.SemanticConventions.TOOL_PARAMETERS] = _serialize(toolParameters);
201
+ }
202
+ if (toolCall !== void 0 && typeof toolCall === "object") {
203
+ const toolCallAttrs = _flattenToolCall(toolCall);
204
+ Object.assign(otelAttributes, toolCallAttrs);
205
+ }
206
+ }
207
+ if (type === "agent") {
208
+ const agentName = attributes?.agentName;
209
+ if (agentName !== void 0) {
210
+ otelAttributes[import_openinference_semantic_conventions2.SemanticConventions.AGENT_NAME] = String(agentName);
211
+ }
212
+ }
213
+ if (type === "retriever") {
214
+ const documents = attributes?.documents;
215
+ const query = attributes?.query;
216
+ if (documents !== void 0 && Array.isArray(documents)) {
217
+ const docAttrs = _flattenDocuments(documents);
218
+ Object.assign(otelAttributes, docAttrs);
219
+ }
220
+ if (query !== void 0) {
221
+ otelAttributes["retriever.query"] = String(query);
222
+ }
223
+ }
159
224
  const metadataAttrs = _flattenAndSerializeMetadata(
160
225
  metadata,
161
226
  import_openinference_semantic_conventions2.SemanticConventions.METADATA
@@ -166,6 +231,11 @@ function createObservationAttributes(type, attributes) {
166
231
  OtelSpanAttributes.OBSERVATION_METADATA
167
232
  );
168
233
  Object.assign(otelAttributes, obsetvabilityMetadataAttrs);
234
+ for (const [key, value] of Object.entries(attributes)) {
235
+ if (!(key in otelAttributes) && value !== void 0 && value !== null) {
236
+ otelAttributes[key] = typeof value === "string" ? value : _serialize(value);
237
+ }
238
+ }
169
239
  return Object.fromEntries(
170
240
  Object.entries(otelAttributes).filter(([_, v]) => v != null)
171
241
  );
@@ -199,6 +269,96 @@ function _flattenAndSerializeMetadata(metadata, prefix) {
199
269
  }
200
270
  return metadataAttributes;
201
271
  }
272
+ function _flattenLLMMessages(messages, prefix) {
273
+ const attributes = {};
274
+ if (!messages || !Array.isArray(messages)) {
275
+ return attributes;
276
+ }
277
+ try {
278
+ messages.forEach((msg, index) => {
279
+ if (!msg || typeof msg !== "object") return;
280
+ const baseKey = `${prefix}.${index}.message`;
281
+ if (msg.role !== void 0) {
282
+ attributes[`${baseKey}.role`] = String(msg.role);
283
+ }
284
+ if (msg.content !== void 0) {
285
+ attributes[`${baseKey}.content`] = String(msg.content);
286
+ }
287
+ if (msg.toolCallId !== void 0) {
288
+ attributes[`${baseKey}.tool_call_id`] = String(msg.toolCallId);
289
+ }
290
+ if (msg.toolCalls && Array.isArray(msg.toolCalls)) {
291
+ msg.toolCalls.forEach((toolCall, tcIndex) => {
292
+ if (!toolCall || typeof toolCall !== "object") return;
293
+ const tcKey = `${baseKey}.tool_calls.${tcIndex}`;
294
+ if (toolCall.id !== void 0) {
295
+ attributes[`${tcKey}.id`] = String(toolCall.id);
296
+ }
297
+ if (toolCall.function !== void 0) {
298
+ if (toolCall.function.name !== void 0) {
299
+ attributes[`${tcKey}.function.name`] = String(toolCall.function.name);
300
+ }
301
+ if (toolCall.function.arguments !== void 0) {
302
+ attributes[`${tcKey}.function.arguments`] = String(toolCall.function.arguments);
303
+ }
304
+ }
305
+ });
306
+ }
307
+ });
308
+ } catch (e) {
309
+ }
310
+ return attributes;
311
+ }
312
+ function _flattenDocuments(documents) {
313
+ const attributes = {};
314
+ if (!documents || !Array.isArray(documents)) {
315
+ return attributes;
316
+ }
317
+ try {
318
+ documents.forEach((doc, index) => {
319
+ if (!doc || typeof doc !== "object") return;
320
+ const baseKey = `retrieval.documents.${index}.document`;
321
+ if (doc.id !== void 0) {
322
+ attributes[`${baseKey}.id`] = String(doc.id);
323
+ }
324
+ if (doc.content !== void 0) {
325
+ attributes[`${baseKey}.content`] = String(doc.content);
326
+ }
327
+ if (doc.score !== void 0) {
328
+ attributes[`${baseKey}.score`] = String(doc.score);
329
+ }
330
+ if (doc.metadata !== void 0 && typeof doc.metadata === "object") {
331
+ const metadataSerialized = _serialize(doc.metadata);
332
+ if (metadataSerialized) {
333
+ attributes[`${baseKey}.metadata`] = metadataSerialized;
334
+ }
335
+ }
336
+ });
337
+ } catch (e) {
338
+ }
339
+ return attributes;
340
+ }
341
+ function _flattenToolCall(toolCall) {
342
+ const attributes = {};
343
+ if (!toolCall || typeof toolCall !== "object") {
344
+ return attributes;
345
+ }
346
+ try {
347
+ if (toolCall.id !== void 0) {
348
+ attributes["tool_call.id"] = String(toolCall.id);
349
+ }
350
+ if (toolCall.function !== void 0) {
351
+ if (toolCall.function.name !== void 0) {
352
+ attributes["tool_call.function.name"] = String(toolCall.function.name);
353
+ }
354
+ if (toolCall.function.arguments !== void 0) {
355
+ attributes["tool_call.function.arguments"] = String(toolCall.function.arguments);
356
+ }
357
+ }
358
+ } catch (e) {
359
+ }
360
+ return attributes;
361
+ }
202
362
  var import_openinference_semantic_conventions2;
203
363
  var init_attributes = __esm({
204
364
  "src/core/attributes.ts"() {
@@ -254,22 +414,22 @@ function getTracer() {
254
414
  OBSERVABILITY_SDK_VERSION
255
415
  );
256
416
  }
257
- var import_api, OBSERVABILITY_GLOBAL_SYMBOL, OBSERVABILITY_SDK_NAME, OBSERVABILITY_SDK_VERSION;
417
+ var import_api, OBSERVABILITY_GLOBAL_SYMBOL;
258
418
  var init_tracerProvider = __esm({
259
419
  "src/core/tracerProvider.ts"() {
260
420
  "use strict";
261
421
  import_api = require("@opentelemetry/api");
422
+ init_constants();
262
423
  OBSERVABILITY_GLOBAL_SYMBOL = /* @__PURE__ */ Symbol.for("observability");
263
- OBSERVABILITY_SDK_NAME = "ag-kit-observability";
264
- OBSERVABILITY_SDK_VERSION = "0.1.0";
265
424
  }
266
425
  });
267
426
 
268
427
  // src/core/spanWrapper.ts
269
- var BaseObservation, ObservationSpan, ObservationLLM, ObservationEmbedding, ObservationAgent, ObservationTool, ObservationChain, ObservationRetriever, ObservationReranker, ObservationEvaluator, ObservationGuardrail;
428
+ var import_api2, BaseObservation, ObservationLLM, ObservationEmbedding, ObservationAgent, ObservationTool, ObservationChain, ObservationRetriever, ObservationReranker, ObservationEvaluator, ObservationGuardrail;
270
429
  var init_spanWrapper = __esm({
271
430
  "src/core/spanWrapper.ts"() {
272
431
  "use strict";
432
+ import_api2 = require("@opentelemetry/api");
273
433
  init_attributes();
274
434
  init_tracerProvider();
275
435
  BaseObservation = class {
@@ -292,7 +452,7 @@ var init_spanWrapper = __esm({
292
452
  );
293
453
  }
294
454
  }
295
- /** Gets the AG-Kit OpenTelemetry tracer instance */
455
+ /** Gets the OpenTelemetry tracer instance */
296
456
  get tracer() {
297
457
  return getTracer();
298
458
  }
@@ -304,6 +464,27 @@ var init_spanWrapper = __esm({
304
464
  end(endTime) {
305
465
  this.otelSpan.end(endTime);
306
466
  }
467
+ /**
468
+ * Sets the span status.
469
+ *
470
+ * @param status - The status to set on the span
471
+ */
472
+ setStatus(status) {
473
+ this.otelSpan.setStatus(status);
474
+ }
475
+ /**
476
+ * Sets the span status to ERROR.
477
+ *
478
+ * Convenience method for marking the span as failed.
479
+ *
480
+ * @param message - Error description message
481
+ */
482
+ setErrorStatus(message) {
483
+ this.otelSpan.setStatus({
484
+ code: import_api2.SpanStatusCode.ERROR,
485
+ message
486
+ });
487
+ }
307
488
  /**
308
489
  * Updates the OTEL span attributes.
309
490
  *
@@ -327,22 +508,13 @@ var init_spanWrapper = __esm({
327
508
  }
328
509
  startObservation(name, attributes, options) {
329
510
  const { startObservation: startObs } = (init_src(), __toCommonJS(src_exports));
330
- const { asType = "span" } = options || {};
511
+ const { asType = "chain" } = options || {};
331
512
  return startObs(name, attributes, {
332
513
  asType,
333
514
  parentSpanContext: this.otelSpan.spanContext()
334
515
  });
335
516
  }
336
517
  };
337
- ObservationSpan = class extends BaseObservation {
338
- constructor(params) {
339
- super({ ...params, type: "span" });
340
- }
341
- update(attributes) {
342
- super.updateOtelSpanAttributes(attributes);
343
- return this;
344
- }
345
- };
346
518
  ObservationLLM = class extends BaseObservation {
347
519
  constructor(params) {
348
520
  super({ ...params, type: "llm" });
@@ -427,6 +599,171 @@ var init_spanWrapper = __esm({
427
599
  }
428
600
  });
429
601
 
602
+ // src/core/trace-context.ts
603
+ function validateTraceId(traceId) {
604
+ if (!traceId || typeof traceId !== "string") {
605
+ return false;
606
+ }
607
+ if (traceId.length !== 32) {
608
+ return false;
609
+ }
610
+ const chunk1 = traceId.slice(0, 16);
611
+ const chunk2 = traceId.slice(16, 32);
612
+ const value1 = parseInt(chunk1, 16);
613
+ const value2 = parseInt(chunk2, 16);
614
+ if (isNaN(value1) || isNaN(value2)) {
615
+ return false;
616
+ }
617
+ if (value1 === 0 && value2 === 0) {
618
+ return false;
619
+ }
620
+ return true;
621
+ }
622
+ function validateSpanId(spanId) {
623
+ if (!spanId || typeof spanId !== "string") {
624
+ return false;
625
+ }
626
+ if (spanId.length !== 16) {
627
+ return false;
628
+ }
629
+ const value = parseInt(spanId, 16);
630
+ if (isNaN(value)) {
631
+ return false;
632
+ }
633
+ if (value === 0) {
634
+ return false;
635
+ }
636
+ return true;
637
+ }
638
+ function validateTraceContext(traceId, parentSpanId) {
639
+ const result = {
640
+ errors: [],
641
+ isValid: false,
642
+ hasTraceId: false,
643
+ hasParentSpanId: false
644
+ };
645
+ if (!traceId && !parentSpanId) {
646
+ result.isValid = true;
647
+ return result;
648
+ }
649
+ if (!traceId && parentSpanId) {
650
+ result.errors.push(
651
+ "parentSpanId provided without traceId - traceId is required when inheriting parent span"
652
+ );
653
+ return result;
654
+ }
655
+ if (traceId) {
656
+ if (!validateTraceId(traceId)) {
657
+ result.errors.push(
658
+ `Invalid traceId format: '${traceId}' - must be 32 hex characters and not all zeros`
659
+ );
660
+ } else {
661
+ result.traceId = traceId.toLowerCase();
662
+ result.hasTraceId = true;
663
+ }
664
+ }
665
+ if (parentSpanId) {
666
+ if (!validateSpanId(parentSpanId)) {
667
+ result.errors.push(
668
+ `Invalid parentSpanId format: '${parentSpanId}' - must be 16 hex characters and not all zeros`
669
+ );
670
+ } else {
671
+ result.parentSpanId = parentSpanId.toLowerCase();
672
+ result.hasParentSpanId = true;
673
+ }
674
+ }
675
+ result.isValid = result.errors.length === 0;
676
+ return result;
677
+ }
678
+ function createSpanLinkFromContext(traceId, parentSpanId, linkType = "follows_from", sourceSystem = "gateway") {
679
+ const externalContext = {
680
+ traceId,
681
+ spanId: parentSpanId,
682
+ traceFlags: import_api3.TraceFlags.SAMPLED
683
+ };
684
+ const link = {
685
+ context: externalContext,
686
+ attributes: {
687
+ "link.type": linkType,
688
+ "link.source": sourceSystem,
689
+ "link.trace_id": traceId,
690
+ "link.span_id": parentSpanId
691
+ }
692
+ };
693
+ return link;
694
+ }
695
+ function extractTraceContextFromHeaders(headers, traceIdHeader = "x-trace-id", parentSpanIdHeader = "x-parent-span-id") {
696
+ if (!headers) {
697
+ return [void 0, void 0];
698
+ }
699
+ let traceId;
700
+ let parentSpanId;
701
+ if (headers instanceof Headers) {
702
+ traceId = headers.get(traceIdHeader) || void 0;
703
+ parentSpanId = headers.get(parentSpanIdHeader) || void 0;
704
+ } else {
705
+ const headersLower = {};
706
+ for (const [key, value] of Object.entries(headers)) {
707
+ headersLower[key.toLowerCase()] = value;
708
+ }
709
+ traceId = headersLower[traceIdHeader.toLowerCase()];
710
+ parentSpanId = headersLower[parentSpanIdHeader.toLowerCase()];
711
+ }
712
+ return [traceId, parentSpanId];
713
+ }
714
+ function processTraceContextFromHeaders(headers, logger, linkType = "follows_from", sourceSystem = "gateway") {
715
+ const [traceId, parentSpanId] = extractTraceContextFromHeaders(headers);
716
+ const validation = validateTraceContext(traceId, parentSpanId);
717
+ if (!validation.isValid) {
718
+ if (logger && logger.warn) {
719
+ validation.errors.forEach((error) => {
720
+ logger.warn(`Trace context validation failed: ${error}`);
721
+ });
722
+ }
723
+ return {
724
+ traceId: void 0,
725
+ parentSpanId: void 0,
726
+ isInherited: false,
727
+ hasParentLink: false,
728
+ spanAttributes: {},
729
+ links: []
730
+ };
731
+ }
732
+ const normalizedTraceId = validation.traceId;
733
+ const normalizedParentSpanId = validation.parentSpanId;
734
+ const attributes = {};
735
+ const links = [];
736
+ if (normalizedTraceId) {
737
+ attributes["trace.inherited"] = true;
738
+ attributes["trace.external_trace_id"] = normalizedTraceId;
739
+ }
740
+ if (normalizedTraceId && normalizedParentSpanId) {
741
+ const link = createSpanLinkFromContext(
742
+ normalizedTraceId,
743
+ normalizedParentSpanId,
744
+ linkType,
745
+ sourceSystem
746
+ );
747
+ links.push(link);
748
+ attributes["trace.external_parent_span_id"] = normalizedParentSpanId;
749
+ }
750
+ return {
751
+ traceId: normalizedTraceId,
752
+ parentSpanId: normalizedParentSpanId,
753
+ isInherited: !!normalizedTraceId,
754
+ hasParentLink: !!normalizedParentSpanId,
755
+ spanAttributes: attributes,
756
+ links
757
+ };
758
+ }
759
+ var import_api3;
760
+ var init_trace_context = __esm({
761
+ "src/core/trace-context.ts"() {
762
+ "use strict";
763
+ import_api3 = require("@opentelemetry/api");
764
+ }
765
+ });
766
+
430
767
  // src/index.ts
431
768
  var src_exports = {};
432
769
  __export(src_exports, {
@@ -438,34 +775,42 @@ __export(src_exports, {
438
775
  ObservationLLM: () => ObservationLLM,
439
776
  ObservationReranker: () => ObservationReranker,
440
777
  ObservationRetriever: () => ObservationRetriever,
441
- ObservationSpan: () => ObservationSpan,
442
778
  ObservationTool: () => ObservationTool,
443
779
  createObservationAttributes: () => createObservationAttributes,
780
+ createSpanLinkFromContext: () => createSpanLinkFromContext,
444
781
  createTraceAttributes: () => createTraceAttributes,
782
+ extractTraceContextFromHeaders: () => extractTraceContextFromHeaders,
445
783
  getActiveSpanId: () => getActiveSpanId,
446
784
  getActiveTraceId: () => getActiveTraceId,
447
785
  getTracer: () => getTracer,
448
786
  getTracerProvider: () => getTracerProvider,
449
787
  observe: () => observe,
788
+ processTraceContextFromHeaders: () => processTraceContextFromHeaders,
450
789
  setTracerProvider: () => setTracerProvider,
451
790
  startActiveObservation: () => startActiveObservation,
452
791
  startObservation: () => startObservation,
453
792
  updateActiveObservation: () => updateActiveObservation,
454
- updateActiveTrace: () => updateActiveTrace
793
+ updateActiveTrace: () => updateActiveTrace,
794
+ validateSpanId: () => validateSpanId,
795
+ validateTraceContext: () => validateTraceContext,
796
+ validateTraceId: () => validateTraceId
455
797
  });
456
798
  function createOtelSpan(params) {
457
799
  return getTracer().startSpan(
458
800
  params.name,
459
- { startTime: params.startTime },
801
+ {
802
+ startTime: params.startTime,
803
+ links: params.links || []
804
+ },
460
805
  createParentContext(params.parentSpanContext)
461
806
  );
462
807
  }
463
808
  function createParentContext(parentSpanContext) {
464
809
  if (!parentSpanContext) return;
465
- return import_api2.trace.setSpanContext(import_api2.context.active(), parentSpanContext);
810
+ return import_api4.trace.setSpanContext(import_api4.context.active(), parentSpanContext);
466
811
  }
467
812
  function startObservation(name, attributes, options) {
468
- const { asType = "span", ...observationOptions } = options || {};
813
+ const { asType = "chain", ...observationOptions } = options || {};
469
814
  const otelSpan = createOtelSpan({
470
815
  name,
471
816
  ...observationOptions
@@ -516,16 +861,15 @@ function startObservation(name, attributes, options) {
516
861
  otelSpan,
517
862
  attributes
518
863
  });
519
- case "span":
520
864
  default:
521
- return new ObservationSpan({
865
+ return new ObservationChain({
522
866
  otelSpan,
523
867
  attributes
524
868
  });
525
869
  }
526
870
  }
527
871
  function updateActiveTrace(attributes) {
528
- const span = import_api2.trace.getActiveSpan();
872
+ const span = import_api4.trace.getActiveSpan();
529
873
  if (!span) {
530
874
  console.warn(
531
875
  "[Observability] No active OTEL span in context. Skipping trace update."
@@ -535,10 +879,10 @@ function updateActiveTrace(attributes) {
535
879
  span.setAttributes(createTraceAttributes(attributes));
536
880
  }
537
881
  function getActiveTraceId() {
538
- return import_api2.trace.getActiveSpan()?.spanContext().traceId;
882
+ return import_api4.trace.getActiveSpan()?.spanContext().traceId;
539
883
  }
540
884
  function getActiveSpanId() {
541
- return import_api2.trace.getActiveSpan()?.spanContext().spanId;
885
+ return import_api4.trace.getActiveSpan()?.spanContext().spanId;
542
886
  }
543
887
  function wrapPromise(promise, span, endOnExit) {
544
888
  return promise.then(
@@ -550,7 +894,7 @@ function wrapPromise(promise, span, endOnExit) {
550
894
  },
551
895
  (err) => {
552
896
  span.setStatus({
553
- code: import_api2.SpanStatusCode.ERROR,
897
+ code: import_api4.SpanStatusCode.ERROR,
554
898
  message: err instanceof Error ? err.message : "Unknown error"
555
899
  });
556
900
  if (endOnExit !== false) {
@@ -561,11 +905,11 @@ function wrapPromise(promise, span, endOnExit) {
561
905
  );
562
906
  }
563
907
  function startActiveObservation(name, fn, options) {
564
- const { asType = "span", endOnExit, ...observationOptions } = options || {};
908
+ const { asType = "chain", endOnExit, ...observationOptions } = options || {};
565
909
  return getTracer().startActiveSpan(
566
910
  name,
567
911
  { startTime: observationOptions?.startTime },
568
- createParentContext(observationOptions?.parentSpanContext) ?? import_api2.context.active(),
912
+ createParentContext(observationOptions?.parentSpanContext) ?? import_api4.context.active(),
569
913
  (span) => {
570
914
  try {
571
915
  let observation;
@@ -582,9 +926,6 @@ function startActiveObservation(name, fn, options) {
582
926
  case "tool":
583
927
  observation = new ObservationTool({ otelSpan: span });
584
928
  break;
585
- case "chain":
586
- observation = new ObservationChain({ otelSpan: span });
587
- break;
588
929
  case "retriever":
589
930
  observation = new ObservationRetriever({ otelSpan: span });
590
931
  break;
@@ -597,9 +938,9 @@ function startActiveObservation(name, fn, options) {
597
938
  case "guardrail":
598
939
  observation = new ObservationGuardrail({ otelSpan: span });
599
940
  break;
600
- case "span":
941
+ case "chain":
601
942
  default:
602
- observation = new ObservationSpan({ otelSpan: span });
943
+ observation = new ObservationChain({ otelSpan: span });
603
944
  }
604
945
  const result = fn(observation);
605
946
  if (result instanceof Promise) {
@@ -616,7 +957,7 @@ function startActiveObservation(name, fn, options) {
616
957
  }
617
958
  } catch (err) {
618
959
  span.setStatus({
619
- code: import_api2.SpanStatusCode.ERROR,
960
+ code: import_api4.SpanStatusCode.ERROR,
620
961
  message: err instanceof Error ? err.message : "Unknown error"
621
962
  });
622
963
  if (endOnExit !== false) {
@@ -628,14 +969,14 @@ function startActiveObservation(name, fn, options) {
628
969
  );
629
970
  }
630
971
  function updateActiveObservation(attributes) {
631
- const span = import_api2.trace.getActiveSpan();
972
+ const span = import_api4.trace.getActiveSpan();
632
973
  if (!span) {
633
974
  console.warn(
634
975
  "[Observability] No active OTEL span in context. Skipping observation update."
635
976
  );
636
977
  return;
637
978
  }
638
- span.setAttributes(createObservationAttributes("span", attributes));
979
+ span.setAttributes(createObservationAttributes("chain", attributes));
639
980
  }
640
981
  function _captureArguments(args) {
641
982
  if (args.length === 0) return {};
@@ -644,7 +985,7 @@ function _captureArguments(args) {
644
985
  }
645
986
  function observe(fn, options = {}) {
646
987
  const {
647
- asType = "span",
988
+ asType = "chain",
648
989
  captureInput = true,
649
990
  captureOutput = true,
650
991
  ...observationOptions
@@ -660,8 +1001,8 @@ function observe(fn, options = {}) {
660
1001
  asType
661
1002
  }
662
1003
  );
663
- const activeContext = import_api2.trace.setSpan(import_api2.context.active(), observation.otelSpan);
664
- const result = import_api2.context.with(activeContext, () => fn.apply(this, args));
1004
+ const activeContext = import_api4.trace.setSpan(import_api4.context.active(), observation.otelSpan);
1005
+ const result = import_api4.context.with(activeContext, () => fn.apply(this, args));
665
1006
  if (result instanceof Promise) {
666
1007
  return result.then(
667
1008
  (value) => {
@@ -691,16 +1032,17 @@ function observe(fn, options = {}) {
691
1032
  Object.defineProperty(wrappedFunction, "length", { value: fn.length });
692
1033
  return wrappedFunction;
693
1034
  }
694
- var import_api2;
1035
+ var import_api4;
695
1036
  var init_src = __esm({
696
1037
  "src/index.ts"() {
697
1038
  "use strict";
698
- import_api2 = require("@opentelemetry/api");
1039
+ import_api4 = require("@opentelemetry/api");
699
1040
  init_attributes();
700
1041
  init_spanWrapper();
701
1042
  init_tracerProvider();
702
1043
  init_attributes();
703
1044
  init_tracerProvider();
1045
+ init_trace_context();
704
1046
  }
705
1047
  });
706
1048
 
@@ -727,6 +1069,8 @@ var CallbackHandler = class extends import_base.BaseCallbackHandler {
727
1069
  last_trace_id = null;
728
1070
  // External parent context from AG-UI.Server span
729
1071
  externalParentSpanContext;
1072
+ // External metadata from AG-UI.Server (e.g., threadId, runId)
1073
+ externalMetadata;
730
1074
  // Adapter name for ROOT span prefix
731
1075
  adapterName;
732
1076
  // Logger for debug output (defaults to noopLogger for silent operation)
@@ -748,10 +1092,12 @@ var CallbackHandler = class extends import_base.BaseCallbackHandler {
748
1092
  * to the server-level span, creating a unified trace hierarchy.
749
1093
  *
750
1094
  * @param spanContext - SpanContext from the AG-UI.Server span
1095
+ * @param metadata - Optional metadata from server (e.g., threadId, runId)
751
1096
  * @public
752
1097
  */
753
- setExternalParentContext(spanContext) {
1098
+ setExternalParentContext(spanContext, metadata) {
754
1099
  this.externalParentSpanContext = spanContext;
1100
+ this.externalMetadata = metadata;
755
1101
  }
756
1102
  async handleLLMNewToken(token, _idx, runId, _parentRunId, _tags, _fields) {
757
1103
  if (runId && !(runId in this.completionStartTimes)) {
@@ -761,7 +1107,6 @@ var CallbackHandler = class extends import_base.BaseCallbackHandler {
761
1107
  }
762
1108
  async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, name) {
763
1109
  try {
764
- this.logger.debug?.(`Chain start with Id: ${runId}`);
765
1110
  const runName = name ?? chain.id.at(-1)?.toString() ?? "Langchain Run";
766
1111
  this.registerPromptInfo(parentRunId, metadata);
767
1112
  let finalInput = inputs;
@@ -781,11 +1126,11 @@ var CallbackHandler = class extends import_base.BaseCallbackHandler {
781
1126
  parentRunId,
782
1127
  runId,
783
1128
  tags,
784
- metadata,
1129
+ metadata: this.joinTagsAndMetaData(tags, metadata),
785
1130
  attributes: {
786
1131
  input: finalInput
787
1132
  },
788
- asType: "span"
1133
+ asType: "chain"
789
1134
  });
790
1135
  const traceTags = [.../* @__PURE__ */ new Set([...tags ?? [], ...this.tags])];
791
1136
  if (!parentRunId) {
@@ -862,10 +1207,15 @@ var CallbackHandler = class extends import_base.BaseCallbackHandler {
862
1207
  }
863
1208
  }
864
1209
  let extractedModelName;
1210
+ let extractedSystem;
1211
+ let extractedProvider;
865
1212
  if (extraParams) {
866
1213
  const invocationParamsModelName = extraParams.invocation_params.model;
867
1214
  const metadataModelName = metadata && "ls_model_name" in metadata ? metadata["ls_model_name"] : void 0;
868
1215
  extractedModelName = invocationParamsModelName ?? metadataModelName;
1216
+ if (metadata && "ls_provider" in metadata) {
1217
+ extractedProvider = metadata["ls_provider"];
1218
+ }
869
1219
  }
870
1220
  const registeredPrompt = this.promptToParentRunMap.get(
871
1221
  parentRunId ?? "root"
@@ -958,7 +1308,7 @@ var CallbackHandler = class extends import_base.BaseCallbackHandler {
958
1308
  attributes: {
959
1309
  input
960
1310
  },
961
- metadata,
1311
+ metadata: this.joinTagsAndMetaData(tags, metadata),
962
1312
  tags,
963
1313
  asType: "tool"
964
1314
  });
@@ -977,8 +1327,8 @@ var CallbackHandler = class extends import_base.BaseCallbackHandler {
977
1327
  input: query
978
1328
  },
979
1329
  tags,
980
- metadata,
981
- asType: "span"
1330
+ metadata: this.joinTagsAndMetaData(tags, metadata),
1331
+ asType: "retriever"
982
1332
  });
983
1333
  } catch (e) {
984
1334
  this.logger.debug?.(e instanceof Error ? e.message : String(e));
@@ -1123,15 +1473,17 @@ var CallbackHandler = class extends import_base.BaseCallbackHandler {
1123
1473
  if (!parentRunId && this.adapterName) {
1124
1474
  finalRunName = `Adapter.${this.adapterName}`;
1125
1475
  }
1476
+ const serverMetadata = this.externalMetadata ? { "agui.thread_id": this.externalMetadata.threadId, "agui.run_id": this.externalMetadata.runId } : {};
1126
1477
  const observation = startObservation(
1127
1478
  finalRunName,
1128
1479
  {
1129
1480
  version: this.version,
1130
1481
  metadata: this.joinTagsAndMetaData(tags, metadata),
1131
- ...attributes
1482
+ ...attributes,
1483
+ ...serverMetadata
1132
1484
  },
1133
1485
  {
1134
- asType: asType ?? "span",
1486
+ asType: asType ?? "chain",
1135
1487
  parentSpanContext
1136
1488
  }
1137
1489
  );
@@ -1145,6 +1497,15 @@ var CallbackHandler = class extends import_base.BaseCallbackHandler {
1145
1497
  this.logger.warn?.("Observation not found in runMap. Skipping operation.");
1146
1498
  return;
1147
1499
  }
1500
+ const level = attributes.level;
1501
+ const statusMessage = attributes.statusMessage;
1502
+ if (level === "ERROR") {
1503
+ try {
1504
+ observation.setErrorStatus(statusMessage || "Unknown error");
1505
+ } catch (e) {
1506
+ this.logger.debug?.("Failed to set span error status:", e);
1507
+ }
1508
+ }
1148
1509
  observation.update(attributes).end();
1149
1510
  this.last_trace_id = observation.traceId;
1150
1511
  this.runMap.delete(runId);
@@ -1166,7 +1527,7 @@ var CallbackHandler = class extends import_base.BaseCallbackHandler {
1166
1527
  if (!metadata) {
1167
1528
  return;
1168
1529
  }
1169
- const reservedKeys = ["promptInfo", "userId", "sessionId"];
1530
+ const reservedKeys = ["promptInfo", "userId", "sessionId", "thread_id", "runId", "run_id"];
1170
1531
  return Object.fromEntries(
1171
1532
  Object.entries(metadata).filter(([key, _]) => !reservedKeys.includes(key))
1172
1533
  );