netra-sdk 1.1.0-beta → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { __toESM, require_decamelize, require_camelcase, init_esm_node, __publicField, v7_default, __require } from './chunk-WMQRYJGR.js';
2
- import { createContextKey, propagation, trace, SpanKind, context, SpanStatusCode, ROOT_CONTEXT } from '@opentelemetry/api';
2
+ import { createContextKey, propagation, context, trace, SpanKind, SpanStatusCode, ROOT_CONTEXT } from '@opentelemetry/api';
3
3
  import { createRequire } from 'module';
4
4
  import { AsyncLocalStorage } from 'async_hooks';
5
5
  import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
@@ -39,6 +39,37 @@ var Logger = class {
39
39
  }
40
40
  };
41
41
  Logger._debugMode = false;
42
+ function injectTraceContextHeaders(headers) {
43
+ const carrier = { ...headers };
44
+ try {
45
+ propagation.inject(context.active(), carrier);
46
+ } catch {
47
+ Logger.warn("netra: Failed to inject trace context headers");
48
+ return headers;
49
+ }
50
+ return carrier;
51
+ }
52
+ function extractContextFromHeaders(headers) {
53
+ const carrier = {};
54
+ for (const [key, value] of Object.entries(headers)) {
55
+ if (typeof value === "string") {
56
+ carrier[key.toLowerCase()] = value;
57
+ } else if (Array.isArray(value) && value.length > 0) {
58
+ carrier[key.toLowerCase()] = value[0];
59
+ }
60
+ }
61
+ return propagation.extract(context.active(), carrier);
62
+ }
63
+ function runWithExtractedContext(headers, fn) {
64
+ const extractedCtx = extractContextFromHeaders(headers);
65
+ return context.with(extractedCtx, fn);
66
+ }
67
+ function netraExpressMiddleware() {
68
+ return (req, _res, next) => {
69
+ const extractedCtx = extractContextFromHeaders(req.headers);
70
+ context.with(extractedCtx, next);
71
+ };
72
+ }
42
73
 
43
74
  // src/api/http-client.ts
