netra-sdk 1.2.0 → 1.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.js CHANGED
@@ -4,8 +4,8 @@ import { createRequire } from 'module';
4
4
  import { AsyncLocalStorage } from 'async_hooks';
5
5
  import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
6
6
  import { initialize } from '@traceloop/node-server-sdk';
7
- import * as dotenv from 'dotenv';
8
7
  import shimmer from 'shimmer';
8
+ import * as dotenv from 'dotenv';
9
9
  import { CompositePropagator, W3CTraceContextPropagator, W3CBaggagePropagator, ExportResultCode } from '@opentelemetry/core';
10
10
  import * as http from 'http';
11
11
  import * as https from 'https';
@@ -22,6 +22,9 @@ var Logger = class {
22
22
  static get isDebug() {
23
23
  return this._debugMode || ["1", "true"].includes((process.env.NETRA_DEBUG ?? "").toLowerCase());
24
24
  }
25
+ static isDebugMode() {
26
+ return this.isDebug;
27
+ }
25
28
  static debug(...args) {
26
29
  if (this.isDebug) console.debug(PREFIX, ...args);
27
30
  }
@@ -575,6 +578,9 @@ var Usage = class {
575
578
  }
576
579
  };
577
580
 
581
+ // src/version.ts
582
+ var SDK_VERSION = "1.4.0";
583
+
578
584
  // src/config.ts
