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.cjs CHANGED
@@ -9,8 +9,8 @@ var module$1 = require('module');
9
9
  var async_hooks = require('async_hooks');
10
10
  var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
11
11
  var nodeServerSdk = require('@traceloop/node-server-sdk');
12
- var dotenv = require('dotenv');
13
12
  var shimmer = require('shimmer');
13
+ var dotenv = require('dotenv');
14
14
  var core = require('@opentelemetry/core');
15
15
  var http = require('http');
16
16
  var https = require('https');
@@ -40,8 +40,8 @@ function _interopNamespace(e) {
40
40
  }
41
41
 
42
42
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
43
- var dotenv__namespace = /*#__PURE__*/_interopNamespace(dotenv);
44
43
  var shimmer__default = /*#__PURE__*/_interopDefault(shimmer);
44
+ var dotenv__namespace = /*#__PURE__*/_interopNamespace(dotenv);
45
45
  var http__namespace = /*#__PURE__*/_interopNamespace(http);
46
46
  var https__namespace = /*#__PURE__*/_interopNamespace(https);
47
47
  var pLimit__default = /*#__PURE__*/_interopDefault(pLimit);
@@ -1340,7 +1340,7 @@ var require_validation = __commonJS({
1340
1340
  exports$1.needsEscaping = needsEscaping3;
1341
1341
  exports$1.escapeObject = escapeObject3;
1342
1342
  exports$1.isEscapedObject = isEscapedObject;
1343
- exports$1.serializeValue = serializeValue3;
1343
+ exports$1.serializeValue = serializeValue2;
1344
1344
  exports$1.serializeLcObject = serializeLcObject;
1345
1345
  exports$1.escapeIfNeeded = escapeIfNeeded3;
1346
1346
  exports$1.unescapeValue = unescapeValue;
@@ -1374,7 +1374,7 @@ var require_validation = __commonJS({
1374
1374
  id
1375
1375
  };
1376
1376
  }
1377
- function serializeValue3(obj) {
1377
+ function serializeValue2(obj) {
1378
1378
  if (isSerializableLike3(obj)) {
1379
1379
  return serializeLcObject(obj);
1380
1380
  }
@@ -1385,12 +1385,12 @@ var require_validation = __commonJS({
1385
1385
  }
1386
1386
  const result = {};
1387
1387
  for (const [key, value] of Object.entries(record)) {
1388
- result[key] = serializeValue3(value);
1388
+ result[key] = serializeValue2(value);
1389
1389
  }
1390
1390
  return result;
1391
1391
  }
1392
1392
  if (Array.isArray(obj)) {
1393
- return obj.map((item) => serializeValue3(item));
1393
+ return obj.map((item) => serializeValue2(item));
1394
1394
  }
1395
1395
  if (typeof obj === "string" || typeof obj === "number" || typeof obj === "boolean" || obj === null) {
1396
1396
  return obj;
@@ -1406,7 +1406,7 @@ var require_validation = __commonJS({
1406
1406
  if (secretFields.has(key)) {
1407
1407
  newKwargs[key] = value;
1408
1408
  } else {
1409
- newKwargs[key] = serializeValue3(value);
1409
+ newKwargs[key] = serializeValue2(value);
1410
1410
  }
1411
1411
  }
1412
1412
  serialized.kwargs = newKwargs;
@@ -14493,6 +14493,9 @@ var Logger = class {
14493
14493
  static get isDebug() {
14494
14494
  return this._debugMode || ["1", "true"].includes((process.env.NETRA_DEBUG ?? "").toLowerCase());
14495
14495
  }
14496
+ static isDebugMode() {
14497
+ return this.isDebug;
14498
+ }
14496
14499
  static debug(...args) {
14497
14500
  if (this.isDebug) console.debug(PREFIX, ...args);
14498
14501
  }
@@ -15046,6 +15049,9 @@ var Usage = class {
15046
15049
  }
15047
15050
  };
15048
15051
 
15052
+ // src/version.ts
15053
+ var SDK_VERSION = "1.4.0";
15054
+
15049
15055
  // src/config.ts
15050
15056
  var NetraInstruments = /* @__PURE__ */ ((NetraInstruments2) => {
15051
15057
  NetraInstruments2["ALL"] = "__all__";
@@ -15081,7 +15087,8 @@ var DEFAULT_INSTRUMENTS_FOR_ROOT = /* @__PURE__ */ new Set([
15081
15087
  // AI frameworks
15082
15088
  "langchain" /* LANGCHAIN */,
15083
15089
  "langgraph" /* LANGGRAPH */,
15084
- "llama_index" /* LLAMA_INDEX */
15090
+ "llama_index" /* LLAMA_INDEX */,
15091
+ "openai_agents" /* OPENAI_AGENTS */
15085
15092
  ]);
15086
15093
  var DEFAULT_INSTRUMENTS = /* @__PURE__ */ new Set([
15087
15094
  ...DEFAULT_INSTRUMENTS_FOR_ROOT,
@@ -15243,11 +15250,34 @@ var Config = class {
15243
15250
  const headerStr = Object.entries(this.headers).map(([k, v]) => `${k}=${v}`).join(",");
15244
15251
  process.env.TRACELOOP_HEADERS = headerStr;
15245
15252
  }
15253
+ this._setResourceAttributesEnv();
15254
+ }
15255
+ _setResourceAttributesEnv() {
15256
+ const attrs = {
15257
+ "deployment.environment": this.environment,
15258
+ "service.name": this.appName
15259
+ };
15260
+ for (const [k, v] of Object.entries(this.resourceAttributes)) {
15261
+ attrs[k] = String(v);
15262
+ }
15263
+ const existing = process.env.OTEL_RESOURCE_ATTRIBUTES;
15264
+ if (existing) {
15265
+ for (const pair of existing.split(",")) {
15266
+ const eqIdx = pair.indexOf("=");
15267
+ if (eqIdx <= 0) continue;
15268
+ const key = decodeURIComponent(pair.slice(0, eqIdx).trim());
15269
+ if (key) {
15270
+ attrs[key] = decodeURIComponent(pair.slice(eqIdx + 1).trim());
15271
+ }
15272
+ }
15273
+ }
15274
+ const encodeAttrValue = (s) => encodeURIComponent(s);
15275
+ process.env.OTEL_RESOURCE_ATTRIBUTES = Object.entries(attrs).map(([k, v]) => `${encodeAttrValue(k)}=${encodeAttrValue(v)}`).join(",");
15246
15276
  }
15247
15277
  };
15248
15278
  Config.SDK_NAME = "netra";
15249
15279
  Config.LIBRARY_NAME = "netra";
15250
- Config.LIBRARY_VERSION = "1.0.0";
15280
+ Config.LIBRARY_VERSION = SDK_VERSION;
15251
15281
  Config.TRIAL_BLOCK_DURATION_SECONDS = 900;
15252
15282
  // 15 minutes
15253
15283
  Config.ATTRIBUTE_MAX_LEN = parseInt(
@@ -15256,6 +15286,9 @@ Config.ATTRIBUTE_MAX_LEN = parseInt(
15256
15286
  Config.CONVERSATION_MAX_LEN = parseInt(
15257
15287
  process.env.NETRA_CONVERSATION_CONTENT_MAX_LEN || "50000"
15258
15288
  );
15289
+ Config.SPAN_ATTRIBUTE_MAX_SIZE = parseInt(
15290
+ process.env.NETRA_SPAN_ATTRIBUTE_MAX_SIZE || "30000"
15291
+ );
15259
15292
 
15260
15293
  // src/utils/pattern-matching.ts
15261
15294
  function compilePatterns(patterns) {
@@ -15517,6 +15550,57 @@ var ConversationType = /* @__PURE__ */ ((ConversationType3) => {
15517
15550
  return ConversationType3;
15518
15551
  })(ConversationType || {});
15519
15552
 
15553
+ // src/utils/serialization.ts
15554
+ var ELLIPSIS = "...";
15555
+ function truncate(s, maxLength) {
15556
+ if (s.length <= maxLength) return s;
15557
+ if (maxLength <= ELLIPSIS.length) return s.slice(0, maxLength);
15558
+ return s.slice(0, maxLength - ELLIPSIS.length) + ELLIPSIS;
15559
+ }
15560
+ function safeStringify(value, maxLength) {
15561
+ if (typeof value === "string") {
15562
+ if (maxLength && value.length > maxLength) {
15563
+ return truncate(value, maxLength);
15564
+ }
15565
+ return value;
15566
+ }
15567
+ const seen = /* @__PURE__ */ new WeakSet();
15568
+ let result;
15569
+ try {
15570
+ result = JSON.stringify(value, (_key, val) => {
15571
+ if (typeof val === "function")
15572
+ return `[Function: ${val.name || "anonymous"}]`;
15573
+ if (typeof val === "symbol") return val.toString();
15574
+ if (typeof val === "bigint") return val.toString();
15575
+ if (val !== null && typeof val === "object") {
15576
+ if (seen.has(val)) return "[Circular]";
15577
+ seen.add(val);
15578
+ const name = val.constructor?.name;
15579
+ if (name && name !== "Object" && name !== "Array" && Object.keys(val).length > 20) {
15580
+ return `[${name}]`;
15581
+ }
15582
+ }
15583
+ return val;
15584
+ }) ?? String(value);
15585
+ } catch {
15586
+ result = value?.constructor?.name ? `[${value.constructor.name}]` : String(value);
15587
+ }
15588
+ if (maxLength && result.length > maxLength) {
15589
+ return truncate(result, maxLength);
15590
+ }
15591
+ return result;
15592
+ }
15593
+ function serializeValue(value, maxLength) {
15594
+ if (value === null || value === void 0) return String(value);
15595
+ const t = typeof value;
15596
+ if (t === "string" || t === "number" || t === "boolean") {
15597
+ const s = String(value);
15598
+ if (maxLength && s.length > maxLength) return truncate(s, maxLength);
15599
+ return s;
15600
+ }
15601
+ return safeStringify(value, maxLength);
15602
+ }
15603
+
15520
15604
  // src/session-manager.ts
15521
15605
  var MODULE_NAME = "netra.session-manager";
15522
15606
  var entityStorage = new async_hooks.AsyncLocalStorage();
@@ -15530,12 +15614,6 @@ var globalFallbackContext = {
15530
15614
  function getEntityContext() {
15531
15615
  return entityStorage.getStore() ?? globalFallbackContext;
15532
15616
  }
15533
- function serializeValue(value) {
15534
- if (typeof value === "string") {
15535
- return value.substring(0, Config.ATTRIBUTE_MAX_LEN);
15536
- }
15537
- return JSON.stringify(value).substring(0, Config.ATTRIBUTE_MAX_LEN);
15538
- }
15539
15617
  var SessionManager = class _SessionManager {
15540
15618
  // Span registry (name → stack)
15541
15619
  static registerSpan(name, span2) {
@@ -15650,7 +15728,10 @@ var SessionManager = class _SessionManager {
15650
15728
  */
15651
15729
  static setInput(value) {
15652
15730
  try {
15653
- _SessionManager.setAttributeOnActiveSpan("netra.user.input", serializeValue(value));
15731
+ _SessionManager.setAttributeOnActiveSpan(
15732
+ "netra.user.input",
15733
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
15734
+ );
15654
15735
  } catch (e) {
15655
15736
  Logger.error("setInput failed:", e);
15656
15737
  }
@@ -15662,7 +15743,10 @@ var SessionManager = class _SessionManager {
15662
15743
  */
15663
15744
  static setOutput(value) {
15664
15745
  try {
15665
- _SessionManager.setAttributeOnActiveSpan("netra.user.output", serializeValue(value));
15746
+ _SessionManager.setAttributeOnActiveSpan(
15747
+ "netra.user.output",
15748
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
15749
+ );
15666
15750
  } catch (e) {
15667
15751
  Logger.error("setOutput failed:", e);
15668
15752
  }
@@ -15674,7 +15758,10 @@ var SessionManager = class _SessionManager {
15674
15758
  */
15675
15759
  static setRootInput(value) {
15676
15760
  try {
15677
- RootSpanProcessor.setAttributeOnRootSpan("netra.user.input", serializeValue(value));
15761
+ RootSpanProcessor.setAttributeOnRootSpan(
15762
+ "netra.user.input",
15763
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
15764
+ );
15678
15765
  } catch (e) {
15679
15766
  Logger.error("setRootInput failed:", e);
15680
15767
  }
@@ -15686,7 +15773,10 @@ var SessionManager = class _SessionManager {
15686
15773
  */
15687
15774
  static setRootOutput(value) {
15688
15775
  try {
15689
- RootSpanProcessor.setAttributeOnRootSpan("netra.user.output", serializeValue(value));
15776
+ RootSpanProcessor.setAttributeOnRootSpan(
15777
+ "netra.user.output",
15778
+ serializeValue(value, Config.ATTRIBUTE_MAX_LEN)
15779
+ );
15690
15780
  } catch (e) {
15691
15781
  Logger.error("setRootOutput failed:", e);
15692
15782
  }
@@ -17253,6 +17343,58 @@ var Prompts = class {
17253
17343
  }
17254
17344
  };
17255
17345
 
17346
+ // src/processors/attribute-size-limit-processor.ts
17347
+ var DEFAULT_MAX_ATTRIBUTE_SIZE = 32e3;
17348
+ var AttributeSizeLimitProcessor = class {
17349
+ constructor(maxAttributeSize) {
17350
+ this.maxAttributeSize = maxAttributeSize ?? DEFAULT_MAX_ATTRIBUTE_SIZE;
17351
+ }
17352
+ onStart(span2, _parentContext) {
17353
+ try {
17354
+ this._wrapSetAttribute(span2);
17355
+ } catch (e) {
17356
+ Logger.debug("AttributeSizeLimitProcessor.onStart error:", e);
17357
+ }
17358
+ }
17359
+ onEnd(_span) {
17360
+ }
17361
+ shutdown() {
17362
+ return Promise.resolve();
17363
+ }
17364
+ forceFlush() {
17365
+ return Promise.resolve();
17366
+ }
17367
+ _wrapSetAttribute(span2) {
17368
+ const original = span2.setAttribute.bind(span2);
17369
+ const maxLen = this.maxAttributeSize;
17370
+ const patched = (key, value) => {
17371
+ try {
17372
+ return original(key, truncateValue(value, maxLen));
17373
+ } catch {
17374
+ try {
17375
+ return original(key, value);
17376
+ } catch {
17377
+ return span2;
17378
+ }
17379
+ }
17380
+ };
17381
+ span2.setAttribute = patched;
17382
+ }
17383
+ };
17384
+ function truncateValue(value, maxLen) {
17385
+ if (typeof value === "string") {
17386
+ return value.length > maxLen ? value.substring(0, maxLen) : value;
17387
+ }
17388
+ if (Array.isArray(value)) {
17389
+ const serialized = JSON.stringify(value);
17390
+ if (serialized.length > maxLen) {
17391
+ return serialized.substring(0, maxLen);
17392
+ }
17393
+ return value;
17394
+ }
17395
+ return value;
17396
+ }
17397
+
17256
17398
  // src/processors/instrumentation-span-processor.ts
17257
17399
  var ALLOWED_INSTRUMENTATION_NAMES = /* @__PURE__ */ new Set([
17258
17400
  "openai",
@@ -17658,6 +17800,9 @@ function setSessionBaggage(key, value) {
17658
17800
  }
17659
17801
  }
17660
17802
  var SessionSpanProcessor = class {
17803
+ constructor(environment = "local") {
17804
+ this.environment = environment;
17805
+ }
17661
17806
  /**
17662
17807
  * Called when a span starts. Adds session and entity context attributes.
17663
17808
  */
@@ -17666,6 +17811,7 @@ var SessionSpanProcessor = class {
17666
17811
  span2.setAttribute("library.name", Config.LIBRARY_NAME);
17667
17812
  span2.setAttribute("library.version", Config.LIBRARY_VERSION);
17668
17813
  span2.setAttribute("sdk.name", Config.SDK_NAME);
17814
+ span2.setAttribute("deployment.environment", this.environment);
17669
17815
  const ctxToUse = parentContext || api.context.active();
17670
17816
  const baggage = api.propagation.getBaggage(ctxToUse);
17671
17817
  const sessionId = baggage?.getEntry("session_id")?.value ?? sessionValues.get("session_id");
@@ -18072,6 +18218,184 @@ var SpanIOProcessor = class {
18072
18218
  }
18073
18219
  };
18074
18220
 
18221
+ // src/instrumentation/anthropic/version.ts
18222
+ var __version__ = "1.0.0";
18223
+
18224
+ // src/utils/response-handler.ts
18225
+ function isAsyncIterable(value) {
18226
+ return value != null && typeof value[Symbol.asyncIterator] === "function";
18227
+ }
18228
+ function isPromise(value) {
18229
+ return value != null && typeof value.then === "function";
18230
+ }
18231
+ var ITERATOR_METHODS = /* @__PURE__ */ new Set(["next", "return", "throw"]);
18232
+ function wrapAsyncIterable(source, callbacks) {
18233
+ function createWrappedIterator() {
18234
+ const iterator = source[Symbol.asyncIterator]();
18235
+ let done = false;
18236
+ const safeFinalize = (status) => {
18237
+ if (done) return;
18238
+ done = true;
18239
+ try {
18240
+ callbacks.finalize(status);
18241
+ } catch (e) {
18242
+ Logger.error("netra: finalize callback error", e);
18243
+ }
18244
+ };
18245
+ return {
18246
+ async next(value) {
18247
+ try {
18248
+ const result = await callbacks.withContext(() => iterator.next(value));
18249
+ if (!result.done) {
18250
+ try {
18251
+ callbacks.onChunk?.(result.value);
18252
+ } catch (e) {
18253
+ Logger.error("netra: onChunk callback error", e);
18254
+ }
18255
+ } else {
18256
+ safeFinalize("ok");
18257
+ }
18258
+ return result;
18259
+ } catch (e) {
18260
+ try {
18261
+ callbacks.onError(e);
18262
+ } catch {
18263
+ Logger.error("netra: onError callback error", e);
18264
+ }
18265
+ safeFinalize("error");
18266
+ throw e;
18267
+ }
18268
+ },
18269
+ async return(value) {
18270
+ try {
18271
+ const result = await callbacks.withContext(
18272
+ () => iterator.return?.(value) ?? { done: true, value }
18273
+ );
18274
+ safeFinalize("ok");
18275
+ return result;
18276
+ } catch (e) {
18277
+ try {
18278
+ callbacks.onError(e);
18279
+ } catch {
18280
+ Logger.error("netra: onError callback error", e);
18281
+ }
18282
+ safeFinalize("error");
18283
+ throw e;
18284
+ }
18285
+ },
18286
+ async throw(e) {
18287
+ try {
18288
+ const result = await callbacks.withContext(() => {
18289
+ if (iterator.throw) return iterator.throw(e);
18290
+ throw e;
18291
+ });
18292
+ if (result.done) safeFinalize("ok");
18293
+ return result;
18294
+ } catch (err) {
18295
+ try {
18296
+ callbacks.onError(err);
18297
+ } catch {
18298
+ Logger.error("netra: onError callback error", err);
18299
+ }
18300
+ safeFinalize("error");
18301
+ throw err;
18302
+ }
18303
+ }
18304
+ };
18305
+ }
18306
+ let directIterator = null;
18307
+ return new Proxy(source, {
18308
+ get(target, prop) {
18309
+ if (prop === Symbol.asyncIterator) {
18310
+ return () => createWrappedIterator();
18311
+ }
18312
+ if (typeof prop === "string" && ITERATOR_METHODS.has(prop)) {
18313
+ if (!directIterator) directIterator = createWrappedIterator();
18314
+ return directIterator[prop].bind(directIterator);
18315
+ }
18316
+ const value = target[prop];
18317
+ if (typeof value === "function") return value.bind(target);
18318
+ return value;
18319
+ }
18320
+ });
18321
+ }
18322
+ function wrapPromise(promise, callbacks, options) {
18323
+ let finalized = false;
18324
+ function safeFinalize(status) {
18325
+ if (finalized) return;
18326
+ finalized = true;
18327
+ try {
18328
+ callbacks.finalize(status);
18329
+ } catch (e) {
18330
+ Logger.error("netra: finalize callback error", e);
18331
+ }
18332
+ }
18333
+ const instrumentedPromise = (async () => {
18334
+ try {
18335
+ const value = await promise;
18336
+ if (isAsyncIterable(value)) {
18337
+ return wrapAsyncIterable(value, callbacks);
18338
+ }
18339
+ try {
18340
+ callbacks.onSuccess?.(value);
18341
+ } catch (e) {
18342
+ Logger.error("netra: onSuccess callback error", e);
18343
+ }
18344
+ safeFinalize("ok");
18345
+ return value;
18346
+ } catch (error) {
18347
+ try {
18348
+ callbacks.onError(error);
18349
+ } catch {
18350
+ Logger.error("netra: onError callback error", error);
18351
+ }
18352
+ safeFinalize("error");
18353
+ throw error;
18354
+ }
18355
+ })();
18356
+ if (!options?.preserveOriginal) {
18357
+ return instrumentedPromise;
18358
+ }
18359
+ const original = options.preserveOriginal;
18360
+ return new Proxy(instrumentedPromise, {
18361
+ get(target, prop, receiver) {
18362
+ if (prop === "then" || prop === "catch" || prop === "finally") {
18363
+ const value2 = Reflect.get(target, prop, receiver);
18364
+ if (typeof value2 === "function") return value2.bind(target);
18365
+ return value2;
18366
+ }
18367
+ const originalValue = original[prop];
18368
+ if (originalValue !== void 0) {
18369
+ if (typeof originalValue === "function")
18370
+ return originalValue.bind(original);
18371
+ return originalValue;
18372
+ }
18373
+ const value = Reflect.get(target, prop, receiver);
18374
+ if (typeof value === "function") return value.bind(target);
18375
+ return value;
18376
+ }
18377
+ });
18378
+ }
18379
+ function wrapResponse(response, callbacks, options) {
18380
+ if (isAsyncIterable(response)) {
18381
+ return wrapAsyncIterable(response, callbacks);
18382
+ }
18383
+ if (isPromise(response)) {
18384
+ return wrapPromise(response, callbacks, options);
18385
+ }
18386
+ try {
18387
+ callbacks.onSuccess?.(response);
18388
+ } catch (e) {
18389
+ Logger.error("netra: onSuccess callback error", e);
18390
+ }
18391
+ try {
18392
+ callbacks.finalize("ok");
18393
+ } catch (e) {
18394
+ Logger.error("netra: finalize callback error", e);
18395
+ }
18396
+ return response;
18397
+ }
18398
+
18075
18399
  // src/instrumentation/span-attributes.ts
18076
18400
  var SpanAttributes2 = {
18077
18401
  LLM_SYSTEM: "gen_ai.system",
@@ -18082,10 +18406,14 @@ var SpanAttributes2 = {
18082
18406
  LLM_REQUEST_TOP_P: "gen_ai.request.top_p",
18083
18407
  LLM_REQUEST_REASONING: "gen_ai.request.reasoning",
18084
18408
  LLM_REQUEST_REASONING_EFFORT: "gen_ai.request.reasoning_effort",
18409
+ LLM_REQUEST_TOOL_NAME: "gen_ai.request.tool.name",
18410
+ LLM_REQUEST_TOOL_ID: "gen_ai.request.tool.id",
18085
18411
  LLM_RESPONSE_MODEL: "gen_ai.response.model",
18412
+ LLM_RESPONSE_FINISH_REASON: "llm.response.finish_reason",
18086
18413
  LLM_USAGE_PROMPT_TOKENS: "gen_ai.usage.prompt_tokens",
18087
18414
  LLM_USAGE_COMPLETION_TOKENS: "gen_ai.usage.completion_tokens",
18088
18415
  LLM_USAGE_CACHE_READ_INPUT_TOKENS: "gen_ai.usage.cache_read_input_tokens",
18416
+ LLM_USAGE_CACHE_CREATION_INPUT_TOKENS: "gen_ai.usage.cache_creation_input_tokens",
18089
18417
  LLM_USAGE_REASONING_TOKENS: "gen_ai.usage.reasoning_tokens",
18090
18418
  LLM_USAGE_TOTAL_TOKENS: "llm.usage.total_tokens",
18091
18419
  LLM_FREQUENCY_PENALTY: "llm.frequency_penalty",
@@ -18095,16 +18423,18 @@ var SpanAttributes2 = {
18095
18423
  LLM_COMPLETIONS: "gen_ai.completion",
18096
18424
  LLM_PROMPTS: "gen_ai.prompt"
18097
18425
  };
18098
-
18099
- // src/instrumentation/utils.ts
18426
+ var VALID_NATIVE_TRACING_MODES = /* @__PURE__ */ new Set(["both", "netra", "netra-strict"]);
18427
+ function parseNativeTracingEnv(name) {
18428
+ const val = process.env[name];
18429
+ if (val === void 0 || val === "") return void 0;
18430
+ if (VALID_NATIVE_TRACING_MODES.has(val)) return val;
18431
+ return void 0;
18432
+ }
18100
18433
  var SUPPRESS_INSTRUMENTATION_KEY = /* @__PURE__ */ Symbol("netra.suppress_instrumentation");
18101
18434
  function shouldSuppressInstrumentation() {
18102
18435
  const ctx = api.context.active();
18103
18436
  return ctx.getValue(SUPPRESS_INSTRUMENTATION_KEY) === true;
18104
18437
  }
18105
- function isPromise(value) {
18106
- return value instanceof Promise;
18107
- }
18108
18438
  function defineHidden(target, key, value) {
18109
18439
  Object.defineProperty(target, key, {
18110
18440
  value,
@@ -18134,18 +18464,6 @@ function isTraceContentEnabled() {
18134
18464
  const raw = process.env.TRACELOOP_TRACE_CONTENT ?? process.env.NETRA_TRACE_CONTENT ?? "";
18135
18465
  return ["1", "true"].includes(String(raw).toLowerCase());
18136
18466
  }
18137
- function safeStringify(value) {
18138
- if (typeof value === "string") return value;
18139
- try {
18140
- return JSON.stringify(value);
18141
- } catch {
18142
- return String(value);
18143
- }
18144
- }
18145
- function truncate(value, maxLen) {
18146
- if (!value || value.length <= maxLen) return value;
18147
- return value.slice(0, maxLen) + "...(truncated)";
18148
- }
18149
18467
  function hasContent(value) {
18150
18468
  if (value === void 0 || value === null) return false;
18151
18469
  if (typeof value === "string") return value.length > 0;
@@ -18176,7 +18494,7 @@ function setModelParams(span2, kwargs) {
18176
18494
  }
18177
18495
  function buildInputMessages(kwargs, requestType) {
18178
18496
  const messages = [];
18179
- if (requestType === "chat") {
18497
+ if (requestType === "chat" || requestType === "beta") {
18180
18498
  if (hasContent(kwargs.system)) {
18181
18499
  const systemContent = typeof kwargs.system === "string" ? kwargs.system : safeStringify(kwargs.system);
18182
18500
  messages.push({ role: "system", content: systemContent });
@@ -18184,12 +18502,34 @@ function buildInputMessages(kwargs, requestType) {
18184
18502
  const rawMessages = kwargs.messages;
18185
18503
  if (!Array.isArray(rawMessages)) return messages;
18186
18504
  for (const msg of rawMessages) {
18187
- if (!isDict(msg)) continue;
18188
- if (hasContent(msg.role) && hasContent(msg.content)) {
18505
+ if (!isDict(msg) || !hasContent(msg.role) || !hasContent(msg.content)) {
18506
+ continue;
18507
+ }
18508
+ if (msg.role !== "user" || !Array.isArray(msg.content)) {
18189
18509
  messages.push({
18190
18510
  role: msg.role,
18191
18511
  content: safeStringify(msg.content)
18192
18512
  });
18513
+ continue;
18514
+ }
18515
+ const isToolResult = (b) => isDict(b) && b.type === "tool_result";
18516
+ const userBlocks = msg.content.filter((b) => !isToolResult(b));
18517
+ if (userBlocks.length) {
18518
+ messages.push({
18519
+ role: "user",
18520
+ content: safeStringify(userBlocks)
18521
+ });
18522
+ }
18523
+ for (const block of msg.content) {
18524
+ if (!isToolResult(block)) continue;
18525
+ messages.push({
18526
+ role: "tool",
18527
+ content: safeStringify({
18528
+ tool_use_id: block.tool_use_id,
18529
+ content: block.content,
18530
+ is_error: block.is_error ?? false
18531
+ }, Config.CONVERSATION_MAX_LEN)
18532
+ });
18193
18533
  }
18194
18534
  }
18195
18535
  } else if (requestType === "response") {
@@ -18218,10 +18558,7 @@ function buildInputMessages(kwargs, requestType) {
18218
18558
  } else {
18219
18559
  const input = kwargs.input ?? kwargs.inputs;
18220
18560
  if (hasContent(input)) {
18221
- const content = truncate(
18222
- safeStringify(input),
18223
- Config.CONVERSATION_MAX_LEN
18224
- );
18561
+ const content = safeStringify(input, Config.CONVERSATION_MAX_LEN);
18225
18562
  messages.push({ role: "user", content });
18226
18563
  }
18227
18564
  }
@@ -18288,7 +18625,7 @@ function buildOutputMessages(response) {
18288
18625
  } else if (block.type === "tool_use" && block.name) {
18289
18626
  messages.push({
18290
18627
  role: "tool",
18291
- content: JSON.stringify({ name: block.name, input: block.input })
18628
+ content: JSON.stringify({ id: block.id, name: block.name, input: block.input })
18292
18629
  });
18293
18630
  }
18294
18631
  }
@@ -18298,13 +18635,14 @@ function buildOutputMessages(response) {
18298
18635
  function writePromptAttributes(span2, messages) {
18299
18636
  if (messages.length === 0) return;
18300
18637
  for (let i = 0; i < messages.length; i++) {
18638
+ const msg = messages[i];
18301
18639
  span2.setAttribute(
18302
18640
  `${SpanAttributes2.LLM_PROMPTS}.${i}.role`,
18303
- messages[i].role
18641
+ msg.role
18304
18642
  );
18305
18643
  span2.setAttribute(
18306
18644
  `${SpanAttributes2.LLM_PROMPTS}.${i}.content`,
18307
- messages[i].content
18645
+ msg.content
18308
18646
  );
18309
18647
  }
18310
18648
  span2.setAttribute("input", JSON.stringify(messages));
@@ -18356,6 +18694,9 @@ function setRequestAttributes(span2, kwargs, requestType, system) {
18356
18694
  span2.setAttribute(SpanAttributes2.LLM_REQUEST_MODEL, String(kwargs.model));
18357
18695
  }
18358
18696
  setModelParams(span2, kwargs);
18697
+ if (Array.isArray(kwargs.tools)) {
18698
+ span2.setAttribute("tools", safeStringify(kwargs.tools, Config.ATTRIBUTE_MAX_LEN));
18699
+ }
18359
18700
  if (kwargs.reasoning !== void 0) {
18360
18701
  span2.setAttribute(
18361
18702
  SpanAttributes2.LLM_REQUEST_REASONING,
@@ -18368,7 +18709,7 @@ function setRequestAttributes(span2, kwargs, requestType, system) {
18368
18709
  if (kwargs.suffix !== void 0) {
18369
18710
  span2.setAttribute(
18370
18711
  "llm.request.suffix",
18371
- truncate(safeStringify(kwargs.suffix), Config.CONVERSATION_MAX_LEN)
18712
+ safeStringify(kwargs.suffix, Config.CONVERSATION_MAX_LEN)
18372
18713
  );
18373
18714
  }
18374
18715
  }
@@ -18391,12 +18732,20 @@ function setResponseAttributes(span2, response) {
18391
18732
  }
18392
18733
  }
18393
18734
  function setFinishReason(span2, response) {
18735
+ if (response.stop_reason) {
18736
+ span2.setAttribute(
18737
+ SpanAttributes2.LLM_RESPONSE_FINISH_REASON,
18738
+ String(response.stop_reason)
18739
+ );
18740
+ span2.setAttribute("gen_ai.response.finish_reason", String(response.stop_reason));
18741
+ }
18394
18742
  const choices = response.choices;
18395
- if (!Array.isArray(choices) || choices.length === 0) return;
18396
- const reason = choices[0].finish_reason ?? choices[0].finishReason;
18397
- if (reason) {
18398
- span2.setAttribute("gen_ai.response.finish_reason", String(reason));
18399
- span2.setAttribute("llm.response.finish_reason", String(reason));
18743
+ if (Array.isArray(choices) && choices.length > 0) {
18744
+ const reason = choices[0].finish_reason ?? choices[0].finishReason;
18745
+ if (reason) {
18746
+ span2.setAttribute(SpanAttributes2.LLM_RESPONSE_FINISH_REASON, String(reason));
18747
+ span2.setAttribute("gen_ai.response.finish_reason", String(reason));
18748
+ }
18400
18749
  }
18401
18750
  }
18402
18751
  function setUsageAttributes(span2, response) {
@@ -18423,11 +18772,18 @@ function setUsageAttributes(span2, response) {
18423
18772
  Number(totalTokens)
18424
18773
  );
18425
18774
  }
18426
- const cacheTokens = (usage.prompt_tokens_details ?? usage.input_tokens_details)?.cached_tokens;
18427
- if (cacheTokens !== void 0) {
18775
+ const cacheReadTokens = usage.cache_read_input_tokens ?? (usage.prompt_tokens_details ?? usage.input_tokens_details)?.cached_tokens;
18776
+ if (cacheReadTokens !== void 0) {
18428
18777
  span2.setAttribute(
18429
18778
  SpanAttributes2.LLM_USAGE_CACHE_READ_INPUT_TOKENS,
18430
- Number(cacheTokens)
18779
+ Number(cacheReadTokens)
18780
+ );
18781
+ }
18782
+ const cacheCreationTokens = usage.cache_creation_input_tokens;
18783
+ if (cacheCreationTokens !== void 0) {
18784
+ span2.setAttribute(
18785
+ SpanAttributes2.LLM_USAGE_CACHE_CREATION_INPUT_TOKENS,
18786
+ Number(cacheCreationTokens)
18431
18787
  );
18432
18788
  }
18433
18789
  const reasoningTokens = (usage.completion_tokens_details ?? usage.output_tokens_details)?.reasoning_tokens;
@@ -18449,188 +18805,181 @@ function setEmbeddingResponseMeta(span2, response) {
18449
18805
  }
18450
18806
  }
18451
18807
 
18452
- // src/instrumentation/anthropic/utils.ts
18453
- function setRequestAttributes2(span2, kwargs, requestType) {
18454
- if (!span2.isRecording()) {
18455
- Logger.log("Span is not recording");
18456
- return;
18457
- }
18458
- setRequestAttributes(span2, kwargs, requestType, "anthropic");
18459
- }
18460
- function setResponseAttributes2(span2, response) {
18461
- if (!span2.isRecording()) {
18462
- Logger.log("Span is not recording");
18463
- return;
18464
- }
18465
- if (response?.type === "message_batch") {
18466
- span2.setAttribute("status", response?.processing_status);
18467
- }
18468
- setResponseAttributes(span2, response);
18469
- }
18808
+ // src/instrumentation/anthropic/types.ts
18809
+ var SPAN_NAMES = {
18810
+ CHAT: "anthropic.chat",
18811
+ STREAM: "anthropic.stream",
18812
+ BATCHES: "anthropic.batches",
18813
+ BETA: "anthropic.beta",
18814
+ BETA_STREAM: "anthropic.beta.stream",
18815
+ BETA_TOOL_RUNNER: "anthropic.beta.tool.runner"
18816
+ };
18470
18817
 
18471
- // src/instrumentation/anthropic/version.ts
18472
- var __version__ = "1.0.0";
18473
- var CHAT_SPAN_NAME = "anthropic.chat";
18474
- var BETA_SPAN_NAME = "anthropic.beta";
18475
- var BATCHES_SPAN_NAME = "anthropic.batches";
18476
- var STREAM_ENABLED_REQUESTS = ["chat", "beta"];
18477
- function anthropicWrapper(tracer, spanName, requestType) {
18478
- return function wrapper(wrapped, instance, args, kwargs) {
18479
- if (shouldSuppressInstrumentation()) {
18480
- const result = wrapped.call(instance, ...args);
18481
- return isPromise(result) ? result.then((value) => value) : result;
18482
- }
18483
- const currentContext = api.context.active();
18484
- const isStreaming = args[0]?.stream === true;
18485
- const activeSpan = api.trace.getSpan(api.context.active());
18486
- Logger.debug(`Anthropic invoke (${requestType}). Active TraceId: ${activeSpan?.spanContext().traceId}, SpanId: ${activeSpan?.spanContext().spanId}`);
18487
- if (isStreaming && STREAM_ENABLED_REQUESTS.includes(requestType)) {
18488
- const span2 = tracer.startSpan(
18489
- spanName + ".create",
18490
- {
18491
- kind: api.SpanKind.CLIENT,
18492
- attributes: {
18493
- "llm.request.type": requestType,
18494
- "llm.streaming": true
18495
- }
18496
- },
18497
- currentContext
18498
- );
18499
- try {
18500
- setRequestAttributes2(span2, kwargs, requestType);
18501
- const startTime = Date.now();
18502
- const spanContext = api.trace.setSpan(currentContext, span2);
18503
- const response = api.context.with(spanContext, () => wrapped.call(instance, ...args));
18504
- if (isPromise(response)) {
18505
- return (async () => {
18506
- try {
18507
- const stream = await response;
18508
- return new AsyncStreamingWrapper(span2, stream, startTime, kwargs, spanContext);
18509
- } catch (error) {
18510
- Logger.error("netra.instrumentation.anthropic:", error);
18511
- span2.setStatus({
18512
- code: api.SpanStatusCode.ERROR,
18513
- message: error instanceof Error ? error.message : String(error)
18514
- });
18515
- span2.recordException(error);
18516
- span2.end();
18517
- throw error;
18518
- }
18519
- })();
18818
+ // src/instrumentation/anthropic/utils.ts
18819
+ function processStreamChunk(completeResponse, chunk, span2) {
18820
+ try {
18821
+ switch (chunk.type) {
18822
+ case "message_start": {
18823
+ if (chunk.message?.model) {
18824
+ completeResponse.model = chunk.message.model;
18825
+ }
18826
+ if (chunk.message?.usage) {
18827
+ completeResponse.usage = chunk.message.usage;
18828
+ }
18829
+ break;
18830
+ }
18831
+ case "content_block_start": {
18832
+ if (!completeResponse.content) {
18833
+ completeResponse.content = [];
18834
+ }
18835
+ const block = chunk.content_block;
18836
+ if (!block) break;
18837
+ if (block.type === "tool_use") {
18838
+ completeResponse.content.push({
18839
+ type: "tool_use",
18840
+ id: block.id,
18841
+ name: block.name,
18842
+ input: ""
18843
+ });
18520
18844
  } else {
18521
- return new AsyncStreamingWrapper(span2, response, startTime, kwargs, spanContext);
18845
+ completeResponse.content.push({
18846
+ type: block.type,
18847
+ text: ""
18848
+ });
18522
18849
  }
18523
- } catch (error) {
18524
- Logger.error("netra.instrumentation.anthropic:", error);
18525
- span2.setStatus({
18526
- code: api.SpanStatusCode.ERROR,
18527
- message: error instanceof Error ? error.message : String(error)
18528
- });
18529
- span2.recordException(error);
18530
- span2.end();
18531
- throw error;
18850
+ break;
18532
18851
  }
18533
- } else {
18534
- return tracer.startActiveSpan(
18535
- spanName,
18536
- {
18537
- kind: api.SpanKind.CLIENT,
18538
- attributes: { "llm.request.type": requestType }
18539
- },
18540
- (span2) => {
18541
- try {
18542
- setRequestAttributes2(span2, kwargs, requestType);
18543
- const startTime = Date.now();
18544
- const spanContext = api.trace.setSpan(currentContext, span2);
18545
- const response = api.context.with(spanContext, () => wrapped.call(instance, ...args));
18546
- if (isPromise(response)) {
18547
- const instrumentedPromise = (async () => {
18548
- try {
18549
- const value = await response;
18550
- const endTime = Date.now();
18551
- const responseDict = modelAsDict(value);
18552
- setResponseAttributes2(span2, responseDict);
18553
- span2.setAttribute(
18554
- "llm.response.duration",
18555
- (endTime - startTime) / 1e3
18556
- );
18557
- span2.setStatus({ code: api.SpanStatusCode.OK });
18558
- span2.end();
18559
- return value;
18560
- } catch (error) {
18561
- Logger.error("netra.instrumentation.anthropic:", error);
18562
- span2.setStatus({
18563
- code: api.SpanStatusCode.ERROR,
18564
- message: error instanceof Error ? error.message : String(error)
18565
- });
18566
- span2.recordException(error);
18567
- span2.end();
18568
- throw error;
18569
- }
18570
- })();
18571
- return new Proxy(instrumentedPromise, {
18572
- get(target, prop, receiver) {
18573
- if (prop === "then" || prop === "catch" || prop === "finally") {
18574
- const value2 = Reflect.get(target, prop, receiver);
18575
- if (typeof value2 === "function") {
18576
- return value2.bind(target);
18577
- }
18578
- return value2;
18579
- }
18580
- const responseValue = response[prop];
18581
- if (responseValue !== void 0) {
18582
- if (typeof responseValue === "function") {
18583
- return responseValue.bind(response);
18584
- }
18585
- return responseValue;
18586
- }
18587
- const value = Reflect.get(target, prop, receiver);
18588
- if (typeof value === "function") {
18589
- return value.bind(target);
18590
- }
18591
- return value;
18592
- }
18593
- });
18594
- } else {
18595
- const endTime = Date.now();
18596
- const responseDict = modelAsDict(response);
18597
- setResponseAttributes2(span2, responseDict);
18598
- span2.setAttribute(
18599
- "llm.response.duration",
18600
- (endTime - startTime) / 1e3
18852
+ case "content_block_delta": {
18853
+ if (!completeResponse.content || completeResponse.content.length === 0) {
18854
+ completeResponse.content = [{ type: "text", text: "" }];
18855
+ }
18856
+ const targetIndex = chunk.index ?? completeResponse.content.length - 1;
18857
+ const targetBlock = completeResponse.content[targetIndex];
18858
+ if (!targetBlock) break;
18859
+ if (chunk.delta?.type === "input_json_delta" && targetBlock.type === "tool_use") {
18860
+ targetBlock.input += chunk.delta.partial_json ?? "";
18861
+ } else if (chunk.delta?.text) {
18862
+ targetBlock.text += chunk.delta.text;
18863
+ }
18864
+ break;
18865
+ }
18866
+ case "content_block_stop": {
18867
+ const blocks = completeResponse.content;
18868
+ if (blocks && blocks.length > 0) {
18869
+ const finishedBlock = blocks[blocks.length - 1];
18870
+ if (finishedBlock?.type === "tool_use" && typeof finishedBlock.input === "string") {
18871
+ try {
18872
+ finishedBlock.input = JSON.parse(finishedBlock.input);
18873
+ } catch {
18874
+ Logger.warn(
18875
+ "netra.instrumentation.anthropic: Failed to parse tool use input"
18601
18876
  );
18602
- span2.setStatus({ code: api.SpanStatusCode.OK });
18603
- span2.end();
18604
- return response;
18605
18877
  }
18606
- } catch (error) {
18607
- Logger.error("netra.instrumentation.anthropic:", error);
18608
- span2.setStatus({
18609
- code: api.SpanStatusCode.ERROR,
18610
- message: error instanceof Error ? error.message : String(error)
18611
- });
18612
- span2.recordException(error);
18613
- span2.end();
18614
- throw error;
18615
18878
  }
18616
18879
  }
18617
- );
18880
+ break;
18881
+ }
18882
+ case "message_delta": {
18883
+ if (chunk.delta?.stop_reason) {
18884
+ completeResponse.stop_reason = chunk.delta.stop_reason;
18885
+ }
18886
+ const usageData = chunk.usage ?? chunk.delta?.usage;
18887
+ if (usageData) {
18888
+ completeResponse.usage = {
18889
+ ...completeResponse.usage ?? {},
18890
+ ...usageData
18891
+ };
18892
+ }
18893
+ break;
18894
+ }
18895
+ case "message_stop": {
18896
+ if (chunk.usage) {
18897
+ completeResponse.usage = {
18898
+ ...completeResponse.usage ?? {},
18899
+ ...chunk.usage
18900
+ };
18901
+ }
18902
+ break;
18903
+ }
18618
18904
  }
18619
- };
18905
+ if (Logger.isDebugMode()) {
18906
+ span2.addEvent("llm.content.completion.chunk", {
18907
+ "chunk.type": chunk.type
18908
+ });
18909
+ }
18910
+ } catch (e) {
18911
+ Logger.error(
18912
+ "netra.instrumentation.anthropic: processStreamChunk error",
18913
+ e
18914
+ );
18915
+ }
18916
+ }
18917
+ function finalizeStreamSpan(span2, completeResponse, startTime, code) {
18918
+ try {
18919
+ const endTime = Date.now();
18920
+ setResponseAttributes2(span2, {
18921
+ model: completeResponse.model,
18922
+ content: completeResponse.content,
18923
+ usage: completeResponse.usage,
18924
+ stop_reason: completeResponse.stop_reason
18925
+ });
18926
+ span2.setAttribute("llm.response.duration", (endTime - startTime) / 1e3);
18927
+ span2.setStatus({ code });
18928
+ } catch (e) {
18929
+ Logger.error(
18930
+ "netra.instrumentation.anthropic: finalizeStreamSpan error",
18931
+ e
18932
+ );
18933
+ } finally {
18934
+ span2.end();
18935
+ }
18620
18936
  }
18621
- var chatWrapper = (tracer) => anthropicWrapper(tracer, CHAT_SPAN_NAME, "chat");
18622
- var betaWrapper = (tracer) => anthropicWrapper(tracer, BETA_SPAN_NAME, "beta");
18623
- var batchesWrapper = (tracer) => anthropicWrapper(tracer, BATCHES_SPAN_NAME, "batches");
18937
+ function setRequestAttributes2(span2, kwargs, requestType) {
18938
+ try {
18939
+ if (!span2.isRecording()) {
18940
+ Logger.log("Span is not recording");
18941
+ return;
18942
+ }
18943
+ setRequestAttributes(span2, kwargs, requestType, "anthropic");
18944
+ } catch (e) {
18945
+ Logger.error(
18946
+ "netra.instrumentation.anthropic: setRequestAttributes error",
18947
+ e
18948
+ );
18949
+ }
18950
+ }
18951
+ function setResponseAttributes2(span2, response) {
18952
+ try {
18953
+ if (!span2.isRecording()) {
18954
+ Logger.log("Span is not recording");
18955
+ return;
18956
+ }
18957
+ if (response?.type === "message_batch") {
18958
+ span2.setAttribute("status", response?.processing_status);
18959
+ }
18960
+ setResponseAttributes(span2, response);
18961
+ } catch (e) {
18962
+ Logger.error(
18963
+ "netra.instrumentation.anthropic: setResponseAttributes error",
18964
+ e
18965
+ );
18966
+ }
18967
+ }
18968
+
18969
+ // src/instrumentation/anthropic/wrappers.ts
18624
18970
  var WRAPPER_OWN_PROPS = /* @__PURE__ */ new Set([
18625
18971
  "span",
18626
18972
  "messageStream",
18627
18973
  "startTime",
18628
18974
  "requestKwargs",
18629
18975
  "completeResponse",
18630
- "processChunk",
18631
- "finalizeSpan",
18976
+ "finalizeSpanOnce",
18632
18977
  "processEventData",
18633
- "finalizeSpanFromMessage"
18978
+ "finalizeSpanFromMessage",
18979
+ "parentContext",
18980
+ "spanFinalized",
18981
+ "completionPending",
18982
+ "listenerMap"
18634
18983
  ]);
18635
18984
  var EVENT_EMITTER_METHODS = /* @__PURE__ */ new Set([
18636
18985
  "on",
@@ -18644,20 +18993,90 @@ var EVENT_EMITTER_METHODS = /* @__PURE__ */ new Set([
18644
18993
  "listenerCount"
18645
18994
  ]);
18646
18995
  var LISTENER_REGISTRATION_METHODS = /* @__PURE__ */ new Set(["on", "once", "addListener"]);
18996
+ var LISTENER_REMOVAL_METHODS = /* @__PURE__ */ new Set(["off", "removeListener"]);
18647
18997
  var COMPLETION_METHODS = /* @__PURE__ */ new Set(["finalMessage", "done", "finalText"]);
18648
- var TRACKED_STREAM_EVENTS = /* @__PURE__ */ new Set(["message", "contentBlock", "text", "finalMessage"]);
18998
+ var TRACKED_STREAM_EVENTS = /* @__PURE__ */ new Set([
18999
+ "message",
19000
+ "contentBlock",
19001
+ "text",
19002
+ "finalMessage"
19003
+ ]);
19004
+ var MAX_TOOL_ATTR_LENGTH = 4096;
19005
+ function wrapRunnableTools(tools, tracer, parentContext) {
19006
+ return tools.map((tool) => {
19007
+ if (typeof tool.run !== "function") return tool;
19008
+ const originalRun = tool.run;
19009
+ const toolName = tool.name ?? "unknown_tool";
19010
+ const wrappedRun = async function(input, runContext) {
19011
+ const toolUseId = runContext?.toolUse?.id ?? runContext?.toolUseBlock?.id;
19012
+ const traceContent = isTraceContentEnabled();
19013
+ const attrs = {
19014
+ "netra.span.type": "TOOL",
19015
+ [SpanAttributes2.LLM_REQUEST_TOOL_NAME]: toolName
19016
+ };
19017
+ if (toolUseId) attrs[SpanAttributes2.LLM_REQUEST_TOOL_ID] = toolUseId;
19018
+ if (traceContent) {
19019
+ attrs.input = safeStringify(input, MAX_TOOL_ATTR_LENGTH);
19020
+ }
19021
+ const span2 = tracer.startSpan(
19022
+ toolName,
19023
+ { kind: api.SpanKind.INTERNAL, attributes: attrs },
19024
+ parentContext
19025
+ );
19026
+ const spanCtx = api.trace.setSpan(parentContext, span2);
19027
+ try {
19028
+ const result = await api.context.with(
19029
+ spanCtx,
19030
+ () => originalRun.call(this, input, runContext)
19031
+ );
19032
+ if (traceContent) {
19033
+ span2.setAttribute(
19034
+ "output",
19035
+ safeStringify(result, MAX_TOOL_ATTR_LENGTH)
19036
+ );
19037
+ }
19038
+ span2.setStatus({ code: api.SpanStatusCode.OK });
19039
+ return result;
19040
+ } catch (error) {
19041
+ span2.setStatus({
19042
+ code: api.SpanStatusCode.ERROR,
19043
+ message: error instanceof Error ? error.message : String(error)
19044
+ });
19045
+ span2.recordException(error);
19046
+ throw error;
19047
+ } finally {
19048
+ span2.end();
19049
+ }
19050
+ };
19051
+ const wrapped = Object.create(
19052
+ Object.getPrototypeOf(tool),
19053
+ Object.getOwnPropertyDescriptors(tool)
19054
+ );
19055
+ wrapped.run = wrappedRun;
19056
+ return wrapped;
19057
+ });
19058
+ }
18649
19059
  var MessageStreamWrapper = class {
18650
- constructor(span2, messageStream, startTime, requestKwargs, spanContext) {
19060
+ constructor(span2, messageStream, startTime, requestKwargs, spanContext, parentContext) {
18651
19061
  this.completeResponse = {
18652
19062
  content: [],
18653
19063
  model: "",
18654
19064
  usage: {}
18655
19065
  };
19066
+ this.spanFinalized = false;
19067
+ this.completionPending = false;
19068
+ this.listenerMap = /* @__PURE__ */ new WeakMap();
18656
19069
  defineHidden(this, "span", span2);
18657
19070
  defineHidden(this, "messageStream", messageStream);
18658
19071
  defineHidden(this, "startTime", startTime);
18659
19072
  defineHidden(this, "requestKwargs", requestKwargs);
18660
- defineHidden(this, "spanContext", spanContext || api.trace.setSpan(api.context.active(), span2));
19073
+ defineHidden(
19074
+ this,
19075
+ "spanContext",
19076
+ spanContext || api.trace.setSpan(api.context.active(), span2)
19077
+ );
19078
+ defineHidden(this, "parentContext", parentContext || api.context.active());
19079
+ this.registerSafetyNetListeners();
18661
19080
  return new Proxy(this, {
18662
19081
  get(target, prop, receiver) {
18663
19082
  if (prop === "toJSON") {
@@ -18671,67 +19090,135 @@ var MessageStreamWrapper = class {
18671
19090
  }
18672
19091
  if (typeof prop === "string" && EVENT_EMITTER_METHODS.has(prop)) {
18673
19092
  const method = target.messageStream[prop];
18674
- if (typeof method === "function") {
18675
- if (LISTENER_REGISTRATION_METHODS.has(prop)) {
18676
- return function(event, listener) {
18677
- const wrappedListener = (...args) => {
19093
+ if (typeof method !== "function") return method;
19094
+ if (LISTENER_REGISTRATION_METHODS.has(prop)) {
19095
+ return function(event, listener) {
19096
+ const wrappedListener = (...args) => {
19097
+ try {
18678
19098
  target.span.addEvent(`messagestream.event.${event}`, {
18679
19099
  "event.type": event
18680
19100
  });
18681
- if (TRACKED_STREAM_EVENTS.has(event)) {
18682
- if (args[0]) {
18683
- target.processEventData(event, args[0]);
18684
- }
19101
+ if (TRACKED_STREAM_EVENTS.has(event) && args[0]) {
19102
+ target.processEventData(event, args[0]);
18685
19103
  }
18686
- return listener(...args);
18687
- };
18688
- return method.call(target.messageStream, event, wrappedListener);
19104
+ } catch (e) {
19105
+ Logger.error(
19106
+ "netra.instrumentation.anthropic: event tracking error",
19107
+ e
19108
+ );
19109
+ }
19110
+ return listener(...args);
18689
19111
  };
18690
- }
18691
- return method.bind(target.messageStream);
19112
+ let eventMap = target.listenerMap.get(listener);
19113
+ if (!eventMap) {
19114
+ eventMap = /* @__PURE__ */ new Map();
19115
+ target.listenerMap.set(listener, eventMap);
19116
+ }
19117
+ let wrappers = eventMap.get(event);
19118
+ if (!wrappers) {
19119
+ wrappers = [];
19120
+ eventMap.set(event, wrappers);
19121
+ }
19122
+ wrappers.push(wrappedListener);
19123
+ return method.call(target.messageStream, event, wrappedListener);
19124
+ };
19125
+ }
19126
+ if (LISTENER_REMOVAL_METHODS.has(prop)) {
19127
+ return function(event, listener) {
19128
+ const eventMap = target.listenerMap.get(listener);
19129
+ const wrappers = eventMap?.get(event);
19130
+ const wrapped = wrappers?.shift() ?? listener;
19131
+ if (wrappers && wrappers.length === 0) eventMap?.delete(event);
19132
+ return method.call(target.messageStream, event, wrapped);
19133
+ };
18692
19134
  }
18693
- return method;
19135
+ if (prop === "removeAllListeners") {
19136
+ return function(event) {
19137
+ target.listenerMap = /* @__PURE__ */ new WeakMap();
19138
+ return method.call(target.messageStream, event);
19139
+ };
19140
+ }
19141
+ return method.bind(target.messageStream);
18694
19142
  }
18695
19143
  if (typeof prop === "string" && COMPLETION_METHODS.has(prop)) {
18696
19144
  const method = target.messageStream[prop];
18697
- if (typeof method === "function") {
18698
- return async function(...args) {
18699
- try {
18700
- const result = await method.call(target.messageStream, ...args);
18701
- if (prop === "finalMessage" || prop === "done") {
18702
- target.finalizeSpanFromMessage(result);
19145
+ if (typeof method !== "function") return method;
19146
+ return async function(...args) {
19147
+ target.completionPending = true;
19148
+ try {
19149
+ const result = await method.call(target.messageStream, ...args);
19150
+ if (prop === "finalMessage" || prop === "done") {
19151
+ target.finalizeSpanFromMessage(result);
19152
+ } else if (prop === "finalText") {
19153
+ if (typeof result === "string" && result.length > 0) {
19154
+ target.completeResponse.content = [
19155
+ { type: "text", text: result }
19156
+ ];
19157
+ } else {
19158
+ target.flushCurrentText();
18703
19159
  }
18704
- return result;
18705
- } catch (error) {
18706
- target.finalizeSpan(api.SpanStatusCode.ERROR);
18707
- throw error;
19160
+ target.finalizeSpanOnce(api.SpanStatusCode.OK);
18708
19161
  }
18709
- };
18710
- }
18711
- return method;
19162
+ return result;
19163
+ } catch (error) {
19164
+ target.finalizeSpanOnce(api.SpanStatusCode.ERROR);
19165
+ throw error;
19166
+ }
19167
+ };
18712
19168
  }
18713
19169
  const value = target.messageStream[prop];
18714
- if (typeof value === "function") {
19170
+ if (typeof value === "function")
18715
19171
  return value.bind(target.messageStream);
18716
- }
18717
19172
  return value;
18718
19173
  }
18719
19174
  });
18720
19175
  }
19176
+ registerSafetyNetListeners() {
19177
+ try {
19178
+ if (typeof this.messageStream?.on !== "function") return;
19179
+ this.messageStream.on("end", () => {
19180
+ if (!this.completionPending) {
19181
+ this.finalizeSpanOnce(api.SpanStatusCode.OK);
19182
+ }
19183
+ });
19184
+ this.messageStream.on("error", (err) => {
19185
+ if (err && !this.spanFinalized) {
19186
+ this.span.setStatus({
19187
+ code: api.SpanStatusCode.ERROR,
19188
+ message: err instanceof Error ? err.message : String(err)
19189
+ });
19190
+ this.span.recordException(
19191
+ err instanceof Error ? err : new Error(String(err))
19192
+ );
19193
+ }
19194
+ this.finalizeSpanOnce(api.SpanStatusCode.ERROR);
19195
+ });
19196
+ } catch (e) {
19197
+ Logger.error(
19198
+ "netra.instrumentation.anthropic: safety net listener registration failed",
19199
+ e
19200
+ );
19201
+ }
19202
+ }
18721
19203
  toJSON() {
18722
19204
  return this.completeResponse;
18723
19205
  }
18724
19206
  async *[Symbol.asyncIterator]() {
19207
+ let errorOccurred = false;
18725
19208
  try {
18726
19209
  for await (const chunk of this.messageStream) {
18727
- this.processChunk(chunk);
19210
+ processStreamChunk(this.completeResponse, chunk, this.span);
18728
19211
  yield chunk;
18729
19212
  }
18730
- this.finalizeSpan(api.SpanStatusCode.OK);
18731
19213
  } catch (err) {
19214
+ errorOccurred = true;
18732
19215
  Logger.error("netra.instrumentation.anthropic: Stream error", err);
18733
- this.finalizeSpan(api.SpanStatusCode.ERROR);
19216
+ this.finalizeSpanOnce(api.SpanStatusCode.ERROR);
18734
19217
  throw err;
19218
+ } finally {
19219
+ if (!errorOccurred) {
19220
+ this.finalizeSpanOnce(api.SpanStatusCode.OK);
19221
+ }
18735
19222
  }
18736
19223
  }
18737
19224
  getSpanContext() {
@@ -18740,12 +19227,8 @@ var MessageStreamWrapper = class {
18740
19227
  processEventData(eventType, data) {
18741
19228
  switch (eventType) {
18742
19229
  case "message":
18743
- if (data.model) {
18744
- this.completeResponse.model = data.model;
18745
- }
18746
- if (data.usage) {
18747
- this.completeResponse.usage = data.usage;
18748
- }
19230
+ if (data.model) this.completeResponse.model = data.model;
19231
+ if (data.usage) this.completeResponse.usage = data.usage;
18749
19232
  break;
18750
19233
  case "text":
18751
19234
  if (!this.completeResponse.currentText) {
@@ -18766,250 +19249,359 @@ var MessageStreamWrapper = class {
18766
19249
  break;
18767
19250
  }
18768
19251
  }
18769
- processChunk(chunk) {
18770
- switch (chunk.type) {
18771
- case "message_start": {
18772
- if (chunk.message?.model) {
18773
- this.completeResponse.model = chunk.message.model;
18774
- }
18775
- if (chunk.message?.usage) {
18776
- this.completeResponse.usage = chunk.message.usage;
18777
- }
18778
- break;
18779
- }
18780
- case "content_block_start": {
18781
- if (!this.completeResponse.content) {
18782
- this.completeResponse.content = [];
18783
- }
18784
- const block = chunk.content_block;
18785
- if (block.type === "tool_use") {
18786
- this.completeResponse.content.push({
18787
- type: "tool_use",
18788
- id: block.id,
18789
- name: block.name,
18790
- input: ""
18791
- });
18792
- } else {
18793
- this.completeResponse.content.push({
18794
- type: block.type,
18795
- text: ""
18796
- });
18797
- }
18798
- break;
18799
- }
18800
- case "content_block_delta": {
18801
- if (!this.completeResponse.content || this.completeResponse.content.length === 0) {
18802
- this.completeResponse.content = [{ type: "text", text: "" }];
18803
- }
18804
- const lastBlock = this.completeResponse.content[this.completeResponse.content.length - 1];
18805
- if (chunk.delta?.type === "input_json_delta" && lastBlock?.type === "tool_use") {
18806
- lastBlock.input += chunk.delta.partial_json ?? "";
18807
- } else if (lastBlock && chunk.delta?.text) {
18808
- lastBlock.text += chunk.delta.text;
18809
- }
18810
- break;
18811
- }
18812
- case "content_block_stop": {
18813
- const blocks = this.completeResponse.content;
18814
- if (blocks && blocks.length > 0) {
18815
- const finishedBlock = blocks[blocks.length - 1];
18816
- if (finishedBlock?.type === "tool_use" && typeof finishedBlock.input === "string") {
18817
- try {
18818
- finishedBlock.input = JSON.parse(finishedBlock.input);
18819
- } catch {
18820
- Logger.warn("netra.instrumentation.anthropic: Failed to parse tool use input", finishedBlock.input);
18821
- }
18822
- }
18823
- }
18824
- break;
18825
- }
18826
- case "message_delta": {
18827
- if (chunk.delta?.usage) {
18828
- this.completeResponse.usage = {
18829
- ...this.completeResponse.usage,
18830
- ...chunk.delta.usage
18831
- };
18832
- }
18833
- break;
18834
- }
18835
- case "message_stop": {
18836
- if (chunk.usage) {
18837
- this.completeResponse.usage = chunk.usage;
18838
- }
18839
- break;
18840
- }
19252
+ flushCurrentText() {
19253
+ if (this.completeResponse.currentText && (!this.completeResponse.content || this.completeResponse.content.length === 0)) {
19254
+ this.completeResponse.content = [
19255
+ { type: "text", text: this.completeResponse.currentText }
19256
+ ];
18841
19257
  }
18842
- this.span.addEvent("llm.content.completion.chunk", {
18843
- "chunk.type": chunk.type
18844
- });
18845
19258
  }
18846
19259
  finalizeSpanFromMessage(message) {
18847
19260
  if (message) {
18848
19261
  if (message.model) this.completeResponse.model = message.model;
18849
19262
  if (message.content) this.completeResponse.content = message.content;
18850
19263
  if (message.usage) this.completeResponse.usage = message.usage;
19264
+ if (message.stop_reason)
19265
+ this.completeResponse.stop_reason = message.stop_reason;
18851
19266
  }
18852
- this.finalizeSpan(api.SpanStatusCode.OK);
19267
+ this.finalizeSpanOnce(api.SpanStatusCode.OK);
18853
19268
  }
18854
- finalizeSpan(code) {
18855
- const endTime = Date.now();
18856
- const duration = (endTime - this.startTime) / 1e3;
18857
- setResponseAttributes2(this.span, {
18858
- model: this.completeResponse.model,
18859
- content: this.completeResponse.content,
18860
- usage: this.completeResponse.usage
18861
- });
18862
- this.span.setAttribute("llm.response.duration", duration);
18863
- this.span.setStatus({ code });
18864
- this.span.end();
19269
+ finalizeSpanOnce(code) {
19270
+ if (this.spanFinalized) return;
19271
+ this.spanFinalized = true;
19272
+ finalizeStreamSpan(this.span, this.completeResponse, this.startTime, code);
18865
19273
  }
18866
19274
  };
18867
- var AsyncStreamingWrapper = class {
18868
- constructor(span2, response, startTime, requestKwargs, spanContext) {
18869
- this.iterator = null;
18870
- this.completeResponse = {
18871
- choices: [],
18872
- model: ""
18873
- };
18874
- defineHidden(this, "span", span2);
18875
- defineHidden(this, "response", response);
18876
- defineHidden(this, "startTime", startTime);
18877
- defineHidden(this, "requestKwargs", requestKwargs);
18878
- defineHidden(this, "spanContext", spanContext || api.trace.setSpan(api.context.active(), span2));
18879
- }
18880
- toJSON() {
18881
- return this.completeResponse;
18882
- }
18883
- [Symbol.asyncIterator]() {
18884
- return this;
18885
- }
18886
- async next() {
18887
- try {
18888
- if (!this.iterator) {
18889
- if (Symbol.asyncIterator in this.response) {
18890
- this.iterator = this.response[Symbol.asyncIterator]();
18891
- } else if (typeof this.response.next === "function") {
18892
- this.iterator = this.response;
18893
- } else {
18894
- throw new Error("Response is not iterable");
18895
- }
18896
- }
18897
- const result = await api.context.with(this.spanContext, () => this.iterator.next());
18898
- if (result.done) {
18899
- this.finalizeSpan(api.SpanStatusCode.OK);
18900
- return result;
18901
- }
18902
- this.processChunk(result.value);
18903
- return result;
18904
- } catch (error) {
18905
- this.finalizeSpan(api.SpanStatusCode.ERROR);
18906
- throw error;
18907
- }
18908
- }
18909
- processChunk(chunk) {
18910
- switch (chunk.type) {
18911
- case "message_start": {
18912
- if (chunk.message?.model) {
18913
- this.completeResponse.model = chunk.message.model;
18914
- }
18915
- if (chunk.message?.usage) {
18916
- this.completeResponse.usage = chunk.message.usage;
18917
- }
18918
- break;
18919
- }
18920
- case "content_block_start": {
18921
- const content = this.completeResponse.content || [];
18922
- this.completeResponse.content = content;
18923
- const block = chunk.content_block;
18924
- if (block.type === "tool_use") {
18925
- content.push({
18926
- type: "tool_use",
18927
- id: block.id,
18928
- name: block.name,
18929
- input: ""
18930
- });
18931
- } else {
18932
- content.push({
18933
- type: block.type,
18934
- text: ""
18935
- });
18936
- }
18937
- break;
19275
+ function anthropicWrapper(tracer, spanName, requestType) {
19276
+ return function wrapper(original) {
19277
+ return function(...args) {
19278
+ if (shouldSuppressInstrumentation()) {
19279
+ return original.apply(this, args);
18938
19280
  }
18939
- case "content_block_delta": {
18940
- const content = this.completeResponse.content || [];
18941
- if (content.length === 0) {
18942
- content.push({ type: "text", text: "" });
18943
- this.completeResponse.content = content;
18944
- }
18945
- const lastBlock = content[content.length - 1];
18946
- if (chunk.delta?.type === "input_json_delta" && lastBlock?.type === "tool_use") {
18947
- lastBlock.input += chunk.delta.partial_json ?? "";
18948
- } else if (lastBlock && chunk.delta?.text) {
18949
- lastBlock.text += chunk.delta.text;
19281
+ const attributes = args[0] || {};
19282
+ const currentContext = api.context.active();
19283
+ const isStreaming = attributes.stream === true;
19284
+ const activeSpan = api.trace.getSpan(currentContext);
19285
+ Logger.debug(
19286
+ `Anthropic invoke (${requestType}). Active TraceId: ${activeSpan?.spanContext().traceId}, SpanId: ${activeSpan?.spanContext().spanId}`
19287
+ );
19288
+ return tracer.startActiveSpan(
19289
+ spanName,
19290
+ {
19291
+ kind: api.SpanKind.CLIENT,
19292
+ attributes: { "llm.request.type": requestType }
19293
+ },
19294
+ (span2) => {
19295
+ try {
19296
+ setRequestAttributes2(span2, attributes, requestType);
19297
+ if (isStreaming) {
19298
+ span2.setAttribute("llm.streaming", true);
19299
+ }
19300
+ const startTime = Date.now();
19301
+ const spanContext = api.trace.setSpan(currentContext, span2);
19302
+ const response = api.context.with(
19303
+ spanContext,
19304
+ () => original.apply(this, args)
19305
+ );
19306
+ const completeResponse = {
19307
+ content: [],
19308
+ model: "",
19309
+ usage: {}
19310
+ };
19311
+ return wrapResponse(
19312
+ response,
19313
+ {
19314
+ withContext: (fn) => api.context.with(spanContext, fn),
19315
+ onChunk: (chunk) => processStreamChunk(completeResponse, chunk, span2),
19316
+ onError: (error) => {
19317
+ Logger.error("netra.instrumentation.anthropic:", error);
19318
+ span2.setStatus({
19319
+ code: api.SpanStatusCode.ERROR,
19320
+ message: error instanceof Error ? error.message : String(error)
19321
+ });
19322
+ span2.recordException(error);
19323
+ },
19324
+ onSuccess: (value) => {
19325
+ const endTime = Date.now();
19326
+ const responseDict = modelAsDict(value);
19327
+ setResponseAttributes2(span2, responseDict);
19328
+ span2.setAttribute(
19329
+ "llm.response.duration",
19330
+ (endTime - startTime) / 1e3
19331
+ );
19332
+ },
19333
+ finalize: (status) => {
19334
+ const hasStreamData = completeResponse.content?.length || completeResponse.model || completeResponse.usage?.input_tokens !== void 0 || completeResponse.usage?.output_tokens !== void 0;
19335
+ if (status === "ok" && hasStreamData) {
19336
+ finalizeStreamSpan(
19337
+ span2,
19338
+ completeResponse,
19339
+ startTime,
19340
+ api.SpanStatusCode.OK
19341
+ );
19342
+ } else {
19343
+ if (status === "ok") {
19344
+ span2.setStatus({ code: api.SpanStatusCode.OK });
19345
+ }
19346
+ span2.end();
19347
+ }
19348
+ }
19349
+ },
19350
+ { preserveOriginal: response }
19351
+ );
19352
+ } catch (error) {
19353
+ Logger.error("netra.instrumentation.anthropic:", error);
19354
+ span2.setStatus({
19355
+ code: api.SpanStatusCode.ERROR,
19356
+ message: error instanceof Error ? error.message : String(error)
19357
+ });
19358
+ span2.recordException(error);
19359
+ span2.end();
19360
+ throw error;
19361
+ }
18950
19362
  }
18951
- break;
19363
+ );
19364
+ };
19365
+ };
19366
+ }
19367
+ function streamWrapper(tracer, spanName, requestType, originalCreate) {
19368
+ return function wrapper(original) {
19369
+ return function(...args) {
19370
+ if (shouldSuppressInstrumentation()) {
19371
+ return original.apply(this, args);
18952
19372
  }
18953
- case "content_block_stop": {
18954
- const content = this.completeResponse.content || [];
18955
- if (content.length > 0) {
18956
- const finishedBlock = content[content.length - 1];
18957
- if (finishedBlock?.type === "tool_use" && typeof finishedBlock.input === "string") {
18958
- try {
18959
- finishedBlock.input = JSON.parse(finishedBlock.input);
18960
- } catch {
18961
- Logger.warn("netra.instrumentation.anthropic: Failed to parse tool use input", finishedBlock.input);
18962
- }
19373
+ const attributes = args[0] || {};
19374
+ const currentContext = api.context.active();
19375
+ const span2 = tracer.startSpan(
19376
+ spanName,
19377
+ {
19378
+ kind: api.SpanKind.CLIENT,
19379
+ attributes: {
19380
+ "llm.request.type": requestType,
19381
+ "llm.streaming": true,
19382
+ "llm.operation": "stream"
18963
19383
  }
19384
+ },
19385
+ currentContext
19386
+ );
19387
+ const spanContext = api.trace.setSpan(currentContext, span2);
19388
+ setRequestAttributes2(span2, attributes, requestType);
19389
+ const startTime = Date.now();
19390
+ const callTarget = originalCreate ? new Proxy(this, {
19391
+ get(target, prop) {
19392
+ if (prop === "create") return originalCreate.bind(target);
19393
+ const value = target[prop];
19394
+ if (typeof value === "function") return value.bind(target);
19395
+ return value;
18964
19396
  }
18965
- break;
19397
+ }) : this;
19398
+ try {
19399
+ const messageStream = api.context.with(
19400
+ spanContext,
19401
+ () => original.call(callTarget, ...args)
19402
+ );
19403
+ return new MessageStreamWrapper(
19404
+ span2,
19405
+ messageStream,
19406
+ startTime,
19407
+ attributes,
19408
+ spanContext,
19409
+ currentContext
19410
+ );
19411
+ } catch (error) {
19412
+ span2.setStatus({
19413
+ code: api.SpanStatusCode.ERROR,
19414
+ message: error instanceof Error ? error.message : String(error)
19415
+ });
19416
+ span2.recordException(error);
19417
+ span2.end();
19418
+ throw error;
18966
19419
  }
18967
- case "message_delta": {
18968
- if (chunk.delta?.usage) {
18969
- const currentUsage = this.completeResponse.usage || {};
18970
- this.completeResponse.usage = {
18971
- ...currentUsage,
18972
- ...chunk.delta.usage
18973
- };
18974
- }
18975
- break;
19420
+ };
19421
+ };
19422
+ }
19423
+ function toolRunnerWrapper(tracer, spanName, requestType) {
19424
+ return function wrapper(original) {
19425
+ return function(...args) {
19426
+ if (shouldSuppressInstrumentation()) {
19427
+ return original.apply(this, args);
18976
19428
  }
18977
- case "message_stop": {
18978
- if (chunk.usage) {
18979
- this.completeResponse.usage = chunk.usage;
19429
+ const attributes = args[0] || {};
19430
+ const currentContext = api.context.active();
19431
+ const span2 = tracer.startSpan(
19432
+ spanName,
19433
+ {
19434
+ kind: api.SpanKind.CLIENT,
19435
+ attributes: {
19436
+ "llm.request.type": requestType,
19437
+ "netra.span.type": "AGENT",
19438
+ "llm.operation": "tool.runner"
19439
+ }
19440
+ },
19441
+ currentContext
19442
+ );
19443
+ let spanEnded = false;
19444
+ const endSpanOnce = (code, error) => {
19445
+ if (spanEnded) return;
19446
+ spanEnded = true;
19447
+ if (error) {
19448
+ span2.setStatus({ code, message: error.message });
19449
+ span2.recordException(error);
19450
+ } else {
19451
+ span2.setStatus({ code });
18980
19452
  }
18981
- break;
19453
+ span2.end();
19454
+ };
19455
+ try {
19456
+ setRequestAttributes2(span2, attributes, "beta");
19457
+ const spanContext = api.trace.setSpan(currentContext, span2);
19458
+ const wrappedTools = Array.isArray(attributes.tools) ? wrapRunnableTools(attributes.tools, tracer, spanContext) : attributes.tools;
19459
+ const wrappedArgs = [
19460
+ { ...attributes, tools: wrappedTools },
19461
+ ...args.slice(1)
19462
+ ];
19463
+ const runner = api.context.with(
19464
+ spanContext,
19465
+ () => original.apply(this, wrappedArgs)
19466
+ );
19467
+ if (runner == null) {
19468
+ endSpanOnce(api.SpanStatusCode.OK);
19469
+ return runner;
19470
+ }
19471
+ return new Proxy(runner, {
19472
+ get(target, prop, receiver) {
19473
+ if (prop === Symbol.asyncIterator) {
19474
+ return function() {
19475
+ const originalIterator = target[Symbol.asyncIterator]();
19476
+ return {
19477
+ [Symbol.asyncIterator]() {
19478
+ return this;
19479
+ },
19480
+ async next() {
19481
+ try {
19482
+ const result = await api.context.with(
19483
+ spanContext,
19484
+ () => originalIterator.next()
19485
+ );
19486
+ if (result.done) endSpanOnce(api.SpanStatusCode.OK);
19487
+ return result;
19488
+ } catch (error) {
19489
+ endSpanOnce(api.SpanStatusCode.ERROR, error);
19490
+ throw error;
19491
+ }
19492
+ },
19493
+ async return(value2) {
19494
+ try {
19495
+ const result = await (originalIterator.return?.(
19496
+ value2
19497
+ ) ?? {
19498
+ done: true,
19499
+ value: value2
19500
+ });
19501
+ return result;
19502
+ } finally {
19503
+ endSpanOnce(api.SpanStatusCode.OK);
19504
+ }
19505
+ },
19506
+ async throw(error) {
19507
+ const err = error instanceof Error ? error : new Error(String(error));
19508
+ if (originalIterator.throw) {
19509
+ try {
19510
+ const result = await originalIterator.throw(error);
19511
+ if (result.done) {
19512
+ endSpanOnce(api.SpanStatusCode.ERROR, err);
19513
+ }
19514
+ return result;
19515
+ } catch (e) {
19516
+ endSpanOnce(
19517
+ api.SpanStatusCode.ERROR,
19518
+ e instanceof Error ? e : new Error(String(e))
19519
+ );
19520
+ throw e;
19521
+ }
19522
+ }
19523
+ endSpanOnce(api.SpanStatusCode.ERROR, err);
19524
+ throw error;
19525
+ }
19526
+ };
19527
+ };
19528
+ }
19529
+ if (prop === "then" || prop === "catch" || prop === "finally") {
19530
+ const originalMethod = target[prop];
19531
+ if (typeof originalMethod !== "function") return originalMethod;
19532
+ if (prop === "then") {
19533
+ return function(onFulfilled, onRejected) {
19534
+ return originalMethod.call(
19535
+ target,
19536
+ (v) => {
19537
+ endSpanOnce(api.SpanStatusCode.OK);
19538
+ return onFulfilled ? onFulfilled(v) : v;
19539
+ },
19540
+ (e) => {
19541
+ endSpanOnce(
19542
+ api.SpanStatusCode.ERROR,
19543
+ e instanceof Error ? e : new Error(String(e))
19544
+ );
19545
+ if (onRejected) return onRejected(e);
19546
+ throw e;
19547
+ }
19548
+ );
19549
+ };
19550
+ }
19551
+ if (prop === "catch") {
19552
+ return function(onRejected) {
19553
+ return receiver.then(void 0, onRejected);
19554
+ };
19555
+ }
19556
+ if (prop === "finally") {
19557
+ return function(onFinally) {
19558
+ return receiver.then(
19559
+ (v) => {
19560
+ onFinally?.();
19561
+ return v;
19562
+ },
19563
+ (e) => {
19564
+ onFinally?.();
19565
+ throw e;
19566
+ }
19567
+ );
19568
+ };
19569
+ }
19570
+ }
19571
+ const value = target[prop];
19572
+ if (typeof value === "function") return value.bind(target);
19573
+ return value;
19574
+ }
19575
+ });
19576
+ } catch (error) {
19577
+ endSpanOnce(
19578
+ api.SpanStatusCode.ERROR,
19579
+ error instanceof Error ? error : new Error(String(error))
19580
+ );
19581
+ throw error;
18982
19582
  }
18983
- }
18984
- this.span.addEvent("llm.content.completion.chunk", {
18985
- "chunk.type": chunk.type
18986
- });
18987
- }
18988
- finalizeSpan(code) {
18989
- const endTime = Date.now();
18990
- const duration = (endTime - this.startTime) / 1e3;
18991
- setResponseAttributes2(this.span, {
18992
- model: this.completeResponse.model,
18993
- content: this.completeResponse.content,
18994
- usage: this.completeResponse.usage
18995
- });
18996
- this.span.setAttribute("llm.response.duration", duration);
18997
- this.span.setStatus({ code });
18998
- this.span.end();
18999
- }
19000
- };
19583
+ };
19584
+ };
19585
+ }
19586
+ var chatWrapper = (tracer) => anthropicWrapper(tracer, SPAN_NAMES.CHAT, "chat");
19587
+ var betaWrapper = (tracer) => anthropicWrapper(tracer, SPAN_NAMES.BETA, "beta");
19588
+ var batchesWrapper = (tracer) => anthropicWrapper(tracer, SPAN_NAMES.BATCHES, "batches");
19589
+ var chatStreamWrapper = (tracer, originalCreate) => streamWrapper(tracer, SPAN_NAMES.STREAM, "chat", originalCreate);
19590
+ var betaStreamWrapper = (tracer, originalCreate) => streamWrapper(tracer, SPAN_NAMES.BETA_STREAM, "beta", originalCreate);
19591
+ var betaToolRunnerWrapper = (tracer) => toolRunnerWrapper(tracer, SPAN_NAMES.BETA_TOOL_RUNNER, "beta");
19001
19592
 
19002
19593
  // src/instrumentation/anthropic/index.ts
19003
19594
  var INSTRUMENTATION_NAME = "netra.instrumentation.anthropic";
19004
19595
  var INSTRUMENTS = ["anthropic >= 0.71.2"];
19005
- var originalMethods = /* @__PURE__ */ new Map();
19006
19596
  var isInstrumented = false;
19007
19597
  var anthropicClasses = [];
19008
- async function resolveAnthropicAsync() {
19598
+ async function resolveAnthropic() {
19009
19599
  if (anthropicClasses.length > 0) return anthropicClasses;
19010
19600
  try {
19011
19601
  const anthropicModule = await import('@anthropic-ai/sdk');
19012
- anthropicClasses.push(anthropicModule.Anthropic || anthropicModule.default || anthropicModule);
19602
+ anthropicClasses.push(
19603
+ anthropicModule.Anthropic || anthropicModule.default || anthropicModule
19604
+ );
19013
19605
  } catch {
19014
19606
  Logger.warn("Failed to resolve Anthropic ESM module");
19015
19607
  }
@@ -19025,9 +19617,6 @@ async function resolveAnthropicAsync() {
19025
19617
  }
19026
19618
  return anthropicClasses;
19027
19619
  }
19028
- function resolveAnthropic() {
19029
- return anthropicClasses;
19030
- }
19031
19620
  var NetraAnthropicInstrumentor = class {
19032
19621
  constructor() {
19033
19622
  this.tracer = null;
@@ -19035,15 +19624,13 @@ var NetraAnthropicInstrumentor = class {
19035
19624
  instrumentationDependencies() {
19036
19625
  return INSTRUMENTS;
19037
19626
  }
19038
- async instrumentAsync(options = {}) {
19627
+ async instrument(options = {}) {
19039
19628
  if (isInstrumented) {
19040
19629
  Logger.warn("Anthropic is already instrumented");
19041
19630
  return this;
19042
19631
  }
19043
- const classes = await resolveAnthropicAsync();
19044
- if (classes.length === 0) {
19045
- return this;
19046
- }
19632
+ const classes = await resolveAnthropic();
19633
+ if (classes.length === 0) return this;
19047
19634
  try {
19048
19635
  this.tracerProvider = options.tracerProvider;
19049
19636
  if (this.tracerProvider) {
@@ -19058,10 +19645,10 @@ var NetraAnthropicInstrumentor = class {
19058
19645
  Logger.error(`Failed to initialize tracer: ${error}`);
19059
19646
  return this;
19060
19647
  }
19061
- classes.forEach((AnthropicSDK, index) => {
19062
- this._instrumentMessages(AnthropicSDK, index);
19063
- this._instrumentBetaMessages(AnthropicSDK, index);
19064
- this._instrumentBatchMessages(AnthropicSDK, index);
19648
+ classes.forEach((AnthropicSDK) => {
19649
+ this._instrumentMessages(AnthropicSDK);
19650
+ this._instrumentBetaMessages(AnthropicSDK);
19651
+ this._instrumentBatchMessages(AnthropicSDK);
19065
19652
  });
19066
19653
  isInstrumented = true;
19067
19654
  return this;
@@ -19071,185 +19658,137 @@ var NetraAnthropicInstrumentor = class {
19071
19658
  Logger.warn("Anthropic is not instrumented");
19072
19659
  return;
19073
19660
  }
19074
- const classes = resolveAnthropic();
19075
- classes.forEach((AnthropicSDK, index) => {
19076
- this._uninstrumentMessages(AnthropicSDK, index);
19077
- this._uninstrumentBetaMessages(AnthropicSDK, index);
19078
- this._uninstrumentBatchMessages(AnthropicSDK, index);
19661
+ anthropicClasses.forEach((AnthropicSDK) => {
19662
+ this._uninstrumentMessages(AnthropicSDK);
19663
+ this._uninstrumentBetaMessages(AnthropicSDK);
19664
+ this._uninstrumentBatchMessages(AnthropicSDK);
19079
19665
  });
19080
- originalMethods.clear();
19081
19666
  anthropicClasses = [];
19082
19667
  isInstrumented = false;
19083
19668
  }
19084
19669
  isInstrumented() {
19085
19670
  return isInstrumented;
19086
19671
  }
19087
- _instrumentMessages(AnthropicSDK, index) {
19672
+ _instrumentMessages(AnthropicSDK) {
19088
19673
  if (!this.tracer) {
19089
19674
  Logger.warn("Anthropic instrumentation: No tracer available");
19090
19675
  return;
19091
19676
  }
19092
19677
  try {
19093
19678
  const MessagesClass = AnthropicSDK.Messages;
19094
- if (!MessagesClass) {
19679
+ if (!MessagesClass?.prototype) {
19095
19680
  Logger.error(
19096
- "Anthropic instrumentation: Could not find Anthropic Messages class to instrument"
19681
+ "Anthropic instrumentation: Could not find Messages class"
19097
19682
  );
19098
19683
  return;
19099
19684
  }
19100
- if (MessagesClass?.prototype?.stream) {
19101
- const originalStream = MessagesClass.prototype.stream;
19102
- originalMethods.set(`messages.stream-${index}`, originalStream);
19103
- const tracer = this.tracer;
19104
- MessagesClass.prototype.stream = function(...args) {
19105
- const original = originalStream.bind(this);
19106
- const kwargs = args[0] || {};
19107
- const currentContext = api.context.active();
19108
- const span2 = tracer.startSpan("anthropic.stream", {
19109
- kind: api.SpanKind.CLIENT,
19110
- attributes: {
19111
- "llm.request.type": "chat",
19112
- "llm.streaming": true,
19113
- "llm.operation": "stream"
19114
- }
19115
- }, currentContext);
19116
- const spanContext = api.trace.setSpan(currentContext, span2);
19117
- setRequestAttributes2(span2, kwargs, "chat");
19118
- const startTime = Date.now();
19119
- const instrumentedCreate = this.create;
19120
- const originalCreate = originalMethods.get(`messages.create-${index}`);
19121
- if (originalCreate) {
19122
- this.create = originalCreate;
19123
- }
19124
- try {
19125
- const messageStream = api.context.with(spanContext, () => original(...args));
19126
- return new MessageStreamWrapper(span2, messageStream, startTime, kwargs, spanContext);
19127
- } finally {
19128
- if (originalCreate) {
19129
- this.create = instrumentedCreate;
19130
- }
19131
- }
19132
- };
19685
+ const originalCreate = MessagesClass.prototype.create;
19686
+ if (typeof MessagesClass.prototype.create === "function") {
19687
+ shimmer__default.default.wrap(
19688
+ MessagesClass.prototype,
19689
+ "create",
19690
+ chatWrapper(this.tracer)
19691
+ );
19133
19692
  }
19134
- if (MessagesClass?.prototype?.create) {
19135
- const originalCreate = MessagesClass.prototype.create;
19136
- originalMethods.set(`messages.create-${index}`, originalCreate);
19137
- const tracer = this.tracer;
19138
- const wrapper = chatWrapper(tracer);
19139
- MessagesClass.prototype.create = function(...args) {
19140
- const original = originalCreate.bind(this);
19141
- const kwargs = args[0] || {};
19142
- return wrapper(
19143
- (...a) => original(...a),
19144
- this,
19145
- args,
19146
- kwargs
19147
- );
19148
- };
19693
+ if (typeof MessagesClass.prototype.stream === "function") {
19694
+ shimmer__default.default.wrap(
19695
+ MessagesClass.prototype,
19696
+ "stream",
19697
+ chatStreamWrapper(this.tracer, originalCreate)
19698
+ );
19149
19699
  }
19150
19700
  } catch (error) {
19151
19701
  Logger.error(`Failed to instrument messages: ${error}`);
19152
19702
  }
19153
19703
  }
19154
- _instrumentBetaMessages(AnthropicSDK, index) {
19704
+ _instrumentBetaMessages(AnthropicSDK) {
19155
19705
  if (!this.tracer) {
19156
19706
  Logger.warn("Anthropic instrumentation: No tracer available");
19157
19707
  return;
19158
19708
  }
19159
19709
  try {
19160
19710
  const BetaMessagesClass = AnthropicSDK.Beta?.Messages;
19161
- if (!BetaMessagesClass) {
19711
+ if (!BetaMessagesClass?.prototype) {
19162
19712
  Logger.error(
19163
- "Anthropic instrumentation: Could not find Anthropic Beta Messages class to instrument"
19713
+ "Anthropic instrumentation: Could not find Beta Messages class"
19164
19714
  );
19165
19715
  return;
19166
19716
  }
19167
- if (BetaMessagesClass?.prototype?.create) {
19168
- const originalCreate = BetaMessagesClass.prototype.create;
19169
- originalMethods.set(`beta.messages.create-${index}`, originalCreate);
19170
- const tracer = this.tracer;
19171
- const wrapper = betaWrapper(tracer);
19172
- BetaMessagesClass.prototype.create = function(...args) {
19173
- const original = originalCreate.bind(this);
19174
- const kwargs = args[0] || {};
19175
- return wrapper(
19176
- (...a) => original(...a),
19177
- this,
19178
- args,
19179
- kwargs
19180
- );
19181
- };
19717
+ const originalCreate = BetaMessagesClass.prototype.create;
19718
+ if (typeof BetaMessagesClass.prototype.create === "function") {
19719
+ shimmer__default.default.wrap(
19720
+ BetaMessagesClass.prototype,
19721
+ "create",
19722
+ betaWrapper(this.tracer)
19723
+ );
19724
+ }
19725
+ if (typeof BetaMessagesClass.prototype.stream === "function") {
19726
+ shimmer__default.default.wrap(
19727
+ BetaMessagesClass.prototype,
19728
+ "stream",
19729
+ betaStreamWrapper(this.tracer, originalCreate)
19730
+ );
19731
+ }
19732
+ if (typeof BetaMessagesClass.prototype.toolRunner === "function") {
19733
+ shimmer__default.default.wrap(
19734
+ BetaMessagesClass.prototype,
19735
+ "toolRunner",
19736
+ betaToolRunnerWrapper(this.tracer)
19737
+ );
19182
19738
  }
19183
19739
  } catch (error) {
19184
19740
  Logger.error(`Failed to instrument beta: ${error}`);
19185
19741
  }
19186
19742
  }
19187
- _instrumentBatchMessages(AnthropicSDK, index) {
19743
+ _instrumentBatchMessages(AnthropicSDK) {
19188
19744
  if (!this.tracer) {
19189
19745
  Logger.warn("Anthropic instrumentation: No tracer available");
19190
19746
  return;
19191
19747
  }
19192
19748
  try {
19193
19749
  const BatchMessageClass = AnthropicSDK.Messages?.Batches;
19194
- if (!BatchMessageClass) {
19195
- Logger.error(
19196
- "Anthropic instrumentation: Could not find Anthropic Batches class to instrument"
19197
- );
19750
+ if (!BatchMessageClass?.prototype) {
19751
+ Logger.error("Anthropic instrumentation: Could not find Batches class");
19198
19752
  return;
19199
19753
  }
19200
- if (BatchMessageClass?.prototype?.create) {
19201
- const originalCreate = BatchMessageClass.prototype.create;
19202
- originalMethods.set(`batch.messages.create-${index}`, originalCreate);
19203
- const tracer = this.tracer;
19204
- const wrapper = batchesWrapper(tracer);
19205
- BatchMessageClass.prototype.create = function(...args) {
19206
- const original = originalCreate.bind(this);
19207
- const kwargs = args[0] || {};
19208
- return wrapper(
19209
- (...a) => original(...a),
19210
- this,
19211
- args,
19212
- kwargs
19213
- );
19214
- };
19754
+ if (typeof BatchMessageClass.prototype.create === "function") {
19755
+ shimmer__default.default.wrap(
19756
+ BatchMessageClass.prototype,
19757
+ "create",
19758
+ batchesWrapper(this.tracer)
19759
+ );
19215
19760
  }
19216
19761
  } catch (error) {
19217
19762
  Logger.error(`Failed to instrument batches: ${error}`);
19218
19763
  }
19219
19764
  }
19220
- _uninstrumentMessages(AnthropicSDK, index) {
19765
+ _uninstrumentMessages(AnthropicSDK) {
19221
19766
  try {
19222
- const MessagesClass = AnthropicSDK.Messages;
19223
- const originalCreate = originalMethods.get(`messages.create-${index}`);
19224
- if (originalCreate && MessagesClass?.prototype) {
19225
- MessagesClass.prototype.create = originalCreate;
19226
- }
19227
- const originalStream = originalMethods.get(`messages.stream-${index}`);
19228
- if (originalStream && MessagesClass?.prototype) {
19229
- MessagesClass.prototype.stream = originalStream;
19230
- }
19767
+ const proto = AnthropicSDK.Messages?.prototype;
19768
+ if (!proto) return;
19769
+ if (typeof proto.create === "function") shimmer__default.default.unwrap(proto, "create");
19770
+ if (typeof proto.stream === "function") shimmer__default.default.unwrap(proto, "stream");
19231
19771
  } catch (error) {
19232
19772
  Logger.error(`Failed to uninstrument messages: ${error}`);
19233
19773
  }
19234
19774
  }
19235
- _uninstrumentBetaMessages(AnthropicSDK, index) {
19775
+ _uninstrumentBetaMessages(AnthropicSDK) {
19236
19776
  try {
19237
- const BetaMessagesClass = AnthropicSDK.Beta?.Messages;
19238
- const originalCreate = originalMethods.get(`beta.messages.create-${index}`);
19239
- if (originalCreate && BetaMessagesClass?.prototype) {
19240
- BetaMessagesClass.prototype.create = originalCreate;
19241
- }
19777
+ const proto = AnthropicSDK.Beta?.Messages?.prototype;
19778
+ if (!proto) return;
19779
+ if (typeof proto.create === "function") shimmer__default.default.unwrap(proto, "create");
19780
+ if (typeof proto.stream === "function") shimmer__default.default.unwrap(proto, "stream");
19781
+ if (typeof proto.toolRunner === "function")
19782
+ shimmer__default.default.unwrap(proto, "toolRunner");
19242
19783
  } catch (error) {
19243
19784
  Logger.error(`Failed to uninstrument beta: ${error}`);
19244
19785
  }
19245
19786
  }
19246
- _uninstrumentBatchMessages(AnthropicSDK, index) {
19787
+ _uninstrumentBatchMessages(AnthropicSDK) {
19247
19788
  try {
19248
- const BatchMessagesClass = AnthropicSDK.Messages?.Batches;
19249
- const originalCreate = originalMethods.get(`batch.messages.create-${index}`);
19250
- if (originalCreate && BatchMessagesClass?.prototype) {
19251
- BatchMessagesClass.prototype.create = originalCreate;
19252
- }
19789
+ const proto = AnthropicSDK.Messages?.Batches?.prototype;
19790
+ if (!proto) return;
19791
+ if (typeof proto.create === "function") shimmer__default.default.unwrap(proto, "create");
19253
19792
  } catch (error) {
19254
19793
  Logger.error(`Failed to uninstrument batches: ${error}`);
19255
19794
  }
@@ -19665,7 +20204,7 @@ function _setEmbeddingResponseAttributes(span2, response) {
19665
20204
  }
19666
20205
 
19667
20206
  // src/instrumentation/google-genai/wrappers.ts
19668
- var CHAT_SPAN_NAME2 = "google_genai.chat";
20207
+ var CHAT_SPAN_NAME = "google_genai.chat";
19669
20208
  var EMBEDDING_SPAN_NAME = "google_genai.embedding";
19670
20209
  function googleGenAIWrapper(tracer, spanName, requestType) {
19671
20210
  return function wrapper(original) {
@@ -19944,10 +20483,10 @@ function googleGenAIStartChatWrapper(tracer, spanName, requestType) {
19944
20483
  };
19945
20484
  };
19946
20485
  }
19947
- var chatWrapper2 = (tracer) => googleGenAIWrapper(tracer, CHAT_SPAN_NAME2, "chat");
20486
+ var chatWrapper2 = (tracer) => googleGenAIWrapper(tracer, CHAT_SPAN_NAME, "chat");
19948
20487
  var embeddingsWrapper = (tracer) => googleGenAIWrapper(tracer, EMBEDDING_SPAN_NAME, "embedding");
19949
- var chatStreamWrapper = (tracer) => googleGenAIStreamWrapper(tracer, CHAT_SPAN_NAME2, "chat");
19950
- var startChatWrapper = (tracer) => googleGenAIStartChatWrapper(tracer, CHAT_SPAN_NAME2, "chat");
20488
+ var chatStreamWrapper2 = (tracer) => googleGenAIStreamWrapper(tracer, CHAT_SPAN_NAME, "chat");
20489
+ var startChatWrapper = (tracer) => googleGenAIStartChatWrapper(tracer, CHAT_SPAN_NAME, "chat");
19951
20490
  var INSTRUMENTATION_NAME2 = "netra.instrumentation.google_genai";
19952
20491
  var INSTRUMENTS2 = ["@google/genai >= 0.24.1"];
19953
20492
  var isInstrumented2 = false;
@@ -20073,7 +20612,7 @@ var NetraGoogleGenerativeAIInstrumentor = class {
20073
20612
  shimmer__default.default.wrap(
20074
20613
  GenerativeModel.prototype,
20075
20614
  "generateContentStream",
20076
- chatStreamWrapper(tracer)
20615
+ chatStreamWrapper2(tracer)
20077
20616
  );
20078
20617
  shimmer__default.default.wrap(
20079
20618
  GenerativeModel.prototype,
@@ -20135,8 +20674,8 @@ function setResponseAttributes4(span2, response) {
20135
20674
  }
20136
20675
 
20137
20676
  // src/instrumentation/groq/wrappers.ts
20138
- var CHAT_SPAN_NAME3 = "groq.chat";
20139
- var STREAM_ENABLED_REQUESTS2 = ["chat"];
20677
+ var CHAT_SPAN_NAME2 = "groq.chat";
20678
+ var STREAM_ENABLED_REQUESTS = ["chat"];
20140
20679
  function groqWrapper(tracer, spanName, requestType) {
20141
20680
  return function wrapper(wrapped, instance, args, kwargs) {
20142
20681
  if (shouldSuppressInstrumentation()) {
@@ -20144,7 +20683,7 @@ function groqWrapper(tracer, spanName, requestType) {
20144
20683
  return isPromise(result) ? result.then((value) => value) : result;
20145
20684
  }
20146
20685
  const isStreaming = kwargs.stream === true;
20147
- if (isStreaming && STREAM_ENABLED_REQUESTS2.includes(requestType)) {
20686
+ if (isStreaming && STREAM_ENABLED_REQUESTS.includes(requestType)) {
20148
20687
  const currentContext = api.context.active();
20149
20688
  const span2 = tracer.startSpan(
20150
20689
  spanName,
@@ -20162,7 +20701,7 @@ function groqWrapper(tracer, spanName, requestType) {
20162
20701
  return (async () => {
20163
20702
  try {
20164
20703
  const stream = await response;
20165
- return new AsyncStreamingWrapper2(span2, stream, startTime, kwargs);
20704
+ return new AsyncStreamingWrapper(span2, stream, startTime, kwargs);
20166
20705
  } catch (error) {
20167
20706
  Logger.error("netra.instrumentation.groq:", error);
20168
20707
  span2.setStatus({
@@ -20251,7 +20790,7 @@ function groqWrapper(tracer, spanName, requestType) {
20251
20790
  }
20252
20791
  };
20253
20792
  }
20254
- var chatWrapper3 = (tracer) => groqWrapper(tracer, CHAT_SPAN_NAME3, "chat");
20793
+ var chatWrapper3 = (tracer) => groqWrapper(tracer, CHAT_SPAN_NAME2, "chat");
20255
20794
  var StreamingWrapper = class {
20256
20795
  constructor(span2, response, startTime, requestKwargs) {
20257
20796
  this.iterator = null;
@@ -20349,7 +20888,7 @@ var StreamingWrapper = class {
20349
20888
  this.span.end();
20350
20889
  }
20351
20890
  };
20352
- var AsyncStreamingWrapper2 = class {
20891
+ var AsyncStreamingWrapper = class {
20353
20892
  constructor(span2, response, startTime, requestKwargs) {
20354
20893
  this.iterator = null;
20355
20894
  this.completeResponse = {
@@ -20469,7 +21008,7 @@ var AsyncStreamingWrapper2 = class {
20469
21008
  // src/instrumentation/groq/index.ts
20470
21009
  var INSTRUMENTATION_NAME3 = "netra.instrumentation.groq";
20471
21010
  var INSTRUMENTS3 = ["groq-sdk >= 0.3.0"];
20472
- var originalMethods2 = /* @__PURE__ */ new Map();
21011
+ var originalMethods = /* @__PURE__ */ new Map();
20473
21012
  var isInstrumented3 = false;
20474
21013
  var groqClasses = [];
20475
21014
  async function resolveGroqAsync() {
@@ -20580,7 +21119,7 @@ var NetraGroqInstrumentor = class {
20580
21119
  classes.forEach((Groq, index) => {
20581
21120
  this._uninstrumentChatCompletions(Groq, index);
20582
21121
  });
20583
- originalMethods2.clear();
21122
+ originalMethods.clear();
20584
21123
  groqClasses = [];
20585
21124
  isInstrumented3 = false;
20586
21125
  }
@@ -20601,7 +21140,7 @@ var NetraGroqInstrumentor = class {
20601
21140
  return;
20602
21141
  }
20603
21142
  const originalCreate = CompletionsClass.prototype.create;
20604
- originalMethods2.set(`chat.completions.create-${index}`, originalCreate);
21143
+ originalMethods.set(`chat.completions.create-${index}`, originalCreate);
20605
21144
  const tracer = this.tracer;
20606
21145
  const wrapper = chatWrapper3(tracer);
20607
21146
  CompletionsClass.prototype.create = function(...args) {
@@ -20619,7 +21158,7 @@ var NetraGroqInstrumentor = class {
20619
21158
  _uninstrumentChatCompletions(Groq, index) {
20620
21159
  try {
20621
21160
  const CompletionsClass = Groq.Chat?.Completions;
20622
- const originalCreate = originalMethods2.get(`chat.completions.create-${index}`);
21161
+ const originalCreate = originalMethods.get(`chat.completions.create-${index}`);
20623
21162
  if (originalCreate && CompletionsClass?.prototype) {
20624
21163
  CompletionsClass.prototype.create = originalCreate;
20625
21164
  }
@@ -21458,7 +21997,7 @@ var INSTRUMENTATION_NAME4 = "netra.instrumentation.langgraph";
21458
21997
  var INSTRUMENTS4 = ["langgraph >= 1.1.1"];
21459
21998
  var isInstrumented4 = false;
21460
21999
  var LanggraphClass = null;
21461
- var originalMethods3 = /* @__PURE__ */ new Map();
22000
+ var originalMethods2 = /* @__PURE__ */ new Map();
21462
22001
  function findModuleInCache(moduleName) {
21463
22002
  if (typeof __require !== "undefined" && __require.cache) {
21464
22003
  const cache = __require.cache;
@@ -21554,7 +22093,7 @@ var NetraLanggraphInstrumentor = class {
21554
22093
  this._uninstrumentInvoke(Langgraph);
21555
22094
  this._uninstrumentStream(Langgraph);
21556
22095
  }
21557
- originalMethods3.clear();
22096
+ originalMethods2.clear();
21558
22097
  LanggraphClass = null;
21559
22098
  isInstrumented4 = false;
21560
22099
  }
@@ -21571,8 +22110,8 @@ var NetraLanggraphInstrumentor = class {
21571
22110
  }
21572
22111
  Logger.debug(`Found invoke on prototype: ${targetProto.constructor?.name}`);
21573
22112
  const originalInvoke = targetProto.invoke;
21574
- originalMethods3.set("langgraph.graph.invoke", originalInvoke);
21575
- originalMethods3.set("langgraph.graph.invoke.proto", targetProto);
22113
+ originalMethods2.set("langgraph.graph.invoke", originalInvoke);
22114
+ originalMethods2.set("langgraph.graph.invoke.proto", targetProto);
21576
22115
  const tracer = this.tracer;
21577
22116
  const wrapper = new LanggraphWrapper(tracer);
21578
22117
  const patchedInvoke = async function(input, config2, ...rest) {
@@ -21606,8 +22145,8 @@ var NetraLanggraphInstrumentor = class {
21606
22145
  }
21607
22146
  Logger.debug(`Found stream on prototype: ${targetProto.constructor?.name}`);
21608
22147
  const originalStream = targetProto.stream;
21609
- originalMethods3.set("langgraph.graph.stream", originalStream);
21610
- originalMethods3.set("langgraph.graph.stream.proto", targetProto);
22148
+ originalMethods2.set("langgraph.graph.stream", originalStream);
22149
+ originalMethods2.set("langgraph.graph.stream.proto", targetProto);
21611
22150
  const tracer = this.tracer;
21612
22151
  const wrapper = new LanggraphWrapper(tracer);
21613
22152
  targetProto.stream = async function(input, config2, ...rest) {
@@ -21627,8 +22166,8 @@ var NetraLanggraphInstrumentor = class {
21627
22166
  }
21628
22167
  _uninstrumentInvoke(Langgraph) {
21629
22168
  try {
21630
- const originalInvoke = originalMethods3.get("langgraph.graph.invoke");
21631
- const targetProto = originalMethods3.get("langgraph.graph.invoke.proto") || Langgraph?.prototype;
22169
+ const originalInvoke = originalMethods2.get("langgraph.graph.invoke");
22170
+ const targetProto = originalMethods2.get("langgraph.graph.invoke.proto") || Langgraph?.prototype;
21632
22171
  if (originalInvoke && targetProto?.invoke) {
21633
22172
  targetProto.invoke = originalInvoke;
21634
22173
  }
@@ -21639,8 +22178,8 @@ var NetraLanggraphInstrumentor = class {
21639
22178
  }
21640
22179
  _uninstrumentStream(Langgraph) {
21641
22180
  try {
21642
- const originalStream = originalMethods3.get("langgraph.graph.stream");
21643
- const targetProto = originalMethods3.get("langgraph.graph.stream.proto") || Langgraph?.prototype;
22181
+ const originalStream = originalMethods2.get("langgraph.graph.stream");
22182
+ const targetProto = originalMethods2.get("langgraph.graph.stream.proto") || Langgraph?.prototype;
21644
22183
  if (originalStream && targetProto?.stream) {
21645
22184
  targetProto.stream = originalStream;
21646
22185
  }
@@ -21680,11 +22219,11 @@ function setResponseAttributes5(span2, response) {
21680
22219
  }
21681
22220
 
21682
22221
  // src/instrumentation/mistralai/wrappers.ts
21683
- var CHAT_SPAN_NAME4 = "mistralai.chat";
22222
+ var CHAT_SPAN_NAME3 = "mistralai.chat";
21684
22223
  var EMBEDDING_SPAN_NAME2 = "mistralai.embedding";
21685
22224
  var FIM_SPAN_NAME = "mistralai.fim";
21686
22225
  var AGENTS_SPAN_NAME = "mistralai.agents";
21687
- var CHAT_STREAM_SPAN_NAME = CHAT_SPAN_NAME4;
22226
+ var CHAT_STREAM_SPAN_NAME = CHAT_SPAN_NAME3;
21688
22227
  var FIM_STREAM_SPAN_NAME = FIM_SPAN_NAME;
21689
22228
  var AGENTS_STREAM_SPAN_NAME = AGENTS_SPAN_NAME;
21690
22229
  function mistralWrapper(tracer, spanName, requestType) {
@@ -21779,7 +22318,7 @@ function mistralStreamWrapper(tracer, spanName, requestType) {
21779
22318
  try {
21780
22319
  const stream = await response;
21781
22320
  if (stream && typeof stream === "object" && Symbol.asyncIterator in stream) {
21782
- return new AsyncStreamingWrapper3(span2, stream, startTime, kwargs);
22321
+ return new AsyncStreamingWrapper2(span2, stream, startTime, kwargs);
21783
22322
  }
21784
22323
  return new StreamingWrapper2(span2, stream, startTime, kwargs);
21785
22324
  } catch (error) {
@@ -21795,7 +22334,7 @@ function mistralStreamWrapper(tracer, spanName, requestType) {
21795
22334
  })();
21796
22335
  }
21797
22336
  if (response && typeof response === "object" && Symbol.asyncIterator in response) {
21798
- return new AsyncStreamingWrapper3(span2, response, startTime, kwargs);
22337
+ return new AsyncStreamingWrapper2(span2, response, startTime, kwargs);
21799
22338
  }
21800
22339
  return new StreamingWrapper2(span2, response, startTime, kwargs);
21801
22340
  } catch (error) {
@@ -21810,8 +22349,8 @@ function mistralStreamWrapper(tracer, spanName, requestType) {
21810
22349
  }
21811
22350
  };
21812
22351
  }
21813
- var chatWrapper4 = (tracer) => mistralWrapper(tracer, CHAT_SPAN_NAME4, "chat");
21814
- var chatStreamWrapper2 = (tracer) => mistralStreamWrapper(tracer, CHAT_STREAM_SPAN_NAME, "chat");
22352
+ var chatWrapper4 = (tracer) => mistralWrapper(tracer, CHAT_SPAN_NAME3, "chat");
22353
+ var chatStreamWrapper3 = (tracer) => mistralStreamWrapper(tracer, CHAT_STREAM_SPAN_NAME, "chat");
21815
22354
  var embeddingsWrapper2 = (tracer) => mistralWrapper(tracer, EMBEDDING_SPAN_NAME2, "embedding");
21816
22355
  var fimWrapper = (tracer) => mistralWrapper(tracer, FIM_SPAN_NAME, "fim");
21817
22356
  var fimStreamWrapper = (tracer) => mistralStreamWrapper(tracer, FIM_STREAM_SPAN_NAME, "fim");
@@ -21962,7 +22501,7 @@ var StreamingWrapper2 = class {
21962
22501
  this.span.end();
21963
22502
  }
21964
22503
  };
21965
- var AsyncStreamingWrapper3 = class {
22504
+ var AsyncStreamingWrapper2 = class {
21966
22505
  constructor(span2, response, startTime, requestKwargs) {
21967
22506
  this.iterator = null;
21968
22507
  defineHidden(this, "span", span2);
@@ -22112,7 +22651,7 @@ var AsyncStreamingWrapper3 = class {
22112
22651
  // src/instrumentation/mistralai/index.ts
22113
22652
  var INSTRUMENTATION_NAME5 = "netra.instrumentation.mistral_ai";
22114
22653
  var INSTRUMENTS5 = ["@mistralai/mistralai >= 1.0.0"];
22115
- var originalMethods4 = /* @__PURE__ */ new Map();
22654
+ var originalMethods3 = /* @__PURE__ */ new Map();
22116
22655
  var isInstrumented5 = false;
22117
22656
  var mistralClasses = [];
22118
22657
  async function resolveMistralAsync() {
@@ -22261,7 +22800,7 @@ var NetraMistralAIInstrumentor = class {
22261
22800
  this._uninstrumentFIM(Mistral, index);
22262
22801
  this._uninstrumentAgents(Mistral, index);
22263
22802
  });
22264
- originalMethods4.clear();
22803
+ originalMethods3.clear();
22265
22804
  mistralClasses = [];
22266
22805
  isInstrumented5 = false;
22267
22806
  }
@@ -22307,7 +22846,7 @@ var NetraMistralAIInstrumentor = class {
22307
22846
  let didPatch = false;
22308
22847
  if (ChatClass?.prototype?.complete) {
22309
22848
  const originalComplete = ChatClass.prototype.complete;
22310
- originalMethods4.set(`chat.complete-${index}`, originalComplete);
22849
+ originalMethods3.set(`chat.complete-${index}`, originalComplete);
22311
22850
  const tracer = this.tracer;
22312
22851
  const wrapper = chatWrapper4(tracer);
22313
22852
  ChatClass.prototype.complete = function(...args) {
@@ -22324,9 +22863,9 @@ var NetraMistralAIInstrumentor = class {
22324
22863
  }
22325
22864
  if (ChatClass?.prototype?.stream) {
22326
22865
  const originalStream = ChatClass.prototype.stream;
22327
- originalMethods4.set(`chat.stream-${index}`, originalStream);
22866
+ originalMethods3.set(`chat.stream-${index}`, originalStream);
22328
22867
  const tracer = this.tracer;
22329
- const wrapper = chatStreamWrapper2(tracer);
22868
+ const wrapper = chatStreamWrapper3(tracer);
22330
22869
  ChatClass.prototype.stream = function(...args) {
22331
22870
  const original = originalStream.bind(this);
22332
22871
  const kwargs = args[0] || {};
@@ -22352,7 +22891,7 @@ var NetraMistralAIInstrumentor = class {
22352
22891
  let didPatch = false;
22353
22892
  if (EmbeddingsClass?.prototype?.create) {
22354
22893
  const originalCreate = EmbeddingsClass.prototype.create;
22355
- originalMethods4.set(`embeddings.create-${index}`, originalCreate);
22894
+ originalMethods3.set(`embeddings.create-${index}`, originalCreate);
22356
22895
  const tracer = this.tracer;
22357
22896
  const wrapper = embeddingsWrapper2(tracer);
22358
22897
  EmbeddingsClass.prototype.create = function(...args) {
@@ -22380,7 +22919,7 @@ var NetraMistralAIInstrumentor = class {
22380
22919
  let didPatch = false;
22381
22920
  if (FimClass?.prototype?.complete) {
22382
22921
  const originalComplete = FimClass.prototype.complete;
22383
- originalMethods4.set(`fim.complete-${index}`, originalComplete);
22922
+ originalMethods3.set(`fim.complete-${index}`, originalComplete);
22384
22923
  const tracer = this.tracer;
22385
22924
  const wrapper = fimWrapper(tracer);
22386
22925
  FimClass.prototype.complete = function(...args) {
@@ -22397,7 +22936,7 @@ var NetraMistralAIInstrumentor = class {
22397
22936
  }
22398
22937
  if (FimClass?.prototype?.stream) {
22399
22938
  const originalStream = FimClass.prototype.stream;
22400
- originalMethods4.set(`fim.stream-${index}`, originalStream);
22939
+ originalMethods3.set(`fim.stream-${index}`, originalStream);
22401
22940
  const tracer = this.tracer;
22402
22941
  const wrapper = fimStreamWrapper(tracer);
22403
22942
  FimClass.prototype.stream = function(...args) {
@@ -22425,7 +22964,7 @@ var NetraMistralAIInstrumentor = class {
22425
22964
  let didPatch = false;
22426
22965
  if (AgentsClass?.prototype?.complete) {
22427
22966
  const originalComplete = AgentsClass.prototype.complete;
22428
- originalMethods4.set(`agents.complete-${index}`, originalComplete);
22967
+ originalMethods3.set(`agents.complete-${index}`, originalComplete);
22429
22968
  const tracer = this.tracer;
22430
22969
  const wrapper = agentsWrapper(tracer);
22431
22970
  AgentsClass.prototype.complete = function(...args) {
@@ -22442,7 +22981,7 @@ var NetraMistralAIInstrumentor = class {
22442
22981
  }
22443
22982
  if (AgentsClass?.prototype?.stream) {
22444
22983
  const originalStream = AgentsClass.prototype.stream;
22445
- originalMethods4.set(`agents.stream-${index}`, originalStream);
22984
+ originalMethods3.set(`agents.stream-${index}`, originalStream);
22446
22985
  const tracer = this.tracer;
22447
22986
  const wrapper = agentsStreamWrapper(tracer);
22448
22987
  AgentsClass.prototype.stream = function(...args) {
@@ -22466,11 +23005,11 @@ var NetraMistralAIInstrumentor = class {
22466
23005
  _uninstrumentChat(Mistral, index) {
22467
23006
  try {
22468
23007
  const ChatClass = this._getCtor(Mistral, "chat");
22469
- const originalComplete = originalMethods4.get(`chat.complete-${index}`);
23008
+ const originalComplete = originalMethods3.get(`chat.complete-${index}`);
22470
23009
  if (originalComplete && ChatClass?.prototype) {
22471
23010
  ChatClass.prototype.complete = originalComplete;
22472
23011
  }
22473
- const originalStream = originalMethods4.get(`chat.stream-${index}`);
23012
+ const originalStream = originalMethods3.get(`chat.stream-${index}`);
22474
23013
  if (originalStream && ChatClass?.prototype) {
22475
23014
  ChatClass.prototype.stream = originalStream;
22476
23015
  }
@@ -22481,7 +23020,7 @@ var NetraMistralAIInstrumentor = class {
22481
23020
  _uninstrumentEmbeddings(Mistral, index) {
22482
23021
  try {
22483
23022
  const EmbeddingsClass = this._getCtor(Mistral, "embeddings");
22484
- const originalCreate = originalMethods4.get(`embeddings.create-${index}`);
23023
+ const originalCreate = originalMethods3.get(`embeddings.create-${index}`);
22485
23024
  if (originalCreate && EmbeddingsClass?.prototype) {
22486
23025
  EmbeddingsClass.prototype.create = originalCreate;
22487
23026
  }
@@ -22492,11 +23031,11 @@ var NetraMistralAIInstrumentor = class {
22492
23031
  _uninstrumentFIM(Mistral, index) {
22493
23032
  try {
22494
23033
  const FimClass = this._getCtor(Mistral, "fim");
22495
- const originalComplete = originalMethods4.get(`fim.complete-${index}`);
23034
+ const originalComplete = originalMethods3.get(`fim.complete-${index}`);
22496
23035
  if (originalComplete && FimClass?.prototype) {
22497
23036
  FimClass.prototype.complete = originalComplete;
22498
23037
  }
22499
- const originalStream = originalMethods4.get(`fim.stream-${index}`);
23038
+ const originalStream = originalMethods3.get(`fim.stream-${index}`);
22500
23039
  if (originalStream && FimClass?.prototype) {
22501
23040
  FimClass.prototype.stream = originalStream;
22502
23041
  }
@@ -22507,11 +23046,11 @@ var NetraMistralAIInstrumentor = class {
22507
23046
  _uninstrumentAgents(Mistral, index) {
22508
23047
  try {
22509
23048
  const AgentsClass = this._getCtor(Mistral, "agents");
22510
- const originalComplete = originalMethods4.get(`agents.complete-${index}`);
23049
+ const originalComplete = originalMethods3.get(`agents.complete-${index}`);
22511
23050
  if (originalComplete && AgentsClass?.prototype) {
22512
23051
  AgentsClass.prototype.complete = originalComplete;
22513
23052
  }
22514
- const originalStream = originalMethods4.get(`agents.stream-${index}`);
23053
+ const originalStream = originalMethods3.get(`agents.stream-${index}`);
22515
23054
  if (originalStream && AgentsClass?.prototype) {
22516
23055
  AgentsClass.prototype.stream = originalStream;
22517
23056
  }
@@ -22539,7 +23078,7 @@ function setResponseAttributes6(span2, response) {
22539
23078
  }
22540
23079
 
22541
23080
  // src/instrumentation/openai/wrappers.ts
22542
- var SPAN_NAMES = {
23081
+ var SPAN_NAMES2 = {
22543
23082
  chat: "openai.chat",
22544
23083
  embedding: "openai.embedding",
22545
23084
  response: "openai.response"
@@ -22680,7 +23219,7 @@ var StreamingWrapper3 = class extends BaseStreamHandler {
22680
23219
  throw new Error("Response is not iterable");
22681
23220
  }
22682
23221
  };
22683
- var AsyncStreamingWrapper4 = class extends BaseStreamHandler {
23222
+ var AsyncStreamingWrapper3 = class extends BaseStreamHandler {
22684
23223
  constructor(span2, response, startTime, requestKwargs) {
22685
23224
  super(span2, startTime, requestKwargs);
22686
23225
  this.iterator = null;
@@ -22736,7 +23275,7 @@ function executeStreaming(span2, ctx, kwargs, requestType, call) {
22736
23275
  return (async () => {
22737
23276
  try {
22738
23277
  const stream = await response;
22739
- return new AsyncStreamingWrapper4(span2, stream, startTime, kwargs);
23278
+ return new AsyncStreamingWrapper3(span2, stream, startTime, kwargs);
22740
23279
  } catch (error) {
22741
23280
  handleSpanError(span2, error);
22742
23281
  throw error;
@@ -22774,7 +23313,7 @@ function executeNonStreaming(span2, kwargs, requestType, call) {
22774
23313
  }
22775
23314
  }
22776
23315
  function openAIWrapper(tracer, requestType) {
22777
- const spanName = SPAN_NAMES[requestType];
23316
+ const spanName = SPAN_NAMES2[requestType];
22778
23317
  const spanOpts = { kind: api.SpanKind.CLIENT, attributes: { "llm.request.type": requestType } };
22779
23318
  return (wrapped, instance, args, kwargs) => {
22780
23319
  if (shouldSuppressInstrumentation()) {
@@ -23603,6 +24142,8 @@ var cachedAgentsModule = null;
23603
24142
  var isInstrumented6 = false;
23604
24143
  var activeTracer = null;
23605
24144
  var activeProcessor = null;
24145
+ var originalProcessors = null;
24146
+ var didReplaceProcessors = false;
23606
24147
  async function resolveAgentsModule() {
23607
24148
  if (cachedAgentsModule) return cachedAgentsModule;
23608
24149
  try {
@@ -23655,20 +24196,51 @@ var NetraOpenAIAgentsInstrumentor = class {
23655
24196
  }
23656
24197
  const systemName = options.systemName ?? DEFAULT_LLM_SYSTEM;
23657
24198
  activeProcessor = new NetraAgentsTracingProcessor(activeTracer, systemName);
24199
+ const mode = options.nativeTracing ?? parseNativeTracingEnv("NATIVE_TRACING_MODE") ?? "netra-strict";
24200
+ const canSet = typeof agentsModule.setTraceProcessors === "function";
24201
+ const canAdd = typeof agentsModule.addTraceProcessor === "function";
24202
+ let strategy;
24203
+ if (mode === "both" || mode === "netra" && !canSet) {
24204
+ strategy = "append";
24205
+ } else if (canSet) {
24206
+ strategy = "replace";
24207
+ } else {
24208
+ strategy = "skip";
24209
+ }
23658
24210
  try {
23659
- if (typeof agentsModule.addTraceProcessor === "function") {
23660
- agentsModule.addTraceProcessor(activeProcessor);
23661
- } else if (typeof agentsModule.setTraceProcessors === "function") {
23662
- const existing = typeof agentsModule.getTraceProcessors === "function" ? agentsModule.getTraceProcessors() : [];
23663
- agentsModule.setTraceProcessors([...existing, activeProcessor]);
23664
- } else {
23665
- Logger.warn(
23666
- "OpenAI Agents SDK does not expose addTraceProcessor or setTraceProcessors.",
23667
- "Tracing integration may not work."
23668
- );
23669
- activeProcessor = null;
23670
- activeTracer = null;
23671
- return this;
24211
+ switch (strategy) {
24212
+ case "replace":
24213
+ if (typeof agentsModule.getTraceProcessors === "function") {
24214
+ originalProcessors = agentsModule.getTraceProcessors();
24215
+ }
24216
+ agentsModule.setTraceProcessors([activeProcessor]);
24217
+ didReplaceProcessors = true;
24218
+ Logger.debug("OpenAI Agents native tracing disabled \u2014 traces will only be sent to Netra.");
24219
+ break;
24220
+ case "append":
24221
+ if (canAdd) {
24222
+ agentsModule.addTraceProcessor(activeProcessor);
24223
+ } else {
24224
+ Logger.warn("OpenAI Agents SDK does not expose addTraceProcessor or setTraceProcessors.");
24225
+ activeProcessor = null;
24226
+ activeTracer = null;
24227
+ return this;
24228
+ }
24229
+ if (mode === "netra") {
24230
+ Logger.warn(
24231
+ "Cannot exclusively replace native trace processors in this @openai/agents version.",
24232
+ "Traces may still be sent to OpenAI."
24233
+ );
24234
+ }
24235
+ break;
24236
+ case "skip":
24237
+ Logger.warn(
24238
+ 'nativeTracing is "netra-strict" but the installed @openai/agents version',
24239
+ "does not support processor replacement. Skipping instrumentation."
24240
+ );
24241
+ activeProcessor = null;
24242
+ activeTracer = null;
24243
+ return this;
23672
24244
  }
23673
24245
  } catch (error) {
23674
24246
  Logger.warn("Failed to register trace processor with @openai/agents:", error);
@@ -23688,6 +24260,21 @@ var NetraOpenAIAgentsInstrumentor = class {
23688
24260
  activeProcessor.shutdown();
23689
24261
  activeProcessor = null;
23690
24262
  }
24263
+ if (didReplaceProcessors && cachedAgentsModule) {
24264
+ try {
24265
+ if (originalProcessors && typeof cachedAgentsModule.setTraceProcessors === "function") {
24266
+ cachedAgentsModule.setTraceProcessors(originalProcessors);
24267
+ Logger.debug("Restored original OpenAI Agents trace processors");
24268
+ } else if (typeof cachedAgentsModule.setDefaultOpenAITracingExporter === "function") {
24269
+ cachedAgentsModule.setDefaultOpenAITracingExporter();
24270
+ Logger.debug("Restored default OpenAI Agents tracing exporter");
24271
+ }
24272
+ } catch (error) {
24273
+ Logger.debug("Failed to restore original trace processors:", error);
24274
+ }
24275
+ }
24276
+ originalProcessors = null;
24277
+ didReplaceProcessors = false;
23691
24278
  activeTracer = null;
23692
24279
  cachedAgentsModule = null;
23693
24280
  isInstrumented6 = false;
@@ -23952,7 +24539,7 @@ function repositoryQueryWrapper(tracer) {
23952
24539
  var __version__8 = "1.0.0";
23953
24540
  var require2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
23954
24541
  var INSTRUMENTATION_NAME8 = "netra.instrumentation.typeorm";
23955
- var originalMethods5 = /* @__PURE__ */ new Map();
24542
+ var originalMethods4 = /* @__PURE__ */ new Map();
23956
24543
  var isInstrumented7 = false;
23957
24544
  var NetraTypeORMInstrumentor = class {
23958
24545
  constructor() {
@@ -23986,7 +24573,7 @@ var NetraTypeORMInstrumentor = class {
23986
24573
  });
23987
24574
  this._uninstrumentRepository().catch(() => {
23988
24575
  });
23989
- originalMethods5.clear();
24576
+ originalMethods4.clear();
23990
24577
  isInstrumented7 = false;
23991
24578
  }
23992
24579
  isInstrumented() {
@@ -24005,7 +24592,7 @@ var NetraTypeORMInstrumentor = class {
24005
24592
  }
24006
24593
  if (DataSource.prototype?.query) {
24007
24594
  const originalQuery = DataSource.prototype.query;
24008
- originalMethods5.set("DataSource.prototype.query", originalQuery);
24595
+ originalMethods4.set("DataSource.prototype.query", originalQuery);
24009
24596
  const tracer = this.tracer;
24010
24597
  const wrapper = queryWrapper(tracer);
24011
24598
  DataSource.prototype.query = function(...args) {
@@ -24030,7 +24617,7 @@ var NetraTypeORMInstrumentor = class {
24030
24617
  }
24031
24618
  if (EntityManager.prototype?.query) {
24032
24619
  const originalQuery = EntityManager.prototype.query;
24033
- originalMethods5.set("EntityManager.prototype.query", originalQuery);
24620
+ originalMethods4.set("EntityManager.prototype.query", originalQuery);
24034
24621
  const tracer = this.tracer;
24035
24622
  const wrapper = managerQueryWrapper(tracer);
24036
24623
  EntityManager.prototype.query = function(...args) {
@@ -24055,7 +24642,7 @@ var NetraTypeORMInstrumentor = class {
24055
24642
  }
24056
24643
  if (Repository.prototype?.query) {
24057
24644
  const originalQuery = Repository.prototype.query;
24058
- originalMethods5.set("Repository.prototype.query", originalQuery);
24645
+ originalMethods4.set("Repository.prototype.query", originalQuery);
24059
24646
  const tracer = this.tracer;
24060
24647
  const wrapper = repositoryQueryWrapper(tracer);
24061
24648
  Repository.prototype.query = function(...args) {
@@ -24071,7 +24658,7 @@ var NetraTypeORMInstrumentor = class {
24071
24658
  try {
24072
24659
  const typeorm = require2("typeorm");
24073
24660
  const DataSource = typeorm.DataSource || typeorm.default?.DataSource;
24074
- const originalQuery = originalMethods5.get("DataSource.prototype.query");
24661
+ const originalQuery = originalMethods4.get("DataSource.prototype.query");
24075
24662
  if (originalQuery && DataSource?.prototype) {
24076
24663
  DataSource.prototype.query = originalQuery;
24077
24664
  }
@@ -24083,7 +24670,7 @@ var NetraTypeORMInstrumentor = class {
24083
24670
  try {
24084
24671
  const typeorm = require2("typeorm");
24085
24672
  const EntityManager = typeorm.EntityManager || typeorm.default?.EntityManager;
24086
- const originalQuery = originalMethods5.get("EntityManager.prototype.query");
24673
+ const originalQuery = originalMethods4.get("EntityManager.prototype.query");
24087
24674
  if (originalQuery && EntityManager?.prototype) {
24088
24675
  EntityManager.prototype.query = originalQuery;
24089
24676
  }
@@ -24095,7 +24682,7 @@ var NetraTypeORMInstrumentor = class {
24095
24682
  try {
24096
24683
  const typeorm = require2("typeorm");
24097
24684
  const Repository = typeorm.Repository || typeorm.default?.Repository;
24098
- const originalQuery = originalMethods5.get("Repository.prototype.query");
24685
+ const originalQuery = originalMethods4.get("Repository.prototype.query");
24099
24686
  if (originalQuery && Repository?.prototype) {
24100
24687
  Repository.prototype.query = originalQuery;
24101
24688
  }
@@ -24570,7 +25157,9 @@ function initInstrumentations(config2, instruments, blockInstruments, rootInstru
24570
25157
  mistral: false,
24571
25158
  langgraph: false,
24572
25159
  googleGenAI: false,
24573
- anthropic: false};
25160
+ anthropic: false,
25161
+ openAiAgents: false
25162
+ };
24574
25163
  const resolved = enableAll ? new Set(Object.values(NetraInstruments).filter((v) => v !== "__all__" /* ALL */)) : instruments && instruments.size > 0 ? instruments : DEFAULT_INSTRUMENTS;
24575
25164
  instrumentModules.google_vertexai = false;
24576
25165
  instrumentModules.langchain = false;
@@ -24618,6 +25207,9 @@ function initInstrumentations(config2, instruments, blockInstruments, rootInstru
24618
25207
  if (resolved.has("anthropic" /* ANTHROPIC */)) {
24619
25208
  customInstrumentModules.anthropic = true;
24620
25209
  }
25210
+ if (resolved.has("openai_agents" /* OPENAI_AGENTS */)) {
25211
+ customInstrumentModules.openAiAgents = true;
25212
+ }
24621
25213
  if (blockInstruments && blockInstruments.size > 0) {
24622
25214
  const blockAll = blockInstruments.has("__all__" /* ALL */);
24623
25215
  if (blockAll || blockInstruments.has("openai" /* OPENAI */)) customInstrumentModules.openai = false;
@@ -24626,6 +25218,7 @@ function initInstrumentations(config2, instruments, blockInstruments, rootInstru
24626
25218
  if (blockAll || blockInstruments.has("langgraph" /* LANGGRAPH */)) customInstrumentModules.langgraph = false;
24627
25219
  if (blockAll || blockInstruments.has("google_genai" /* GOOGLE_GENERATIVE_AI */)) customInstrumentModules.googleGenAI = false;
24628
25220
  if (blockAll || blockInstruments.has("anthropic" /* ANTHROPIC */)) customInstrumentModules.anthropic = false;
25221
+ if (blockAll || blockInstruments.has("openai_agents" /* OPENAI_AGENTS */)) customInstrumentModules.openAiAgents = false;
24629
25222
  if (blockAll || blockInstruments.has("vertexai" /* VERTEX_AI */)) instrumentModules.google_vertexai = false;
24630
25223
  if (blockAll || blockInstruments.has("langchain" /* LANGCHAIN */)) instrumentModules.langchain = false;
24631
25224
  if (blockAll || blockInstruments.has("llama_index" /* LLAMA_INDEX */)) instrumentModules.llamaIndex = false;
@@ -24742,13 +25335,13 @@ async function initCustomInstrumentationsAsync(config2, tracerProvider, customIn
24742
25335
  }
24743
25336
  if (customInstrumentModules.anthropic) {
24744
25337
  try {
24745
- await anthropicInstrumentor.instrumentAsync({ tracerProvider });
25338
+ await anthropicInstrumentor.instrument({ tracerProvider });
24746
25339
  Logger.debug("Custom Anthropic instrumentation enabled");
24747
25340
  } catch (e) {
24748
25341
  Logger.debug("Failed to initialize custom Anthropic instrumentation:", e);
24749
25342
  }
24750
25343
  }
24751
- if (customInstrumentModules.openaiAgents && !blockInstruments?.has("openai_agents" /* OPENAI_AGENTS */)) {
25344
+ if (customInstrumentModules.openAiAgents && !blockInstruments?.has("openai_agents" /* OPENAI_AGENTS */)) {
24752
25345
  try {
24753
25346
  await openaiAgentsInstrumentor.instrument({ tracerProvider });
24754
25347
  Logger.debug("Custom OpenAI Agents SDK instrumentation enabled");
@@ -24894,7 +25487,7 @@ function addCustomSpanProcessors(tracerProvider, config2, rootInstrumentNames) {
24894
25487
  }
24895
25488
  const instrumentationProcessor = new InstrumentationSpanProcessor();
24896
25489
  provider.addSpanProcessor(instrumentationProcessor);
24897
- const sessionProcessor = new SessionSpanProcessor();
25490
+ const sessionProcessor = new SessionSpanProcessor(config2.environment);
24898
25491
  provider.addSpanProcessor(sessionProcessor);
24899
25492
  const spanIOProcessor = new SpanIOProcessor();
24900
25493
  provider.addSpanProcessor(spanIOProcessor);
@@ -24906,6 +25499,10 @@ function addCustomSpanProcessors(tracerProvider, config2, rootInstrumentNames) {
24906
25499
  const scrubbingProcessor = new ScrubbingSpanProcessor();
24907
25500
  provider.addSpanProcessor(scrubbingProcessor);
24908
25501
  }
25502
+ const sizeLimitProcessor = new AttributeSizeLimitProcessor(
25503
+ Config.SPAN_ATTRIBUTE_MAX_SIZE
25504
+ );
25505
+ provider.addSpanProcessor(sizeLimitProcessor);
24909
25506
  Logger.debug("Custom span processors registered successfully");
24910
25507
  return provider;
24911
25508
  } catch (e) {
@@ -25554,33 +26151,6 @@ var Tracer17 = class {
25554
26151
  }
25555
26152
  }
25556
26153
  };
25557
- function safeStringify3(value, maxLen = 1e3) {
25558
- const seen = /* @__PURE__ */ new WeakSet();
25559
- try {
25560
- return JSON.stringify(value, (_key, val) => {
25561
- if (typeof val === "function") return `[Function: ${val.name || "anonymous"}]`;
25562
- if (typeof val === "symbol") return val.toString();
25563
- if (typeof val === "bigint") return val.toString();
25564
- if (val !== null && typeof val === "object") {
25565
- if (seen.has(val)) return "[Circular]";
25566
- seen.add(val);
25567
- const name = val.constructor?.name;
25568
- if (name && name !== "Object" && name !== "Array" && Object.keys(val).length > 20) {
25569
- return `[${name}]`;
25570
- }
25571
- }
25572
- return val;
25573
- }).substring(0, maxLen);
25574
- } catch {
25575
- return value?.constructor?.name ? `[${value.constructor.name}]` : String(typeof value);
25576
- }
25577
- }
25578
- function serializeValue2(value) {
25579
- if (value === null || value === void 0) return String(value);
25580
- const t = typeof value;
25581
- if (t === "string" || t === "number" || t === "boolean") return String(value);
25582
- return safeStringify3(value);
25583
- }
25584
26154
  function spanHasOutput(span2) {
25585
26155
  try {
25586
26156
  for (const field of ["attributes", "_attributes"]) {
@@ -25595,13 +26165,13 @@ function spanHasOutput(span2) {
25595
26165
  function addInputAttributes(span2, args, entityType) {
25596
26166
  span2.setAttribute(`${Config.LIBRARY_NAME}.entity.type`, entityType);
25597
26167
  if (args.length > 0) {
25598
- span2.setAttribute("input", safeStringify3(args));
26168
+ span2.setAttribute("input", safeStringify(args, Config.ATTRIBUTE_MAX_LEN));
25599
26169
  }
25600
26170
  }
25601
26171
  function addOutputAttributes(span2, result) {
25602
26172
  if (spanHasOutput(span2)) return;
25603
26173
  try {
25604
- span2.setAttribute("output", serializeValue2(result));
26174
+ span2.setAttribute("output", serializeValue(result, Config.ATTRIBUTE_MAX_LEN));
25605
26175
  } catch (e) {
25606
26176
  span2.setAttribute("output_error", String(e));
25607
26177
  }
@@ -25621,69 +26191,63 @@ function createFunctionWrapper(func, entityType, name, asType = "SPAN" /* SPAN *
25621
26191
  span2.setAttribute("netra.span.type", asType);
25622
26192
  SessionManager.registerSpan(spanName, span2);
25623
26193
  };
25624
- const handleError = (span2, e) => {
26194
+ const recordError = (span2, e) => {
25625
26195
  span2.setAttribute(`${Config.LIBRARY_NAME}.entity.error`, String(e));
25626
26196
  span2.setStatus({
25627
26197
  code: api.SpanStatusCode.ERROR,
25628
26198
  message: e instanceof Error ? e.message : String(e)
25629
26199
  });
25630
26200
  span2.recordException(e);
25631
- throw e;
25632
26201
  };
25633
26202
  const cleanup = (span2) => {
25634
26203
  span2.end();
25635
26204
  SessionManager.unregisterSpan(spanName, span2);
25636
26205
  SessionManager.popEntity(entityType);
25637
26206
  };
25638
- if (isAsync) {
25639
- const wrapper = async function(...args) {
25640
- SessionManager.pushEntity(entityType, spanName);
25641
- const tracer = api.trace.getTracer(moduleName);
25642
- return tracer.startActiveSpan(spanName, async (span2) => {
25643
- try {
25644
- initSpan(span2);
25645
- addInputAttributes(span2, args, entityType);
25646
- const result = await func.call(this, ...args);
25647
- addOutputAttributes(span2, result);
25648
- return result;
25649
- } catch (e) {
25650
- handleError(span2, e);
25651
- } finally {
25652
- cleanup(span2);
25653
- }
25654
- });
25655
- };
25656
- return wrapper;
25657
- } else {
25658
- const wrapper = function(...args) {
25659
- SessionManager.pushEntity(entityType, spanName);
25660
- const tracer = api.trace.getTracer(moduleName);
25661
- return tracer.startActiveSpan(spanName, (span2) => {
25662
- let returnedPromise = false;
25663
- try {
25664
- initSpan(span2);
25665
- addInputAttributes(span2, args, entityType);
25666
- const result = func.call(this, ...args);
25667
- if (result != null && typeof result.then === "function") {
25668
- returnedPromise = true;
25669
- return result.then((resolved) => {
25670
- addOutputAttributes(span2, resolved);
25671
- return resolved;
25672
- }).catch((e) => handleError(span2, e)).finally(() => cleanup(span2));
25673
- }
25674
- addOutputAttributes(span2, result);
25675
- return result;
25676
- } catch (e) {
25677
- handleError(span2, e);
25678
- } finally {
25679
- if (!returnedPromise) {
25680
- cleanup(span2);
25681
- }
25682
- }
25683
- });
25684
- };
25685
- return wrapper;
25686
- }
26207
+ const wrapperFn = isAsync ? async function(...args) {
26208
+ SessionManager.pushEntity(entityType, spanName);
26209
+ const tracer = api.trace.getTracer(moduleName);
26210
+ return tracer.startActiveSpan(spanName, async (span2) => {
26211
+ try {
26212
+ initSpan(span2);
26213
+ addInputAttributes(span2, args, entityType);
26214
+ const result = await func.call(this, ...args);
26215
+ const spanCtx = api.trace.setSpan(api.context.active(), span2);
26216
+ return wrapResponse(result, {
26217
+ withContext: (fn) => api.context.with(spanCtx, fn),
26218
+ onError: (e) => recordError(span2, e),
26219
+ onSuccess: (value) => addOutputAttributes(span2, value),
26220
+ finalize: () => cleanup(span2)
26221
+ });
26222
+ } catch (e) {
26223
+ recordError(span2, e);
26224
+ cleanup(span2);
26225
+ throw e;
26226
+ }
26227
+ });
26228
+ } : function(...args) {
26229
+ SessionManager.pushEntity(entityType, spanName);
26230
+ const tracer = api.trace.getTracer(moduleName);
26231
+ return tracer.startActiveSpan(spanName, (span2) => {
26232
+ try {
26233
+ initSpan(span2);
26234
+ addInputAttributes(span2, args, entityType);
26235
+ const result = func.call(this, ...args);
26236
+ const spanCtx = api.trace.setSpan(api.context.active(), span2);
26237
+ return wrapResponse(result, {
26238
+ withContext: (fn) => api.context.with(spanCtx, fn),
26239
+ onError: (e) => recordError(span2, e),
26240
+ onSuccess: (value) => addOutputAttributes(span2, value),
26241
+ finalize: () => cleanup(span2)
26242
+ });
26243
+ } catch (e) {
26244
+ recordError(span2, e);
26245
+ cleanup(span2);
26246
+ throw e;
26247
+ }
26248
+ });
26249
+ };
26250
+ return wrapperFn;
25687
26251
  }
25688
26252
  var SKIP_STATIC_PROPS = /* @__PURE__ */ new Set([
25689
26253
  "length",
@@ -26070,14 +26634,11 @@ Received ${signal}. Shutting down Netra SDK...`);
26070
26634
  spanWrapper.end();
26071
26635
  throw e;
26072
26636
  }
26073
- if (result instanceof Promise) {
26074
- return result.catch((e) => {
26075
- spanWrapper.setError(e instanceof Error ? e.message : String(e));
26076
- throw e;
26077
- }).finally(() => spanWrapper.end());
26078
- }
26079
- spanWrapper.end();
26080
- return result;
26637
+ return wrapResponse(result, {
26638
+ withContext: (fn2) => spanWrapper.withActive(fn2),
26639
+ onError: (e) => spanWrapper.setError(e instanceof Error ? e.message : String(e)),
26640
+ finalize: () => spanWrapper.end()
26641
+ });
26081
26642
  });
26082
26643
  }
26083
26644
  };
@@ -26088,6 +26649,7 @@ Netra.withBlockedSpansLocal = withBlockedSpansLocal;
26088
26649
  var index_default = Netra;
26089
26650
 
26090
26651
  exports.Aggregation = Aggregation;
26652
+ exports.AttributeSizeLimitProcessor = AttributeSizeLimitProcessor;
26091
26653
  exports.BaseTask = BaseTask;
26092
26654
  exports.ChartType = ChartType;
26093
26655
  exports.Config = Config;