44
75
  var NetraHttpClient = class {
@@ -112,7 +143,7 @@ var NetraHttpClient = class {
112
143
  );
113
144
  const response = await fetch(url.toString(), {
114
145
  method: "GET",
115
- headers: this.headers,
146
+ headers: injectTraceContextHeaders(this.headers),
116
147
  signal: controller.signal
117
148
  });
118
149
  clearTimeout(timeoutId);
@@ -141,7 +172,7 @@ var NetraHttpClient = class {
141
172
  );
142
173
  const response = await fetch(url.toString(), {
143
174
  method: "POST",
144
- headers: this.headers,
175
+ headers: injectTraceContextHeaders(this.headers),
145
176
  body: body ? JSON.stringify(body) : void 0,
146
177
  signal: controller.signal
147
178
  });
@@ -1694,13 +1725,13 @@ async function runSingleEvaluator(params) {
1694
1725
  if (config2) {
1695
1726
  expectedName = config2.name;
1696
1727
  }
1697
- const context14 = {
1728
+ const context16 = {
1698
1729
  input: itemInput,
1699
1730
  taskOutput,
1700
1731
  expectedOutput,
1701
1732
  metadata
1702
1733
  };
1703
- let result = evaluator.evaluate(context14);
1734
+ let result = evaluator.evaluate(context16);
1704
1735
  if (result instanceof Promise) {
1705
1736
  result = await result;
1706
1737
  }
@@ -2054,10 +2085,14 @@ var Evaluation = class {
2054
2085
  ctx.spanId = formatSpanId(spanContext.spanId);
2055
2086
  }
2056
2087
  ctx.sessionId = getSessionIdFromBaggage();
2057
- const { output, status } = await executeTask(task2, ctx.itemInput);
2088
+ const { output, status } = await span2.withActive(
2089
+ () => executeTask(task2, ctx.itemInput)
2090
+ );
2058
2091
  ctx.taskOutput = output;
2059
2092
  ctx.status = status;
2060
- ctx.testRunItemId = await this.postCompletedStatus(runId, ctx);
2093
+ ctx.testRunItemId = await span2.withActive(
2094
+ () => this.postCompletedStatus(runId, ctx)
2095
+ );
2061
2096
  if (evaluators && ctx.status === "completed") {
2062
2097
  const evalTask = this.runEvaluatorsForItem(runId, ctx, evaluators);
2063
2098
  bgEvalTasks.push(evalTask);
@@ -3671,6 +3706,10 @@ function setModelParams(span2, kwargs) {
3671
3706
  function buildInputMessages(kwargs, requestType) {
3672
3707
  const messages = [];
3673
3708
  if (requestType === "chat") {
3709
+ if (hasContent(kwargs.system)) {
3710
+ const systemContent = typeof kwargs.system === "string" ? kwargs.system : safeStringify(kwargs.system);
3711
+ messages.push({ role: "system", content: systemContent });
3712
+ }
3674
3713
  const rawMessages = kwargs.messages;
3675
3714
  if (!Array.isArray(rawMessages)) return messages;
3676
3715
  for (const msg of rawMessages) {
@@ -3995,7 +4034,7 @@ function anthropicWrapper(tracer, spanName, requestType) {
3995
4034
  return (async () => {
3996
4035
  try {
3997
4036
  const stream = await response;
3998
- return new AsyncStreamingWrapper(span2, stream, startTime, kwargs);
4037
+ return new AsyncStreamingWrapper(span2, stream, startTime, kwargs, spanContext);
3999
4038
  } catch (error) {
4000
4039
  Logger.error("netra.instrumentation.anthropic:", error);
4001
4040
  span2.setStatus({
@@ -4008,7 +4047,7 @@ function anthropicWrapper(tracer, spanName, requestType) {
4008
4047
  }
4009
4048
  })();
4010
4049
  } else {
4011
- return new AsyncStreamingWrapper(span2, response, startTime, kwargs);
4050
+ return new AsyncStreamingWrapper(span2, response, startTime, kwargs, spanContext);
4012
4051
  }
4013
4052
  } catch (error) {
4014
4053
  Logger.error("netra.instrumentation.anthropic:", error);
@@ -4137,7 +4176,7 @@ var LISTENER_REGISTRATION_METHODS = /* @__PURE__ */ new Set(["on", "once", "addL
4137
4176
  var COMPLETION_METHODS = /* @__PURE__ */ new Set(["finalMessage", "done", "finalText"]);
4138
4177
  var TRACKED_STREAM_EVENTS = /* @__PURE__ */ new Set(["message", "contentBlock", "text", "finalMessage"]);
4139
4178
  var MessageStreamWrapper = class {
4140
- constructor(span2, messageStream, startTime, requestKwargs) {
4179
+ constructor(span2, messageStream, startTime, requestKwargs, spanContext) {
4141
4180
  this.completeResponse = {
4142
4181
  content: [],
4143
4182
  model: "",
@@ -4147,6 +4186,7 @@ var MessageStreamWrapper = class {
4147
4186
  defineHidden(this, "messageStream", messageStream);
4148
4187
  defineHidden(this, "startTime", startTime);
4149
4188
  defineHidden(this, "requestKwargs", requestKwargs);
4189
+ defineHidden(this, "spanContext", spanContext || trace.setSpan(context.active(), span2));
4150
4190
  return new Proxy(this, {
4151
4191
  get(target, prop, receiver) {
4152
4192
  if (prop === "toJSON") {
@@ -4223,6 +4263,9 @@ var MessageStreamWrapper = class {
4223
4263
  throw err;
4224
4264
  }
4225
4265
  }
4266
+ getSpanContext() {
4267
+ return this.spanContext;
4268
+ }
4226
4269
  processEventData(eventType, data) {
4227
4270
  switch (eventType) {
4228
4271
  case "message":
@@ -4267,10 +4310,20 @@ var MessageStreamWrapper = class {
4267
4310
  if (!this.completeResponse.content) {
4268
4311
  this.completeResponse.content = [];
4269
4312
  }
4270
- this.completeResponse.content.push({
4271
- type: chunk.content_block.type,
4272
- text: ""
4273
- });
4313
+ const block = chunk.content_block;
4314
+ if (block.type === "tool_use") {
4315
+ this.completeResponse.content.push({
4316
+ type: "tool_use",
4317
+ id: block.id,
4318
+ name: block.name,
4319
+ input: ""
4320
+ });
4321
+ } else {
4322
+ this.completeResponse.content.push({
4323
+ type: block.type,
4324
+ text: ""
4325
+ });
4326
+ }
4274
4327
  break;
4275
4328
  }
4276
4329
  case "content_block_delta": {
@@ -4278,11 +4331,27 @@ var MessageStreamWrapper = class {
4278
4331
  this.completeResponse.content = [{ type: "text", text: "" }];
4279
4332
  }
4280
4333
  const lastBlock = this.completeResponse.content[this.completeResponse.content.length - 1];
4281
- if (lastBlock && chunk.delta?.text) {
4334
+ if (chunk.delta?.type === "input_json_delta" && lastBlock?.type === "tool_use") {
4335
+ lastBlock.input += chunk.delta.partial_json ?? "";
4336
+ } else if (lastBlock && chunk.delta?.text) {
4282
4337
  lastBlock.text += chunk.delta.text;
4283
4338
  }
4284
4339
  break;
4285
4340
  }
4341
+ case "content_block_stop": {
4342
+ const blocks = this.completeResponse.content;
4343
+ if (blocks && blocks.length > 0) {
4344
+ const finishedBlock = blocks[blocks.length - 1];
4345
+ if (finishedBlock?.type === "tool_use" && typeof finishedBlock.input === "string") {
4346
+ try {
4347
+ finishedBlock.input = JSON.parse(finishedBlock.input);
4348
+ } catch {
4349
+ Logger.warn("netra.instrumentation.anthropic: Failed to parse tool use input", finishedBlock.input);
4350
+ }
4351
+ }
4352
+ }
4353
+ break;
4354
+ }
4286
4355
  case "message_delta": {
4287
4356
  if (chunk.delta?.usage) {
4288
4357
  this.completeResponse.usage = {
@@ -4325,7 +4394,7 @@ var MessageStreamWrapper = class {
4325
4394
  }
4326
4395
  };
4327
4396
  var AsyncStreamingWrapper = class {
4328
- constructor(span2, response, startTime, requestKwargs) {
4397
+ constructor(span2, response, startTime, requestKwargs, spanContext) {
4329
4398
  this.iterator = null;
4330
4399
  this.completeResponse = {
4331
4400
  choices: [],
@@ -4335,6 +4404,7 @@ var AsyncStreamingWrapper = class {
4335
4404
  defineHidden(this, "response", response);
4336
4405
  defineHidden(this, "startTime", startTime);
4337
4406
  defineHidden(this, "requestKwargs", requestKwargs);
4407
+ defineHidden(this, "spanContext", spanContext || trace.setSpan(context.active(), span2));
4338
4408
  }
4339
4409
  toJSON() {
4340
4410
  return this.completeResponse;
@@ -4353,7 +4423,7 @@ var AsyncStreamingWrapper = class {
4353
4423
  throw new Error("Response is not iterable");
4354
4424
  }
4355
4425
  }
4356
- const result = await this.iterator.next();
4426
+ const result = await context.with(this.spanContext, () => this.iterator.next());
4357
4427
  if (result.done) {
4358
4428
  this.finalizeSpan(SpanStatusCode.OK);
4359
4429
  return result;
@@ -4379,10 +4449,20 @@ var AsyncStreamingWrapper = class {
4379
4449
  case "content_block_start": {
4380
4450
  const content = this.completeResponse.content || [];
4381
4451
  this.completeResponse.content = content;
4382
- content.push({
4383
- type: chunk.content_block.type,
4384
- text: ""
4385
- });
4452
+ const block = chunk.content_block;
4453
+ if (block.type === "tool_use") {
4454
+ content.push({
4455
+ type: "tool_use",
4456
+ id: block.id,
4457
+ name: block.name,
4458
+ input: ""
4459
+ });
4460
+ } else {
4461
+ content.push({
4462
+ type: block.type,
4463
+ text: ""
4464
+ });
4465
+ }
4386
4466
  break;
4387
4467
  }
4388
4468
  case "content_block_delta": {
@@ -4392,11 +4472,27 @@ var AsyncStreamingWrapper = class {
4392
4472
  this.completeResponse.content = content;
4393
4473
  }
4394
4474
  const lastBlock = content[content.length - 1];
4395
- if (lastBlock && chunk.delta?.text) {
4475
+ if (chunk.delta?.type === "input_json_delta" && lastBlock?.type === "tool_use") {
4476
+ lastBlock.input += chunk.delta.partial_json ?? "";
4477
+ } else if (lastBlock && chunk.delta?.text) {
4396
4478
  lastBlock.text += chunk.delta.text;
4397
4479
  }
4398
4480
  break;
4399
4481
  }
4482
+ case "content_block_stop": {
4483
+ const content = this.completeResponse.content || [];
4484
+ if (content.length > 0) {
4485
+ const finishedBlock = content[content.length - 1];
4486
+ if (finishedBlock?.type === "tool_use" && typeof finishedBlock.input === "string") {
4487
+ try {
4488
+ finishedBlock.input = JSON.parse(finishedBlock.input);
4489
+ } catch {
4490
+ Logger.warn("netra.instrumentation.anthropic: Failed to parse tool use input", finishedBlock.input);
4491
+ }
4492
+ }
4493
+ }
4494
+ break;
4495
+ }
4400
4496
  case "message_delta": {
4401
4497
  if (chunk.delta?.usage) {
4402
4498
  const currentUsage = this.completeResponse.usage || {};
@@ -4437,19 +4533,29 @@ var INSTRUMENTATION_NAME = "netra.instrumentation.anthropic";
4437
4533
  var INSTRUMENTS = ["anthropic >= 0.71.2"];
4438
4534
  var originalMethods = /* @__PURE__ */ new Map();
4439
4535
  var isInstrumented = false;
4440
- var AnthropicClass = null;
4536
+ var anthropicClasses = [];
4441
4537
  async function resolveAnthropicAsync() {
4442
- if (AnthropicClass) return AnthropicClass;
4538
+ if (anthropicClasses.length > 0) return anthropicClasses;
4443
4539
  try {
4444
4540
  const anthropicModule = await import('@anthropic-ai/sdk');
4445
- AnthropicClass = anthropicModule.Anthropic || anthropicModule.default || anthropicModule;
4446
- return AnthropicClass;
4541
+ anthropicClasses.push(anthropicModule.Anthropic || anthropicModule.default || anthropicModule);
4447
4542
  } catch {
4448
- return null;
4543
+ Logger.warn("Failed to resolve Anthropic ESM module");
4544
+ }
4545
+ try {
4546
+ const req = createRequire(import.meta.url);
4547
+ const mod = req("@anthropic-ai/sdk");
4548
+ const cjsClass = mod.Anthropic || mod.default || mod;
4549
+ if (!anthropicClasses.includes(cjsClass)) {
4550
+ anthropicClasses.push(cjsClass);
4551
+ }
4552
+ } catch {
4553
+ Logger.warn("Failed to resolve Anthropic CJS module");
4449
4554
  }
4555
+ return anthropicClasses;
4450
4556
  }
4451
4557
  function resolveAnthropic() {
4452
- return AnthropicClass;
4558
+ return anthropicClasses;
4453
4559
  }
4454
4560
  var NetraAnthropicInstrumentor = class {
4455
4561
  constructor() {
@@ -4463,8 +4569,8 @@ var NetraAnthropicInstrumentor = class {
4463
4569
  Logger.warn("Anthropic is already instrumented");
4464
4570
  return this;
4465
4571
  }
4466
- const Anthropic = await resolveAnthropicAsync();
4467
- if (!Anthropic) {
4572
+ const classes = await resolveAnthropicAsync();
4573
+ if (classes.length === 0) {
4468
4574
  return this;
4469
4575
  }
4470
4576
  try {
@@ -4481,9 +4587,11 @@ var NetraAnthropicInstrumentor = class {
4481
4587
  Logger.error(`Failed to initialize tracer: ${error}`);
4482
4588
  return this;
4483
4589
  }
4484
- this._instrumentMessages();
4485
- this._instrumentBetaMessages();
4486
- this._instrumentBatchMessages();
4590
+ classes.forEach((AnthropicSDK, index) => {
4591
+ this._instrumentMessages(AnthropicSDK, index);
4592
+ this._instrumentBetaMessages(AnthropicSDK, index);
4593
+ this._instrumentBatchMessages(AnthropicSDK, index);
4594
+ });
4487
4595
  isInstrumented = true;
4488
4596
  return this;
4489
4597
  }
@@ -4492,27 +4600,25 @@ var NetraAnthropicInstrumentor = class {
4492
4600
  Logger.warn("Anthropic is not instrumented");
4493
4601
  return;
4494
4602
  }
4495
- this._uninstrumentMessages();
4496
- this._uninstrumentBetaMessages();
4497
- this._uninstrumentBatchMessages();
4603
+ const classes = resolveAnthropic();
4604
+ classes.forEach((AnthropicSDK, index) => {
4605
+ this._uninstrumentMessages(AnthropicSDK, index);
4606
+ this._uninstrumentBetaMessages(AnthropicSDK, index);
4607
+ this._uninstrumentBatchMessages(AnthropicSDK, index);
4608
+ });
4498
4609
  originalMethods.clear();
4499
- AnthropicClass = null;
4610
+ anthropicClasses = [];
4500
4611
  isInstrumented = false;
4501
4612
  }
4502
4613
  isInstrumented() {
4503
4614
  return isInstrumented;
4504
4615
  }
4505
- _instrumentMessages() {
4616
+ _instrumentMessages(AnthropicSDK, index) {
4506
4617
  if (!this.tracer) {
4507
4618
  Logger.warn("Anthropic instrumentation: No tracer available");
4508
4619
  return;
4509
4620
  }
4510
4621
  try {
4511
- const AnthropicSDK = resolveAnthropic();
4512
- if (!AnthropicSDK) {
4513
- Logger.warn("Anthropic instrumentation: Anthropic SDK not available");
4514
- return;
4515
- }
4516
4622
  const MessagesClass = AnthropicSDK.Messages;
4517
4623
  if (!MessagesClass) {
4518
4624
  Logger.error(
@@ -4522,11 +4628,12 @@ var NetraAnthropicInstrumentor = class {
4522
4628
  }
4523
4629
  if (MessagesClass?.prototype?.stream) {
4524
4630
  const originalStream = MessagesClass.prototype.stream;
4525
- originalMethods.set("messages.stream", originalStream);
4631
+ originalMethods.set(`messages.stream-${index}`, originalStream);
4526
4632
  const tracer = this.tracer;
4527
4633
  MessagesClass.prototype.stream = function(...args) {
4528
4634
  const original = originalStream.bind(this);
4529
4635
  const kwargs = args[0] || {};
4636
+ const currentContext = context.active();
4530
4637
  const span2 = tracer.startSpan("anthropic.stream", {
4531
4638
  kind: SpanKind.CLIENT,
4532
4639
  attributes: {
@@ -4534,17 +4641,18 @@ var NetraAnthropicInstrumentor = class {
4534
4641
  "llm.streaming": true,
4535
4642
  "llm.operation": "stream"
4536
4643
  }
4537
- });
4644
+ }, currentContext);
4645
+ const spanContext = trace.setSpan(currentContext, span2);
4538
4646
  setRequestAttributes2(span2, kwargs, "chat");
4539
4647
  const startTime = Date.now();
4540
4648
  const instrumentedCreate = this.create;
4541
- const originalCreate = originalMethods.get("messages.create");
4649
+ const originalCreate = originalMethods.get(`messages.create-${index}`);
4542
4650
  if (originalCreate) {
4543
4651
  this.create = originalCreate;
4544
4652
  }
4545
4653
  try {
4546
- const messageStream = original(...args);
4547
- return new MessageStreamWrapper(span2, messageStream, startTime, kwargs);
4654
+ const messageStream = context.with(spanContext, () => original(...args));
4655
+ return new MessageStreamWrapper(span2, messageStream, startTime, kwargs, spanContext);
4548
4656
  } finally {
4549
4657
  if (originalCreate) {
4550
4658
  this.create = instrumentedCreate;
@@ -4554,7 +4662,7 @@ var NetraAnthropicInstrumentor = class {
4554
4662
  }
4555
4663
  if (MessagesClass?.prototype?.create) {
4556
4664
  const originalCreate = MessagesClass.prototype.create;
4557
- originalMethods.set("messages.create", originalCreate);
4665
+ originalMethods.set(`messages.create-${index}`, originalCreate);
4558
4666
  const tracer = this.tracer;
4559
4667
  const wrapper = chatWrapper(tracer);
4560
4668
  MessagesClass.prototype.create = function(...args) {
@@ -4572,17 +4680,12 @@ var NetraAnthropicInstrumentor = class {
4572
4680
  Logger.error(`Failed to instrument messages: ${error}`);
4573
4681
  }
4574
4682
  }
4575
- _instrumentBetaMessages() {
4683
+ _instrumentBetaMessages(AnthropicSDK, index) {
4576
4684
  if (!this.tracer) {
4577
4685
  Logger.warn("Anthropic instrumentation: No tracer available");
4578
4686
  return;
4579
4687
  }
4580
4688
  try {
4581
- const AnthropicSDK = resolveAnthropic();
4582
- if (!AnthropicSDK) {
4583
- Logger.warn("Anthropic instrumentation: Anthropic SDK not available");
4584
- return;
4585
- }
4586
4689
  const BetaMessagesClass = AnthropicSDK.Beta?.Messages;
4587
4690
  if (!BetaMessagesClass) {
4588
4691
  Logger.error(
@@ -4592,7 +4695,7 @@ var NetraAnthropicInstrumentor = class {
4592
4695
  }
4593
4696
  if (BetaMessagesClass?.prototype?.create) {
4594
4697
  const originalCreate = BetaMessagesClass.prototype.create;
4595
- originalMethods.set("beta.messages.create", originalCreate);
4698
+ originalMethods.set(`beta.messages.create-${index}`, originalCreate);
4596
4699
  const tracer = this.tracer;
4597
4700
  const wrapper = betaWrapper(tracer);
4598
4701
  BetaMessagesClass.prototype.create = function(...args) {
@@ -4610,17 +4713,12 @@ var NetraAnthropicInstrumentor = class {
4610
4713
  Logger.error(`Failed to instrument beta: ${error}`);
4611
4714
  }
4612
4715
  }
4613
- _instrumentBatchMessages() {
4716
+ _instrumentBatchMessages(AnthropicSDK, index) {
4614
4717
  if (!this.tracer) {
4615
4718
  Logger.warn("Anthropic instrumentation: No tracer available");
4616
4719
  return;
4617
4720
  }
4618
4721
  try {
4619
- const AnthropicSDK = resolveAnthropic();
4620
- if (!AnthropicSDK) {
4621
- Logger.warn("Anthropic instrumentation: Anthropic SDK not available");
4622
- return;
4623
- }
4624
4722
  const BatchMessageClass = AnthropicSDK.Messages?.Batches;
4625
4723
  if (!BatchMessageClass) {
4626
4724
  Logger.error(
@@ -4630,7 +4728,7 @@ var NetraAnthropicInstrumentor = class {
4630
4728
  }
4631
4729
  if (BatchMessageClass?.prototype?.create) {
4632
4730
  const originalCreate = BatchMessageClass.prototype.create;
4633
- originalMethods.set("batch.messages.create", originalCreate);
4731
+ originalMethods.set(`batch.messages.create-${index}`, originalCreate);
4634
4732
  const tracer = this.tracer;
4635
4733
  const wrapper = batchesWrapper(tracer);
4636
4734
  BatchMessageClass.prototype.create = function(...args) {
@@ -4648,25 +4746,25 @@ var NetraAnthropicInstrumentor = class {
4648
4746
  Logger.error(`Failed to instrument batches: ${error}`);
4649
4747
  }
4650
4748
  }
4651
- _uninstrumentMessages() {
4749
+ _uninstrumentMessages(AnthropicSDK, index) {
4652
4750
  try {
4653
- const AnthropicSDK = resolveAnthropic();
4654
- if (!AnthropicSDK) return;
4655
4751
  const MessagesClass = AnthropicSDK.Messages;
4656
- const originalCreate = originalMethods.get("messages.create");
4752
+ const originalCreate = originalMethods.get(`messages.create-${index}`);
4657
4753
  if (originalCreate && MessagesClass?.prototype) {
4658
4754
  MessagesClass.prototype.create = originalCreate;
4659
4755
  }
4756
+ const originalStream = originalMethods.get(`messages.stream-${index}`);
4757
+ if (originalStream && MessagesClass?.prototype) {
4758
+ MessagesClass.prototype.stream = originalStream;
4759
+ }
4660
4760
  } catch (error) {
4661
4761
  Logger.error(`Failed to uninstrument messages: ${error}`);
4662
4762
  }
4663
4763
  }
4664
- _uninstrumentBetaMessages() {
4764
+ _uninstrumentBetaMessages(AnthropicSDK, index) {
4665
4765
  try {
4666
- const AnthropicSDK = resolveAnthropic();
4667
- if (!AnthropicSDK) return;
4668
4766
  const BetaMessagesClass = AnthropicSDK.Beta?.Messages;
4669
- const originalCreate = originalMethods.get("beta.messages.create");
4767
+ const originalCreate = originalMethods.get(`beta.messages.create-${index}`);
4670
4768
  if (originalCreate && BetaMessagesClass?.prototype) {
4671
4769
  BetaMessagesClass.prototype.create = originalCreate;
4672
4770
  }
@@ -4674,12 +4772,10 @@ var NetraAnthropicInstrumentor = class {
4674
4772
  Logger.error(`Failed to uninstrument beta: ${error}`);
4675
4773
  }
4676
4774
  }
4677
- _uninstrumentBatchMessages() {
4775
+ _uninstrumentBatchMessages(AnthropicSDK, index) {
4678
4776
  try {
4679
- const AnthropicSDK = resolveAnthropic();
4680
- if (!AnthropicSDK) return;
4681
4777
  const BatchMessagesClass = AnthropicSDK.Messages?.Batches;
4682
- const originalCreate = originalMethods.get("batch.messages.create");
4778
+ const originalCreate = originalMethods.get(`batch.messages.create-${index}`);
4683
4779
  if (originalCreate && BatchMessagesClass?.prototype) {
4684
4780
  BatchMessagesClass.prototype.create = originalCreate;
4685
4781
  }
@@ -4701,6 +4797,16 @@ function safeStringify2(value) {
4701
4797
  return String(value);
4702
4798
  }
4703
4799
  }
4800
+ function extractModelName(model) {
4801
+ if (model && model.startsWith("models/")) {
4802
+ return model.replace(/^models\//, "");
4803
+ }
4804
+ return model;
4805
+ }
4806
+ function normalizeGenAIRole(raw) {
4807
+ const rawLower = raw.toLowerCase();
4808
+ return rawLower === "model" ? "assistant" : rawLower;
4809
+ }
4704
4810
  function setRequestAttributes3(span2, kwargs, requestType, args) {
4705
4811
  span2._netra_kwargs = kwargs;
4706
4812
  if (!span2.isRecording()) {
@@ -4818,6 +4924,26 @@ function _setPromptAttributes(span2, kwargs, args) {
4818
4924
  promptIndex++;
4819
4925
  }
4820
4926
  }
4927
+ if (kwargs.history && Array.isArray(kwargs.history)) {
4928
+ for (const turn of kwargs.history) {
4929
+ const role = normalizeGenAIRole(String(turn.role ?? "user"));
4930
+ const parts = turn.parts;
4931
+ if (Array.isArray(parts)) {
4932
+ const textContent = parts.filter((p) => p.text !== void 0).map((p) => String(p.text)).join("");
4933
+ if (textContent) {
4934
+ span2.setAttribute(
4935
+ `${SpanAttributes2.LLM_PROMPTS}.${promptIndex}.role`,
4936
+ role
4937
+ );
4938
+ span2.setAttribute(
4939
+ `${SpanAttributes2.LLM_PROMPTS}.${promptIndex}.content`,
4940
+ textContent
4941
+ );
4942
+ promptIndex++;
4943
+ }
4944
+ }
4945
+ }
4946
+ }
4821
4947
  if (!args) return;
4822
4948
  if (typeof args === "string") {
4823
4949
  span2.setAttribute(
@@ -5022,7 +5148,7 @@ function _setCompletionAttributes(span2, response) {
5022
5148
  const candidate = candidates[i];
5023
5149
  const content = candidate.content;
5024
5150
  if (!content) continue;
5025
- const role = String(content.role ?? "model");
5151
+ const role = normalizeGenAIRole(String(content.role ?? "model"));
5026
5152
  const parts = content.parts;
5027
5153
  if (!Array.isArray(parts)) continue;
5028
5154
  const textContent = parts.filter((p) => p.text !== void 0).map((p) => String(p.text)).join("");
@@ -5080,12 +5206,16 @@ function googleGenAIWrapper(tracer, spanName, requestType) {
5080
5206
  const modelInstance = this;
5081
5207
  const modelName = modelInstance.model;
5082
5208
  const systemInstruction = modelInstance.systemInstruction;
5209
+ const history = modelInstance.history;
5083
5210
  if (modelName) {
5084
- kwargs.model = modelName;
5211
+ kwargs.model = extractModelName(modelName);
5085
5212
  }
5086
5213
  if (systemInstruction) {
5087
5214
  kwargs.systemInstruction = systemInstruction;
5088
5215
  }
5216
+ if (history) {
5217
+ kwargs.history = history;
5218
+ }
5089
5219
  const currentContext = context.active();
5090
5220
  return tracer.startActiveSpan(
5091
5221
  spanName,
@@ -5163,8 +5293,10 @@ function googleGenAIStreamWrapper(tracer, spanName, requestType) {
5163
5293
  const modelInstance = this;
5164
5294
  const modelName = modelInstance.model;
5165
5295
  const systemInstruction = modelInstance.systemInstruction;
5166
- if (modelName) kwargs.model = modelName;
5296
+ const history = modelInstance.history;
5297
+ if (modelName) kwargs.model = extractModelName(modelName);
5167
5298
  if (systemInstruction) kwargs.systemInstruction = systemInstruction;
5299
+ if (history) kwargs.history = history;
5168
5300
  const currentContext = context.active();
5169
5301
  return tracer.startActiveSpan(
5170
5302
  spanName,
@@ -5303,25 +5435,75 @@ function googleGenAIStreamWrapper(tracer, spanName, requestType) {
5303
5435
  };
5304
5436
  };
5305
5437
  }
5438
+ function googleGenAIStartChatWrapper(tracer, spanName, requestType) {
5439
+ const sendMessageWrapperFn = googleGenAIWrapper(tracer, spanName, requestType);
5440
+ const sendMessageStreamWrapperFn = googleGenAIStreamWrapper(tracer, spanName, requestType);
5441
+ return function wrapper(original) {
5442
+ return function(...args) {
5443
+ const chatSession = original.apply(this, args);
5444
+ if (!chatSession) return chatSession;
5445
+ const modelInstance = this;
5446
+ const modelName = modelInstance.model;
5447
+ const systemInstruction = modelInstance.systemInstruction;
5448
+ const chatHistory = args[0]?.history;
5449
+ if (typeof chatSession.sendMessage === "function" && !chatSession.__netra_patched) {
5450
+ const originalSendMessage = chatSession.sendMessage.bind(chatSession);
5451
+ const wrappedSendMessage = sendMessageWrapperFn(originalSendMessage);
5452
+ chatSession.sendMessage = function(...sendArgs) {
5453
+ const ctx = this;
5454
+ if (modelName) ctx.model = modelName;
5455
+ if (systemInstruction) ctx.systemInstruction = systemInstruction;
5456
+ if (chatHistory) ctx.history = chatHistory;
5457
+ return wrappedSendMessage.apply(this, sendArgs);
5458
+ };
5459
+ if (typeof chatSession.sendMessageStream === "function") {
5460
+ const originalSendStream = chatSession.sendMessageStream.bind(chatSession);
5461
+ const wrappedSendStream = sendMessageStreamWrapperFn(originalSendStream);
5462
+ chatSession.sendMessageStream = function(...sendArgs) {
5463
+ const ctx = this;
5464
+ if (modelName) ctx.model = modelName;
5465
+ if (systemInstruction) ctx.systemInstruction = systemInstruction;
5466
+ if (chatHistory) ctx.history = chatHistory;
5467
+ return wrappedSendStream.apply(this, sendArgs);
5468
+ };
5469
+ }
5470
+ chatSession.__netra_patched = true;
5471
+ }
5472
+ return chatSession;
5473
+ };
5474
+ };
5475
+ }
5306
5476
  var chatWrapper2 = (tracer) => googleGenAIWrapper(tracer, CHAT_SPAN_NAME2, "chat");
5307
5477
  var embeddingsWrapper = (tracer) => googleGenAIWrapper(tracer, EMBEDDING_SPAN_NAME, "embedding");
5308
5478
  var chatStreamWrapper = (tracer) => googleGenAIStreamWrapper(tracer, CHAT_SPAN_NAME2, "chat");
5309
- var GenerativeModel = null;
5479
+ var startChatWrapper = (tracer) => googleGenAIStartChatWrapper(tracer, CHAT_SPAN_NAME2, "chat");
5310
5480
  var INSTRUMENTATION_NAME2 = "netra.instrumentation.google_genai";
5311
5481
  var INSTRUMENTS2 = ["@google/genai >= 0.24.1"];
5312
5482
  var isInstrumented2 = false;
5483
+ var generativeModelClasses = [];
5313
5484
  async function resolveGoogleGenerativeAIAsync() {
5314
- if (GenerativeModel) return GenerativeModel;
5485
+ if (generativeModelClasses.length > 0) return generativeModelClasses;
5315
5486
  try {
5316
5487
  const googleGenAIModule = await import('@google/generative-ai');
5317
- GenerativeModel = googleGenAIModule.GenerativeModel || googleGenAIModule.default?.GenerativeModel || googleGenAIModule.default || googleGenAIModule;
5318
- return GenerativeModel;
5488
+ const esmClass = googleGenAIModule.GenerativeModel || googleGenAIModule.default?.GenerativeModel || googleGenAIModule.default || googleGenAIModule;
5489
+ generativeModelClasses.push(esmClass);
5319
5490
  } catch {
5320
- return null;
5491
+ Logger.warn("Failed to resolve Google GenAI ESM module");
5321
5492
  }
5493
+ try {
5494
+ const req = createRequire(import.meta.url);
5495
+ const mod = req("@google/generative-ai");
5496
+ const cjsClass = mod.GenerativeModel || mod.default?.GenerativeModel || mod.default || mod;
5497
+ if (!generativeModelClasses.includes(cjsClass)) {
5498
+ generativeModelClasses.push(cjsClass);
5499
+ }
5500
+ } catch {
5501
+ Logger.warn("Failed to resolve Google GenAI CJS module");
5502
+ }
5503
+ return generativeModelClasses;
5322
5504
  }
5323
5505
  function resolveGoogleGenerativeAI() {
5324
- return GenerativeModel;
5506
+ return generativeModelClasses;
5325
5507
  }
5326
5508
  var NetraGoogleGenerativeAIInstrumentor = class {
5327
5509
  constructor() {
@@ -5335,16 +5517,15 @@ var NetraGoogleGenerativeAIInstrumentor = class {
5335
5517
  }
5336
5518
  /**
5337
5519
  * Instrument Google GenAI client methods (async version)
5338
- * Uses dynamic import() to ensure we get the same ES module instance
5339
- * that the application uses.
5520
+ * Tries both ESM and CJS resolution to cover dual-package setups.
5340
5521
  */
5341
5522
  async instrumentAsync(options = {}) {
5342
5523
  if (isInstrumented2) {
5343
5524
  Logger.warn("Google GenAI is already instrumented");
5344
5525
  return this;
5345
5526
  }
5346
- const model = await resolveGoogleGenerativeAIAsync();
5347
- if (!model) {
5527
+ const classes = await resolveGoogleGenerativeAIAsync();
5528
+ if (classes.length === 0) {
5348
5529
  return this;
5349
5530
  }
5350
5531
  try {
@@ -5354,7 +5535,7 @@ var NetraGoogleGenerativeAIInstrumentor = class {
5354
5535
  Logger.error(`Failed to initialize tracer: ${error}`);
5355
5536
  return this;
5356
5537
  }
5357
- this._instrumentGenerativeModel();
5538
+ classes.forEach((model) => this._instrumentGenerativeModel(model));
5358
5539
  isInstrumented2 = true;
5359
5540
  return this;
5360
5541
  }
@@ -5366,7 +5547,8 @@ var NetraGoogleGenerativeAIInstrumentor = class {
5366
5547
  Logger.warn("Google GenAI is already instrumented");
5367
5548
  return this;
5368
5549
  }
5369
- if (!resolveGoogleGenerativeAI()) {
5550
+ const classes = resolveGoogleGenerativeAI();
5551
+ if (classes.length === 0) {
5370
5552
  this.instrumentAsync(options).catch((e) => {
5371
5553
  Logger.error("Failed to instrument Google GenAI:", e);
5372
5554
  });
@@ -5379,7 +5561,7 @@ var NetraGoogleGenerativeAIInstrumentor = class {
5379
5561
  Logger.error(`Failed to initialize tracer: ${error}`);
5380
5562
  return this;
5381
5563
  }
5382
- this._instrumentGenerativeModel();
5564
+ classes.forEach((model) => this._instrumentGenerativeModel(model));
5383
5565
  isInstrumented2 = true;
5384
5566
  return this;
5385
5567
  }
@@ -5391,8 +5573,9 @@ var NetraGoogleGenerativeAIInstrumentor = class {
5391
5573
  Logger.warn("Google GenAI is not instrumented");
5392
5574
  return;
5393
5575
  }
5394
- this._uninstrumentGenerativeModel();
5395
- GenerativeModel = null;
5576
+ const classes = resolveGoogleGenerativeAI();
5577
+ classes.forEach((model) => this._uninstrumentGenerativeModel(model));
5578
+ generativeModelClasses = [];
5396
5579
  isInstrumented2 = false;
5397
5580
  }
5398
5581
  /**
@@ -5401,10 +5584,10 @@ var NetraGoogleGenerativeAIInstrumentor = class {
5401
5584
  isInstrumented() {
5402
5585
  return isInstrumented2;
5403
5586
  }
5404
- _instrumentGenerativeModel() {
5587
+ _instrumentGenerativeModel(GenerativeModel) {
5405
5588
  if (!this.tracer) return;
5406
5589
  try {
5407
- if (!GenerativeModel) {
5590
+ if (!GenerativeModel?.prototype) {
5408
5591
  Logger.error(
5409
5592
  "Failed to find Google GenAI GenerativeModel to instrument"
5410
5593
  );
@@ -5426,14 +5609,22 @@ var NetraGoogleGenerativeAIInstrumentor = class {
5426
5609
  "embedContent",
5427
5610
  embeddingsWrapper(tracer)
5428
5611
  );
5612
+ if (typeof GenerativeModel.prototype.startChat === "function") {
5613
+ shimmer.wrap(
5614
+ GenerativeModel.prototype,
5615
+ "startChat",
5616
+ startChatWrapper(tracer)
5617
+ );
5618
+ }
5429
5619
  } catch (error) {
5430
5620
  Logger.debug(
5431
5621
  `Google GenAI instrumentation: failed to instrument: ${error}`
5432
5622
  );
5433
5623
  }
5434
5624
  }
5435
- _uninstrumentGenerativeModel() {
5625
+ _uninstrumentGenerativeModel(GenerativeModel) {
5436
5626
  try {
5627
+ if (!GenerativeModel?.prototype) return;
5437
5628
  if (typeof GenerativeModel.prototype.generateContent === "function") {
5438
5629
  shimmer.unwrap(GenerativeModel.prototype, "generateContent");
5439
5630
  }
@@ -5443,6 +5634,9 @@ var NetraGoogleGenerativeAIInstrumentor = class {
5443
5634
  if (typeof GenerativeModel.prototype.embedContent === "function") {
5444
5635
  shimmer.unwrap(GenerativeModel.prototype, "embedContent");
5445
5636
  }
5637
+ if (typeof GenerativeModel.prototype.startChat === "function") {
5638
+ shimmer.unwrap(GenerativeModel.prototype, "startChat");
5639
+ }
5446
5640
  } catch (error) {
5447
5641
  Logger.debug(`Failed to uninstrument Google GenAI: ${error}`);
5448
5642
  }
@@ -5806,19 +6000,29 @@ var INSTRUMENTATION_NAME3 = "netra.instrumentation.groq";
5806
6000
  var INSTRUMENTS3 = ["groq-sdk >= 0.3.0"];
5807
6001
  var originalMethods2 = /* @__PURE__ */ new Map();
5808
6002
  var isInstrumented3 = false;
5809
- var GroqClass = null;
6003
+ var groqClasses = [];
5810
6004
  async function resolveGroqAsync() {
5811
- if (GroqClass) return GroqClass;
6005
+ if (groqClasses.length > 0) return groqClasses;
5812
6006
  try {
5813
6007
  const groqModule = await import('groq-sdk');
5814
- GroqClass = groqModule.Groq || groqModule.default || groqModule;
5815
- return GroqClass;
6008
+ groqClasses.push(groqModule.Groq || groqModule.default || groqModule);
5816
6009
  } catch {
5817
- return null;
6010
+ Logger.warn("Failed to resolve Groq ESM module");
5818
6011
  }
6012
+ try {
6013
+ const req = createRequire(import.meta.url);
6014
+ const mod = req("groq-sdk");
6015
+ const cjsClass = mod.Groq || mod.default || mod;
6016
+ if (!groqClasses.includes(cjsClass)) {
6017
+ groqClasses.push(cjsClass);
6018
+ }
6019
+ } catch {
6020
+ Logger.warn("Failed to resolve Groq CJS module");
6021
+ }
6022
+ return groqClasses;
5819
6023
  }
5820
6024
  function resolveGroq() {
5821
- return GroqClass;
6025
+ return groqClasses;
5822
6026
  }
5823
6027
  var NetraGroqInstrumentor = class {
5824
6028
  constructor() {
@@ -5829,16 +6033,15 @@ var NetraGroqInstrumentor = class {
5829
6033
  }
5830
6034
  /**
5831
6035
  * Instrument Groq client methods (async version)
5832
- * Uses dynamic import() to ensure we get the same ES module instance
5833
- * that the application uses.
6036
+ * Tries both ESM and CJS resolution to cover dual-package setups.
5834
6037
  */
5835
6038
  async instrumentAsync(options = {}) {
5836
6039
  if (isInstrumented3) {
5837
6040
  Logger.warn("Groq is already instrumented");
5838
6041
  return this;
5839
6042
  }
5840
- const Groq = await resolveGroqAsync();
5841
- if (!Groq) {
6043
+ const classes = await resolveGroqAsync();
6044
+ if (classes.length === 0) {
5842
6045
  return this;
5843
6046
  }
5844
6047
  try {
@@ -5855,21 +6058,23 @@ var NetraGroqInstrumentor = class {
5855
6058
  Logger.error(`Failed to initialize tracer: ${error}`);
5856
6059
  return this;
5857
6060
  }
5858
- this._instrumentChatCompletions(Groq);
6061
+ classes.forEach((Groq, index) => {
6062
+ this._instrumentChatCompletions(Groq, index);
6063
+ });
5859
6064
  isInstrumented3 = true;
5860
6065
  return this;
5861
6066
  }
5862
6067
  /**
5863
6068
  * Instrument Groq client methods (sync version - for backwards compatibility)
5864
- * Note: This uses a cached Groq class. Call instrumentAsync() for proper initialization.
6069
+ * Note: This uses cached Groq classes. Call instrumentAsync() for proper initialization.
5865
6070
  */
5866
6071
  instrument(options = {}) {
5867
6072
  if (isInstrumented3) {
5868
6073
  Logger.warn("Groq is already instrumented");
5869
6074
  return this;
5870
6075
  }
5871
- const Groq = resolveGroq();
5872
- if (!Groq) {
6076
+ const classes = resolveGroq();
6077
+ if (classes.length === 0) {
5873
6078
  this.instrumentAsync(options).catch((e) => {
5874
6079
  Logger.error("Failed to instrument Groq:", e);
5875
6080
  });
@@ -5889,7 +6094,9 @@ var NetraGroqInstrumentor = class {
5889
6094
  Logger.error(`Failed to initialize tracer: ${error}`);
5890
6095
  return this;
5891
6096
  }
5892
- this._instrumentChatCompletions(Groq);
6097
+ classes.forEach((Groq, index) => {
6098
+ this._instrumentChatCompletions(Groq, index);
6099
+ });
5893
6100
  isInstrumented3 = true;
5894
6101
  return this;
5895
6102
  }
@@ -5898,18 +6105,18 @@ var NetraGroqInstrumentor = class {
5898
6105
  Logger.warn("Groq is not instrumented");
5899
6106
  return;
5900
6107
  }
5901
- const Groq = resolveGroq();
5902
- if (Groq) {
5903
- this._uninstrumentChatCompletions(Groq);
5904
- }
6108
+ const classes = resolveGroq();
6109
+ classes.forEach((Groq, index) => {
6110
+ this._uninstrumentChatCompletions(Groq, index);
6111
+ });
5905
6112
  originalMethods2.clear();
5906
- GroqClass = null;
6113
+ groqClasses = [];
5907
6114
  isInstrumented3 = false;
5908
6115
  }
5909
6116
  isInstrumented() {
5910
6117
  return isInstrumented3;
5911
6118
  }
5912
- _instrumentChatCompletions(Groq) {
6119
+ _instrumentChatCompletions(Groq, index) {
5913
6120
  if (!this.tracer) {
5914
6121
  Logger.warn("Groq instrumentation: No tracer available");
5915
6122
  return;
@@ -5923,7 +6130,7 @@ var NetraGroqInstrumentor = class {
5923
6130
  return;
5924
6131
  }
5925
6132
  const originalCreate = CompletionsClass.prototype.create;
5926
- originalMethods2.set("chat.completions.create", originalCreate);
6133
+ originalMethods2.set(`chat.completions.create-${index}`, originalCreate);
5927
6134
  const tracer = this.tracer;
5928
6135
  const wrapper = chatWrapper3(tracer);
5929
6136
  CompletionsClass.prototype.create = function(...args) {
@@ -5938,10 +6145,10 @@ var NetraGroqInstrumentor = class {
5938
6145
  );
5939
6146
  }
5940
6147
  }
5941
- _uninstrumentChatCompletions(Groq) {
6148
+ _uninstrumentChatCompletions(Groq, index) {
5942
6149
  try {
5943
6150
  const CompletionsClass = Groq.Chat?.Completions;
5944
- const originalCreate = originalMethods2.get("chat.completions.create");
6151
+ const originalCreate = originalMethods2.get(`chat.completions.create-${index}`);
5945
6152
  if (originalCreate && CompletionsClass?.prototype) {
5946
6153
  CompletionsClass.prototype.create = originalCreate;
5947
6154
  }
@@ -7436,19 +7643,31 @@ var INSTRUMENTATION_NAME5 = "netra.instrumentation.mistral_ai";
7436
7643
  var INSTRUMENTS5 = ["@mistralai/mistralai >= 1.0.0"];
7437
7644
  var originalMethods4 = /* @__PURE__ */ new Map();
7438
7645
  var isInstrumented5 = false;
7439
- var MistralClass = null;
7646
+ var mistralClasses = [];
7440
7647
  async function resolveMistralAsync() {
7441
- if (MistralClass) return MistralClass;
7648
+ if (mistralClasses.length > 0) return mistralClasses;
7442
7649
  try {
7443
7650
  const mistralModule = await import('@mistralai/mistralai');
7444
- MistralClass = mistralModule.Mistral || mistralModule.default || mistralModule;
7445
- return MistralClass;
7651
+ mistralClasses.push(
7652
+ mistralModule.Mistral || mistralModule.default || mistralModule
7653
+ );
7446
7654
  } catch {
7447
- return null;
7655
+ Logger.warn("Failed to resolve MistralAI ESM module");
7448
7656
  }
7657
+ try {
7658
+ const req = createRequire(import.meta.url);
7659
+ const mod = req("@mistralai/mistralai");
7660
+ const cjsClass = mod.Mistral || mod.default || mod;
7661
+ if (!mistralClasses.includes(cjsClass)) {
7662
+ mistralClasses.push(cjsClass);
7663
+ }
7664
+ } catch {
7665
+ Logger.warn("Failed to resolve MistralAI CJS module");
7666
+ }
7667
+ return mistralClasses;
7449
7668
  }
7450
7669
  function resolveMistral() {
7451
- return MistralClass;
7670
+ return mistralClasses;
7452
7671
  }
7453
7672
  var NetraMistralAIInstrumentor = class {
7454
7673
  constructor() {
@@ -7463,16 +7682,15 @@ var NetraMistralAIInstrumentor = class {
7463
7682
  }
7464
7683
  /**
7465
7684
  * Instrument MistralAI client methods (async version)
7466
- * Uses dynamic import() to ensure we get the same ES module instance
7467
- * that the application uses.
7685
+ * Tries both ESM and CJS resolution to cover dual-package setups.
7468
7686
  */
7469
7687
  async instrumentAsync(options = {}) {
7470
7688
  if (isInstrumented5) {
7471
7689
  Logger.warn("MistralAI is already instrumented");
7472
7690
  return this;
7473
7691
  }
7474
- const Mistral = await resolveMistralAsync();
7475
- if (!Mistral) {
7692
+ const classes = await resolveMistralAsync();
7693
+ if (classes.length === 0) {
7476
7694
  return this;
7477
7695
  }
7478
7696
  try {
@@ -7489,11 +7707,16 @@ var NetraMistralAIInstrumentor = class {
7489
7707
  Logger.error(`Failed to initialize tracer: ${error}`);
7490
7708
  return this;
7491
7709
  }
7492
- const patchedChat = this._instrumentChat(Mistral);
7493
- const patchedEmbeddings = this._instrumentEmbeddings(Mistral);
7494
- const patchedFIM = this._instrumentFIM(Mistral);
7495
- const patchedAgents = this._instrumentAgents(Mistral);
7496
- const didPatch = patchedChat || patchedEmbeddings || patchedFIM || patchedAgents;
7710
+ let didPatch = false;
7711
+ classes.forEach((Mistral, index) => {
7712
+ const patchedChat = this._instrumentChat(Mistral, index);
7713
+ const patchedEmbeddings = this._instrumentEmbeddings(Mistral, index);
7714
+ const patchedFIM = this._instrumentFIM(Mistral, index);
7715
+ const patchedAgents = this._instrumentAgents(Mistral, index);
7716
+ if (patchedChat || patchedEmbeddings || patchedFIM || patchedAgents) {
7717
+ didPatch = true;
7718
+ }
7719
+ });
7497
7720
  if (!didPatch) {
7498
7721
  Logger.warn(
7499
7722
  "MistralAI instrumentation initialized but no methods were patched. Is '@mistralai/mistralai' installed and compatible?"
@@ -7505,15 +7728,15 @@ var NetraMistralAIInstrumentor = class {
7505
7728
  }
7506
7729
  /**
7507
7730
  * Instrument MistralAI client methods (sync version - for backwards compatibility)
7508
- * Note: This uses a cached Mistral class. Call instrumentAsync() for proper initialization.
7731
+ * Note: This uses cached Mistral classes. Call instrumentAsync() for proper initialization.
7509
7732
  */
7510
7733
  instrument(options = {}) {
7511
7734
  if (isInstrumented5) {
7512
7735
  Logger.warn("MistralAI is already instrumented");
7513
7736
  return this;
7514
7737
  }
7515
- const Mistral = resolveMistral();
7516
- if (!Mistral) {
7738
+ const classes = resolveMistral();
7739
+ if (classes.length === 0) {
7517
7740
  this.instrumentAsync(options).catch((e) => {
7518
7741
  Logger.error("Failed to instrument MistralAI:", e);
7519
7742
  });
@@ -7533,11 +7756,16 @@ var NetraMistralAIInstrumentor = class {
7533
7756
  Logger.error(`Failed to initialize tracer: ${error}`);
7534
7757
  return this;
7535
7758
  }
7536
- const patchedChat = this._instrumentChat(Mistral);
7537
- const patchedEmbeddings = this._instrumentEmbeddings(Mistral);
7538
- const patchedFIM = this._instrumentFIM(Mistral);
7539
- const patchedAgents = this._instrumentAgents(Mistral);
7540
- const didPatch = patchedChat || patchedEmbeddings || patchedFIM || patchedAgents;
7759
+ let didPatch = false;
7760
+ classes.forEach((Mistral, index) => {
7761
+ const patchedChat = this._instrumentChat(Mistral, index);
7762
+ const patchedEmbeddings = this._instrumentEmbeddings(Mistral, index);
7763
+ const patchedFIM = this._instrumentFIM(Mistral, index);
7764
+ const patchedAgents = this._instrumentAgents(Mistral, index);
7765
+ if (patchedChat || patchedEmbeddings || patchedFIM || patchedAgents) {
7766
+ didPatch = true;
7767
+ }
7768
+ });
7541
7769
  if (!didPatch) {
7542
7770
  Logger.warn(
7543
7771
  "MistralAI instrumentation initialized but no methods were patched. Is '@mistralai/mistralai' installed and compatible?"
@@ -7555,15 +7783,15 @@ var NetraMistralAIInstrumentor = class {
7555
7783
  Logger.warn("MistralAI is not instrumented");
7556
7784
  return;
7557
7785
  }
7558
- const Mistral = resolveMistral();
7559
- if (Mistral) {
7560
- this._uninstrumentChat(Mistral);
7561
- this._uninstrumentEmbeddings(Mistral);
7562
- this._uninstrumentFIM(Mistral);
7563
- this._uninstrumentAgents(Mistral);
7564
- }
7786
+ const classes = resolveMistral();
7787
+ classes.forEach((Mistral, index) => {
7788
+ this._uninstrumentChat(Mistral, index);
7789
+ this._uninstrumentEmbeddings(Mistral, index);
7790
+ this._uninstrumentFIM(Mistral, index);
7791
+ this._uninstrumentAgents(Mistral, index);
7792
+ });
7565
7793
  originalMethods4.clear();
7566
- MistralClass = null;
7794
+ mistralClasses = [];
7567
7795
  isInstrumented5 = false;
7568
7796
  }
7569
7797
  /**
@@ -7601,14 +7829,14 @@ var NetraMistralAIInstrumentor = class {
7601
7829
  this._ensureResourceCtors(Mistral);
7602
7830
  return this.resourceCtors[name] ?? null;
7603
7831
  }
7604
- _instrumentChat(Mistral) {
7832
+ _instrumentChat(Mistral, index) {
7605
7833
  if (!this.tracer) return false;
7606
7834
  try {
7607
7835
  const ChatClass = this._getCtor(Mistral, "chat");
7608
7836
  let didPatch = false;
7609
7837
  if (ChatClass?.prototype?.complete) {
7610
7838
  const originalComplete = ChatClass.prototype.complete;
7611
- originalMethods4.set("chat.complete", originalComplete);
7839
+ originalMethods4.set(`chat.complete-${index}`, originalComplete);
7612
7840
  const tracer = this.tracer;
7613
7841
  const wrapper = chatWrapper4(tracer);
7614
7842
  ChatClass.prototype.complete = function(...args) {
@@ -7625,7 +7853,7 @@ var NetraMistralAIInstrumentor = class {
7625
7853
  }
7626
7854
  if (ChatClass?.prototype?.stream) {
7627
7855
  const originalStream = ChatClass.prototype.stream;
7628
- originalMethods4.set("chat.stream", originalStream);
7856
+ originalMethods4.set(`chat.stream-${index}`, originalStream);
7629
7857
  const tracer = this.tracer;
7630
7858
  const wrapper = chatStreamWrapper2(tracer);
7631
7859
  ChatClass.prototype.stream = function(...args) {
@@ -7646,14 +7874,14 @@ var NetraMistralAIInstrumentor = class {
7646
7874
  return false;
7647
7875
  }
7648
7876
  }
7649
- _instrumentEmbeddings(Mistral) {
7877
+ _instrumentEmbeddings(Mistral, index) {
7650
7878
  if (!this.tracer) return false;
7651
7879
  try {
7652
7880
  const EmbeddingsClass = this._getCtor(Mistral, "embeddings");
7653
7881
  let didPatch = false;
7654
7882
  if (EmbeddingsClass?.prototype?.create) {
7655
7883
  const originalCreate = EmbeddingsClass.prototype.create;
7656
- originalMethods4.set("embeddings.create", originalCreate);
7884
+ originalMethods4.set(`embeddings.create-${index}`, originalCreate);
7657
7885
  const tracer = this.tracer;
7658
7886
  const wrapper = embeddingsWrapper2(tracer);
7659
7887
  EmbeddingsClass.prototype.create = function(...args) {
@@ -7674,14 +7902,14 @@ var NetraMistralAIInstrumentor = class {
7674
7902
  return false;
7675
7903
  }
7676
7904
  }
7677
- _instrumentFIM(Mistral) {
7905
+ _instrumentFIM(Mistral, index) {
7678
7906
  if (!this.tracer) return false;
7679
7907
  try {
7680
7908
  const FimClass = this._getCtor(Mistral, "fim");
7681
7909
  let didPatch = false;
7682
7910
  if (FimClass?.prototype?.complete) {
7683
7911
  const originalComplete = FimClass.prototype.complete;
7684
- originalMethods4.set("fim.complete", originalComplete);
7912
+ originalMethods4.set(`fim.complete-${index}`, originalComplete);
7685
7913
  const tracer = this.tracer;
7686
7914
  const wrapper = fimWrapper(tracer);
7687
7915
  FimClass.prototype.complete = function(...args) {
@@ -7698,7 +7926,7 @@ var NetraMistralAIInstrumentor = class {
7698
7926
  }
7699
7927
  if (FimClass?.prototype?.stream) {
7700
7928
  const originalStream = FimClass.prototype.stream;
7701
- originalMethods4.set("fim.stream", originalStream);
7929
+ originalMethods4.set(`fim.stream-${index}`, originalStream);
7702
7930
  const tracer = this.tracer;
7703
7931
  const wrapper = fimStreamWrapper(tracer);
7704
7932
  FimClass.prototype.stream = function(...args) {
@@ -7719,14 +7947,14 @@ var NetraMistralAIInstrumentor = class {
7719
7947
  return false;
7720
7948
  }
7721
7949
  }
7722
- _instrumentAgents(Mistral) {
7950
+ _instrumentAgents(Mistral, index) {
7723
7951
  if (!this.tracer) return false;
7724
7952
  try {
7725
7953
  const AgentsClass = this._getCtor(Mistral, "agents");
7726
7954
  let didPatch = false;
7727
7955
  if (AgentsClass?.prototype?.complete) {
7728
7956
  const originalComplete = AgentsClass.prototype.complete;
7729
- originalMethods4.set("agents.complete", originalComplete);
7957
+ originalMethods4.set(`agents.complete-${index}`, originalComplete);
7730
7958
  const tracer = this.tracer;
7731
7959
  const wrapper = agentsWrapper(tracer);
7732
7960
  AgentsClass.prototype.complete = function(...args) {
@@ -7743,7 +7971,7 @@ var NetraMistralAIInstrumentor = class {
7743
7971
  }
7744
7972
  if (AgentsClass?.prototype?.stream) {
7745
7973
  const originalStream = AgentsClass.prototype.stream;
7746
- originalMethods4.set("agents.stream", originalStream);
7974
+ originalMethods4.set(`agents.stream-${index}`, originalStream);
7747
7975
  const tracer = this.tracer;
7748
7976
  const wrapper = agentsStreamWrapper(tracer);
7749
7977
  AgentsClass.prototype.stream = function(...args) {
@@ -7764,14 +7992,14 @@ var NetraMistralAIInstrumentor = class {
7764
7992
  return false;
7765
7993
  }
7766
7994
  }
7767
- _uninstrumentChat(Mistral) {
7995
+ _uninstrumentChat(Mistral, index) {
7768
7996
  try {
7769
7997
  const ChatClass = this._getCtor(Mistral, "chat");
7770
- const originalComplete = originalMethods4.get("chat.complete");
7998
+ const originalComplete = originalMethods4.get(`chat.complete-${index}`);
7771
7999
  if (originalComplete && ChatClass?.prototype) {
7772
8000
  ChatClass.prototype.complete = originalComplete;
7773
8001
  }
7774
- const originalStream = originalMethods4.get("chat.stream");
8002
+ const originalStream = originalMethods4.get(`chat.stream-${index}`);
7775
8003
  if (originalStream && ChatClass?.prototype) {
7776
8004
  ChatClass.prototype.stream = originalStream;
7777
8005
  }
@@ -7779,10 +8007,10 @@ var NetraMistralAIInstrumentor = class {
7779
8007
  Logger.error(`Failed to uninstrument MistralAI chat: ${error}`);
7780
8008
  }
7781
8009
  }
7782
- _uninstrumentEmbeddings(Mistral) {
8010
+ _uninstrumentEmbeddings(Mistral, index) {
7783
8011
  try {
7784
8012
  const EmbeddingsClass = this._getCtor(Mistral, "embeddings");
7785
- const originalCreate = originalMethods4.get("embeddings.create");
8013
+ const originalCreate = originalMethods4.get(`embeddings.create-${index}`);
7786
8014
  if (originalCreate && EmbeddingsClass?.prototype) {
7787
8015
  EmbeddingsClass.prototype.create = originalCreate;
7788
8016
  }
@@ -7790,14 +8018,14 @@ var NetraMistralAIInstrumentor = class {
7790
8018
  Logger.error(`Failed to uninstrument MistralAI embeddings: ${error}`);
7791
8019
  }
7792
8020
  }
7793
- _uninstrumentFIM(Mistral) {
8021
+ _uninstrumentFIM(Mistral, index) {
7794
8022
  try {
7795
8023
  const FimClass = this._getCtor(Mistral, "fim");
7796
- const originalComplete = originalMethods4.get("fim.complete");
8024
+ const originalComplete = originalMethods4.get(`fim.complete-${index}`);
7797
8025
  if (originalComplete && FimClass?.prototype) {
7798
8026
  FimClass.prototype.complete = originalComplete;
7799
8027
  }
7800
- const originalStream = originalMethods4.get("fim.stream");
8028
+ const originalStream = originalMethods4.get(`fim.stream-${index}`);
7801
8029
  if (originalStream && FimClass?.prototype) {
7802
8030
  FimClass.prototype.stream = originalStream;
7803
8031
  }
@@ -7805,14 +8033,14 @@ var NetraMistralAIInstrumentor = class {
7805
8033
  Logger.error(`Failed to uninstrument MistralAI FIM: ${error}`);
7806
8034
  }
7807
8035
  }
7808
- _uninstrumentAgents(Mistral) {
8036
+ _uninstrumentAgents(Mistral, index) {
7809
8037
  try {
7810
8038
  const AgentsClass = this._getCtor(Mistral, "agents");
7811
- const originalComplete = originalMethods4.get("agents.complete");
8039
+ const originalComplete = originalMethods4.get(`agents.complete-${index}`);
7812
8040
  if (originalComplete && AgentsClass?.prototype) {
7813
8041
  AgentsClass.prototype.complete = originalComplete;
7814
8042
  }
7815
- const originalStream = originalMethods4.get("agents.stream");
8043
+ const originalStream = originalMethods4.get(`agents.stream-${index}`);
7816
8044
  if (originalStream && AgentsClass?.prototype) {
7817
8045
  AgentsClass.prototype.stream = originalStream;
7818
8046
  }
@@ -9807,10 +10035,10 @@ function disableTraceloopLangchainCallbackHandler() {
9807
10035
  } catch {
9808
10036
  }
9809
10037
  }
9810
- function resolveRootInstrumentNames(rootInstruments, blockInstruments2) {
10038
+ function resolveRootInstrumentNames(rootInstruments, blockInstruments) {
9811
10039
  const allSentinel = "__all__" /* ALL */;
9812
10040
  const rootHasAll = rootInstruments != null && rootInstruments.has(allSentinel);
9813
- const blockHasAll = blockInstruments2 != null && blockInstruments2.has(allSentinel);
10041
+ const blockHasAll = blockInstruments != null && blockInstruments.has(allSentinel);
9814
10042
  if (blockHasAll) {
9815
10043
  if (rootHasAll) {
9816
10044
  Logger.error(
@@ -9828,9 +10056,9 @@ function resolveRootInstrumentNames(rootInstruments, blockInstruments2) {
9828
10056
  let blockedValues;
9829
10057
  if (blockHasAll) {
9830
10058
  blockedValues = new Set(allInstrumentValues);
9831
- } else if (blockInstruments2 && blockInstruments2.size > 0) {
10059
+ } else if (blockInstruments && blockInstruments.size > 0) {
9832
10060
  blockedValues = new Set(
9833
- [...blockInstruments2].filter((m) => m !== allSentinel).map((m) => m.valueOf())
10061
+ [...blockInstruments].filter((m) => m !== allSentinel).map((m) => m.valueOf())
9834
10062
  );
9835
10063
  } else {
9836
10064
  blockedValues = /* @__PURE__ */ new Set();
@@ -9858,11 +10086,11 @@ function resolveRootInstrumentNames(rootInstruments, blockInstruments2) {
9858
10086
  }
9859
10087
  return resolved;
9860
10088
  }
9861
- function initInstrumentations(config2, instruments2, blockInstruments2, rootInstruments) {
9862
- const enableAll = instruments2 != null && instruments2.has("__all__" /* ALL */);
10089
+ function initInstrumentations(config2, instruments, blockInstruments, rootInstruments) {
10090
+ const enableAll = instruments != null && instruments.has("__all__" /* ALL */);
9863
10091
  const resolvedRootNames = resolveRootInstrumentNames(
9864
10092
  rootInstruments,
9865
- blockInstruments2
10093
+ blockInstruments
9866
10094
  );
9867
10095
  const instrumentModules = {};
9868
10096
  const customInstrumentModules = {
@@ -9872,7 +10100,7 @@ function initInstrumentations(config2, instruments2, blockInstruments2, rootInst
9872
10100
  langgraph: false,
9873
10101
  googleGenAI: false,
9874
10102
  anthropic: false};
9875
- const resolved = enableAll ? new Set(Object.values(NetraInstruments).filter((v) => v !== "__all__" /* ALL */)) : instruments2 && instruments2.size > 0 ? instruments2 : DEFAULT_INSTRUMENTS;
10103
+ const resolved = enableAll ? new Set(Object.values(NetraInstruments).filter((v) => v !== "__all__" /* ALL */)) : instruments && instruments.size > 0 ? instruments : DEFAULT_INSTRUMENTS;
9876
10104
  instrumentModules.google_vertexai = false;
9877
10105
  instrumentModules.langchain = false;
9878
10106
  instrumentModules.llamaIndex = false;
@@ -9919,21 +10147,21 @@ function initInstrumentations(config2, instruments2, blockInstruments2, rootInst
9919
10147
  if (resolved.has("anthropic" /* ANTHROPIC */)) {
9920
10148
  customInstrumentModules.anthropic = true;
9921
10149
  }
9922
- if (blockInstruments2 && blockInstruments2.size > 0) {
9923
- const blockAll = blockInstruments2.has("__all__" /* ALL */);
9924
- if (blockAll || blockInstruments2.has("openai" /* OPENAI */)) customInstrumentModules.openai = false;
9925
- if (blockAll || blockInstruments2.has("groq" /* GROQ */)) customInstrumentModules.groq = false;
9926
- if (blockAll || blockInstruments2.has("mistral_ai" /* MISTRAL */)) customInstrumentModules.mistral = false;
9927
- if (blockAll || blockInstruments2.has("langgraph" /* LANGGRAPH */)) customInstrumentModules.langgraph = false;
9928
- if (blockAll || blockInstruments2.has("google_genai" /* GOOGLE_GENERATIVE_AI */)) customInstrumentModules.googleGenAI = false;
9929
- if (blockAll || blockInstruments2.has("anthropic" /* ANTHROPIC */)) customInstrumentModules.anthropic = false;
9930
- if (blockAll || blockInstruments2.has("vertexai" /* VERTEX_AI */)) instrumentModules.google_vertexai = false;
9931
- if (blockAll || blockInstruments2.has("langchain" /* LANGCHAIN */)) instrumentModules.langchain = false;
9932
- if (blockAll || blockInstruments2.has("llama_index" /* LLAMA_INDEX */)) instrumentModules.llamaIndex = false;
9933
- if (blockAll || blockInstruments2.has("pinecone" /* PINECONE */)) instrumentModules.pinecone = false;
9934
- if (blockAll || blockInstruments2.has("qdrant" /* QDRANT */)) instrumentModules.qdrant = false;
9935
- if (blockAll || blockInstruments2.has("chromadb" /* CHROMADB */)) instrumentModules.chromadb = false;
9936
- if (blockAll || blockInstruments2.has("together" /* TOGETHER */)) instrumentModules.together = false;
10150
+ if (blockInstruments && blockInstruments.size > 0) {
10151
+ const blockAll = blockInstruments.has("__all__" /* ALL */);
10152
+ if (blockAll || blockInstruments.has("openai" /* OPENAI */)) customInstrumentModules.openai = false;
10153
+ if (blockAll || blockInstruments.has("groq" /* GROQ */)) customInstrumentModules.groq = false;
10154
+ if (blockAll || blockInstruments.has("mistral_ai" /* MISTRAL */)) customInstrumentModules.mistral = false;
10155
+ if (blockAll || blockInstruments.has("langgraph" /* LANGGRAPH */)) customInstrumentModules.langgraph = false;
10156
+ if (blockAll || blockInstruments.has("google_genai" /* GOOGLE_GENERATIVE_AI */)) customInstrumentModules.googleGenAI = false;
10157
+ if (blockAll || blockInstruments.has("anthropic" /* ANTHROPIC */)) customInstrumentModules.anthropic = false;
10158
+ if (blockAll || blockInstruments.has("vertexai" /* VERTEX_AI */)) instrumentModules.google_vertexai = false;
10159
+ if (blockAll || blockInstruments.has("langchain" /* LANGCHAIN */)) instrumentModules.langchain = false;
10160
+ if (blockAll || blockInstruments.has("llama_index" /* LLAMA_INDEX */)) instrumentModules.llamaIndex = false;
10161
+ if (blockAll || blockInstruments.has("pinecone" /* PINECONE */)) instrumentModules.pinecone = false;
10162
+ if (blockAll || blockInstruments.has("qdrant" /* QDRANT */)) instrumentModules.qdrant = false;
10163
+ if (blockAll || blockInstruments.has("chromadb" /* CHROMADB */)) instrumentModules.chromadb = false;
10164
+ if (blockAll || blockInstruments.has("together" /* TOGETHER */)) instrumentModules.together = false;
9937
10165
  }
9938
10166
  config2.setTraceloopEnv();
9939
10167
  Logger.debug("Netra SDK Configuration:");
@@ -9990,16 +10218,17 @@ function initInstrumentations(config2, instruments2, blockInstruments2, rootInst
9990
10218
  instrumentationsReady = initCustomInstrumentationsAsync(
9991
10219
  config2,
9992
10220
  tracerProvider,
9993
- customInstrumentModules
10221
+ customInstrumentModules,
10222
+ blockInstruments
9994
10223
  );
9995
- initOpenTelemetryInstrumentations(config2, resolved, blockInstruments2);
10224
+ initOpenTelemetryInstrumentations(config2, resolved, blockInstruments);
9996
10225
  return effectiveProvider;
9997
10226
  }
9998
- function isBlocked(instrument, blockInstruments2) {
9999
- if (!blockInstruments2 || blockInstruments2.size === 0) return false;
10000
- return blockInstruments2.has("__all__" /* ALL */) || blockInstruments2.has(instrument);
10227
+ function isBlocked(instrument, blockInstruments) {
10228
+ if (!blockInstruments || blockInstruments.size === 0) return false;
10229
+ return blockInstruments.has("__all__" /* ALL */) || blockInstruments.has(instrument);
10001
10230
  }
10002
- async function initCustomInstrumentationsAsync(config2, tracerProvider, customInstrumentModules) {
10231
+ async function initCustomInstrumentationsAsync(config2, tracerProvider, customInstrumentModules, blockInstruments) {
10003
10232
  if (customInstrumentModules.mistral) {
10004
10233
  try {
10005
10234
  await mistralAIInstrumentor.instrumentAsync({ tracerProvider });
@@ -10057,21 +10286,21 @@ async function initCustomInstrumentationsAsync(config2, tracerProvider, customIn
10057
10286
  }
10058
10287
  }
10059
10288
  }
10060
- function initOpenTelemetryInstrumentations(config2, resolved, blockInstruments2) {
10289
+ function initOpenTelemetryInstrumentations(config2, resolved, blockInstruments) {
10061
10290
  let netraHost = "";
10062
10291
  try {
10063
10292
  if (config2.otlpEndpoint) {
10064
10293
  netraHost = new URL(config2.otlpEndpoint).host;
10065
10294
  }
10066
10295
  } catch {
10067
- console.debug(`OTEL_NODE_EXCLUDED_URLS: malformed otlpEndpoint '${config2.otlpEndpoint}', skipping host-based exclusion`);
10296
+ Logger.debug(`OTEL_NODE_EXCLUDED_URLS: malformed otlpEndpoint '${config2.otlpEndpoint}', skipping host-based exclusion`);
10068
10297
  }
10069
10298
  const excludeRegexes = (process.env.OTEL_NODE_EXCLUDED_URLS || "").split(",").map((s) => s.trim()).filter(Boolean).map((pattern) => {
10070
10299
  try {
10071
10300
  return new RegExp(pattern);
10072
10301
  } catch {
10073
10302
  if (config2.debugMode) {
10074
- console.debug(
10303
+ Logger.debug(
10075
10304
  `Invalid OTEL_NODE_EXCLUDED_URLS pattern skipped: ${pattern}`
10076
10305
  );
10077
10306
  }
@@ -10082,7 +10311,7 @@ function initOpenTelemetryInstrumentations(config2, resolved, blockInstruments2)
10082
10311
  if (netraHost && url.includes(netraHost)) return true;
10083
10312
  return excludeRegexes.some((re) => re.test(url));
10084
10313
  };
10085
- if (!isBlocked("http" /* HTTP */, blockInstruments2) && (resolved.has("http" /* HTTP */) || resolved.has("express" /* EXPRESS */))) {
10314
+ if (!isBlocked("http" /* HTTP */, blockInstruments) && (resolved.has("http" /* HTTP */) || resolved.has("express" /* EXPRESS */))) {
10086
10315
  try {
10087
10316
  const { HttpInstrumentation } = require3("@opentelemetry/instrumentation-http");
10088
10317
  const { registerInstrumentations } = require3("@opentelemetry/instrumentation");
@@ -10100,7 +10329,7 @@ function initOpenTelemetryInstrumentations(config2, resolved, blockInstruments2)
10100
10329
  Logger.debug("HTTP instrumentation not available:", e);
10101
10330
  }
10102
10331
  }
10103
- const fetchEnabled = !blockInstruments2?.has(NetraInstruments.FETCH) && (!instruments || instruments.has(NetraInstruments.FETCH));
10332
+ const fetchEnabled = !isBlocked("http" /* HTTP */, blockInstruments) && resolved.has("http" /* HTTP */);
10104
10333
  if (fetchEnabled) {
10105
10334
  try {
10106
10335
  const { UndiciInstrumentation } = require3("@opentelemetry/instrumentation-undici");
@@ -10113,29 +10342,29 @@ function initOpenTelemetryInstrumentations(config2, resolved, blockInstruments2)
10113
10342
  });
10114
10343
  registerInstrumentations({ instrumentations: [_undiciInstrumentation] });
10115
10344
  if (config2.debugMode) {
10116
- console.debug("Undici/fetch instrumentation enabled");
10345
+ Logger.debug("Undici/fetch instrumentation enabled");
10117
10346
  }
10118
10347
  } catch (e) {
10119
10348
  if (config2.debugMode) {
10120
- console.debug("Undici/fetch instrumentation not available:", e);
10349
+ Logger.debug("Undici/fetch instrumentation not available:", e);
10121
10350
  }
10122
10351
  }
10123
10352
  }
10124
- if (!isBlocked("prisma" /* PRISMA */, blockInstruments2) && resolved.has("prisma" /* PRISMA */) && isPackageInstalled("@prisma/instrumentation")) {
10353
+ if (!isBlocked("prisma" /* PRISMA */, blockInstruments) && resolved.has("prisma" /* PRISMA */) && isPackageInstalled("@prisma/instrumentation")) {
10125
10354
  try {
10126
10355
  const { PrismaInstrumentation } = require3("@prisma/instrumentation");
10127
10356
  } catch (e) {
10128
10357
  Logger.debug("Prisma instrumentation not available:", e);
10129
10358
  }
10130
10359
  }
10131
- if (!isBlocked("typeorm" /* TYPEORM */, blockInstruments2) && resolved.has("typeorm" /* TYPEORM */) && isPackageInstalled("typeorm")) {
10360
+ if (!isBlocked("typeorm" /* TYPEORM */, blockInstruments) && resolved.has("typeorm" /* TYPEORM */) && isPackageInstalled("typeorm")) {
10132
10361
  typeORMInstrumentor.instrument().then(() => {
10133
10362
  Logger.debug("TypeORM instrumentation successfully initialized");
10134
10363
  }).catch((e) => {
10135
10364
  Logger.debug("TypeORM instrumentation error:", e);
10136
10365
  });
10137
10366
  }
10138
- if (!isBlocked("express" /* EXPRESS */, blockInstruments2) && resolved.has("express" /* EXPRESS */)) {
10367
+ if (!isBlocked("express" /* EXPRESS */, blockInstruments) && resolved.has("express" /* EXPRESS */)) {
10139
10368
  try {
10140
10369
  const { ExpressInstrumentation } = require3("@opentelemetry/instrumentation-express");
10141
10370
  const { registerInstrumentations } = require3("@opentelemetry/instrumentation");
@@ -10282,19 +10511,19 @@ async function uninstrumentAll() {
10282
10511
  if (_httpInstrumentation) {
10283
10512
  _httpInstrumentation.disable();
10284
10513
  _httpInstrumentation = null;
10285
- console.debug("HTTP instrumentation disabled");
10514
+ Logger.debug("HTTP instrumentation disabled");
10286
10515
  }
10287
10516
  } catch (e) {
10288
- console.debug("Failed to uninstrument HTTP:", e);
10517
+ Logger.debug("Failed to uninstrument HTTP:", e);
10289
10518
  }
10290
10519
  try {
10291
10520
  if (_undiciInstrumentation) {
10292
10521
  _undiciInstrumentation.disable();
10293
10522
  _undiciInstrumentation = null;
10294
- console.debug("Undici/fetch instrumentation disabled");
10523
+ Logger.debug("Undici/fetch instrumentation disabled");
10295
10524
  }
10296
10525
  } catch (e) {
10297
- console.debug("Failed to uninstrument undici:", e);
10526
+ Logger.debug("Failed to uninstrument undici:", e);
10298
10527
  }
10299
10528
  }
10300
10529
  var LOG_PREFIX = "netra.simulation";
@@ -10317,11 +10546,20 @@ var SimulationHttpClient = class {
10317
10546
  const headers = this._buildHeaders(config2);
10318
10547
  const timeout = this._getTimeout();
10319
10548
  try {
10320
- return axios.create({
10549
+ const instance = axios.create({
10321
10550
  baseURL,
10322
10551
  headers,
10323
10552
  timeout
10324
10553
  });
10554
+ instance.interceptors.request.use(
10555
+ (config3) => {
10556
+ const traceHeaders = injectTraceContextHeaders({});
10557
+ Object.assign(config3.headers, traceHeaders);
10558
+ return config3;
10559
+ },
10560
+ (error) => Promise.reject(error)
10561
+ );
10562
+ return instance;
10325
10563
  } catch (error) {
10326
10564
  Logger.error(`${LOG_PREFIX}: Failed to create HTTP client:`, error);
10327
10565
  return null;
@@ -10367,7 +10605,7 @@ var SimulationHttpClient = class {
10367
10605
  /**
10368
10606
  * Create a new simulation run for the specified dataset.
10369
10607
  */
10370
- async createRun(name, datasetId, context14) {
10608
+ async createRun(name, datasetId, context16) {
10371
10609
  if (!this.client) {
10372
10610
  Logger.error(`${LOG_PREFIX}: Client not initialized`);
10373
10611
  return null;
@@ -10377,7 +10615,7 @@ var SimulationHttpClient = class {
10377
10615
  const payload = {
10378
10616
  name,
10379
10617
  datasetId,
10380
- context: context14 || {}
10618
+ context: context16 || {}
10381
10619
  };
10382
10620
  const response = await this.client.post(url, payload);
10383
10621
  const data = response.data;
@@ -10561,14 +10799,14 @@ var Simulation = class {
10561
10799
  name,
10562
10800
  datasetId,
10563
10801
  task: task2,
10564
- context: context14,
10802
+ context: context16,
10565
10803
  maxConcurrency = 5
10566
10804
  } = options;
10567
10805
  if (!validateSimulationInputs(datasetId, task2)) {
10568
10806
  return null;
10569
10807
  }
10570
10808
  const startTime = Date.now();
10571
- const runResult = await this._client.createRun(name, datasetId, context14);
10809
+ const runResult = await this._client.createRun(name, datasetId, context16);
10572
10810
  if (!runResult) {
10573
10811
  return null;
10574
10812
  }
@@ -10680,24 +10918,23 @@ var Simulation = class {
10680
10918
  let turnId = initialTurnId;
10681
10919
  let sessionId = null;
10682
10920
  while (true) {
10921
+ const span2 = new SpanWrapper(SPAN_NAME, {}, LOG_PREFIX3);
10922
+ span2.start();
10683
10923
  try {
10684
- const span2 = new SpanWrapper(SPAN_NAME, {}, LOG_PREFIX3);
10685
- span2.start();
10686
10924
  const traceId = span2.getCurrentSpan()?.spanContext().traceId ?? "";
10687
- const [responseMessage, taskSessionId] = await executeTask2(
10688
- task2,
10689
- message,
10690
- sessionId
10925
+ const [responseMessage, taskSessionId] = await span2.withActive(
10926
+ () => executeTask2(task2, message, sessionId)
10691
10927
  );
10692
10928
  if (taskSessionId) {
10693
10929
  sessionId = taskSessionId;
10694
10930
  }
10695
- span2.end();
10696
- const response = await this._client.triggerConversation(
10697
- responseMessage,
10698
- turnId,
10699
- sessionId || "",
10700
- traceId
10931
+ const response = await span2.withActive(
10932
+ () => this._client.triggerConversation(
10933
+ responseMessage,
10934
+ turnId,
10935
+ sessionId || "",
10936
+ traceId
10937
+ )
10701
10938
  );
10702
10939
  if (response === null) {
10703
10940
  const errorMsg = "Failed to get conversation response";
@@ -10732,6 +10969,8 @@ var Simulation = class {
10732
10969
  error: errorMsg,
10733
10970
  turnId
10734
10971
  };
10972
+ } finally {
10973
+ span2.end();
10735
10974
  }
10736
10975
  }
10737
10976
  }
@@ -10745,20 +10984,33 @@ var Tracer17 = class {
10745
10984
  }
10746
10985
  }
10747
10986
  };
10748
- function serializeValue2(value) {
10987
+ function safeStringify3(value, maxLen = 1e3) {
10988
+ const seen = /* @__PURE__ */ new WeakSet();
10749
10989
  try {
10750
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null || value === void 0) {
10751
- return String(value);
10752
- } else if (Array.isArray(value) || typeof value === "object") {
10753
- return JSON.stringify(value).substring(0, 1e3);
10754
- } else {
10755
- return String(value).substring(0, 1e3);
10756
- }
10757
- } catch (e) {
10758
- Logger.warn("serializeValue: serialization failed, falling back to type name:", e);
10759
- return String(typeof value);
10990
+ return JSON.stringify(value, (_key, val) => {
10991
+ if (typeof val === "function") return `[Function: ${val.name || "anonymous"}]`;
10992
+ if (typeof val === "symbol") return val.toString();
10993
+ if (typeof val === "bigint") return val.toString();
10994
+ if (val !== null && typeof val === "object") {
10995
+ if (seen.has(val)) return "[Circular]";
10996
+ seen.add(val);
10997
+ const name = val.constructor?.name;
10998
+ if (name && name !== "Object" && name !== "Array" && Object.keys(val).length > 20) {
10999
+ return `[${name}]`;
11000
+ }
11001
+ }
11002
+ return val;
11003
+ }).substring(0, maxLen);
11004
+ } catch {
11005
+ return value?.constructor?.name ? `[${value.constructor.name}]` : String(typeof value);
10760
11006
  }
10761
11007
  }
11008
+ function serializeValue2(value) {
11009
+ if (value === null || value === void 0) return String(value);
11010
+ const t = typeof value;
11011
+ if (t === "string" || t === "number" || t === "boolean") return String(value);
11012
+ return safeStringify3(value);
11013
+ }
10762
11014
  function spanHasOutput(span2) {
10763
11015
  try {
10764
11016
  for (const field of ["attributes", "_attributes"]) {
@@ -10772,12 +11024,8 @@ function spanHasOutput(span2) {
10772
11024
  }
10773
11025
  function addInputAttributes(span2, args, entityType) {
10774
11026
  span2.setAttribute(`${Config.LIBRARY_NAME}.entity.type`, entityType);
10775
- try {
10776
- if (args.length > 0) {
10777
- span2.setAttribute("input", JSON.stringify(args));
10778
- }
10779
- } catch (e) {
10780
- span2.setAttribute("input_error", String(e));
11027
+ if (args.length > 0) {
11028
+ span2.setAttribute("input", safeStringify3(args));
10781
11029
  }
10782
11030
  }
10783
11031
  function addOutputAttributes(span2, result) {
@@ -11269,6 +11517,6 @@ Netra._metricsEnabled = false;
11269
11517
  Netra.withBlockedSpansLocal = withBlockedSpansLocal;
11270
11518
  var index_default = Netra;
11271
11519
 
11272
- export { Aggregation, BaseTask, ChartType, Config, ConversationType, DEFAULT_INSTRUMENTS, DEFAULT_INSTRUMENTS_FOR_ROOT, Dashboard, DimensionField, EntryStatus, Evaluation, FilterField, FilterType, FilteringSpanExporter, GroupBy, InstrumentationSpanProcessor, Measure, Netra, NetraAgentsTracingProcessor, NetraInstruments, NetraOpenAIAgentsInstrumentor, Operator, Prompts, RunEntryContext, RunStatus, Scope, ScrubbingSpanProcessor, SessionSpanProcessor, Simulation, SpanIOProcessor, SpanType, TrialAwareOTLPExporter, Usage, agent, index_default as default, metadataField, mistralAIInstrumentor, openaiAgentsInstrumentor, span, task, workflow };
11520
+ export { Aggregation, BaseTask, ChartType, Config, ConversationType, DEFAULT_INSTRUMENTS, DEFAULT_INSTRUMENTS_FOR_ROOT, Dashboard, DimensionField, EntryStatus, Evaluation, FilterField, FilterType, FilteringSpanExporter, GroupBy, InstrumentationSpanProcessor, Measure, Netra, NetraAgentsTracingProcessor, NetraInstruments, NetraOpenAIAgentsInstrumentor, Operator, Prompts, RunEntryContext, RunStatus, Scope, ScrubbingSpanProcessor, SessionSpanProcessor, Simulation, SpanIOProcessor, SpanType, TrialAwareOTLPExporter, Usage, agent, index_default as default, metadataField, mistralAIInstrumentor, netraExpressMiddleware, openaiAgentsInstrumentor, runWithExtractedContext, span, task, workflow };
11273
11521
  //# sourceMappingURL=index.js.map
11274
11522
  //# sourceMappingURL=index.js.map