579
585
  var NetraInstruments = /* @__PURE__ */ ((NetraInstruments2) => {
580
586
  NetraInstruments2["ALL"] = "__all__";
@@ -610,7 +616,8 @@ var DEFAULT_INSTRUMENTS_FOR_ROOT = /* @__PURE__ */ new Set([
610
616
  // AI frameworks
611
617
  "langchain" /* LANGCHAIN */,
612
618
  "langgraph" /* LANGGRAPH */,
613
- "llama_index" /* LLAMA_INDEX */
619
+ "llama_index" /* LLAMA_INDEX */,
620
+ "openai_agents" /* OPENAI_AGENTS */
614
621
  ]);
615
622
  var DEFAULT_INSTRUMENTS = /* @__PURE__ */ new Set([
616
623
  ...DEFAULT_INSTRUMENTS_FOR_ROOT,
@@ -772,11 +779,34 @@ var Config = class {
772
779
  const headerStr = Object.entries(this.headers).map(([k, v]) => `${k}=${v}`).join(",");
773
780
  process.env.TRACELOOP_HEADERS = headerStr;
774
781
  }
782
+ this._setResourceAttributesEnv();
783
+ }
784
+ _setResourceAttributesEnv() {
785
+ const attrs = {
786
+ "deployment.environment": this.environment,
787
+ "service.name": this.appName
788
+ };
789
+ for (const [k, v] of Object.entries(this.resourceAttributes)) {
790
+ attrs[k] = String(v);
791
+ }
792
+ const existing = process.env.OTEL_RESOURCE_ATTRIBUTES;
793
+ if (existing) {
794
+ for (const pair of existing.split(",")) {
795
+ const eqIdx = pair.indexOf("=");
796
+ if (eqIdx <= 0) continue;
797
+ const key = decodeURIComponent(pair.slice(0, eqIdx).trim());
798
+ if (key) {
799
+ attrs[key] = decodeURIComponent(pair.slice(eqIdx + 1).trim());
800
+ }
801
+ }
802
+ }
803
+ const encodeAttrValue = (s) => encodeURIComponent(s);
804
+ process.env.OTEL_RESOURCE_ATTRIBUTES = Object.entries(attrs).map(([k, v]) => `${encodeAttrValue(k)}=${encodeAttrValue(v)}`).join(",");
775
805
  }
776
806
  };
777
807
  Config.SDK_NAME = "netra";
778
808
  Config.LIBRARY_NAME = "netra";
779
- Config.LIBRARY_VERSION = "1.0.0";
809
+ Config.LIBRARY_VERSION = SDK_VERSION;
780
810
  Config.TRIAL_BLOCK_DURATION_SECONDS = 900;
781
811
  // 15 minutes
782
812
  Config.ATTRIBUTE_MAX_LEN = parseInt(
@@ -785,6 +815,9 @@ Config.ATTRIBUTE_MAX_LEN = parseInt(
785
815
  Config.CONVERSATION_MAX_LEN = parseInt(
786
816
  process.env.NETRA_CONVERSATION_CONTENT_MAX_LEN || "50000"
787
817
  );
818
+ Config.SPAN_ATTRIBUTE_MAX_SIZE = parseInt(
819
+ process.env.NETRA_SPAN_ATTRIBUTE_MAX_SIZE || "30000"
820
+ );
788
821
 
789
822
  // src/utils/pattern-matching.ts
790
823
  function compilePatterns(patterns) {
@@ -1046,6 +1079,57 @@ var ConversationType = /* @__PURE__ */ ((ConversationType3) => {
1046
1079
  return ConversationType3;
1047
1080
  })(ConversationType || {});
1048
1081
 
1082
+ // src/utils/serialization.ts
1083
+ var ELLIPSIS = "...";
1084
+ function truncate(s, maxLength) {
1085
+ if (s.length <= maxLength) return s;
1086
+ if (maxLength <= ELLIPSIS.length) return s.slice(0, maxLength);
1087
+ return s.slice(0, maxLength - ELLIPSIS.length) + ELLIPSIS;
1088
+ }
1089
+ function safeStringify(value, maxLength) {
1090
+ if (typeof value === "string") {
1091
+ if (maxLength && value.length > maxLength) {
1092
+ return truncate(value, maxLength);
1093
+ }
1094
+ return value;
1095
+ }
1096
+ const seen = /* @__PURE__ */ new WeakSet();
1097
+ let result;
1098
+ try {
1099
+ result = JSON.stringify(value, (_key, val) => {
1100
+ if (typeof val === "function")
1101
+ return `[Function: ${val.name || "anonymous"}]`;
1102
+ if (typeof val === "symbol") return val.toString();
1103
+ if (typeof val === "bigint") return val.toString();
1104
+ if (val !== null && typeof val === "object") {
1105
+ if (seen.has(val)) return "[Circular]";
1106
+ seen.add(val);
1107
+ const name = val.constructor?.name;
1108
+ if (name && name !== "Object" && name !== "Array" && Object.keys(val).length > 20) {
1109
+ return `[${name}]`;
1110
+ }
1111
+ }
1112
+ return val;
1113
+ }) ?? String(value);
1114
+ } catch {
1115
+ result = value?.constructor?.name ? `[${value.constructor.name}]` : String(value);
1116
+ }
1117
+ if (maxLength && result.length > maxLength) {
1118
+ return truncate(result, maxLength);
1119
+ }
1120
+ return result;
1121
+ }
1122
+ function serializeValue(value, maxLength) {
1123
+ if (value === null || value === void 0) return String(value);
1124
+ const t = typeof value;
1125
+ if (t === "string" || t === "number" || t === "boolean") {
1126
+ const s = String(value);
1127
+ if (maxLength && s.length > maxLength) return truncate(s, maxLength);
1128
+ return s;
1129
+ }
1130
+ return safeStringify(value, maxLength);
1131
+ }
1132
+
1049
1133
  // src/session-manager.ts
1050
1134
  var MODULE_NAME = "netra.session-manager";
1051
1135
  var entityStorage = new AsyncLocalStorage();
@@ -1059,12 +1143,6 @@ var globalFallbackContext = {
1059
1143
  function getEntityContext() {
1060
1144
  return entityStorage.getStore() ?? globalFallbackContext;
1061
1145
  }
1062
- function serializeValue(value) {
1063
- if (typeof value === "string") {
1064
- return value.substring(0, Config.ATTRIBUTE_MAX_LEN);
1065
- }
1066
- return JSON.stringify(value).substring(0, Config.ATTRIBUTE_MAX_LEN);
1067
- }
1068
1146
  var SessionManager = class _SessionManager {
1069
1147
  // Span registry (name → stack)
1070
1148
  static registerSpan(name, span2) {
@@ -1179,7 +1257,10 @@ var SessionManager = class _SessionManager {
1179
1257
  */
1180
1258
  static setInput(value) {
1181
1259
  try {
1182
- _SessionManager.setAttributeOnActiveSpan("netra.user.input", serializeValue(value));
1260
+ _SessionManager.setAttributeOnActiveSpan(
1261
+ "netra.user.input",
1262
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
1263
+ );
1183
1264
  } catch (e) {
1184
1265
  Logger.error("setInput failed:", e);
1185
1266
  }
@@ -1191,7 +1272,10 @@ var SessionManager = class _SessionManager {
1191
1272
  */
1192
1273
  static setOutput(value) {
1193
1274
  try {
1194
- _SessionManager.setAttributeOnActiveSpan("netra.user.output", serializeValue(value));
1275
+ _SessionManager.setAttributeOnActiveSpan(
1276
+ "netra.user.output",
1277
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
1278
+ );
1195
1279
  } catch (e) {
1196
1280
  Logger.error("setOutput failed:", e);
1197
1281
  }
@@ -1203,7 +1287,10 @@ var SessionManager = class _SessionManager {
1203
1287
  */
1204
1288
  static setRootInput(value) {
1205
1289
  try {
1206
- RootSpanProcessor.setAttributeOnRootSpan("netra.user.input", serializeValue(value));
1290
+ RootSpanProcessor.setAttributeOnRootSpan(
1291
+ "netra.user.input",
1292
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
1293
+ );
1207
1294
  } catch (e) {
1208
1295
  Logger.error("setRootInput failed:", e);
1209
1296
  }
@@ -1215,7 +1302,10 @@ var SessionManager = class _SessionManager {
1215
1302
  */
1216
1303
  static setRootOutput(value) {
1217
1304
  try {
1218
- RootSpanProcessor.setAttributeOnRootSpan("netra.user.output", serializeValue(value));
1305
+ RootSpanProcessor.setAttributeOnRootSpan(
1306
+ "netra.user.output",
1307
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
1308
+ );
1219
1309
  } catch (e) {
1220
1310
  Logger.error("setRootOutput failed:", e);
1221
1311
  }
@@ -2782,6 +2872,58 @@ var Prompts = class {
2782
2872
  }
2783
2873
  };
2784
2874
 
2875
+ // src/processors/attribute-size-limit-processor.ts
2876
+ var DEFAULT_MAX_ATTRIBUTE_SIZE = 32e3;
2877
+ var AttributeSizeLimitProcessor = class {
2878
+ constructor(maxAttributeSize) {
2879
+ this.maxAttributeSize = maxAttributeSize ?? DEFAULT_MAX_ATTRIBUTE_SIZE;
2880
+ }
2881
+ onStart(span2, _parentContext) {
2882
+ try {
2883
+ this._wrapSetAttribute(span2);
2884
+ } catch (e) {
2885
+ Logger.debug("AttributeSizeLimitProcessor.onStart error:", e);
2886
+ }
2887
+ }
2888
+ onEnd(_span) {
2889
+ }
2890
+ shutdown() {
2891
+ return Promise.resolve();
2892
+ }
2893
+ forceFlush() {
2894
+ return Promise.resolve();
2895
+ }
2896
+ _wrapSetAttribute(span2) {
2897
+ const original = span2.setAttribute.bind(span2);
2898
+ const maxLen = this.maxAttributeSize;
2899
+ const patched = (key, value) => {
2900
+ try {
2901
+ return original(key, truncateValue(value, maxLen));
2902
+ } catch {
2903
+ try {
2904
+ return original(key, value);
2905
+ } catch {
2906
+ return span2;
2907
+ }
2908
+ }
2909
+ };
2910
+ span2.setAttribute = patched;
2911
+ }
2912
+ };
2913
+ function truncateValue(value, maxLen) {
2914
+ if (typeof value === "string") {
2915
+ return value.length > maxLen ? value.substring(0, maxLen) : value;
2916
+ }
2917
+ if (Array.isArray(value)) {
2918
+ const serialized = JSON.stringify(value);
2919
+ if (serialized.length > maxLen) {
2920
+ return serialized.substring(0, maxLen);
2921
+ }
2922
+ return value;
2923
+ }
2924
+ return value;
2925
+ }
2926
+
2785
2927
  // src/processors/instrumentation-span-processor.ts
2786
2928
  var ALLOWED_INSTRUMENTATION_NAMES = /* @__PURE__ */ new Set([
2787
2929
  "openai",
@@ -3187,6 +3329,9 @@ function setSessionBaggage(key, value) {
3187
3329
  }
3188
3330
  }
3189
3331
  var SessionSpanProcessor = class {
3332
+ constructor(environment = "local") {
3333
+ this.environment = environment;
3334
+ }
3190
3335
  /**
3191
3336
  * Called when a span starts. Adds session and entity context attributes.
3192
3337
  */
@@ -3195,6 +3340,7 @@ var SessionSpanProcessor = class {
3195
3340
  span2.setAttribute("library.name", Config.LIBRARY_NAME);
3196
3341
  span2.setAttribute("library.version", Config.LIBRARY_VERSION);
3197
3342
  span2.setAttribute("sdk.name", Config.SDK_NAME);
3343
+ span2.setAttribute("deployment.environment", this.environment);
3198
3344
  const ctxToUse = parentContext || context.active();
3199
3345
  const baggage = propagation.getBaggage(ctxToUse);
3200
3346
  const sessionId = baggage?.getEntry("session_id")?.value ?? sessionValues.get("session_id");
@@ -3601,6 +3747,184 @@ var SpanIOProcessor = class {
3601
3747
  }
3602
3748
  };
3603
3749
 
3750
+ // src/instrumentation/anthropic/version.ts
3751
+ var __version__ = "1.0.0";
3752
+
3753
+ // src/utils/response-handler.ts
3754
+ function isAsyncIterable(value) {
3755
+ return value != null && typeof value[Symbol.asyncIterator] === "function";
3756
+ }
3757
+ function isPromise(value) {
3758
+ return value != null && typeof value.then === "function";
3759
+ }
3760
+ var ITERATOR_METHODS = /* @__PURE__ */ new Set(["next", "return", "throw"]);
3761
+ function wrapAsyncIterable(source, callbacks) {
3762
+ function createWrappedIterator() {
3763
+ const iterator = source[Symbol.asyncIterator]();
3764
+ let done = false;
3765
+ const safeFinalize = (status) => {
3766
+ if (done) return;
3767
+ done = true;
3768
+ try {
3769
+ callbacks.finalize(status);
3770
+ } catch (e) {
3771
+ Logger.error("netra: finalize callback error", e);
3772
+ }
3773
+ };
3774
+ return {
3775
+ async next(value) {
3776
+ try {
3777
+ const result = await callbacks.withContext(() => iterator.next(value));
3778
+ if (!result.done) {
3779
+ try {
3780
+ callbacks.onChunk?.(result.value);
3781
+ } catch (e) {
3782
+ Logger.error("netra: onChunk callback error", e);
3783
+ }
3784
+ } else {
3785
+ safeFinalize("ok");
3786
+ }
3787
+ return result;
3788
+ } catch (e) {
3789
+ try {
3790
+ callbacks.onError(e);
3791
+ } catch {
3792
+ Logger.error("netra: onError callback error", e);
3793
+ }
3794
+ safeFinalize("error");
3795
+ throw e;
3796
+ }
3797
+ },
3798
+ async return(value) {
3799
+ try {
3800
+ const result = await callbacks.withContext(
3801
+ () => iterator.return?.(value) ?? { done: true, value }
3802
+ );
3803
+ safeFinalize("ok");
3804
+ return result;
3805
+ } catch (e) {
3806
+ try {
3807
+ callbacks.onError(e);
3808
+ } catch {
3809
+ Logger.error("netra: onError callback error", e);
3810
+ }
3811
+ safeFinalize("error");
3812
+ throw e;
3813
+ }
3814
+ },
3815
+ async throw(e) {
3816
+ try {
3817
+ const result = await callbacks.withContext(() => {
3818
+ if (iterator.throw) return iterator.throw(e);
3819
+ throw e;
3820
+ });
3821
+ if (result.done) safeFinalize("ok");
3822
+ return result;
3823
+ } catch (err) {
3824
+ try {
3825
+ callbacks.onError(err);
3826
+ } catch {
3827
+ Logger.error("netra: onError callback error", err);
3828
+ }
3829
+ safeFinalize("error");
3830
+ throw err;
3831
+ }
3832
+ }
3833
+ };
3834
+ }
3835
+ let directIterator = null;
3836
+ return new Proxy(source, {
3837
+ get(target, prop) {
3838
+ if (prop === Symbol.asyncIterator) {
3839
+ return () => createWrappedIterator();
3840
+ }
3841
+ if (typeof prop === "string" && ITERATOR_METHODS.has(prop)) {
3842
+ if (!directIterator) directIterator = createWrappedIterator();
3843
+ return directIterator[prop].bind(directIterator);
3844
+ }
3845
+ const value = target[prop];
3846
+ if (typeof value === "function") return value.bind(target);
3847
+ return value;
3848
+ }
3849
+ });
3850
+ }
3851
+ function wrapPromise(promise, callbacks, options) {
3852
+ let finalized = false;
3853
+ function safeFinalize(status) {
3854
+ if (finalized) return;
3855
+ finalized = true;
3856
+ try {
3857
+ callbacks.finalize(status);
3858
+ } catch (e) {
3859
+ Logger.error("netra: finalize callback error", e);
3860
+ }
3861
+ }
3862
+ const instrumentedPromise = (async () => {
3863
+ try {
3864
+ const value = await promise;
3865
+ if (isAsyncIterable(value)) {
3866
+ return wrapAsyncIterable(value, callbacks);
3867
+ }
3868
+ try {
3869
+ callbacks.onSuccess?.(value);
3870
+ } catch (e) {
3871
+ Logger.error("netra: onSuccess callback error", e);
3872
+ }
3873
+ safeFinalize("ok");
3874
+ return value;
3875
+ } catch (error) {
3876
+ try {
3877
+ callbacks.onError(error);
3878
+ } catch {
3879
+ Logger.error("netra: onError callback error", error);
3880
+ }
3881
+ safeFinalize("error");
3882
+ throw error;
3883
+ }
3884
+ })();
3885
+ if (!options?.preserveOriginal) {
3886
+ return instrumentedPromise;
3887
+ }
3888
+ const original = options.preserveOriginal;
3889
+ return new Proxy(instrumentedPromise, {
3890
+ get(target, prop, receiver) {
3891
+ if (prop === "then" || prop === "catch" || prop === "finally") {
3892
+ const value2 = Reflect.get(target, prop, receiver);
3893
+ if (typeof value2 === "function") return value2.bind(target);
3894
+ return value2;
3895
+ }
3896
+ const originalValue = original[prop];
3897
+ if (originalValue !== void 0) {
3898
+ if (typeof originalValue === "function")
3899
+ return originalValue.bind(original);
3900
+ return originalValue;
3901
+ }
3902
+ const value = Reflect.get(target, prop, receiver);
3903
+ if (typeof value === "function") return value.bind(target);
3904
+ return value;
3905
+ }
3906
+ });
3907
+ }
3908
+ function wrapResponse(response, callbacks, options) {
3909
+ if (isAsyncIterable(response)) {
3910
+ return wrapAsyncIterable(response, callbacks);
3911
+ }
3912
+ if (isPromise(response)) {
3913
+ return wrapPromise(response, callbacks, options);
3914
+ }
3915
+ try {
3916
+ callbacks.onSuccess?.(response);
3917
+ } catch (e) {
3918
+ Logger.error("netra: onSuccess callback error", e);
3919
+ }
3920
+ try {
3921
+ callbacks.finalize("ok");
3922
+ } catch (e) {
3923
+ Logger.error("netra: finalize callback error", e);
3924
+ }
3925
+ return response;
3926
+ }
3927
+
3604
3928
  // src/instrumentation/span-attributes.ts
3605
3929
  var SpanAttributes2 = {
3606
3930
  LLM_SYSTEM: "gen_ai.system",
@@ -3611,10 +3935,14 @@ var SpanAttributes2 = {
3611
3935
  LLM_REQUEST_TOP_P: "gen_ai.request.top_p",
3612
3936
  LLM_REQUEST_REASONING: "gen_ai.request.reasoning",
3613
3937
  LLM_REQUEST_REASONING_EFFORT: "gen_ai.request.reasoning_effort",
3938
+ LLM_REQUEST_TOOL_NAME: "gen_ai.request.tool.name",
3939
+ LLM_REQUEST_TOOL_ID: "gen_ai.request.tool.id",
3614
3940
  LLM_RESPONSE_MODEL: "gen_ai.response.model",
3941
+ LLM_RESPONSE_FINISH_REASON: "llm.response.finish_reason",
3615
3942
  LLM_USAGE_PROMPT_TOKENS: "gen_ai.usage.prompt_tokens",
3616
3943
  LLM_USAGE_COMPLETION_TOKENS: "gen_ai.usage.completion_tokens",
3617
3944
  LLM_USAGE_CACHE_READ_INPUT_TOKENS: "gen_ai.usage.cache_read_input_tokens",
3945
+ LLM_USAGE_CACHE_CREATION_INPUT_TOKENS: "gen_ai.usage.cache_creation_input_tokens",
3618
3946
  LLM_USAGE_REASONING_TOKENS: "gen_ai.usage.reasoning_tokens",
3619
3947
  LLM_USAGE_TOTAL_TOKENS: "llm.usage.total_tokens",
3620
3948
  LLM_FREQUENCY_PENALTY: "llm.frequency_penalty",
@@ -3624,16 +3952,18 @@ var SpanAttributes2 = {
3624
3952
  LLM_COMPLETIONS: "gen_ai.completion",
3625
3953
  LLM_PROMPTS: "gen_ai.prompt"
3626
3954
  };
3627
-
3628
- // src/instrumentation/utils.ts
3955
+ var VALID_NATIVE_TRACING_MODES = /* @__PURE__ */ new Set(["both", "netra", "netra-strict"]);
3956
+ function parseNativeTracingEnv(name) {
3957
+ const val = process.env[name];
3958
+ if (val === void 0 || val === "") return void 0;
3959
+ if (VALID_NATIVE_TRACING_MODES.has(val)) return val;
3960
+ return void 0;
3961
+ }
3629
3962
  var SUPPRESS_INSTRUMENTATION_KEY = /* @__PURE__ */ Symbol("netra.suppress_instrumentation");
3630
3963
  function shouldSuppressInstrumentation() {
3631
3964
  const ctx = context.active();
3632
3965
  return ctx.getValue(SUPPRESS_INSTRUMENTATION_KEY) === true;
3633
3966
  }
3634
- function isPromise(value) {
3635
- return value instanceof Promise;
3636
- }
3637
3967
  function defineHidden(target, key, value) {
3638
3968
  Object.defineProperty(target, key, {
3639
3969
  value,
@@ -3663,18 +3993,6 @@ function isTraceContentEnabled() {
3663
3993
  const raw = process.env.TRACELOOP_TRACE_CONTENT ?? process.env.NETRA_TRACE_CONTENT ?? "";
3664
3994
  return ["1", "true"].includes(String(raw).toLowerCase());
3665
3995
  }
3666
- function safeStringify(value) {
3667
- if (typeof value === "string") return value;
3668
- try {
3669
- return JSON.stringify(value);
3670
- } catch {
3671
- return String(value);
3672
- }
3673
- }
3674
- function truncate(value, maxLen) {
3675
- if (!value || value.length <= maxLen) return value;
3676
- return value.slice(0, maxLen) + "...(truncated)";
3677
- }
3678
3996
  function hasContent(value) {
3679
3997
  if (value === void 0 || value === null) return false;
3680
3998
  if (typeof value === "string") return value.length > 0;
@@ -3705,7 +4023,7 @@ function setModelParams(span2, kwargs) {
3705
4023
  }
3706
4024
  function buildInputMessages(kwargs, requestType) {
3707
4025
  const messages = [];
3708
- if (requestType === "chat") {
4026
+ if (requestType === "chat" || requestType === "beta") {
3709
4027
  if (hasContent(kwargs.system)) {
3710
4028
  const systemContent = typeof kwargs.system === "string" ? kwargs.system : safeStringify(kwargs.system);
3711
4029
  messages.push({ role: "system", content: systemContent });
@@ -3713,12 +4031,34 @@ function buildInputMessages(kwargs, requestType) {
3713
4031
  const rawMessages = kwargs.messages;
3714
4032
  if (!Array.isArray(rawMessages)) return messages;
3715
4033
  for (const msg of rawMessages) {
3716
- if (!isDict(msg)) continue;
3717
- if (hasContent(msg.role) && hasContent(msg.content)) {
4034
+ if (!isDict(msg) || !hasContent(msg.role) || !hasContent(msg.content)) {
4035
+ continue;
4036
+ }
4037
+ if (msg.role !== "user" || !Array.isArray(msg.content)) {
3718
4038
  messages.push({
3719
4039
  role: msg.role,
3720
4040
  content: safeStringify(msg.content)
3721
4041
  });
4042
+ continue;
4043
+ }
4044
+ const isToolResult = (b) => isDict(b) && b.type === "tool_result";
4045
+ const userBlocks = msg.content.filter((b) => !isToolResult(b));
4046
+ if (userBlocks.length) {
4047
+ messages.push({
4048
+ role: "user",
4049
+ content: safeStringify(userBlocks)
4050
+ });
4051
+ }
4052
+ for (const block of msg.content) {
4053
+ if (!isToolResult(block)) continue;
4054
+ messages.push({
4055
+ role: "tool",
4056
+ content: safeStringify({
4057
+ tool_use_id: block.tool_use_id,
4058
+ content: block.content,
4059
+ is_error: block.is_error ?? false
4060
+ }, Config.CONVERSATION_MAX_LEN)
4061
+ });
3722
4062
  }
3723
4063
  }
3724
4064
  } else if (requestType === "response") {
@@ -3747,10 +4087,7 @@ function buildInputMessages(kwargs, requestType) {
3747
4087
  } else {
3748
4088
  const input = kwargs.input ?? kwargs.inputs;
3749
4089
  if (hasContent(input)) {
3750
- const content = truncate(
3751
- safeStringify(input),
3752
- Config.CONVERSATION_MAX_LEN
3753
- );
4090
+ const content = safeStringify(input, Config.CONVERSATION_MAX_LEN);
3754
4091
  messages.push({ role: "user", content });
3755
4092
  }
3756
4093
  }
@@ -3817,7 +4154,7 @@ function buildOutputMessages(response) {
3817
4154
  } else if (block.type === "tool_use" && block.name) {
3818
4155
  messages.push({
3819
4156
  role: "tool",
3820
- content: JSON.stringify({ name: block.name, input: block.input })
4157
+ content: JSON.stringify({ id: block.id, name: block.name, input: block.input })
3821
4158
  });
3822
4159
  }
3823
4160
  }
@@ -3827,13 +4164,14 @@ function buildOutputMessages(response) {
3827
4164
  function writePromptAttributes(span2, messages) {
3828
4165
  if (messages.length === 0) return;
3829
4166
  for (let i = 0; i < messages.length; i++) {
4167
+ const msg = messages[i];
3830
4168
  span2.setAttribute(
3831
4169
  `${SpanAttributes2.LLM_PROMPTS}.${i}.role`,
3832
- messages[i].role
4170
+ msg.role
3833
4171
  );
3834
4172
  span2.setAttribute(
3835
4173
  `${SpanAttributes2.LLM_PROMPTS}.${i}.content`,
3836
- messages[i].content
4174
+ msg.content
3837
4175
  );
3838
4176
  }
3839
4177
  span2.setAttribute("input", JSON.stringify(messages));
@@ -3885,6 +4223,9 @@ function setRequestAttributes(span2, kwargs, requestType, system) {
3885
4223
  span2.setAttribute(SpanAttributes2.LLM_REQUEST_MODEL, String(kwargs.model));
3886
4224
  }
3887
4225
  setModelParams(span2, kwargs);
4226
+ if (Array.isArray(kwargs.tools)) {
4227
+ span2.setAttribute("tools", safeStringify(kwargs.tools, Config.ATTRIBUTE_MAX_LEN));
4228
+ }
3888
4229
  if (kwargs.reasoning !== void 0) {
3889
4230
  span2.setAttribute(
3890
4231
  SpanAttributes2.LLM_REQUEST_REASONING,
@@ -3897,7 +4238,7 @@ function setRequestAttributes(span2, kwargs, requestType, system) {
3897
4238
  if (kwargs.suffix !== void 0) {
3898
4239
  span2.setAttribute(
3899
4240
  "llm.request.suffix",
3900
- truncate(safeStringify(kwargs.suffix), Config.CONVERSATION_MAX_LEN)
4241
+ safeStringify(kwargs.suffix, Config.CONVERSATION_MAX_LEN)
3901
4242
  );
3902
4243
  }
3903
4244
  }
@@ -3920,12 +4261,20 @@ function setResponseAttributes(span2, response) {
3920
4261
  }
3921
4262
  }
3922
4263
  function setFinishReason(span2, response) {
4264
+ if (response.stop_reason) {
4265
+ span2.setAttribute(
4266
+ SpanAttributes2.LLM_RESPONSE_FINISH_REASON,
4267
+ String(response.stop_reason)
4268
+ );
4269
+ span2.setAttribute("gen_ai.response.finish_reason", String(response.stop_reason));
4270
+ }
3923
4271
  const choices = response.choices;
3924
- if (!Array.isArray(choices) || choices.length === 0) return;
3925
- const reason = choices[0].finish_reason ?? choices[0].finishReason;
3926
- if (reason) {
3927
- span2.setAttribute("gen_ai.response.finish_reason", String(reason));
3928
- span2.setAttribute("llm.response.finish_reason", String(reason));
4272
+ if (Array.isArray(choices) && choices.length > 0) {
4273
+ const reason = choices[0].finish_reason ?? choices[0].finishReason;
4274
+ if (reason) {
4275
+ span2.setAttribute(SpanAttributes2.LLM_RESPONSE_FINISH_REASON, String(reason));
4276
+ span2.setAttribute("gen_ai.response.finish_reason", String(reason));
4277
+ }
3929
4278
  }
3930
4279
  }
3931
4280
  function setUsageAttributes(span2, response) {
@@ -3952,11 +4301,18 @@ function setUsageAttributes(span2, response) {
3952
4301
  Number(totalTokens)
3953
4302
  );
3954
4303
  }
3955
- const cacheTokens = (usage.prompt_tokens_details ?? usage.input_tokens_details)?.cached_tokens;
3956
- if (cacheTokens !== void 0) {
4304
+ const cacheReadTokens = usage.cache_read_input_tokens ?? (usage.prompt_tokens_details ?? usage.input_tokens_details)?.cached_tokens;
4305
+ if (cacheReadTokens !== void 0) {
3957
4306
  span2.setAttribute(
3958
4307
  SpanAttributes2.LLM_USAGE_CACHE_READ_INPUT_TOKENS,
3959
- Number(cacheTokens)
4308
+ Number(cacheReadTokens)
4309
+ );
4310
+ }
4311
+ const cacheCreationTokens = usage.cache_creation_input_tokens;
4312
+ if (cacheCreationTokens !== void 0) {
4313
+ span2.setAttribute(
4314
+ SpanAttributes2.LLM_USAGE_CACHE_CREATION_INPUT_TOKENS,
4315
+ Number(cacheCreationTokens)
3960
4316
  );
3961
4317
  }
3962
4318
  const reasoningTokens = (usage.completion_tokens_details ?? usage.output_tokens_details)?.reasoning_tokens;
@@ -3978,188 +4334,181 @@ function setEmbeddingResponseMeta(span2, response) {
3978
4334
  }
3979
4335
  }
3980
4336
 
3981
- // src/instrumentation/anthropic/utils.ts
3982
- function setRequestAttributes2(span2, kwargs, requestType) {
3983
- if (!span2.isRecording()) {
3984
- Logger.log("Span is not recording");
3985
- return;
3986
- }
3987
- setRequestAttributes(span2, kwargs, requestType, "anthropic");
3988
- }
3989
- function setResponseAttributes2(span2, response) {
3990
- if (!span2.isRecording()) {
3991
- Logger.log("Span is not recording");
3992
- return;
3993
- }
3994
- if (response?.type === "message_batch") {
3995
- span2.setAttribute("status", response?.processing_status);
3996
- }
3997
- setResponseAttributes(span2, response);
3998
- }
4337
+ // src/instrumentation/anthropic/types.ts
4338
+ var SPAN_NAMES = {
4339
+ CHAT: "anthropic.chat",
4340
+ STREAM: "anthropic.stream",
4341
+ BATCHES: "anthropic.batches",
4342
+ BETA: "anthropic.beta",
4343
+ BETA_STREAM: "anthropic.beta.stream",
4344
+ BETA_TOOL_RUNNER: "anthropic.beta.tool.runner"
4345
+ };
3999
4346
 
4000
- // src/instrumentation/anthropic/version.ts
4001
- var __version__ = "1.0.0";
4002
- var CHAT_SPAN_NAME = "anthropic.chat";
4003
- var BETA_SPAN_NAME = "anthropic.beta";
4004
- var BATCHES_SPAN_NAME = "anthropic.batches";
4005
- var STREAM_ENABLED_REQUESTS = ["chat", "beta"];
4006
- function anthropicWrapper(tracer, spanName, requestType) {
4007
- return function wrapper(wrapped, instance, args, kwargs) {
4008
- if (shouldSuppressInstrumentation()) {
4009
- const result = wrapped.call(instance, ...args);
4010
- return isPromise(result) ? result.then((value) => value) : result;
4011
- }
4012
- const currentContext = context.active();
4013
- const isStreaming = args[0]?.stream === true;
4014
- const activeSpan = trace.getSpan(context.active());
4015
- Logger.debug(`Anthropic invoke (${requestType}). Active TraceId: ${activeSpan?.spanContext().traceId}, SpanId: ${activeSpan?.spanContext().spanId}`);
4016
- if (isStreaming && STREAM_ENABLED_REQUESTS.includes(requestType)) {
4017
- const span2 = tracer.startSpan(
4018
- spanName + ".create",
4019
- {
4020
- kind: SpanKind.CLIENT,
4021
- attributes: {
4022
- "llm.request.type": requestType,
4023
- "llm.streaming": true
4024
- }
4025
- },
4026
- currentContext
4027
- );
4028
- try {
4029
- setRequestAttributes2(span2, kwargs, requestType);
4030
- const startTime = Date.now();
4031
- const spanContext = trace.setSpan(currentContext, span2);
4032
- const response = context.with(spanContext, () => wrapped.call(instance, ...args));
4033
- if (isPromise(response)) {
4034
- return (async () => {
4035
- try {
4036
- const stream = await response;
4037
- return new AsyncStreamingWrapper(span2, stream, startTime, kwargs, spanContext);
4038
- } catch (error) {
4039
- Logger.error("netra.instrumentation.anthropic:", error);
4040
- span2.setStatus({
4041
- code: SpanStatusCode.ERROR,
4042
- message: error instanceof Error ? error.message : String(error)
4043
- });
4044
- span2.recordException(error);
4045
- span2.end();
4046
- throw error;
4047
- }
4048
- })();
4049
- } else {
4050
- return new AsyncStreamingWrapper(span2, response, startTime, kwargs, spanContext);
4347
+ // src/instrumentation/anthropic/utils.ts
4348
+ function processStreamChunk(completeResponse, chunk, span2) {
4349
+ try {
4350
+ switch (chunk.type) {
4351
+ case "message_start": {
4352
+ if (chunk.message?.model) {
4353
+ completeResponse.model = chunk.message.model;
4051
4354
  }
4052
- } catch (error) {
4053
- Logger.error("netra.instrumentation.anthropic:", error);
4054
- span2.setStatus({
4055
- code: SpanStatusCode.ERROR,
4056
- message: error instanceof Error ? error.message : String(error)
4057
- });
4058
- span2.recordException(error);
4059
- span2.end();
4060
- throw error;
4355
+ if (chunk.message?.usage) {
4356
+ completeResponse.usage = chunk.message.usage;
4357
+ }
4358
+ break;
4061
4359
  }
4062
- } else {
4063
- return tracer.startActiveSpan(
4064
- spanName,
4065
- {
4066
- kind: SpanKind.CLIENT,
4067
- attributes: { "llm.request.type": requestType }
4068
- },
4069
- (span2) => {
4070
- try {
4071
- setRequestAttributes2(span2, kwargs, requestType);
4072
- const startTime = Date.now();
4073
- const spanContext = trace.setSpan(currentContext, span2);
4074
- const response = context.with(spanContext, () => wrapped.call(instance, ...args));
4075
- if (isPromise(response)) {
4076
- const instrumentedPromise = (async () => {
4077
- try {
4078
- const value = await response;
4079
- const endTime = Date.now();
4080
- const responseDict = modelAsDict(value);
4081
- setResponseAttributes2(span2, responseDict);
4082
- span2.setAttribute(
4083
- "llm.response.duration",
4084
- (endTime - startTime) / 1e3
4085
- );
4086
- span2.setStatus({ code: SpanStatusCode.OK });
4087
- span2.end();
4088
- return value;
4089
- } catch (error) {
4090
- Logger.error("netra.instrumentation.anthropic:", error);
4091
- span2.setStatus({
4092
- code: SpanStatusCode.ERROR,
4093
- message: error instanceof Error ? error.message : String(error)
4094
- });
4095
- span2.recordException(error);
4096
- span2.end();
4097
- throw error;
4098
- }
4099
- })();
4100
- return new Proxy(instrumentedPromise, {
4101
- get(target, prop, receiver) {
4102
- if (prop === "then" || prop === "catch" || prop === "finally") {
4103
- const value2 = Reflect.get(target, prop, receiver);
4104
- if (typeof value2 === "function") {
4105
- return value2.bind(target);
4106
- }
4107
- return value2;
4108
- }
4109
- const responseValue = response[prop];
4110
- if (responseValue !== void 0) {
4111
- if (typeof responseValue === "function") {
4112
- return responseValue.bind(response);
4113
- }
4114
- return responseValue;
4115
- }
4116
- const value = Reflect.get(target, prop, receiver);
4117
- if (typeof value === "function") {
4118
- return value.bind(target);
4119
- }
4120
- return value;
4121
- }
4122
- });
4123
- } else {
4124
- const endTime = Date.now();
4125
- const responseDict = modelAsDict(response);
4126
- setResponseAttributes2(span2, responseDict);
4127
- span2.setAttribute(
4128
- "llm.response.duration",
4129
- (endTime - startTime) / 1e3
4360
+ case "content_block_start": {
4361
+ if (!completeResponse.content) {
4362
+ completeResponse.content = [];
4363
+ }
4364
+ const block = chunk.content_block;
4365
+ if (!block) break;
4366
+ if (block.type === "tool_use") {
4367
+ completeResponse.content.push({
4368
+ type: "tool_use",
4369
+ id: block.id,
4370
+ name: block.name,
4371
+ input: ""
4372
+ });
4373
+ } else {
4374
+ completeResponse.content.push({
4375
+ type: block.type,
4376
+ text: ""
4377
+ });
4378
+ }
4379
+ break;
4380
+ }
4381
+ case "content_block_delta": {
4382
+ if (!completeResponse.content || completeResponse.content.length === 0) {
4383
+ completeResponse.content = [{ type: "text", text: "" }];
4384
+ }
4385
+ const targetIndex = chunk.index ?? completeResponse.content.length - 1;
4386
+ const targetBlock = completeResponse.content[targetIndex];
4387
+ if (!targetBlock) break;
4388
+ if (chunk.delta?.type === "input_json_delta" && targetBlock.type === "tool_use") {
4389
+ targetBlock.input += chunk.delta.partial_json ?? "";
4390
+ } else if (chunk.delta?.text) {
4391
+ targetBlock.text += chunk.delta.text;
4392
+ }
4393
+ break;
4394
+ }
4395
+ case "content_block_stop": {
4396
+ const blocks = completeResponse.content;
4397
+ if (blocks && blocks.length > 0) {
4398
+ const finishedBlock = blocks[blocks.length - 1];
4399
+ if (finishedBlock?.type === "tool_use" && typeof finishedBlock.input === "string") {
4400
+ try {
4401
+ finishedBlock.input = JSON.parse(finishedBlock.input);
4402
+ } catch {
4403
+ Logger.warn(
4404
+ "netra.instrumentation.anthropic: Failed to parse tool use input"
4130
4405
  );
4131
- span2.setStatus({ code: SpanStatusCode.OK });
4132
- span2.end();
4133
- return response;
4134
4406
  }
4135
- } catch (error) {
4136
- Logger.error("netra.instrumentation.anthropic:", error);
4137
- span2.setStatus({
4138
- code: SpanStatusCode.ERROR,
4139
- message: error instanceof Error ? error.message : String(error)
4140
- });
4141
- span2.recordException(error);
4142
- span2.end();
4143
- throw error;
4144
4407
  }
4145
4408
  }
4146
- );
4409
+ break;
4410
+ }
4411
+ case "message_delta": {
4412
+ if (chunk.delta?.stop_reason) {
4413
+ completeResponse.stop_reason = chunk.delta.stop_reason;
4414
+ }
4415
+ const usageData = chunk.usage ?? chunk.delta?.usage;
4416
+ if (usageData) {
4417
+ completeResponse.usage = {
4418
+ ...completeResponse.usage ?? {},
4419
+ ...usageData
4420
+ };
4421
+ }
4422
+ break;
4423
+ }
4424
+ case "message_stop": {
4425
+ if (chunk.usage) {
4426
+ completeResponse.usage = {
4427
+ ...completeResponse.usage ?? {},
4428
+ ...chunk.usage
4429
+ };
4430
+ }
4431
+ break;
4432
+ }
4147
4433
  }
4148
- };
4434
+ if (Logger.isDebugMode()) {
4435
+ span2.addEvent("llm.content.completion.chunk", {
4436
+ "chunk.type": chunk.type
4437
+ });
4438
+ }
4439
+ } catch (e) {
4440
+ Logger.error(
4441
+ "netra.instrumentation.anthropic: processStreamChunk error",
4442
+ e
4443
+ );
4444
+ }
4149
4445
  }
4150
- var chatWrapper = (tracer) => anthropicWrapper(tracer, CHAT_SPAN_NAME, "chat");
4151
- var betaWrapper = (tracer) => anthropicWrapper(tracer, BETA_SPAN_NAME, "beta");
4152
- var batchesWrapper = (tracer) => anthropicWrapper(tracer, BATCHES_SPAN_NAME, "batches");
4446
+ function finalizeStreamSpan(span2, completeResponse, startTime, code) {
4447
+ try {
4448
+ const endTime = Date.now();
4449
+ setResponseAttributes2(span2, {
4450
+ model: completeResponse.model,
4451
+ content: completeResponse.content,
4452
+ usage: completeResponse.usage,
4453
+ stop_reason: completeResponse.stop_reason
4454
+ });
4455
+ span2.setAttribute("llm.response.duration", (endTime - startTime) / 1e3);
4456
+ span2.setStatus({ code });
4457
+ } catch (e) {
4458
+ Logger.error(
4459
+ "netra.instrumentation.anthropic: finalizeStreamSpan error",
4460
+ e
4461
+ );
4462
+ } finally {
4463
+ span2.end();
4464
+ }
4465
+ }
4466
+ function setRequestAttributes2(span2, kwargs, requestType) {
4467
+ try {
4468
+ if (!span2.isRecording()) {
4469
+ Logger.log("Span is not recording");
4470
+ return;
4471
+ }
4472
+ setRequestAttributes(span2, kwargs, requestType, "anthropic");
4473
+ } catch (e) {
4474
+ Logger.error(
4475
+ "netra.instrumentation.anthropic: setRequestAttributes error",
4476
+ e
4477
+ );
4478
+ }
4479
+ }
4480
+ function setResponseAttributes2(span2, response) {
4481
+ try {
4482
+ if (!span2.isRecording()) {
4483
+ Logger.log("Span is not recording");
4484
+ return;
4485
+ }
4486
+ if (response?.type === "message_batch") {
4487
+ span2.setAttribute("status", response?.processing_status);
4488
+ }
4489
+ setResponseAttributes(span2, response);
4490
+ } catch (e) {
4491
+ Logger.error(
4492
+ "netra.instrumentation.anthropic: setResponseAttributes error",
4493
+ e
4494
+ );
4495
+ }
4496
+ }
4497
+
4498
+ // src/instrumentation/anthropic/wrappers.ts
4153
4499
  var WRAPPER_OWN_PROPS = /* @__PURE__ */ new Set([
4154
4500
  "span",
4155
4501
  "messageStream",
4156
4502
  "startTime",
4157
4503
  "requestKwargs",
4158
4504
  "completeResponse",
4159
- "processChunk",
4160
- "finalizeSpan",
4505
+ "finalizeSpanOnce",
4161
4506
  "processEventData",
4162
- "finalizeSpanFromMessage"
4507
+ "finalizeSpanFromMessage",
4508
+ "parentContext",
4509
+ "spanFinalized",
4510
+ "completionPending",
4511
+ "listenerMap"
4163
4512
  ]);
4164
4513
  var EVENT_EMITTER_METHODS = /* @__PURE__ */ new Set([
4165
4514
  "on",
@@ -4173,20 +4522,90 @@ var EVENT_EMITTER_METHODS = /* @__PURE__ */ new Set([
4173
4522
  "listenerCount"
4174
4523
  ]);
4175
4524
  var LISTENER_REGISTRATION_METHODS = /* @__PURE__ */ new Set(["on", "once", "addListener"]);
4525
+ var LISTENER_REMOVAL_METHODS = /* @__PURE__ */ new Set(["off", "removeListener"]);
4176
4526
  var COMPLETION_METHODS = /* @__PURE__ */ new Set(["finalMessage", "done", "finalText"]);
4177
- var TRACKED_STREAM_EVENTS = /* @__PURE__ */ new Set(["message", "contentBlock", "text", "finalMessage"]);
4527
+ var TRACKED_STREAM_EVENTS = /* @__PURE__ */ new Set([
4528
+ "message",
4529
+ "contentBlock",
4530
+ "text",
4531
+ "finalMessage"
4532
+ ]);
4533
+ var MAX_TOOL_ATTR_LENGTH = 4096;
4534
+ function wrapRunnableTools(tools, tracer, parentContext) {
4535
+ return tools.map((tool) => {
4536
+ if (typeof tool.run !== "function") return tool;
4537
+ const originalRun = tool.run;
4538
+ const toolName = tool.name ?? "unknown_tool";
4539
+ const wrappedRun = async function(input, runContext) {
4540
+ const toolUseId = runContext?.toolUse?.id ?? runContext?.toolUseBlock?.id;
4541
+ const traceContent = isTraceContentEnabled();
4542
+ const attrs = {
4543
+ "netra.span.type": "TOOL",
4544
+ [SpanAttributes2.LLM_REQUEST_TOOL_NAME]: toolName
4545
+ };
4546
+ if (toolUseId) attrs[SpanAttributes2.LLM_REQUEST_TOOL_ID] = toolUseId;
4547
+ if (traceContent) {
4548
+ attrs.input = safeStringify(input, MAX_TOOL_ATTR_LENGTH);
4549
+ }
4550
+ const span2 = tracer.startSpan(
4551
+ toolName,
4552
+ { kind: SpanKind.INTERNAL, attributes: attrs },
4553
+ parentContext
4554
+ );
4555
+ const spanCtx = trace.setSpan(parentContext, span2);
4556
+ try {
4557
+ const result = await context.with(
4558
+ spanCtx,
4559
+ () => originalRun.call(this, input, runContext)
4560
+ );
4561
+ if (traceContent) {
4562
+ span2.setAttribute(
4563
+ "output",
4564
+ safeStringify(result, MAX_TOOL_ATTR_LENGTH)
4565
+ );
4566
+ }
4567
+ span2.setStatus({ code: SpanStatusCode.OK });
4568
+ return result;
4569
+ } catch (error) {
4570
+ span2.setStatus({
4571
+ code: SpanStatusCode.ERROR,
4572
+ message: error instanceof Error ? error.message : String(error)
4573
+ });
4574
+ span2.recordException(error);
4575
+ throw error;
4576
+ } finally {
4577
+ span2.end();
4578
+ }
4579
+ };
4580
+ const wrapped = Object.create(
4581
+ Object.getPrototypeOf(tool),
4582
+ Object.getOwnPropertyDescriptors(tool)
4583
+ );
4584
+ wrapped.run = wrappedRun;
4585
+ return wrapped;
4586
+ });
4587
+ }
4178
4588
  var MessageStreamWrapper = class {
4179
- constructor(span2, messageStream, startTime, requestKwargs, spanContext) {
4589
+ constructor(span2, messageStream, startTime, requestKwargs, spanContext, parentContext) {
4180
4590
  this.completeResponse = {
4181
4591
  content: [],
4182
4592
  model: "",
4183
4593
  usage: {}
4184
4594
  };
4595
+ this.spanFinalized = false;
4596
+ this.completionPending = false;
4597
+ this.listenerMap = /* @__PURE__ */ new WeakMap();
4185
4598
  defineHidden(this, "span", span2);
4186
4599
  defineHidden(this, "messageStream", messageStream);
4187
4600
  defineHidden(this, "startTime", startTime);
4188
4601
  defineHidden(this, "requestKwargs", requestKwargs);
4189
- defineHidden(this, "spanContext", spanContext || trace.setSpan(context.active(), span2));
4602
+ defineHidden(
4603
+ this,
4604
+ "spanContext",
4605
+ spanContext || trace.setSpan(context.active(), span2)
4606
+ );
4607
+ defineHidden(this, "parentContext", parentContext || context.active());
4608
+ this.registerSafetyNetListeners();
4190
4609
  return new Proxy(this, {
4191
4610
  get(target, prop, receiver) {
4192
4611
  if (prop === "toJSON") {
@@ -4200,67 +4619,135 @@ var MessageStreamWrapper = class {
4200
4619
  }
4201
4620
  if (typeof prop === "string" && EVENT_EMITTER_METHODS.has(prop)) {
4202
4621
  const method = target.messageStream[prop];
4203
- if (typeof method === "function") {
4204
- if (LISTENER_REGISTRATION_METHODS.has(prop)) {
4205
- return function(event, listener) {
4206
- const wrappedListener = (...args) => {
4622
+ if (typeof method !== "function") return method;
4623
+ if (LISTENER_REGISTRATION_METHODS.has(prop)) {
4624
+ return function(event, listener) {
4625
+ const wrappedListener = (...args) => {
4626
+ try {
4207
4627
  target.span.addEvent(`messagestream.event.${event}`, {
4208
4628
  "event.type": event
4209
4629
  });
4210
- if (TRACKED_STREAM_EVENTS.has(event)) {
4211
- if (args[0]) {
4212
- target.processEventData(event, args[0]);
4213
- }
4630
+ if (TRACKED_STREAM_EVENTS.has(event) && args[0]) {
4631
+ target.processEventData(event, args[0]);
4214
4632
  }
4215
- return listener(...args);
4216
- };
4217
- return method.call(target.messageStream, event, wrappedListener);
4633
+ } catch (e) {
4634
+ Logger.error(
4635
+ "netra.instrumentation.anthropic: event tracking error",
4636
+ e
4637
+ );
4638
+ }
4639
+ return listener(...args);
4218
4640
  };
4219
- }
4220
- return method.bind(target.messageStream);
4641
+ let eventMap = target.listenerMap.get(listener);
4642
+ if (!eventMap) {
4643
+ eventMap = /* @__PURE__ */ new Map();
4644
+ target.listenerMap.set(listener, eventMap);
4645
+ }
4646
+ let wrappers = eventMap.get(event);
4647
+ if (!wrappers) {
4648
+ wrappers = [];
4649
+ eventMap.set(event, wrappers);
4650
+ }
4651
+ wrappers.push(wrappedListener);
4652
+ return method.call(target.messageStream, event, wrappedListener);
4653
+ };
4654
+ }
4655
+ if (LISTENER_REMOVAL_METHODS.has(prop)) {
4656
+ return function(event, listener) {
4657
+ const eventMap = target.listenerMap.get(listener);
4658
+ const wrappers = eventMap?.get(event);
4659
+ const wrapped = wrappers?.shift() ?? listener;
4660
+ if (wrappers && wrappers.length === 0) eventMap?.delete(event);
4661
+ return method.call(target.messageStream, event, wrapped);
4662
+ };
4221
4663
  }
4222
- return method;
4664
+ if (prop === "removeAllListeners") {
4665
+ return function(event) {
4666
+ target.listenerMap = /* @__PURE__ */ new WeakMap();
4667
+ return method.call(target.messageStream, event);
4668
+ };
4669
+ }
4670
+ return method.bind(target.messageStream);
4223
4671
  }
4224
4672
  if (typeof prop === "string" && COMPLETION_METHODS.has(prop)) {
4225
4673
  const method = target.messageStream[prop];
4226
- if (typeof method === "function") {
4227
- return async function(...args) {
4228
- try {
4229
- const result = await method.call(target.messageStream, ...args);
4230
- if (prop === "finalMessage" || prop === "done") {
4231
- target.finalizeSpanFromMessage(result);
4674
+ if (typeof method !== "function") return method;
4675
+ return async function(...args) {
4676
+ target.completionPending = true;
4677
+ try {
4678
+ const result = await method.call(target.messageStream, ...args);
4679
+ if (prop === "finalMessage" || prop === "done") {
4680
+ target.finalizeSpanFromMessage(result);
4681
+ } else if (prop === "finalText") {
4682
+ if (typeof result === "string" && result.length > 0) {
4683
+ target.completeResponse.content = [
4684
+ { type: "text", text: result }
4685
+ ];
4686
+ } else {
4687
+ target.flushCurrentText();
4232
4688
  }
4233
- return result;
4234
- } catch (error) {
4235
- target.finalizeSpan(SpanStatusCode.ERROR);
4236
- throw error;
4689
+ target.finalizeSpanOnce(SpanStatusCode.OK);
4237
4690
  }
4238
- };
4239
- }
4240
- return method;
4691
+ return result;
4692
+ } catch (error) {
4693
+ target.finalizeSpanOnce(SpanStatusCode.ERROR);
4694
+ throw error;
4695
+ }
4696
+ };
4241
4697
  }
4242
4698
  const value = target.messageStream[prop];
4243
- if (typeof value === "function") {
4699
+ if (typeof value === "function")
4244
4700
  return value.bind(target.messageStream);
4245
- }
4246
4701
  return value;
4247
4702
  }
4248
4703
  });
4249
4704
  }
4705
+ registerSafetyNetListeners() {
4706
+ try {
4707
+ if (typeof this.messageStream?.on !== "function") return;
4708
+ this.messageStream.on("end", () => {
4709
+ if (!this.completionPending) {
4710
+ this.finalizeSpanOnce(SpanStatusCode.OK);
4711
+ }
4712
+ });
4713
+ this.messageStream.on("error", (err) => {
4714
+ if (err && !this.spanFinalized) {
4715
+ this.span.setStatus({
4716
+ code: SpanStatusCode.ERROR,
4717
+ message: err instanceof Error ? err.message : String(err)
4718
+ });
4719
+ this.span.recordException(
4720
+ err instanceof Error ? err : new Error(String(err))
4721
+ );
4722
+ }
4723
+ this.finalizeSpanOnce(SpanStatusCode.ERROR);
4724
+ });
4725
+ } catch (e) {
4726
+ Logger.error(
4727
+ "netra.instrumentation.anthropic: safety net listener registration failed",
4728
+ e
4729
+ );
4730
+ }
4731
+ }
4250
4732
  toJSON() {
4251
4733
  return this.completeResponse;
4252
4734
  }
4253
4735
  async *[Symbol.asyncIterator]() {
4736
+ let errorOccurred = false;
4254
4737
  try {
4255
4738
  for await (const chunk of this.messageStream) {
4256
- this.processChunk(chunk);
4739
+ processStreamChunk(this.completeResponse, chunk, this.span);
4257
4740
  yield chunk;
4258
4741
  }
4259
- this.finalizeSpan(SpanStatusCode.OK);
4260
4742
  } catch (err) {
4743
+ errorOccurred = true;
4261
4744
  Logger.error("netra.instrumentation.anthropic: Stream error", err);
4262
- this.finalizeSpan(SpanStatusCode.ERROR);
4745
+ this.finalizeSpanOnce(SpanStatusCode.ERROR);
4263
4746
  throw err;
4747
+ } finally {
4748
+ if (!errorOccurred) {
4749
+ this.finalizeSpanOnce(SpanStatusCode.OK);
4750
+ }
4264
4751
  }
4265
4752
  }
4266
4753
  getSpanContext() {
@@ -4269,12 +4756,8 @@ var MessageStreamWrapper = class {
4269
4756
  processEventData(eventType, data) {
4270
4757
  switch (eventType) {
4271
4758
  case "message":
4272
- if (data.model) {
4273
- this.completeResponse.model = data.model;
4274
- }
4275
- if (data.usage) {
4276
- this.completeResponse.usage = data.usage;
4277
- }
4759
+ if (data.model) this.completeResponse.model = data.model;
4760
+ if (data.usage) this.completeResponse.usage = data.usage;
4278
4761
  break;
4279
4762
  case "text":
4280
4763
  if (!this.completeResponse.currentText) {
@@ -4295,250 +4778,359 @@ var MessageStreamWrapper = class {
4295
4778
  break;
4296
4779
  }
4297
4780
  }
4298
- processChunk(chunk) {
4299
- switch (chunk.type) {
4300
- case "message_start": {
4301
- if (chunk.message?.model) {
4302
- this.completeResponse.model = chunk.message.model;
4303
- }
4304
- if (chunk.message?.usage) {
4305
- this.completeResponse.usage = chunk.message.usage;
4306
- }
4307
- break;
4308
- }
4309
- case "content_block_start": {
4310
- if (!this.completeResponse.content) {
4311
- this.completeResponse.content = [];
4312
- }
4313
- const block = chunk.content_block;
4314
- if (block.type === "tool_use") {
4315
- this.completeResponse.content.push({
4316
- type: "tool_use",
4317
- id: block.id,
4318
- name: block.name,
4319
- input: ""
4320
- });
4321
- } else {
4322
- this.completeResponse.content.push({
4323
- type: block.type,
4324
- text: ""
4325
- });
4326
- }
4327
- break;
4328
- }
4329
- case "content_block_delta": {
4330
- if (!this.completeResponse.content || this.completeResponse.content.length === 0) {
4331
- this.completeResponse.content = [{ type: "text", text: "" }];
4332
- }
4333
- const lastBlock = this.completeResponse.content[this.completeResponse.content.length - 1];
4334
- if (chunk.delta?.type === "input_json_delta" && lastBlock?.type === "tool_use") {
4335
- lastBlock.input += chunk.delta.partial_json ?? "";
4336
- } else if (lastBlock && chunk.delta?.text) {
4337
- lastBlock.text += chunk.delta.text;
4338
- }
4339
- break;
4340
- }
4341
- case "content_block_stop": {
4342
- const blocks = this.completeResponse.content;
4343
- if (blocks && blocks.length > 0) {
4344
- const finishedBlock = blocks[blocks.length - 1];
4345
- if (finishedBlock?.type === "tool_use" && typeof finishedBlock.input === "string") {
4346
- try {
4347
- finishedBlock.input = JSON.parse(finishedBlock.input);
4348
- } catch {
4349
- Logger.warn("netra.instrumentation.anthropic: Failed to parse tool use input", finishedBlock.input);
4350
- }
4351
- }
4352
- }
4353
- break;
4354
- }
4355
- case "message_delta": {
4356
- if (chunk.delta?.usage) {
4357
- this.completeResponse.usage = {
4358
- ...this.completeResponse.usage,
4359
- ...chunk.delta.usage
4360
- };
4361
- }
4362
- break;
4363
- }
4364
- case "message_stop": {
4365
- if (chunk.usage) {
4366
- this.completeResponse.usage = chunk.usage;
4367
- }
4368
- break;
4369
- }
4781
+ flushCurrentText() {
4782
+ if (this.completeResponse.currentText && (!this.completeResponse.content || this.completeResponse.content.length === 0)) {
4783
+ this.completeResponse.content = [
4784
+ { type: "text", text: this.completeResponse.currentText }
4785
+ ];
4370
4786
  }
4371
- this.span.addEvent("llm.content.completion.chunk", {
4372
- "chunk.type": chunk.type
4373
- });
4374
4787
  }
4375
4788
  finalizeSpanFromMessage(message) {
4376
4789
  if (message) {
4377
4790
  if (message.model) this.completeResponse.model = message.model;
4378
4791
  if (message.content) this.completeResponse.content = message.content;
4379
4792
  if (message.usage) this.completeResponse.usage = message.usage;
4793
+ if (message.stop_reason)
4794
+ this.completeResponse.stop_reason = message.stop_reason;
4380
4795
  }
4381
- this.finalizeSpan(SpanStatusCode.OK);
4796
+ this.finalizeSpanOnce(SpanStatusCode.OK);
4382
4797
  }
4383
- finalizeSpan(code) {
4384
- const endTime = Date.now();
4385
- const duration = (endTime - this.startTime) / 1e3;
4386
- setResponseAttributes2(this.span, {
4387
- model: this.completeResponse.model,
4388
- content: this.completeResponse.content,
4389
- usage: this.completeResponse.usage
4390
- });
4391
- this.span.setAttribute("llm.response.duration", duration);
4392
- this.span.setStatus({ code });
4393
- this.span.end();
4798
+ finalizeSpanOnce(code) {
4799
+ if (this.spanFinalized) return;
4800
+ this.spanFinalized = true;
4801
+ finalizeStreamSpan(this.span, this.completeResponse, this.startTime, code);
4394
4802
  }
4395
4803
  };
4396
- var AsyncStreamingWrapper = class {
4397
- constructor(span2, response, startTime, requestKwargs, spanContext) {
4398
- this.iterator = null;
4399
- this.completeResponse = {
4400
- choices: [],
4401
- model: ""
4402
- };
4403
- defineHidden(this, "span", span2);
4404
- defineHidden(this, "response", response);
4405
- defineHidden(this, "startTime", startTime);
4406
- defineHidden(this, "requestKwargs", requestKwargs);
4407
- defineHidden(this, "spanContext", spanContext || trace.setSpan(context.active(), span2));
4408
- }
4409
- toJSON() {
4410
- return this.completeResponse;
4411
- }
4412
- [Symbol.asyncIterator]() {
4413
- return this;
4414
- }
4415
- async next() {
4416
- try {
4417
- if (!this.iterator) {
4418
- if (Symbol.asyncIterator in this.response) {
4419
- this.iterator = this.response[Symbol.asyncIterator]();
4420
- } else if (typeof this.response.next === "function") {
4421
- this.iterator = this.response;
4422
- } else {
4423
- throw new Error("Response is not iterable");
4424
- }
4425
- }
4426
- const result = await context.with(this.spanContext, () => this.iterator.next());
4427
- if (result.done) {
4428
- this.finalizeSpan(SpanStatusCode.OK);
4429
- return result;
4430
- }
4431
- this.processChunk(result.value);
4432
- return result;
4433
- } catch (error) {
4434
- this.finalizeSpan(SpanStatusCode.ERROR);
4435
- throw error;
4436
- }
4437
- }
4438
- processChunk(chunk) {
4439
- switch (chunk.type) {
4440
- case "message_start": {
4441
- if (chunk.message?.model) {
4442
- this.completeResponse.model = chunk.message.model;
4443
- }
4444
- if (chunk.message?.usage) {
4445
- this.completeResponse.usage = chunk.message.usage;
4446
- }
4447
- break;
4448
- }
4449
- case "content_block_start": {
4450
- const content = this.completeResponse.content || [];
4451
- this.completeResponse.content = content;
4452
- const block = chunk.content_block;
4453
- if (block.type === "tool_use") {
4454
- content.push({
4455
- type: "tool_use",
4456
- id: block.id,
4457
- name: block.name,
4458
- input: ""
4459
- });
4460
- } else {
4461
- content.push({
4462
- type: block.type,
4463
- text: ""
4464
- });
4465
- }
4466
- break;
4804
+ function anthropicWrapper(tracer, spanName, requestType) {
4805
+ return function wrapper(original) {
4806
+ return function(...args) {
4807
+ if (shouldSuppressInstrumentation()) {
4808
+ return original.apply(this, args);
4467
4809
  }
4468
- case "content_block_delta": {
4469
- const content = this.completeResponse.content || [];
4470
- if (content.length === 0) {
4471
- content.push({ type: "text", text: "" });
4472
- this.completeResponse.content = content;
4473
- }
4474
- const lastBlock = content[content.length - 1];
4475
- if (chunk.delta?.type === "input_json_delta" && lastBlock?.type === "tool_use") {
4476
- lastBlock.input += chunk.delta.partial_json ?? "";
4477
- } else if (lastBlock && chunk.delta?.text) {
4478
- lastBlock.text += chunk.delta.text;
4810
+ const attributes = args[0] || {};
4811
+ const currentContext = context.active();
4812
+ const isStreaming = attributes.stream === true;
4813
+ const activeSpan = trace.getSpan(currentContext);
4814
+ Logger.debug(
4815
+ `Anthropic invoke (${requestType}). Active TraceId: ${activeSpan?.spanContext().traceId}, SpanId: ${activeSpan?.spanContext().spanId}`
4816
+ );
4817
+ return tracer.startActiveSpan(
4818
+ spanName,
4819
+ {
4820
+ kind: SpanKind.CLIENT,
4821
+ attributes: { "llm.request.type": requestType }
4822
+ },
4823
+ (span2) => {
4824
+ try {
4825
+ setRequestAttributes2(span2, attributes, requestType);
4826
+ if (isStreaming) {
4827
+ span2.setAttribute("llm.streaming", true);
4828
+ }
4829
+ const startTime = Date.now();
4830
+ const spanContext = trace.setSpan(currentContext, span2);
4831
+ const response = context.with(
4832
+ spanContext,
4833
+ () => original.apply(this, args)
4834
+ );
4835
+ const completeResponse = {
4836
+ content: [],
4837
+ model: "",
4838
+ usage: {}
4839
+ };
4840
+ return wrapResponse(
4841
+ response,
4842
+ {
4843
+ withContext: (fn) => context.with(spanContext, fn),
4844
+ onChunk: (chunk) => processStreamChunk(completeResponse, chunk, span2),
4845
+ onError: (error) => {
4846
+ Logger.error("netra.instrumentation.anthropic:", error);
4847
+ span2.setStatus({
4848
+ code: SpanStatusCode.ERROR,
4849
+ message: error instanceof Error ? error.message : String(error)
4850
+ });
4851
+ span2.recordException(error);
4852
+ },
4853
+ onSuccess: (value) => {
4854
+ const endTime = Date.now();
4855
+ const responseDict = modelAsDict(value);
4856
+ setResponseAttributes2(span2, responseDict);
4857
+ span2.setAttribute(
4858
+ "llm.response.duration",
4859
+ (endTime - startTime) / 1e3
4860
+ );
4861
+ },
4862
+ finalize: (status) => {
4863
+ const hasStreamData = completeResponse.content?.length || completeResponse.model || completeResponse.usage?.input_tokens !== void 0 || completeResponse.usage?.output_tokens !== void 0;
4864
+ if (status === "ok" && hasStreamData) {
4865
+ finalizeStreamSpan(
4866
+ span2,
4867
+ completeResponse,
4868
+ startTime,
4869
+ SpanStatusCode.OK
4870
+ );
4871
+ } else {
4872
+ if (status === "ok") {
4873
+ span2.setStatus({ code: SpanStatusCode.OK });
4874
+ }
4875
+ span2.end();
4876
+ }
4877
+ }
4878
+ },
4879
+ { preserveOriginal: response }
4880
+ );
4881
+ } catch (error) {
4882
+ Logger.error("netra.instrumentation.anthropic:", error);
4883
+ span2.setStatus({
4884
+ code: SpanStatusCode.ERROR,
4885
+ message: error instanceof Error ? error.message : String(error)
4886
+ });
4887
+ span2.recordException(error);
4888
+ span2.end();
4889
+ throw error;
4890
+ }
4479
4891
  }
4480
- break;
4892
+ );
4893
+ };
4894
+ };
4895
+ }
4896
+ function streamWrapper(tracer, spanName, requestType, originalCreate) {
4897
+ return function wrapper(original) {
4898
+ return function(...args) {
4899
+ if (shouldSuppressInstrumentation()) {
4900
+ return original.apply(this, args);
4481
4901
  }
4482
- case "content_block_stop": {
4483
- const content = this.completeResponse.content || [];
4484
- if (content.length > 0) {
4485
- const finishedBlock = content[content.length - 1];
4486
- if (finishedBlock?.type === "tool_use" && typeof finishedBlock.input === "string") {
4487
- try {
4488
- finishedBlock.input = JSON.parse(finishedBlock.input);
4489
- } catch {
4490
- Logger.warn("netra.instrumentation.anthropic: Failed to parse tool use input", finishedBlock.input);
4491
- }
4902
+ const attributes = args[0] || {};
4903
+ const currentContext = context.active();
4904
+ const span2 = tracer.startSpan(
4905
+ spanName,
4906
+ {
4907
+ kind: SpanKind.CLIENT,
4908
+ attributes: {
4909
+ "llm.request.type": requestType,
4910
+ "llm.streaming": true,
4911
+ "llm.operation": "stream"
4492
4912
  }
4913
+ },
4914
+ currentContext
4915
+ );
4916
+ const spanContext = trace.setSpan(currentContext, span2);
4917
+ setRequestAttributes2(span2, attributes, requestType);
4918
+ const startTime = Date.now();
4919
+ const callTarget = originalCreate ? new Proxy(this, {
4920
+ get(target, prop) {
4921
+ if (prop === "create") return originalCreate.bind(target);
4922
+ const value = target[prop];
4923
+ if (typeof value === "function") return value.bind(target);
4924
+ return value;
4493
4925
  }
4494
- break;
4926
+ }) : this;
4927
+ try {
4928
+ const messageStream = context.with(
4929
+ spanContext,
4930
+ () => original.call(callTarget, ...args)
4931
+ );
4932
+ return new MessageStreamWrapper(
4933
+ span2,
4934
+ messageStream,
4935
+ startTime,
4936
+ attributes,
4937
+ spanContext,
4938
+ currentContext
4939
+ );
4940
+ } catch (error) {
4941
+ span2.setStatus({
4942
+ code: SpanStatusCode.ERROR,
4943
+ message: error instanceof Error ? error.message : String(error)
4944
+ });
4945
+ span2.recordException(error);
4946
+ span2.end();
4947
+ throw error;
4495
4948
  }
4496
- case "message_delta": {
4497
- if (chunk.delta?.usage) {
4498
- const currentUsage = this.completeResponse.usage || {};
4499
- this.completeResponse.usage = {
4500
- ...currentUsage,
4501
- ...chunk.delta.usage
4502
- };
4503
- }
4504
- break;
4949
+ };
4950
+ };
4951
+ }
4952
+ function toolRunnerWrapper(tracer, spanName, requestType) {
4953
+ return function wrapper(original) {
4954
+ return function(...args) {
4955
+ if (shouldSuppressInstrumentation()) {
4956
+ return original.apply(this, args);
4505
4957
  }
4506
- case "message_stop": {
4507
- if (chunk.usage) {
4508
- this.completeResponse.usage = chunk.usage;
4958
+ const attributes = args[0] || {};
4959
+ const currentContext = context.active();
4960
+ const span2 = tracer.startSpan(
4961
+ spanName,
4962
+ {
4963
+ kind: SpanKind.CLIENT,
4964
+ attributes: {
4965
+ "llm.request.type": requestType,
4966
+ "netra.span.type": "AGENT",
4967
+ "llm.operation": "tool.runner"
4968
+ }
4969
+ },
4970
+ currentContext
4971
+ );
4972
+ let spanEnded = false;
4973
+ const endSpanOnce = (code, error) => {
4974
+ if (spanEnded) return;
4975
+ spanEnded = true;
4976
+ if (error) {
4977
+ span2.setStatus({ code, message: error.message });
4978
+ span2.recordException(error);
4979
+ } else {
4980
+ span2.setStatus({ code });
4509
4981
  }
4510
- break;
4982
+ span2.end();
4983
+ };
4984
+ try {
4985
+ setRequestAttributes2(span2, attributes, "beta");
4986
+ const spanContext = trace.setSpan(currentContext, span2);
4987
+ const wrappedTools = Array.isArray(attributes.tools) ? wrapRunnableTools(attributes.tools, tracer, spanContext) : attributes.tools;
4988
+ const wrappedArgs = [
4989
+ { ...attributes, tools: wrappedTools },
4990
+ ...args.slice(1)
4991
+ ];
4992
+ const runner = context.with(
4993
+ spanContext,
4994
+ () => original.apply(this, wrappedArgs)
4995
+ );
4996
+ if (runner == null) {
4997
+ endSpanOnce(SpanStatusCode.OK);
4998
+ return runner;
4999
+ }
5000
+ return new Proxy(runner, {
5001
+ get(target, prop, receiver) {
5002
+ if (prop === Symbol.asyncIterator) {
5003
+ return function() {
5004
+ const originalIterator = target[Symbol.asyncIterator]();
5005
+ return {
5006
+ [Symbol.asyncIterator]() {
5007
+ return this;
5008
+ },
5009
+ async next() {
5010
+ try {
5011
+ const result = await context.with(
5012
+ spanContext,
5013
+ () => originalIterator.next()
5014
+ );
5015
+ if (result.done) endSpanOnce(SpanStatusCode.OK);
5016
+ return result;
5017
+ } catch (error) {
5018
+ endSpanOnce(SpanStatusCode.ERROR, error);
5019
+ throw error;
5020
+ }
5021
+ },
5022
+ async return(value2) {
5023
+ try {
5024
+ const result = await (originalIterator.return?.(
5025
+ value2
5026
+ ) ?? {
5027
+ done: true,
5028
+ value: value2
5029
+ });
5030
+ return result;
5031
+ } finally {
5032
+ endSpanOnce(SpanStatusCode.OK);
5033
+ }
5034
+ },
5035
+ async throw(error) {
5036
+ const err = error instanceof Error ? error : new Error(String(error));
5037
+ if (originalIterator.throw) {
5038
+ try {
5039
+ const result = await originalIterator.throw(error);
5040
+ if (result.done) {
5041
+ endSpanOnce(SpanStatusCode.ERROR, err);
5042
+ }
5043
+ return result;
5044
+ } catch (e) {
5045
+ endSpanOnce(
5046
+ SpanStatusCode.ERROR,
5047
+ e instanceof Error ? e : new Error(String(e))
5048
+ );
5049
+ throw e;
5050
+ }
5051
+ }
5052
+ endSpanOnce(SpanStatusCode.ERROR, err);
5053
+ throw error;
5054
+ }
5055
+ };
5056
+ };
5057
+ }
5058
+ if (prop === "then" || prop === "catch" || prop === "finally") {
5059
+ const originalMethod = target[prop];
5060
+ if (typeof originalMethod !== "function") return originalMethod;
5061
+ if (prop === "then") {
5062
+ return function(onFulfilled, onRejected) {
5063
+ return originalMethod.call(
5064
+ target,
5065
+ (v) => {
5066
+ endSpanOnce(SpanStatusCode.OK);
5067
+ return onFulfilled ? onFulfilled(v) : v;
5068
+ },
5069
+ (e) => {
5070
+ endSpanOnce(
5071
+ SpanStatusCode.ERROR,
5072
+ e instanceof Error ? e : new Error(String(e))
5073
+ );
5074
+ if (onRejected) return onRejected(e);
5075
+ throw e;
5076
+ }
5077
+ );
5078
+ };
5079
+ }
5080
+ if (prop === "catch") {
5081
+ return function(onRejected) {
5082
+ return receiver.then(void 0, onRejected);
5083
+ };
5084
+ }
5085
+ if (prop === "finally") {
5086
+ return function(onFinally) {
5087
+ return receiver.then(
5088
+ (v) => {
5089
+ onFinally?.();
5090
+ return v;
5091
+ },
5092
+ (e) => {
5093
+ onFinally?.();
5094
+ throw e;
5095
+ }
5096
+ );
5097
+ };
5098
+ }
5099
+ }
5100
+ const value = target[prop];
5101
+ if (typeof value === "function") return value.bind(target);
5102
+ return value;
5103
+ }
5104
+ });
5105
+ } catch (error) {
5106
+ endSpanOnce(
5107
+ SpanStatusCode.ERROR,
5108
+ error instanceof Error ? error : new Error(String(error))
5109
+ );
5110
+ throw error;
4511
5111
  }
4512
- }
4513
- this.span.addEvent("llm.content.completion.chunk", {
4514
- "chunk.type": chunk.type
4515
- });
4516
- }
4517
- finalizeSpan(code) {
4518
- const endTime = Date.now();
4519
- const duration = (endTime - this.startTime) / 1e3;
4520
- setResponseAttributes2(this.span, {
4521
- model: this.completeResponse.model,
4522
- content: this.completeResponse.content,
4523
- usage: this.completeResponse.usage
4524
- });
4525
- this.span.setAttribute("llm.response.duration", duration);
4526
- this.span.setStatus({ code });
4527
- this.span.end();
4528
- }
4529
- };
5112
+ };
5113
+ };
5114
+ }
5115
+ var chatWrapper = (tracer) => anthropicWrapper(tracer, SPAN_NAMES.CHAT, "chat");
5116
+ var betaWrapper = (tracer) => anthropicWrapper(tracer, SPAN_NAMES.BETA, "beta");
5117
+ var batchesWrapper = (tracer) => anthropicWrapper(tracer, SPAN_NAMES.BATCHES, "batches");
5118
+ var chatStreamWrapper = (tracer, originalCreate) => streamWrapper(tracer, SPAN_NAMES.STREAM, "chat", originalCreate);
5119
+ var betaStreamWrapper = (tracer, originalCreate) => streamWrapper(tracer, SPAN_NAMES.BETA_STREAM, "beta", originalCreate);
5120
+ var betaToolRunnerWrapper = (tracer) => toolRunnerWrapper(tracer, SPAN_NAMES.BETA_TOOL_RUNNER, "beta");
4530
5121
 
4531
5122
  // src/instrumentation/anthropic/index.ts
4532
5123
  var INSTRUMENTATION_NAME = "netra.instrumentation.anthropic";
4533
5124
  var INSTRUMENTS = ["anthropic >= 0.71.2"];
4534
- var originalMethods = /* @__PURE__ */ new Map();
4535
5125
  var isInstrumented = false;
4536
5126
  var anthropicClasses = [];
4537
- async function resolveAnthropicAsync() {
5127
+ async function resolveAnthropic() {
4538
5128
  if (anthropicClasses.length > 0) return anthropicClasses;
4539
5129
  try {
4540
5130
  const anthropicModule = await import('@anthropic-ai/sdk');
4541
- anthropicClasses.push(anthropicModule.Anthropic || anthropicModule.default || anthropicModule);
5131
+ anthropicClasses.push(
5132
+ anthropicModule.Anthropic || anthropicModule.default || anthropicModule
5133
+ );
4542
5134
  } catch {
4543
5135
  Logger.warn("Failed to resolve Anthropic ESM module");
4544
5136
  }
@@ -4554,9 +5146,6 @@ async function resolveAnthropicAsync() {
4554
5146
  }
4555
5147
  return anthropicClasses;
4556
5148
  }
4557
- function resolveAnthropic() {
4558
- return anthropicClasses;
4559
- }
4560
5149
  var NetraAnthropicInstrumentor = class {
4561
5150
  constructor() {
4562
5151
  this.tracer = null;
@@ -4564,15 +5153,13 @@ var NetraAnthropicInstrumentor = class {
4564
5153
  instrumentationDependencies() {
4565
5154
  return INSTRUMENTS;
4566
5155
  }
4567
- async instrumentAsync(options = {}) {
5156
+ async instrument(options = {}) {
4568
5157
  if (isInstrumented) {
4569
5158
  Logger.warn("Anthropic is already instrumented");
4570
5159
  return this;
4571
5160
  }
4572
- const classes = await resolveAnthropicAsync();
4573
- if (classes.length === 0) {
4574
- return this;
4575
- }
5161
+ const classes = await resolveAnthropic();
5162
+ if (classes.length === 0) return this;
4576
5163
  try {
4577
5164
  this.tracerProvider = options.tracerProvider;
4578
5165
  if (this.tracerProvider) {
@@ -4587,10 +5174,10 @@ var NetraAnthropicInstrumentor = class {
4587
5174
  Logger.error(`Failed to initialize tracer: ${error}`);
4588
5175
  return this;
4589
5176
  }
4590
- classes.forEach((AnthropicSDK, index) => {
4591
- this._instrumentMessages(AnthropicSDK, index);
4592
- this._instrumentBetaMessages(AnthropicSDK, index);
4593
- this._instrumentBatchMessages(AnthropicSDK, index);
5177
+ classes.forEach((AnthropicSDK) => {
5178
+ this._instrumentMessages(AnthropicSDK);
5179
+ this._instrumentBetaMessages(AnthropicSDK);
5180
+ this._instrumentBatchMessages(AnthropicSDK);
4594
5181
  });
4595
5182
  isInstrumented = true;
4596
5183
  return this;
@@ -4600,185 +5187,137 @@ var NetraAnthropicInstrumentor = class {
4600
5187
  Logger.warn("Anthropic is not instrumented");
4601
5188
  return;
4602
5189
  }
4603
- const classes = resolveAnthropic();
4604
- classes.forEach((AnthropicSDK, index) => {
4605
- this._uninstrumentMessages(AnthropicSDK, index);
4606
- this._uninstrumentBetaMessages(AnthropicSDK, index);
4607
- this._uninstrumentBatchMessages(AnthropicSDK, index);
5190
+ anthropicClasses.forEach((AnthropicSDK) => {
5191
+ this._uninstrumentMessages(AnthropicSDK);
5192
+ this._uninstrumentBetaMessages(AnthropicSDK);
5193
+ this._uninstrumentBatchMessages(AnthropicSDK);
4608
5194
  });
4609
- originalMethods.clear();
4610
5195
  anthropicClasses = [];
4611
5196
  isInstrumented = false;
4612
5197
  }
4613
5198
  isInstrumented() {
4614
5199
  return isInstrumented;
4615
5200
  }
4616
- _instrumentMessages(AnthropicSDK, index) {
5201
+ _instrumentMessages(AnthropicSDK) {
4617
5202
  if (!this.tracer) {
4618
5203
  Logger.warn("Anthropic instrumentation: No tracer available");
4619
5204
  return;
4620
5205
  }
4621
5206
  try {
4622
5207
  const MessagesClass = AnthropicSDK.Messages;
4623
- if (!MessagesClass) {
5208
+ if (!MessagesClass?.prototype) {
4624
5209
  Logger.error(
4625
- "Anthropic instrumentation: Could not find Anthropic Messages class to instrument"
5210
+ "Anthropic instrumentation: Could not find Messages class"
4626
5211
  );
4627
5212
  return;
4628
5213
  }
4629
- if (MessagesClass?.prototype?.stream) {
4630
- const originalStream = MessagesClass.prototype.stream;
4631
- originalMethods.set(`messages.stream-${index}`, originalStream);
4632
- const tracer = this.tracer;
4633
- MessagesClass.prototype.stream = function(...args) {
4634
- const original = originalStream.bind(this);
4635
- const kwargs = args[0] || {};
4636
- const currentContext = context.active();
4637
- const span2 = tracer.startSpan("anthropic.stream", {
4638
- kind: SpanKind.CLIENT,
4639
- attributes: {
4640
- "llm.request.type": "chat",
4641
- "llm.streaming": true,
4642
- "llm.operation": "stream"
4643
- }
4644
- }, currentContext);
4645
- const spanContext = trace.setSpan(currentContext, span2);
4646
- setRequestAttributes2(span2, kwargs, "chat");
4647
- const startTime = Date.now();
4648
- const instrumentedCreate = this.create;
4649
- const originalCreate = originalMethods.get(`messages.create-${index}`);
4650
- if (originalCreate) {
4651
- this.create = originalCreate;
4652
- }
4653
- try {
4654
- const messageStream = context.with(spanContext, () => original(...args));
4655
- return new MessageStreamWrapper(span2, messageStream, startTime, kwargs, spanContext);
4656
- } finally {
4657
- if (originalCreate) {
4658
- this.create = instrumentedCreate;
4659
- }
4660
- }
4661
- };
5214
+ const originalCreate = MessagesClass.prototype.create;
5215
+ if (typeof MessagesClass.prototype.create === "function") {
5216
+ shimmer.wrap(
5217
+ MessagesClass.prototype,
5218
+ "create",
5219
+ chatWrapper(this.tracer)
5220
+ );
4662
5221
  }
4663
- if (MessagesClass?.prototype?.create) {
4664
- const originalCreate = MessagesClass.prototype.create;
4665
- originalMethods.set(`messages.create-${index}`, originalCreate);
4666
- const tracer = this.tracer;
4667
- const wrapper = chatWrapper(tracer);
4668
- MessagesClass.prototype.create = function(...args) {
4669
- const original = originalCreate.bind(this);
4670
- const kwargs = args[0] || {};
4671
- return wrapper(
4672
- (...a) => original(...a),
4673
- this,
4674
- args,
4675
- kwargs
4676
- );
4677
- };
5222
+ if (typeof MessagesClass.prototype.stream === "function") {
5223
+ shimmer.wrap(
5224
+ MessagesClass.prototype,
5225
+ "stream",
5226
+ chatStreamWrapper(this.tracer, originalCreate)
5227
+ );
4678
5228
  }
4679
5229
  } catch (error) {
4680
5230
  Logger.error(`Failed to instrument messages: ${error}`);
4681
5231
  }
4682
5232
  }
4683
- _instrumentBetaMessages(AnthropicSDK, index) {
5233
+ _instrumentBetaMessages(AnthropicSDK) {
4684
5234
  if (!this.tracer) {
4685
5235
  Logger.warn("Anthropic instrumentation: No tracer available");
4686
5236
  return;
4687
5237
  }
4688
5238
  try {
4689
5239
  const BetaMessagesClass = AnthropicSDK.Beta?.Messages;
4690
- if (!BetaMessagesClass) {
5240
+ if (!BetaMessagesClass?.prototype) {
4691
5241
  Logger.error(
4692
- "Anthropic instrumentation: Could not find Anthropic Beta Messages class to instrument"
5242
+ "Anthropic instrumentation: Could not find Beta Messages class"
4693
5243
  );
4694
5244
  return;
4695
5245
  }
4696
- if (BetaMessagesClass?.prototype?.create) {
4697
- const originalCreate = BetaMessagesClass.prototype.create;
4698
- originalMethods.set(`beta.messages.create-${index}`, originalCreate);
4699
- const tracer = this.tracer;
4700
- const wrapper = betaWrapper(tracer);
4701
- BetaMessagesClass.prototype.create = function(...args) {
4702
- const original = originalCreate.bind(this);
4703
- const kwargs = args[0] || {};
4704
- return wrapper(
4705
- (...a) => original(...a),
4706
- this,
4707
- args,
4708
- kwargs
4709
- );
4710
- };
5246
+ const originalCreate = BetaMessagesClass.prototype.create;
5247
+ if (typeof BetaMessagesClass.prototype.create === "function") {
5248
+ shimmer.wrap(
5249
+ BetaMessagesClass.prototype,
5250
+ "create",
5251
+ betaWrapper(this.tracer)
5252
+ );
5253
+ }
5254
+ if (typeof BetaMessagesClass.prototype.stream === "function") {
5255
+ shimmer.wrap(
5256
+ BetaMessagesClass.prototype,
5257
+ "stream",
5258
+ betaStreamWrapper(this.tracer, originalCreate)
5259
+ );
5260
+ }
5261
+ if (typeof BetaMessagesClass.prototype.toolRunner === "function") {
5262
+ shimmer.wrap(
5263
+ BetaMessagesClass.prototype,
5264
+ "toolRunner",
5265
+ betaToolRunnerWrapper(this.tracer)
5266
+ );
4711
5267
  }
4712
5268
  } catch (error) {
4713
5269
  Logger.error(`Failed to instrument beta: ${error}`);
4714
5270
  }
4715
5271
  }
4716
- _instrumentBatchMessages(AnthropicSDK, index) {
5272
+ _instrumentBatchMessages(AnthropicSDK) {
4717
5273
  if (!this.tracer) {
4718
5274
  Logger.warn("Anthropic instrumentation: No tracer available");
4719
5275
  return;
4720
5276
  }
4721
5277
  try {
4722
5278
  const BatchMessageClass = AnthropicSDK.Messages?.Batches;
4723
- if (!BatchMessageClass) {
4724
- Logger.error(
4725
- "Anthropic instrumentation: Could not find Anthropic Batches class to instrument"
4726
- );
5279
+ if (!BatchMessageClass?.prototype) {
5280
+ Logger.error("Anthropic instrumentation: Could not find Batches class");
4727
5281
  return;
4728
5282
  }
4729
- if (BatchMessageClass?.prototype?.create) {
4730
- const originalCreate = BatchMessageClass.prototype.create;
4731
- originalMethods.set(`batch.messages.create-${index}`, originalCreate);
4732
- const tracer = this.tracer;
4733
- const wrapper = batchesWrapper(tracer);
4734
- BatchMessageClass.prototype.create = function(...args) {
4735
- const original = originalCreate.bind(this);
4736
- const kwargs = args[0] || {};
4737
- return wrapper(
4738
- (...a) => original(...a),
4739
- this,
4740
- args,
4741
- kwargs
4742
- );
4743
- };
5283
+ if (typeof BatchMessageClass.prototype.create === "function") {
5284
+ shimmer.wrap(
5285
+ BatchMessageClass.prototype,
5286
+ "create",
5287
+ batchesWrapper(this.tracer)
5288
+ );
4744
5289
  }
4745
5290
  } catch (error) {
4746
5291
  Logger.error(`Failed to instrument batches: ${error}`);
4747
5292
  }
4748
5293
  }
4749
- _uninstrumentMessages(AnthropicSDK, index) {
5294
+ _uninstrumentMessages(AnthropicSDK) {
4750
5295
  try {
4751
- const MessagesClass = AnthropicSDK.Messages;
4752
- const originalCreate = originalMethods.get(`messages.create-${index}`);
4753
- if (originalCreate && MessagesClass?.prototype) {
4754
- MessagesClass.prototype.create = originalCreate;
4755
- }
4756
- const originalStream = originalMethods.get(`messages.stream-${index}`);
4757
- if (originalStream && MessagesClass?.prototype) {
4758
- MessagesClass.prototype.stream = originalStream;
4759
- }
5296
+ const proto = AnthropicSDK.Messages?.prototype;
5297
+ if (!proto) return;
5298
+ if (typeof proto.create === "function") shimmer.unwrap(proto, "create");
5299
+ if (typeof proto.stream === "function") shimmer.unwrap(proto, "stream");
4760
5300
  } catch (error) {
4761
5301
  Logger.error(`Failed to uninstrument messages: ${error}`);
4762
5302
  }
4763
5303
  }
4764
- _uninstrumentBetaMessages(AnthropicSDK, index) {
5304
+ _uninstrumentBetaMessages(AnthropicSDK) {
4765
5305
  try {
4766
- const BetaMessagesClass = AnthropicSDK.Beta?.Messages;
4767
- const originalCreate = originalMethods.get(`beta.messages.create-${index}`);
4768
- if (originalCreate && BetaMessagesClass?.prototype) {
4769
- BetaMessagesClass.prototype.create = originalCreate;
4770
- }
5306
+ const proto = AnthropicSDK.Beta?.Messages?.prototype;
5307
+ if (!proto) return;
5308
+ if (typeof proto.create === "function") shimmer.unwrap(proto, "create");
5309
+ if (typeof proto.stream === "function") shimmer.unwrap(proto, "stream");
5310
+ if (typeof proto.toolRunner === "function")
5311
+ shimmer.unwrap(proto, "toolRunner");
4771
5312
  } catch (error) {
4772
5313
  Logger.error(`Failed to uninstrument beta: ${error}`);
4773
5314
  }
4774
5315
  }
4775
- _uninstrumentBatchMessages(AnthropicSDK, index) {
5316
+ _uninstrumentBatchMessages(AnthropicSDK) {
4776
5317
  try {
4777
- const BatchMessagesClass = AnthropicSDK.Messages?.Batches;
4778
- const originalCreate = originalMethods.get(`batch.messages.create-${index}`);
4779
- if (originalCreate && BatchMessagesClass?.prototype) {
4780
- BatchMessagesClass.prototype.create = originalCreate;
4781
- }
5318
+ const proto = AnthropicSDK.Messages?.Batches?.prototype;
5319
+ if (!proto) return;
5320
+ if (typeof proto.create === "function") shimmer.unwrap(proto, "create");
4782
5321
  } catch (error) {
4783
5322
  Logger.error(`Failed to uninstrument batches: ${error}`);
4784
5323
  }
@@ -5194,7 +5733,7 @@ function _setEmbeddingResponseAttributes(span2, response) {
5194
5733
  }
5195
5734
 
5196
5735
  // src/instrumentation/google-genai/wrappers.ts
5197
- var CHAT_SPAN_NAME2 = "google_genai.chat";
5736
+ var CHAT_SPAN_NAME = "google_genai.chat";
5198
5737
  var EMBEDDING_SPAN_NAME = "google_genai.embedding";
5199
5738
  function googleGenAIWrapper(tracer, spanName, requestType) {
5200
5739
  return function wrapper(original) {
@@ -5473,10 +6012,10 @@ function googleGenAIStartChatWrapper(tracer, spanName, requestType) {
5473
6012
  };
5474
6013
  };
5475
6014
  }
5476
- var chatWrapper2 = (tracer) => googleGenAIWrapper(tracer, CHAT_SPAN_NAME2, "chat");
6015
+ var chatWrapper2 = (tracer) => googleGenAIWrapper(tracer, CHAT_SPAN_NAME, "chat");
5477
6016
  var embeddingsWrapper = (tracer) => googleGenAIWrapper(tracer, EMBEDDING_SPAN_NAME, "embedding");
5478
- var chatStreamWrapper = (tracer) => googleGenAIStreamWrapper(tracer, CHAT_SPAN_NAME2, "chat");
5479
- var startChatWrapper = (tracer) => googleGenAIStartChatWrapper(tracer, CHAT_SPAN_NAME2, "chat");
6017
+ var chatStreamWrapper2 = (tracer) => googleGenAIStreamWrapper(tracer, CHAT_SPAN_NAME, "chat");
6018
+ var startChatWrapper = (tracer) => googleGenAIStartChatWrapper(tracer, CHAT_SPAN_NAME, "chat");
5480
6019
  var INSTRUMENTATION_NAME2 = "netra.instrumentation.google_genai";
5481
6020
  var INSTRUMENTS2 = ["@google/genai >= 0.24.1"];
5482
6021
  var isInstrumented2 = false;
@@ -5602,7 +6141,7 @@ var NetraGoogleGenerativeAIInstrumentor = class {
5602
6141
  shimmer.wrap(
5603
6142
  GenerativeModel.prototype,
5604
6143
  "generateContentStream",
5605
- chatStreamWrapper(tracer)
6144
+ chatStreamWrapper2(tracer)
5606
6145
  );
5607
6146
  shimmer.wrap(
5608
6147
  GenerativeModel.prototype,
@@ -5664,8 +6203,8 @@ function setResponseAttributes4(span2, response) {
5664
6203
  }
5665
6204
 
5666
6205
  // src/instrumentation/groq/wrappers.ts
5667
- var CHAT_SPAN_NAME3 = "groq.chat";
5668
- var STREAM_ENABLED_REQUESTS2 = ["chat"];
6206
+ var CHAT_SPAN_NAME2 = "groq.chat";
6207
+ var STREAM_ENABLED_REQUESTS = ["chat"];
5669
6208
  function groqWrapper(tracer, spanName, requestType) {
5670
6209
  return function wrapper(wrapped, instance, args, kwargs) {
5671
6210
  if (shouldSuppressInstrumentation()) {
@@ -5673,7 +6212,7 @@ function groqWrapper(tracer, spanName, requestType) {
5673
6212
  return isPromise(result) ? result.then((value) => value) : result;
5674
6213
  }
5675
6214
  const isStreaming = kwargs.stream === true;
5676
- if (isStreaming && STREAM_ENABLED_REQUESTS2.includes(requestType)) {
6215
+ if (isStreaming && STREAM_ENABLED_REQUESTS.includes(requestType)) {
5677
6216
  const currentContext = context.active();
5678
6217
  const span2 = tracer.startSpan(
5679
6218
  spanName,
@@ -5691,7 +6230,7 @@ function groqWrapper(tracer, spanName, requestType) {
5691
6230
  return (async () => {
5692
6231
  try {
5693
6232
  const stream = await response;
5694
- return new AsyncStreamingWrapper2(span2, stream, startTime, kwargs);
6233
+ return new AsyncStreamingWrapper(span2, stream, startTime, kwargs);
5695
6234
  } catch (error) {
5696
6235
  Logger.error("netra.instrumentation.groq:", error);
5697
6236
  span2.setStatus({
@@ -5780,7 +6319,7 @@ function groqWrapper(tracer, spanName, requestType) {
5780
6319
  }
5781
6320
  };
5782
6321
  }
5783
- var chatWrapper3 = (tracer) => groqWrapper(tracer, CHAT_SPAN_NAME3, "chat");
6322
+ var chatWrapper3 = (tracer) => groqWrapper(tracer, CHAT_SPAN_NAME2, "chat");
5784
6323
  var StreamingWrapper = class {
5785
6324
  constructor(span2, response, startTime, requestKwargs) {
5786
6325
  this.iterator = null;
@@ -5878,7 +6417,7 @@ var StreamingWrapper = class {
5878
6417
  this.span.end();
5879
6418
  }
5880
6419
  };
5881
- var AsyncStreamingWrapper2 = class {
6420
+ var AsyncStreamingWrapper = class {
5882
6421
  constructor(span2, response, startTime, requestKwargs) {
5883
6422
  this.iterator = null;
5884
6423
  this.completeResponse = {
@@ -5998,7 +6537,7 @@ var AsyncStreamingWrapper2 = class {
5998
6537
  // src/instrumentation/groq/index.ts
5999
6538
  var INSTRUMENTATION_NAME3 = "netra.instrumentation.groq";
6000
6539
  var INSTRUMENTS3 = ["groq-sdk >= 0.3.0"];
6001
- var originalMethods2 = /* @__PURE__ */ new Map();
6540
+ var originalMethods = /* @__PURE__ */ new Map();
6002
6541
  var isInstrumented3 = false;
6003
6542
  var groqClasses = [];
6004
6543
  async function resolveGroqAsync() {
@@ -6109,7 +6648,7 @@ var NetraGroqInstrumentor = class {
6109
6648
  classes.forEach((Groq, index) => {
6110
6649
  this._uninstrumentChatCompletions(Groq, index);
6111
6650
  });
6112
- originalMethods2.clear();
6651
+ originalMethods.clear();
6113
6652
  groqClasses = [];
6114
6653
  isInstrumented3 = false;
6115
6654
  }
@@ -6130,7 +6669,7 @@ var NetraGroqInstrumentor = class {
6130
6669
  return;
6131
6670
  }
6132
6671
  const originalCreate = CompletionsClass.prototype.create;
6133
- originalMethods2.set(`chat.completions.create-${index}`, originalCreate);
6672
+ originalMethods.set(`chat.completions.create-${index}`, originalCreate);
6134
6673
  const tracer = this.tracer;
6135
6674
  const wrapper = chatWrapper3(tracer);
6136
6675
  CompletionsClass.prototype.create = function(...args) {
@@ -6148,7 +6687,7 @@ var NetraGroqInstrumentor = class {
6148
6687
  _uninstrumentChatCompletions(Groq, index) {
6149
6688
  try {
6150
6689
  const CompletionsClass = Groq.Chat?.Completions;
6151
- const originalCreate = originalMethods2.get(`chat.completions.create-${index}`);
6690
+ const originalCreate = originalMethods.get(`chat.completions.create-${index}`);
6152
6691
  if (originalCreate && CompletionsClass?.prototype) {
6153
6692
  CompletionsClass.prototype.create = originalCreate;
6154
6693
  }
@@ -6987,7 +7526,7 @@ var INSTRUMENTATION_NAME4 = "netra.instrumentation.langgraph";
6987
7526
  var INSTRUMENTS4 = ["langgraph >= 1.1.1"];
6988
7527
  var isInstrumented4 = false;
6989
7528
  var LanggraphClass = null;
6990
- var originalMethods3 = /* @__PURE__ */ new Map();
7529
+ var originalMethods2 = /* @__PURE__ */ new Map();
6991
7530
  function findModuleInCache(moduleName) {
6992
7531
  if (typeof __require !== "undefined" && __require.cache) {
6993
7532
  const cache = __require.cache;
@@ -7083,7 +7622,7 @@ var NetraLanggraphInstrumentor = class {
7083
7622
  this._uninstrumentInvoke(Langgraph);
7084
7623
  this._uninstrumentStream(Langgraph);
7085
7624
  }
7086
- originalMethods3.clear();
7625
+ originalMethods2.clear();
7087
7626
  LanggraphClass = null;
7088
7627
  isInstrumented4 = false;
7089
7628
  }
@@ -7100,8 +7639,8 @@ var NetraLanggraphInstrumentor = class {
7100
7639
  }
7101
7640
  Logger.debug(`Found invoke on prototype: ${targetProto.constructor?.name}`);
7102
7641
  const originalInvoke = targetProto.invoke;
7103
- originalMethods3.set("langgraph.graph.invoke", originalInvoke);
7104
- originalMethods3.set("langgraph.graph.invoke.proto", targetProto);
7642
+ originalMethods2.set("langgraph.graph.invoke", originalInvoke);
7643
+ originalMethods2.set("langgraph.graph.invoke.proto", targetProto);
7105
7644
  const tracer = this.tracer;
7106
7645
  const wrapper = new LanggraphWrapper(tracer);
7107
7646
  const patchedInvoke = async function(input, config2, ...rest) {
@@ -7135,8 +7674,8 @@ var NetraLanggraphInstrumentor = class {
7135
7674
  }
7136
7675
  Logger.debug(`Found stream on prototype: ${targetProto.constructor?.name}`);
7137
7676
  const originalStream = targetProto.stream;
7138
- originalMethods3.set("langgraph.graph.stream", originalStream);
7139
- originalMethods3.set("langgraph.graph.stream.proto", targetProto);
7677
+ originalMethods2.set("langgraph.graph.stream", originalStream);
7678
+ originalMethods2.set("langgraph.graph.stream.proto", targetProto);
7140
7679
  const tracer = this.tracer;
7141
7680
  const wrapper = new LanggraphWrapper(tracer);
7142
7681
  targetProto.stream = async function(input, config2, ...rest) {
@@ -7156,8 +7695,8 @@ var NetraLanggraphInstrumentor = class {
7156
7695
  }
7157
7696
  _uninstrumentInvoke(Langgraph) {
7158
7697
  try {
7159
- const originalInvoke = originalMethods3.get("langgraph.graph.invoke");
7160
- const targetProto = originalMethods3.get("langgraph.graph.invoke.proto") || Langgraph?.prototype;
7698
+ const originalInvoke = originalMethods2.get("langgraph.graph.invoke");
7699
+ const targetProto = originalMethods2.get("langgraph.graph.invoke.proto") || Langgraph?.prototype;
7161
7700
  if (originalInvoke && targetProto?.invoke) {
7162
7701
  targetProto.invoke = originalInvoke;
7163
7702
  }
@@ -7168,8 +7707,8 @@ var NetraLanggraphInstrumentor = class {
7168
7707
  }
7169
7708
  _uninstrumentStream(Langgraph) {
7170
7709
  try {
7171
- const originalStream = originalMethods3.get("langgraph.graph.stream");
7172
- const targetProto = originalMethods3.get("langgraph.graph.stream.proto") || Langgraph?.prototype;
7710
+ const originalStream = originalMethods2.get("langgraph.graph.stream");
7711
+ const targetProto = originalMethods2.get("langgraph.graph.stream.proto") || Langgraph?.prototype;
7173
7712
  if (originalStream && targetProto?.stream) {
7174
7713
  targetProto.stream = originalStream;
7175
7714
  }
@@ -7209,11 +7748,11 @@ function setResponseAttributes5(span2, response) {
7209
7748
  }
7210
7749
 
7211
7750
  // src/instrumentation/mistralai/wrappers.ts
7212
- var CHAT_SPAN_NAME4 = "mistralai.chat";
7751
+ var CHAT_SPAN_NAME3 = "mistralai.chat";
7213
7752
  var EMBEDDING_SPAN_NAME2 = "mistralai.embedding";
7214
7753
  var FIM_SPAN_NAME = "mistralai.fim";
7215
7754
  var AGENTS_SPAN_NAME = "mistralai.agents";
7216
- var CHAT_STREAM_SPAN_NAME = CHAT_SPAN_NAME4;
7755
+ var CHAT_STREAM_SPAN_NAME = CHAT_SPAN_NAME3;
7217
7756
  var FIM_STREAM_SPAN_NAME = FIM_SPAN_NAME;
7218
7757
  var AGENTS_STREAM_SPAN_NAME = AGENTS_SPAN_NAME;
7219
7758
  function mistralWrapper(tracer, spanName, requestType) {
@@ -7308,7 +7847,7 @@ function mistralStreamWrapper(tracer, spanName, requestType) {
7308
7847
  try {
7309
7848
  const stream = await response;
7310
7849
  if (stream && typeof stream === "object" && Symbol.asyncIterator in stream) {
7311
- return new AsyncStreamingWrapper3(span2, stream, startTime, kwargs);
7850
+ return new AsyncStreamingWrapper2(span2, stream, startTime, kwargs);
7312
7851
  }
7313
7852
  return new StreamingWrapper2(span2, stream, startTime, kwargs);
7314
7853
  } catch (error) {
@@ -7324,7 +7863,7 @@ function mistralStreamWrapper(tracer, spanName, requestType) {
7324
7863
  })();
7325
7864
  }
7326
7865
  if (response && typeof response === "object" && Symbol.asyncIterator in response) {
7327
- return new AsyncStreamingWrapper3(span2, response, startTime, kwargs);
7866
+ return new AsyncStreamingWrapper2(span2, response, startTime, kwargs);
7328
7867
  }
7329
7868
  return new StreamingWrapper2(span2, response, startTime, kwargs);
7330
7869
  } catch (error) {
@@ -7339,8 +7878,8 @@ function mistralStreamWrapper(tracer, spanName, requestType) {
7339
7878
  }
7340
7879
  };
7341
7880
  }
7342
- var chatWrapper4 = (tracer) => mistralWrapper(tracer, CHAT_SPAN_NAME4, "chat");
7343
- var chatStreamWrapper2 = (tracer) => mistralStreamWrapper(tracer, CHAT_STREAM_SPAN_NAME, "chat");
7881
+ var chatWrapper4 = (tracer) => mistralWrapper(tracer, CHAT_SPAN_NAME3, "chat");
7882
+ var chatStreamWrapper3 = (tracer) => mistralStreamWrapper(tracer, CHAT_STREAM_SPAN_NAME, "chat");
7344
7883
  var embeddingsWrapper2 = (tracer) => mistralWrapper(tracer, EMBEDDING_SPAN_NAME2, "embedding");
7345
7884
  var fimWrapper = (tracer) => mistralWrapper(tracer, FIM_SPAN_NAME, "fim");
7346
7885
  var fimStreamWrapper = (tracer) => mistralStreamWrapper(tracer, FIM_STREAM_SPAN_NAME, "fim");
@@ -7491,7 +8030,7 @@ var StreamingWrapper2 = class {
7491
8030
  this.span.end();
7492
8031
  }
7493
8032
  };
7494
- var AsyncStreamingWrapper3 = class {
8033
+ var AsyncStreamingWrapper2 = class {
7495
8034
  constructor(span2, response, startTime, requestKwargs) {
7496
8035
  this.iterator = null;
7497
8036
  defineHidden(this, "span", span2);
@@ -7641,7 +8180,7 @@ var AsyncStreamingWrapper3 = class {
7641
8180
  // src/instrumentation/mistralai/index.ts
7642
8181
  var INSTRUMENTATION_NAME5 = "netra.instrumentation.mistral_ai";
7643
8182
  var INSTRUMENTS5 = ["@mistralai/mistralai >= 1.0.0"];
7644
- var originalMethods4 = /* @__PURE__ */ new Map();
8183
+ var originalMethods3 = /* @__PURE__ */ new Map();
7645
8184
  var isInstrumented5 = false;
7646
8185
  var mistralClasses = [];
7647
8186
  async function resolveMistralAsync() {
@@ -7790,7 +8329,7 @@ var NetraMistralAIInstrumentor = class {
7790
8329
  this._uninstrumentFIM(Mistral, index);
7791
8330
  this._uninstrumentAgents(Mistral, index);
7792
8331
  });
7793
- originalMethods4.clear();
8332
+ originalMethods3.clear();
7794
8333
  mistralClasses = [];
7795
8334
  isInstrumented5 = false;
7796
8335
  }
@@ -7836,7 +8375,7 @@ var NetraMistralAIInstrumentor = class {
7836
8375
  let didPatch = false;
7837
8376
  if (ChatClass?.prototype?.complete) {
7838
8377
  const originalComplete = ChatClass.prototype.complete;
7839
- originalMethods4.set(`chat.complete-${index}`, originalComplete);
8378
+ originalMethods3.set(`chat.complete-${index}`, originalComplete);
7840
8379
  const tracer = this.tracer;
7841
8380
  const wrapper = chatWrapper4(tracer);
7842
8381
  ChatClass.prototype.complete = function(...args) {
@@ -7853,9 +8392,9 @@ var NetraMistralAIInstrumentor = class {
7853
8392
  }
7854
8393
  if (ChatClass?.prototype?.stream) {
7855
8394
  const originalStream = ChatClass.prototype.stream;
7856
- originalMethods4.set(`chat.stream-${index}`, originalStream);
8395
+ originalMethods3.set(`chat.stream-${index}`, originalStream);
7857
8396
  const tracer = this.tracer;
7858
- const wrapper = chatStreamWrapper2(tracer);
8397
+ const wrapper = chatStreamWrapper3(tracer);
7859
8398
  ChatClass.prototype.stream = function(...args) {
7860
8399
  const original = originalStream.bind(this);
7861
8400
  const kwargs = args[0] || {};
@@ -7881,7 +8420,7 @@ var NetraMistralAIInstrumentor = class {
7881
8420
  let didPatch = false;
7882
8421
  if (EmbeddingsClass?.prototype?.create) {
7883
8422
  const originalCreate = EmbeddingsClass.prototype.create;
7884
- originalMethods4.set(`embeddings.create-${index}`, originalCreate);
8423
+ originalMethods3.set(`embeddings.create-${index}`, originalCreate);
7885
8424
  const tracer = this.tracer;
7886
8425
  const wrapper = embeddingsWrapper2(tracer);
7887
8426
  EmbeddingsClass.prototype.create = function(...args) {
@@ -7909,7 +8448,7 @@ var NetraMistralAIInstrumentor = class {
7909
8448
  let didPatch = false;
7910
8449
  if (FimClass?.prototype?.complete) {
7911
8450
  const originalComplete = FimClass.prototype.complete;
7912
- originalMethods4.set(`fim.complete-${index}`, originalComplete);
8451
+ originalMethods3.set(`fim.complete-${index}`, originalComplete);
7913
8452
  const tracer = this.tracer;
7914
8453
  const wrapper = fimWrapper(tracer);
7915
8454
  FimClass.prototype.complete = function(...args) {
@@ -7926,7 +8465,7 @@ var NetraMistralAIInstrumentor = class {
7926
8465
  }
7927
8466
  if (FimClass?.prototype?.stream) {
7928
8467
  const originalStream = FimClass.prototype.stream;
7929
- originalMethods4.set(`fim.stream-${index}`, originalStream);
8468
+ originalMethods3.set(`fim.stream-${index}`, originalStream);
7930
8469
  const tracer = this.tracer;
7931
8470
  const wrapper = fimStreamWrapper(tracer);
7932
8471
  FimClass.prototype.stream = function(...args) {
@@ -7954,7 +8493,7 @@ var NetraMistralAIInstrumentor = class {
7954
8493
  let didPatch = false;
7955
8494
  if (AgentsClass?.prototype?.complete) {
7956
8495
  const originalComplete = AgentsClass.prototype.complete;
7957
- originalMethods4.set(`agents.complete-${index}`, originalComplete);
8496
+ originalMethods3.set(`agents.complete-${index}`, originalComplete);
7958
8497
  const tracer = this.tracer;
7959
8498
  const wrapper = agentsWrapper(tracer);
7960
8499
  AgentsClass.prototype.complete = function(...args) {
@@ -7971,7 +8510,7 @@ var NetraMistralAIInstrumentor = class {
7971
8510
  }
7972
8511
  if (AgentsClass?.prototype?.stream) {
7973
8512
  const originalStream = AgentsClass.prototype.stream;
7974
- originalMethods4.set(`agents.stream-${index}`, originalStream);
8513
+ originalMethods3.set(`agents.stream-${index}`, originalStream);
7975
8514
  const tracer = this.tracer;
7976
8515
  const wrapper = agentsStreamWrapper(tracer);
7977
8516
  AgentsClass.prototype.stream = function(...args) {
@@ -7995,11 +8534,11 @@ var NetraMistralAIInstrumentor = class {
7995
8534
  _uninstrumentChat(Mistral, index) {
7996
8535
  try {
7997
8536
  const ChatClass = this._getCtor(Mistral, "chat");
7998
- const originalComplete = originalMethods4.get(`chat.complete-${index}`);
8537
+ const originalComplete = originalMethods3.get(`chat.complete-${index}`);
7999
8538
  if (originalComplete && ChatClass?.prototype) {
8000
8539
  ChatClass.prototype.complete = originalComplete;
8001
8540
  }
8002
- const originalStream = originalMethods4.get(`chat.stream-${index}`);
8541
+ const originalStream = originalMethods3.get(`chat.stream-${index}`);
8003
8542
  if (originalStream && ChatClass?.prototype) {
8004
8543
  ChatClass.prototype.stream = originalStream;
8005
8544
  }
@@ -8010,7 +8549,7 @@ var NetraMistralAIInstrumentor = class {
8010
8549
  _uninstrumentEmbeddings(Mistral, index) {
8011
8550
  try {
8012
8551
  const EmbeddingsClass = this._getCtor(Mistral, "embeddings");
8013
- const originalCreate = originalMethods4.get(`embeddings.create-${index}`);
8552
+ const originalCreate = originalMethods3.get(`embeddings.create-${index}`);
8014
8553
  if (originalCreate && EmbeddingsClass?.prototype) {
8015
8554
  EmbeddingsClass.prototype.create = originalCreate;
8016
8555
  }
@@ -8021,11 +8560,11 @@ var NetraMistralAIInstrumentor = class {
8021
8560
  _uninstrumentFIM(Mistral, index) {
8022
8561
  try {
8023
8562
  const FimClass = this._getCtor(Mistral, "fim");
8024
- const originalComplete = originalMethods4.get(`fim.complete-${index}`);
8563
+ const originalComplete = originalMethods3.get(`fim.complete-${index}`);
8025
8564
  if (originalComplete && FimClass?.prototype) {
8026
8565
  FimClass.prototype.complete = originalComplete;
8027
8566
  }
8028
- const originalStream = originalMethods4.get(`fim.stream-${index}`);
8567
+ const originalStream = originalMethods3.get(`fim.stream-${index}`);
8029
8568
  if (originalStream && FimClass?.prototype) {
8030
8569
  FimClass.prototype.stream = originalStream;
8031
8570
  }
@@ -8036,11 +8575,11 @@ var NetraMistralAIInstrumentor = class {
8036
8575
  _uninstrumentAgents(Mistral, index) {
8037
8576
  try {
8038
8577
  const AgentsClass = this._getCtor(Mistral, "agents");
8039
- const originalComplete = originalMethods4.get(`agents.complete-${index}`);
8578
+ const originalComplete = originalMethods3.get(`agents.complete-${index}`);
8040
8579
  if (originalComplete && AgentsClass?.prototype) {
8041
8580
  AgentsClass.prototype.complete = originalComplete;
8042
8581
  }
8043
- const originalStream = originalMethods4.get(`agents.stream-${index}`);
8582
+ const originalStream = originalMethods3.get(`agents.stream-${index}`);
8044
8583
  if (originalStream && AgentsClass?.prototype) {
8045
8584
  AgentsClass.prototype.stream = originalStream;
8046
8585
  }
@@ -8068,7 +8607,7 @@ function setResponseAttributes6(span2, response) {
8068
8607
  }
8069
8608
 
8070
8609
  // src/instrumentation/openai/wrappers.ts
8071
- var SPAN_NAMES = {
8610
+ var SPAN_NAMES2 = {
8072
8611
  chat: "openai.chat",
8073
8612
  embedding: "openai.embedding",
8074
8613
  response: "openai.response"
@@ -8209,7 +8748,7 @@ var StreamingWrapper3 = class extends BaseStreamHandler {
8209
8748
  throw new Error("Response is not iterable");
8210
8749
  }
8211
8750
  };
8212
- var AsyncStreamingWrapper4 = class extends BaseStreamHandler {
8751
+ var AsyncStreamingWrapper3 = class extends BaseStreamHandler {
8213
8752
  constructor(span2, response, startTime, requestKwargs) {
8214
8753
  super(span2, startTime, requestKwargs);
8215
8754
  this.iterator = null;
@@ -8265,7 +8804,7 @@ function executeStreaming(span2, ctx, kwargs, requestType, call) {
8265
8804
  return (async () => {
8266
8805
  try {
8267
8806
  const stream = await response;
8268
- return new AsyncStreamingWrapper4(span2, stream, startTime, kwargs);
8807
+ return new AsyncStreamingWrapper3(span2, stream, startTime, kwargs);
8269
8808
  } catch (error) {
8270
8809
  handleSpanError(span2, error);
8271
8810
  throw error;
@@ -8303,7 +8842,7 @@ function executeNonStreaming(span2, kwargs, requestType, call) {
8303
8842
  }
8304
8843
  }
8305
8844
  function openAIWrapper(tracer, requestType) {
8306
- const spanName = SPAN_NAMES[requestType];
8845
+ const spanName = SPAN_NAMES2[requestType];
8307
8846
  const spanOpts = { kind: SpanKind.CLIENT, attributes: { "llm.request.type": requestType } };
8308
8847
  return (wrapped, instance, args, kwargs) => {
8309
8848
  if (shouldSuppressInstrumentation()) {
@@ -9132,6 +9671,8 @@ var cachedAgentsModule = null;
9132
9671
  var isInstrumented6 = false;
9133
9672
  var activeTracer = null;
9134
9673
  var activeProcessor = null;
9674
+ var originalProcessors = null;
9675
+ var didReplaceProcessors = false;
9135
9676
  async function resolveAgentsModule() {
9136
9677
  if (cachedAgentsModule) return cachedAgentsModule;
9137
9678
  try {
@@ -9184,20 +9725,51 @@ var NetraOpenAIAgentsInstrumentor = class {
9184
9725
  }
9185
9726
  const systemName = options.systemName ?? DEFAULT_LLM_SYSTEM;
9186
9727
  activeProcessor = new NetraAgentsTracingProcessor(activeTracer, systemName);
9728
+ const mode = options.nativeTracing ?? parseNativeTracingEnv("NATIVE_TRACING_MODE") ?? "netra-strict";
9729
+ const canSet = typeof agentsModule.setTraceProcessors === "function";
9730
+ const canAdd = typeof agentsModule.addTraceProcessor === "function";
9731
+ let strategy;
9732
+ if (mode === "both" || mode === "netra" && !canSet) {
9733
+ strategy = "append";
9734
+ } else if (canSet) {
9735
+ strategy = "replace";
9736
+ } else {
9737
+ strategy = "skip";
9738
+ }
9187
9739
  try {
9188
- if (typeof agentsModule.addTraceProcessor === "function") {
9189
- agentsModule.addTraceProcessor(activeProcessor);
9190
- } else if (typeof agentsModule.setTraceProcessors === "function") {
9191
- const existing = typeof agentsModule.getTraceProcessors === "function" ? agentsModule.getTraceProcessors() : [];
9192
- agentsModule.setTraceProcessors([...existing, activeProcessor]);
9193
- } else {
9194
- Logger.warn(
9195
- "OpenAI Agents SDK does not expose addTraceProcessor or setTraceProcessors.",
9196
- "Tracing integration may not work."
9197
- );
9198
- activeProcessor = null;
9199
- activeTracer = null;
9200
- return this;
9740
+ switch (strategy) {
9741
+ case "replace":
9742
+ if (typeof agentsModule.getTraceProcessors === "function") {
9743
+ originalProcessors = agentsModule.getTraceProcessors();
9744
+ }
9745
+ agentsModule.setTraceProcessors([activeProcessor]);
9746
+ didReplaceProcessors = true;
9747
+ Logger.debug("OpenAI Agents native tracing disabled \u2014 traces will only be sent to Netra.");
9748
+ break;
9749
+ case "append":
9750
+ if (canAdd) {
9751
+ agentsModule.addTraceProcessor(activeProcessor);
9752
+ } else {
9753
+ Logger.warn("OpenAI Agents SDK does not expose addTraceProcessor or setTraceProcessors.");
9754
+ activeProcessor = null;
9755
+ activeTracer = null;
9756
+ return this;
9757
+ }
9758
+ if (mode === "netra") {
9759
+ Logger.warn(
9760
+ "Cannot exclusively replace native trace processors in this @openai/agents version.",
9761
+ "Traces may still be sent to OpenAI."
9762
+ );
9763
+ }
9764
+ break;
9765
+ case "skip":
9766
+ Logger.warn(
9767
+ 'nativeTracing is "netra-strict" but the installed @openai/agents version',
9768
+ "does not support processor replacement. Skipping instrumentation."
9769
+ );
9770
+ activeProcessor = null;
9771
+ activeTracer = null;
9772
+ return this;
9201
9773
  }
9202
9774
  } catch (error) {
9203
9775
  Logger.warn("Failed to register trace processor with @openai/agents:", error);
@@ -9217,6 +9789,21 @@ var NetraOpenAIAgentsInstrumentor = class {
9217
9789
  activeProcessor.shutdown();
9218
9790
  activeProcessor = null;
9219
9791
  }
9792
+ if (didReplaceProcessors && cachedAgentsModule) {
9793
+ try {
9794
+ if (originalProcessors && typeof cachedAgentsModule.setTraceProcessors === "function") {
9795
+ cachedAgentsModule.setTraceProcessors(originalProcessors);
9796
+ Logger.debug("Restored original OpenAI Agents trace processors");
9797
+ } else if (typeof cachedAgentsModule.setDefaultOpenAITracingExporter === "function") {
9798
+ cachedAgentsModule.setDefaultOpenAITracingExporter();
9799
+ Logger.debug("Restored default OpenAI Agents tracing exporter");
9800
+ }
9801
+ } catch (error) {
9802
+ Logger.debug("Failed to restore original trace processors:", error);
9803
+ }
9804
+ }
9805
+ originalProcessors = null;
9806
+ didReplaceProcessors = false;
9220
9807
  activeTracer = null;
9221
9808
  cachedAgentsModule = null;
9222
9809
  isInstrumented6 = false;
@@ -9481,7 +10068,7 @@ function repositoryQueryWrapper(tracer) {
9481
10068
  var __version__8 = "1.0.0";
9482
10069
  var require2 = createRequire(import.meta.url);
9483
10070
  var INSTRUMENTATION_NAME8 = "netra.instrumentation.typeorm";
9484
- var originalMethods5 = /* @__PURE__ */ new Map();
10071
+ var originalMethods4 = /* @__PURE__ */ new Map();
9485
10072
  var isInstrumented7 = false;
9486
10073
  var NetraTypeORMInstrumentor = class {
9487
10074
  constructor() {
@@ -9515,7 +10102,7 @@ var NetraTypeORMInstrumentor = class {
9515
10102
  });
9516
10103
  this._uninstrumentRepository().catch(() => {
9517
10104
  });
9518
- originalMethods5.clear();
10105
+ originalMethods4.clear();
9519
10106
  isInstrumented7 = false;
9520
10107
  }
9521
10108
  isInstrumented() {
@@ -9534,7 +10121,7 @@ var NetraTypeORMInstrumentor = class {
9534
10121
  }
9535
10122
  if (DataSource.prototype?.query) {
9536
10123
  const originalQuery = DataSource.prototype.query;
9537
- originalMethods5.set("DataSource.prototype.query", originalQuery);
10124
+ originalMethods4.set("DataSource.prototype.query", originalQuery);
9538
10125
  const tracer = this.tracer;
9539
10126
  const wrapper = queryWrapper(tracer);
9540
10127
  DataSource.prototype.query = function(...args) {
@@ -9559,7 +10146,7 @@ var NetraTypeORMInstrumentor = class {
9559
10146
  }
9560
10147
  if (EntityManager.prototype?.query) {
9561
10148
  const originalQuery = EntityManager.prototype.query;
9562
- originalMethods5.set("EntityManager.prototype.query", originalQuery);
10149
+ originalMethods4.set("EntityManager.prototype.query", originalQuery);
9563
10150
  const tracer = this.tracer;
9564
10151
  const wrapper = managerQueryWrapper(tracer);
9565
10152
  EntityManager.prototype.query = function(...args) {
@@ -9584,7 +10171,7 @@ var NetraTypeORMInstrumentor = class {
9584
10171
  }
9585
10172
  if (Repository.prototype?.query) {
9586
10173
  const originalQuery = Repository.prototype.query;
9587
- originalMethods5.set("Repository.prototype.query", originalQuery);
10174
+ originalMethods4.set("Repository.prototype.query", originalQuery);
9588
10175
  const tracer = this.tracer;
9589
10176
  const wrapper = repositoryQueryWrapper(tracer);
9590
10177
  Repository.prototype.query = function(...args) {
@@ -9600,7 +10187,7 @@ var NetraTypeORMInstrumentor = class {
9600
10187
  try {
9601
10188
  const typeorm = require2("typeorm");
9602
10189
  const DataSource = typeorm.DataSource || typeorm.default?.DataSource;
9603
- const originalQuery = originalMethods5.get("DataSource.prototype.query");
10190
+ const originalQuery = originalMethods4.get("DataSource.prototype.query");
9604
10191
  if (originalQuery && DataSource?.prototype) {
9605
10192
  DataSource.prototype.query = originalQuery;
9606
10193
  }
@@ -9612,7 +10199,7 @@ var NetraTypeORMInstrumentor = class {
9612
10199
  try {
9613
10200
  const typeorm = require2("typeorm");
9614
10201
  const EntityManager = typeorm.EntityManager || typeorm.default?.EntityManager;
9615
- const originalQuery = originalMethods5.get("EntityManager.prototype.query");
10202
+ const originalQuery = originalMethods4.get("EntityManager.prototype.query");
9616
10203
  if (originalQuery && EntityManager?.prototype) {
9617
10204
  EntityManager.prototype.query = originalQuery;
9618
10205
  }
@@ -9624,7 +10211,7 @@ var NetraTypeORMInstrumentor = class {
9624
10211
  try {
9625
10212
  const typeorm = require2("typeorm");
9626
10213
  const Repository = typeorm.Repository || typeorm.default?.Repository;
9627
- const originalQuery = originalMethods5.get("Repository.prototype.query");
10214
+ const originalQuery = originalMethods4.get("Repository.prototype.query");
9628
10215
  if (originalQuery && Repository?.prototype) {
9629
10216
  Repository.prototype.query = originalQuery;
9630
10217
  }
@@ -10099,7 +10686,9 @@ function initInstrumentations(config2, instruments, blockInstruments, rootInstru
10099
10686
  mistral: false,
10100
10687
  langgraph: false,
10101
10688
  googleGenAI: false,
10102
- anthropic: false};
10689
+ anthropic: false,
10690
+ openAiAgents: false
10691
+ };
10103
10692
  const resolved = enableAll ? new Set(Object.values(NetraInstruments).filter((v) => v !== "__all__" /* ALL */)) : instruments && instruments.size > 0 ? instruments : DEFAULT_INSTRUMENTS;
10104
10693
  instrumentModules.google_vertexai = false;
10105
10694
  instrumentModules.langchain = false;
@@ -10147,6 +10736,9 @@ function initInstrumentations(config2, instruments, blockInstruments, rootInstru
10147
10736
  if (resolved.has("anthropic" /* ANTHROPIC */)) {
10148
10737
  customInstrumentModules.anthropic = true;
10149
10738
  }
10739
+ if (resolved.has("openai_agents" /* OPENAI_AGENTS */)) {
10740
+ customInstrumentModules.openAiAgents = true;
10741
+ }
10150
10742
  if (blockInstruments && blockInstruments.size > 0) {
10151
10743
  const blockAll = blockInstruments.has("__all__" /* ALL */);
10152
10744
  if (blockAll || blockInstruments.has("openai" /* OPENAI */)) customInstrumentModules.openai = false;
@@ -10155,6 +10747,7 @@ function initInstrumentations(config2, instruments, blockInstruments, rootInstru
10155
10747
  if (blockAll || blockInstruments.has("langgraph" /* LANGGRAPH */)) customInstrumentModules.langgraph = false;
10156
10748
  if (blockAll || blockInstruments.has("google_genai" /* GOOGLE_GENERATIVE_AI */)) customInstrumentModules.googleGenAI = false;
10157
10749
  if (blockAll || blockInstruments.has("anthropic" /* ANTHROPIC */)) customInstrumentModules.anthropic = false;
10750
+ if (blockAll || blockInstruments.has("openai_agents" /* OPENAI_AGENTS */)) customInstrumentModules.openAiAgents = false;
10158
10751
  if (blockAll || blockInstruments.has("vertexai" /* VERTEX_AI */)) instrumentModules.google_vertexai = false;
10159
10752
  if (blockAll || blockInstruments.has("langchain" /* LANGCHAIN */)) instrumentModules.langchain = false;
10160
10753
  if (blockAll || blockInstruments.has("llama_index" /* LLAMA_INDEX */)) instrumentModules.llamaIndex = false;
@@ -10271,13 +10864,13 @@ async function initCustomInstrumentationsAsync(config2, tracerProvider, customIn
10271
10864
  }
10272
10865
  if (customInstrumentModules.anthropic) {
10273
10866
  try {
10274
- await anthropicInstrumentor.instrumentAsync({ tracerProvider });
10867
+ await anthropicInstrumentor.instrument({ tracerProvider });
10275
10868
  Logger.debug("Custom Anthropic instrumentation enabled");
10276
10869
  } catch (e) {
10277
10870
  Logger.debug("Failed to initialize custom Anthropic instrumentation:", e);
10278
10871
  }
10279
10872
  }
10280
- if (customInstrumentModules.openaiAgents && !blockInstruments?.has("openai_agents" /* OPENAI_AGENTS */)) {
10873
+ if (customInstrumentModules.openAiAgents && !blockInstruments?.has("openai_agents" /* OPENAI_AGENTS */)) {
10281
10874
  try {
10282
10875
  await openaiAgentsInstrumentor.instrument({ tracerProvider });
10283
10876
  Logger.debug("Custom OpenAI Agents SDK instrumentation enabled");
@@ -10423,7 +11016,7 @@ function addCustomSpanProcessors(tracerProvider, config2, rootInstrumentNames) {
10423
11016
  }
10424
11017
  const instrumentationProcessor = new InstrumentationSpanProcessor();
10425
11018
  provider.addSpanProcessor(instrumentationProcessor);
10426
- const sessionProcessor = new SessionSpanProcessor();
11019
+ const sessionProcessor = new SessionSpanProcessor(config2.environment);
10427
11020
  provider.addSpanProcessor(sessionProcessor);
10428
11021
  const spanIOProcessor = new SpanIOProcessor();
10429
11022
  provider.addSpanProcessor(spanIOProcessor);
@@ -10435,6 +11028,10 @@ function addCustomSpanProcessors(tracerProvider, config2, rootInstrumentNames) {
10435
11028
  const scrubbingProcessor = new ScrubbingSpanProcessor();
10436
11029
  provider.addSpanProcessor(scrubbingProcessor);
10437
11030
  }
11031
+ const sizeLimitProcessor = new AttributeSizeLimitProcessor(
11032
+ Config.SPAN_ATTRIBUTE_MAX_SIZE
11033
+ );
11034
+ provider.addSpanProcessor(sizeLimitProcessor);
10438
11035
  Logger.debug("Custom span processors registered successfully");
10439
11036
  return provider;
10440
11037
  } catch (e) {
@@ -11083,33 +11680,6 @@ var Tracer17 = class {
11083
11680
  }
11084
11681
  }
11085
11682
  };
11086
- function safeStringify3(value, maxLen = 1e3) {
11087
- const seen = /* @__PURE__ */ new WeakSet();
11088
- try {
11089
- return JSON.stringify(value, (_key, val) => {
11090
- if (typeof val === "function") return `[Function: ${val.name || "anonymous"}]`;
11091
- if (typeof val === "symbol") return val.toString();
11092
- if (typeof val === "bigint") return val.toString();
11093
- if (val !== null && typeof val === "object") {
11094
- if (seen.has(val)) return "[Circular]";
11095
- seen.add(val);
11096
- const name = val.constructor?.name;
11097
- if (name && name !== "Object" && name !== "Array" && Object.keys(val).length > 20) {
11098
- return `[${name}]`;
11099
- }
11100
- }
11101
- return val;
11102
- }).substring(0, maxLen);
11103
- } catch {
11104
- return value?.constructor?.name ? `[${value.constructor.name}]` : String(typeof value);
11105
- }
11106
- }
11107
- function serializeValue2(value) {
11108
- if (value === null || value === void 0) return String(value);
11109
- const t = typeof value;
11110
- if (t === "string" || t === "number" || t === "boolean") return String(value);
11111
- return safeStringify3(value);
11112
- }
11113
11683
  function spanHasOutput(span2) {
11114
11684
  try {
11115
11685
  for (const field of ["attributes", "_attributes"]) {
@@ -11124,13 +11694,13 @@ function spanHasOutput(span2) {
11124
11694
  function addInputAttributes(span2, args, entityType) {
11125
11695
  span2.setAttribute(`${Config.LIBRARY_NAME}.entity.type`, entityType);
11126
11696
  if (args.length > 0) {
11127
- span2.setAttribute("input", safeStringify3(args));
11697
+ span2.setAttribute("input", safeStringify(args, Config.ATTRIBUTE_MAX_LEN));
11128
11698
  }
11129
11699
  }
11130
11700
  function addOutputAttributes(span2, result) {
11131
11701
  if (spanHasOutput(span2)) return;
11132
11702
  try {
11133
- span2.setAttribute("output", serializeValue2(result));
11703
+ span2.setAttribute("output", serializeValue(result, Config.ATTRIBUTE_MAX_LEN));
11134
11704
  } catch (e) {
11135
11705
  span2.setAttribute("output_error", String(e));
11136
11706
  }
@@ -11150,69 +11720,63 @@ function createFunctionWrapper(func, entityType, name, asType = "SPAN" /* SPAN *
11150
11720
  span2.setAttribute("netra.span.type", asType);
11151
11721
  SessionManager.registerSpan(spanName, span2);
11152
11722
  };
11153
- const handleError = (span2, e) => {
11723
+ const recordError = (span2, e) => {
11154
11724
  span2.setAttribute(`${Config.LIBRARY_NAME}.entity.error`, String(e));
11155
11725
  span2.setStatus({
11156
11726
  code: SpanStatusCode.ERROR,
11157
11727
  message: e instanceof Error ? e.message : String(e)
11158
11728
  });
11159
11729
  span2.recordException(e);
11160
- throw e;
11161
11730
  };
11162
11731
  const cleanup = (span2) => {
11163
11732
  span2.end();
11164
11733
  SessionManager.unregisterSpan(spanName, span2);
11165
11734
  SessionManager.popEntity(entityType);
11166
11735
  };
11167
- if (isAsync) {
11168
- const wrapper = async function(...args) {
11169
- SessionManager.pushEntity(entityType, spanName);
11170
- const tracer = trace.getTracer(moduleName);
11171
- return tracer.startActiveSpan(spanName, async (span2) => {
11172
- try {
11173
- initSpan(span2);
11174
- addInputAttributes(span2, args, entityType);
11175
- const result = await func.call(this, ...args);
11176
- addOutputAttributes(span2, result);
11177
- return result;
11178
- } catch (e) {
11179
- handleError(span2, e);
11180
- } finally {
11181
- cleanup(span2);
11182
- }
11183
- });
11184
- };
11185
- return wrapper;
11186
- } else {
11187
- const wrapper = function(...args) {
11188
- SessionManager.pushEntity(entityType, spanName);
11189
- const tracer = trace.getTracer(moduleName);
11190
- return tracer.startActiveSpan(spanName, (span2) => {
11191
- let returnedPromise = false;
11192
- try {
11193
- initSpan(span2);
11194
- addInputAttributes(span2, args, entityType);
11195
- const result = func.call(this, ...args);
11196
- if (result != null && typeof result.then === "function") {
11197
- returnedPromise = true;
11198
- return result.then((resolved) => {
11199
- addOutputAttributes(span2, resolved);
11200
- return resolved;
11201
- }).catch((e) => handleError(span2, e)).finally(() => cleanup(span2));
11202
- }
11203
- addOutputAttributes(span2, result);
11204
- return result;
11205
- } catch (e) {
11206
- handleError(span2, e);
11207
- } finally {
11208
- if (!returnedPromise) {
11209
- cleanup(span2);
11210
- }
11211
- }
11212
- });
11213
- };
11214
- return wrapper;
11215
- }
11736
+ const wrapperFn = isAsync ? async function(...args) {
11737
+ SessionManager.pushEntity(entityType, spanName);
11738
+ const tracer = trace.getTracer(moduleName);
11739
+ return tracer.startActiveSpan(spanName, async (span2) => {
11740
+ try {
11741
+ initSpan(span2);
11742
+ addInputAttributes(span2, args, entityType);
11743
+ const result = await func.call(this, ...args);
11744
+ const spanCtx = trace.setSpan(context.active(), span2);
11745
+ return wrapResponse(result, {
11746
+ withContext: (fn) => context.with(spanCtx, fn),
11747
+ onError: (e) => recordError(span2, e),
11748
+ onSuccess: (value) => addOutputAttributes(span2, value),
11749
+ finalize: () => cleanup(span2)
11750
+ });
11751
+ } catch (e) {
11752
+ recordError(span2, e);
11753
+ cleanup(span2);
11754
+ throw e;
11755
+ }
11756
+ });
11757
+ } : function(...args) {
11758
+ SessionManager.pushEntity(entityType, spanName);
11759
+ const tracer = trace.getTracer(moduleName);
11760
+ return tracer.startActiveSpan(spanName, (span2) => {
11761
+ try {
11762
+ initSpan(span2);
11763
+ addInputAttributes(span2, args, entityType);
11764
+ const result = func.call(this, ...args);
11765
+ const spanCtx = trace.setSpan(context.active(), span2);
11766
+ return wrapResponse(result, {
11767
+ withContext: (fn) => context.with(spanCtx, fn),
11768
+ onError: (e) => recordError(span2, e),
11769
+ onSuccess: (value) => addOutputAttributes(span2, value),
11770
+ finalize: () => cleanup(span2)
11771
+ });
11772
+ } catch (e) {
11773
+ recordError(span2, e);
11774
+ cleanup(span2);
11775
+ throw e;
11776
+ }
11777
+ });
11778
+ };
11779
+ return wrapperFn;
11216
11780
  }
11217
11781
  var SKIP_STATIC_PROPS = /* @__PURE__ */ new Set([
11218
11782
  "length",
@@ -11599,14 +12163,11 @@ Received ${signal}. Shutting down Netra SDK...`);
11599
12163
  spanWrapper.end();
11600
12164
  throw e;
11601
12165
  }
11602
- if (result instanceof Promise) {
11603
- return result.catch((e) => {
11604
- spanWrapper.setError(e instanceof Error ? e.message : String(e));
11605
- throw e;
11606
- }).finally(() => spanWrapper.end());
11607
- }
11608
- spanWrapper.end();
11609
- return result;
12166
+ return wrapResponse(result, {
12167
+ withContext: (fn2) => spanWrapper.withActive(fn2),
12168
+ onError: (e) => spanWrapper.setError(e instanceof Error ? e.message : String(e)),
12169
+ finalize: () => spanWrapper.end()
12170
+ });
11610
12171
  });
11611
12172
  }
11612
12173
  };
@@ -11616,6 +12177,6 @@ Netra._metricsEnabled = false;
11616
12177
  Netra.withBlockedSpansLocal = withBlockedSpansLocal;
11617
12178
  var index_default = Netra;
11618
12179
 
11619
- export { Aggregation, BaseTask, ChartType, Config, ConversationType, DEFAULT_INSTRUMENTS, DEFAULT_INSTRUMENTS_FOR_ROOT, Dashboard, DimensionField, EntryStatus, Evaluation, FilterField, FilterType, FilteringSpanExporter, GroupBy, InstrumentationSpanProcessor, Measure, Netra, NetraAgentsTracingProcessor, NetraInstruments, NetraOpenAIAgentsInstrumentor, Operator, Prompts, RunEntryContext, RunStatus, Scope, ScrubbingSpanProcessor, SessionSpanProcessor, Simulation, SpanIOProcessor, SpanType, TrialAwareOTLPExporter, Usage, agent, index_default as default, metadataField, mistralAIInstrumentor, netraExpressMiddleware, openaiAgentsInstrumentor, runWithExtractedContext, span, task, workflow };
12180
+ export { Aggregation, AttributeSizeLimitProcessor, BaseTask, ChartType, Config, ConversationType, DEFAULT_INSTRUMENTS, DEFAULT_INSTRUMENTS_FOR_ROOT, Dashboard, DimensionField, EntryStatus, Evaluation, FilterField, FilterType, FilteringSpanExporter, GroupBy, InstrumentationSpanProcessor, Measure, Netra, NetraAgentsTracingProcessor, NetraInstruments, NetraOpenAIAgentsInstrumentor, Operator, Prompts, RunEntryContext, RunStatus, Scope, ScrubbingSpanProcessor, SessionSpanProcessor, Simulation, SpanIOProcessor, SpanType, TrialAwareOTLPExporter, Usage, agent, index_default as default, metadataField, mistralAIInstrumentor, netraExpressMiddleware, openaiAgentsInstrumentor, runWithExtractedContext, span, task, workflow };
11620
12181
  //# sourceMappingURL=index.js.map
11621
12182
  //# sourceMappingURL=index.js.map