netra-sdk 1.1.0-beta.1 → 1.2.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 +606 -267
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +113 -6
- package/dist/index.d.ts +113 -6
- package/dist/index.js +582 -245
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
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,
|
|
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
|
|
1728
|
+
const context16 = {
|
|
1698
1729
|
input: itemInput,
|
|
1699
1730
|
taskOutput,
|
|
1700
1731
|
expectedOutput,
|
|
1701
1732
|
metadata
|
|
1702
1733
|
};
|
|
1703
|
-
let result = evaluator.evaluate(
|
|
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
|
|
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
|
|
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
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
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 (
|
|
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
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
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 (
|
|
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
|
|
4536
|
+
var anthropicClasses = [];
|
|
4441
4537
|
async function resolveAnthropicAsync() {
|
|
4442
|
-
if (
|
|
4538
|
+
if (anthropicClasses.length > 0) return anthropicClasses;
|
|
4443
4539
|
try {
|
|
4444
4540
|
const anthropicModule = await import('@anthropic-ai/sdk');
|
|
4445
|
-
|
|
4446
|
-
return AnthropicClass;
|
|
4541
|
+
anthropicClasses.push(anthropicModule.Anthropic || anthropicModule.default || anthropicModule);
|
|
4447
4542
|
} catch {
|
|
4448
|
-
|
|
4543
|
+
Logger.warn("Failed to resolve Anthropic ESM module");
|
|
4449
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");
|
|
4554
|
+
}
|
|
4555
|
+
return anthropicClasses;
|
|
4450
4556
|
}
|
|
4451
4557
|
function resolveAnthropic() {
|
|
4452
|
-
return
|
|
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
|
|
4467
|
-
if (
|
|
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
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
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
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
|
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 (
|
|
5485
|
+
if (generativeModelClasses.length > 0) return generativeModelClasses;
|
|
5315
5486
|
try {
|
|
5316
5487
|
const googleGenAIModule = await import('@google/generative-ai');
|
|
5317
|
-
|
|
5318
|
-
|
|
5488
|
+
const esmClass = googleGenAIModule.GenerativeModel || googleGenAIModule.default?.GenerativeModel || googleGenAIModule.default || googleGenAIModule;
|
|
5489
|
+
generativeModelClasses.push(esmClass);
|
|
5319
5490
|
} catch {
|
|
5320
|
-
|
|
5491
|
+
Logger.warn("Failed to resolve Google GenAI ESM module");
|
|
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");
|
|
5321
5502
|
}
|
|
5503
|
+
return generativeModelClasses;
|
|
5322
5504
|
}
|
|
5323
5505
|
function resolveGoogleGenerativeAI() {
|
|
5324
|
-
return
|
|
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
|
-
*
|
|
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
|
|
5347
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
5395
|
-
|
|
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
|
|
6003
|
+
var groqClasses = [];
|
|
5810
6004
|
async function resolveGroqAsync() {
|
|
5811
|
-
if (
|
|
6005
|
+
if (groqClasses.length > 0) return groqClasses;
|
|
5812
6006
|
try {
|
|
5813
6007
|
const groqModule = await import('groq-sdk');
|
|
5814
|
-
|
|
5815
|
-
return GroqClass;
|
|
6008
|
+
groqClasses.push(groqModule.Groq || groqModule.default || groqModule);
|
|
5816
6009
|
} catch {
|
|
5817
|
-
|
|
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
|
|
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
|
-
*
|
|
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
|
|
5841
|
-
if (
|
|
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
|
-
|
|
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
|
|
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
|
|
5872
|
-
if (
|
|
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
|
-
|
|
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
|
|
5902
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
|
7646
|
+
var mistralClasses = [];
|
|
7440
7647
|
async function resolveMistralAsync() {
|
|
7441
|
-
if (
|
|
7648
|
+
if (mistralClasses.length > 0) return mistralClasses;
|
|
7442
7649
|
try {
|
|
7443
7650
|
const mistralModule = await import('@mistralai/mistralai');
|
|
7444
|
-
|
|
7445
|
-
|
|
7651
|
+
mistralClasses.push(
|
|
7652
|
+
mistralModule.Mistral || mistralModule.default || mistralModule
|
|
7653
|
+
);
|
|
7446
7654
|
} catch {
|
|
7447
|
-
|
|
7655
|
+
Logger.warn("Failed to resolve MistralAI ESM module");
|
|
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");
|
|
7448
7666
|
}
|
|
7667
|
+
return mistralClasses;
|
|
7449
7668
|
}
|
|
7450
7669
|
function resolveMistral() {
|
|
7451
|
-
return
|
|
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
|
-
*
|
|
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
|
|
7475
|
-
if (
|
|
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
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
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
|
|
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
|
|
7516
|
-
if (
|
|
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
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
7540
|
-
|
|
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
|
|
7559
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
8043
|
+
const originalStream = originalMethods4.get(`agents.stream-${index}`);
|
|
7816
8044
|
if (originalStream && AgentsClass?.prototype) {
|
|
7817
8045
|
AgentsClass.prototype.stream = originalStream;
|
|
7818
8046
|
}
|
|
@@ -10065,14 +10293,14 @@ function initOpenTelemetryInstrumentations(config2, resolved, blockInstruments)
|
|
|
10065
10293
|
netraHost = new URL(config2.otlpEndpoint).host;
|
|
10066
10294
|
}
|
|
10067
10295
|
} catch {
|
|
10068
|
-
|
|
10296
|
+
Logger.debug(`OTEL_NODE_EXCLUDED_URLS: malformed otlpEndpoint '${config2.otlpEndpoint}', skipping host-based exclusion`);
|
|
10069
10297
|
}
|
|
10070
10298
|
const excludeRegexes = (process.env.OTEL_NODE_EXCLUDED_URLS || "").split(",").map((s) => s.trim()).filter(Boolean).map((pattern) => {
|
|
10071
10299
|
try {
|
|
10072
10300
|
return new RegExp(pattern);
|
|
10073
10301
|
} catch {
|
|
10074
10302
|
if (config2.debugMode) {
|
|
10075
|
-
|
|
10303
|
+
Logger.debug(
|
|
10076
10304
|
`Invalid OTEL_NODE_EXCLUDED_URLS pattern skipped: ${pattern}`
|
|
10077
10305
|
);
|
|
10078
10306
|
}
|
|
@@ -10114,11 +10342,11 @@ function initOpenTelemetryInstrumentations(config2, resolved, blockInstruments)
|
|
|
10114
10342
|
});
|
|
10115
10343
|
registerInstrumentations({ instrumentations: [_undiciInstrumentation] });
|
|
10116
10344
|
if (config2.debugMode) {
|
|
10117
|
-
|
|
10345
|
+
Logger.debug("Undici/fetch instrumentation enabled");
|
|
10118
10346
|
}
|
|
10119
10347
|
} catch (e) {
|
|
10120
10348
|
if (config2.debugMode) {
|
|
10121
|
-
|
|
10349
|
+
Logger.debug("Undici/fetch instrumentation not available:", e);
|
|
10122
10350
|
}
|
|
10123
10351
|
}
|
|
10124
10352
|
}
|
|
@@ -10283,22 +10511,145 @@ async function uninstrumentAll() {
|
|
|
10283
10511
|
if (_httpInstrumentation) {
|
|
10284
10512
|
_httpInstrumentation.disable();
|
|
10285
10513
|
_httpInstrumentation = null;
|
|
10286
|
-
|
|
10514
|
+
Logger.debug("HTTP instrumentation disabled");
|
|
10287
10515
|
}
|
|
10288
10516
|
} catch (e) {
|
|
10289
|
-
|
|
10517
|
+
Logger.debug("Failed to uninstrument HTTP:", e);
|
|
10290
10518
|
}
|
|
10291
10519
|
try {
|
|
10292
10520
|
if (_undiciInstrumentation) {
|
|
10293
10521
|
_undiciInstrumentation.disable();
|
|
10294
10522
|
_undiciInstrumentation = null;
|
|
10295
|
-
|
|
10523
|
+
Logger.debug("Undici/fetch instrumentation disabled");
|
|
10296
10524
|
}
|
|
10297
10525
|
} catch (e) {
|
|
10298
|
-
|
|
10526
|
+
Logger.debug("Failed to uninstrument undici:", e);
|
|
10299
10527
|
}
|
|
10300
10528
|
}
|
|
10529
|
+
|
|
10530
|
+
// src/simulation/task.ts
|
|
10531
|
+
var BaseTask = class {
|
|
10532
|
+
};
|
|
10533
|
+
|
|
10534
|
+
// src/simulation/utils.ts
|
|
10301
10535
|
var LOG_PREFIX = "netra.simulation";
|
|
10536
|
+
var DEFAULT_FILE_DOWNLOAD_TIMEOUT_S = 30;
|
|
10537
|
+
var MAX_FILE_DOWNLOAD_WORKERS = 8;
|
|
10538
|
+
var _cachedFileDownloadTimeoutMs = null;
|
|
10539
|
+
function validateSimulationInputs(datasetId, task2) {
|
|
10540
|
+
if (!datasetId) {
|
|
10541
|
+
Logger.error(`${LOG_PREFIX}: dataset_id is required`);
|
|
10542
|
+
return false;
|
|
10543
|
+
}
|
|
10544
|
+
if (!(task2 instanceof BaseTask)) {
|
|
10545
|
+
Logger.error(`${LOG_PREFIX}: task must be a BaseTask instance`);
|
|
10546
|
+
return false;
|
|
10547
|
+
}
|
|
10548
|
+
return true;
|
|
10549
|
+
}
|
|
10550
|
+
function _getFileDownloadTimeout() {
|
|
10551
|
+
if (_cachedFileDownloadTimeoutMs !== null) {
|
|
10552
|
+
return _cachedFileDownloadTimeoutMs;
|
|
10553
|
+
}
|
|
10554
|
+
const envVal = process.env.NETRA_SIMULATION_FILE_DOWNLOAD_TIMEOUT;
|
|
10555
|
+
if (envVal) {
|
|
10556
|
+
const parsed = parseFloat(envVal);
|
|
10557
|
+
if (!isNaN(parsed) && parsed > 0) {
|
|
10558
|
+
_cachedFileDownloadTimeoutMs = parsed * 1e3;
|
|
10559
|
+
return _cachedFileDownloadTimeoutMs;
|
|
10560
|
+
}
|
|
10561
|
+
Logger.warn(
|
|
10562
|
+
`${LOG_PREFIX}: Invalid file download timeout '${envVal}', using default ${DEFAULT_FILE_DOWNLOAD_TIMEOUT_S}s`
|
|
10563
|
+
);
|
|
10564
|
+
}
|
|
10565
|
+
_cachedFileDownloadTimeoutMs = DEFAULT_FILE_DOWNLOAD_TIMEOUT_S * 1e3;
|
|
10566
|
+
return _cachedFileDownloadTimeoutMs;
|
|
10567
|
+
}
|
|
10568
|
+
async function _downloadSingleFile(fileData, timeoutMs, signal) {
|
|
10569
|
+
try {
|
|
10570
|
+
const response = await axios.get(fileData.downloadUrl, {
|
|
10571
|
+
responseType: "arraybuffer",
|
|
10572
|
+
timeout: timeoutMs,
|
|
10573
|
+
signal
|
|
10574
|
+
});
|
|
10575
|
+
const encoded = Buffer.from(response.data).toString("base64");
|
|
10576
|
+
return {
|
|
10577
|
+
fileName: fileData.fileName,
|
|
10578
|
+
contentType: fileData.contentType,
|
|
10579
|
+
description: fileData.description,
|
|
10580
|
+
data: encoded
|
|
10581
|
+
};
|
|
10582
|
+
} catch (error) {
|
|
10583
|
+
if (axios.isCancel(error)) {
|
|
10584
|
+
throw new Error(
|
|
10585
|
+
`Download of '${fileData.fileName}' was cancelled`
|
|
10586
|
+
);
|
|
10587
|
+
}
|
|
10588
|
+
const status = axios.isAxiosError(error) ? error.response?.status : void 0;
|
|
10589
|
+
const reason = status ? `HTTP ${status}` : error instanceof Error ? error.message : String(error);
|
|
10590
|
+
Logger.error(
|
|
10591
|
+
`${LOG_PREFIX}: Failed to download file '${fileData.fileName}': ${reason}`
|
|
10592
|
+
);
|
|
10593
|
+
throw new Error(
|
|
10594
|
+
`Failed to download file '${fileData.fileName}': ${reason}`
|
|
10595
|
+
);
|
|
10596
|
+
}
|
|
10597
|
+
}
|
|
10598
|
+
function parseFiles(rawFiles) {
|
|
10599
|
+
if (!rawFiles) {
|
|
10600
|
+
return [];
|
|
10601
|
+
}
|
|
10602
|
+
const parsed = [];
|
|
10603
|
+
for (const entry of rawFiles) {
|
|
10604
|
+
const fileName = entry.fileName || "";
|
|
10605
|
+
const downloadUrl = entry.downloadUrl || "";
|
|
10606
|
+
if (!fileName || !downloadUrl) {
|
|
10607
|
+
Logger.warn(
|
|
10608
|
+
`${LOG_PREFIX}: Skipping malformed file attachment (missing fileName or downloadUrl)`
|
|
10609
|
+
);
|
|
10610
|
+
continue;
|
|
10611
|
+
}
|
|
10612
|
+
parsed.push({
|
|
10613
|
+
fileName,
|
|
10614
|
+
contentType: entry.contentType || "",
|
|
10615
|
+
description: entry.description || void 0,
|
|
10616
|
+
downloadUrl
|
|
10617
|
+
});
|
|
10618
|
+
}
|
|
10619
|
+
return parsed;
|
|
10620
|
+
}
|
|
10621
|
+
async function processFiles(files) {
|
|
10622
|
+
if (!files || files.length === 0) {
|
|
10623
|
+
return null;
|
|
10624
|
+
}
|
|
10625
|
+
const timeoutMs = _getFileDownloadTimeout();
|
|
10626
|
+
const limit = pLimit(MAX_FILE_DOWNLOAD_WORKERS);
|
|
10627
|
+
const controller = new AbortController();
|
|
10628
|
+
const downloadPromises = files.map(
|
|
10629
|
+
(file) => limit(() => _downloadSingleFile(file, timeoutMs, controller.signal))
|
|
10630
|
+
);
|
|
10631
|
+
try {
|
|
10632
|
+
return await Promise.all(downloadPromises);
|
|
10633
|
+
} catch (error) {
|
|
10634
|
+
controller.abort();
|
|
10635
|
+
limit.clearQueue();
|
|
10636
|
+
throw error;
|
|
10637
|
+
}
|
|
10638
|
+
}
|
|
10639
|
+
async function executeTask2(task2, message, sessionId, rawFiles) {
|
|
10640
|
+
const processedFiles = rawFiles && rawFiles.length > 0 ? await processFiles(rawFiles) : null;
|
|
10641
|
+
const result = task2.run(message, sessionId, processedFiles);
|
|
10642
|
+
const resolvedResult = result instanceof Promise ? await result : result;
|
|
10643
|
+
if (typeof resolvedResult === "object" && resolvedResult !== null && "message" in resolvedResult && "sessionId" in resolvedResult) {
|
|
10644
|
+
return [resolvedResult.message, resolvedResult.sessionId];
|
|
10645
|
+
}
|
|
10646
|
+
throw new Error(
|
|
10647
|
+
`Task must return TaskResult, got ${typeof resolvedResult}`
|
|
10648
|
+
);
|
|
10649
|
+
}
|
|
10650
|
+
|
|
10651
|
+
// src/simulation/client.ts
|
|
10652
|
+
var LOG_PREFIX2 = "netra.simulation";
|
|
10302
10653
|
var DEFAULT_TIMEOUT = 1e4;
|
|
10303
10654
|
var SimulationHttpClient = class {
|
|
10304
10655
|
constructor(config2) {
|
|
@@ -10311,20 +10662,29 @@ var SimulationHttpClient = class {
|
|
|
10311
10662
|
_createClient(config2) {
|
|
10312
10663
|
const endpoint = (config2.otlpEndpoint || "").trim();
|
|
10313
10664
|
if (!endpoint) {
|
|
10314
|
-
Logger.error(`${
|
|
10665
|
+
Logger.error(`${LOG_PREFIX2}: NETRA_OTLP_ENDPOINT is required`);
|
|
10315
10666
|
return null;
|
|
10316
10667
|
}
|
|
10317
10668
|
const baseURL = this._resolveBaseUrl(endpoint);
|
|
10318
10669
|
const headers = this._buildHeaders(config2);
|
|
10319
10670
|
const timeout = this._getTimeout();
|
|
10320
10671
|
try {
|
|
10321
|
-
|
|
10672
|
+
const instance = axios.create({
|
|
10322
10673
|
baseURL,
|
|
10323
10674
|
headers,
|
|
10324
10675
|
timeout
|
|
10325
10676
|
});
|
|
10677
|
+
instance.interceptors.request.use(
|
|
10678
|
+
(config3) => {
|
|
10679
|
+
const traceHeaders = injectTraceContextHeaders({});
|
|
10680
|
+
Object.assign(config3.headers, traceHeaders);
|
|
10681
|
+
return config3;
|
|
10682
|
+
},
|
|
10683
|
+
(error) => Promise.reject(error)
|
|
10684
|
+
);
|
|
10685
|
+
return instance;
|
|
10326
10686
|
} catch (error) {
|
|
10327
|
-
Logger.error(`${
|
|
10687
|
+
Logger.error(`${LOG_PREFIX2}: Failed to create HTTP client:`, error);
|
|
10328
10688
|
return null;
|
|
10329
10689
|
}
|
|
10330
10690
|
}
|
|
@@ -10359,7 +10719,7 @@ var SimulationHttpClient = class {
|
|
|
10359
10719
|
const timeout = parseFloat(timeoutStr);
|
|
10360
10720
|
if (isNaN(timeout)) {
|
|
10361
10721
|
Logger.warn(
|
|
10362
|
-
`${
|
|
10722
|
+
`${LOG_PREFIX2}: Invalid timeout '${timeoutStr}', using default ${DEFAULT_TIMEOUT}ms`
|
|
10363
10723
|
);
|
|
10364
10724
|
return DEFAULT_TIMEOUT;
|
|
10365
10725
|
}
|
|
@@ -10368,9 +10728,9 @@ var SimulationHttpClient = class {
|
|
|
10368
10728
|
/**
|
|
10369
10729
|
* Create a new simulation run for the specified dataset.
|
|
10370
10730
|
*/
|
|
10371
|
-
async createRun(name, datasetId,
|
|
10731
|
+
async createRun(name, datasetId, context16) {
|
|
10372
10732
|
if (!this.client) {
|
|
10373
|
-
Logger.error(`${
|
|
10733
|
+
Logger.error(`${LOG_PREFIX2}: Client not initialized`);
|
|
10374
10734
|
return null;
|
|
10375
10735
|
}
|
|
10376
10736
|
try {
|
|
@@ -10378,14 +10738,14 @@ var SimulationHttpClient = class {
|
|
|
10378
10738
|
const payload = {
|
|
10379
10739
|
name,
|
|
10380
10740
|
datasetId,
|
|
10381
|
-
context:
|
|
10741
|
+
context: context16 || {}
|
|
10382
10742
|
};
|
|
10383
10743
|
const response = await this.client.post(url, payload);
|
|
10384
10744
|
const data = response.data;
|
|
10385
10745
|
const responseData = data.data || {};
|
|
10386
10746
|
const userMessages = responseData.userMessages || [];
|
|
10387
10747
|
if (userMessages.length === 0) {
|
|
10388
|
-
Logger.warn(`${
|
|
10748
|
+
Logger.warn(`${LOG_PREFIX2}: No user messages returned from create_run`);
|
|
10389
10749
|
return null;
|
|
10390
10750
|
}
|
|
10391
10751
|
const runId = responseData.id || "";
|
|
@@ -10393,7 +10753,8 @@ var SimulationHttpClient = class {
|
|
|
10393
10753
|
(msg) => ({
|
|
10394
10754
|
runItemId: msg.testRunItemId || "",
|
|
10395
10755
|
message: msg.userMessage || "",
|
|
10396
|
-
turnId: msg.turnId || ""
|
|
10756
|
+
turnId: msg.turnId || "",
|
|
10757
|
+
files: parseFiles(msg.attachments)
|
|
10397
10758
|
})
|
|
10398
10759
|
);
|
|
10399
10760
|
return {
|
|
@@ -10402,7 +10763,7 @@ var SimulationHttpClient = class {
|
|
|
10402
10763
|
};
|
|
10403
10764
|
} catch (error) {
|
|
10404
10765
|
const errorMsg = this._extractErrorMessage(error);
|
|
10405
|
-
Logger.error(`${
|
|
10766
|
+
Logger.error(`${LOG_PREFIX2}: Failed to create simulation run:`, errorMsg);
|
|
10406
10767
|
return null;
|
|
10407
10768
|
}
|
|
10408
10769
|
}
|
|
@@ -10411,7 +10772,7 @@ var SimulationHttpClient = class {
|
|
|
10411
10772
|
*/
|
|
10412
10773
|
async triggerConversation(message, turnId, sessionId, traceId) {
|
|
10413
10774
|
if (!this.client) {
|
|
10414
|
-
Logger.error(`${
|
|
10775
|
+
Logger.error(`${LOG_PREFIX2}: Client not initialized`);
|
|
10415
10776
|
return null;
|
|
10416
10777
|
}
|
|
10417
10778
|
try {
|
|
@@ -10434,7 +10795,7 @@ var SimulationHttpClient = class {
|
|
|
10434
10795
|
}
|
|
10435
10796
|
const userMessages = responseData.userMessages || [];
|
|
10436
10797
|
if (userMessages.length === 0) {
|
|
10437
|
-
Logger.warn(`${
|
|
10798
|
+
Logger.warn(`${LOG_PREFIX2}: No user messages in continue response`);
|
|
10438
10799
|
return null;
|
|
10439
10800
|
}
|
|
10440
10801
|
const nextMsg = userMessages[0];
|
|
@@ -10442,11 +10803,12 @@ var SimulationHttpClient = class {
|
|
|
10442
10803
|
decision,
|
|
10443
10804
|
nextTurnId: nextMsg.turnId || "",
|
|
10444
10805
|
nextUserMessage: nextMsg.userMessage || "",
|
|
10445
|
-
nextRunItemId: nextMsg.testRunItemId || ""
|
|
10806
|
+
nextRunItemId: nextMsg.testRunItemId || "",
|
|
10807
|
+
nextFiles: parseFiles(nextMsg.attachments)
|
|
10446
10808
|
};
|
|
10447
10809
|
} catch (error) {
|
|
10448
10810
|
const errorMsg = this._extractErrorMessage(error);
|
|
10449
|
-
Logger.error(`${
|
|
10811
|
+
Logger.error(`${LOG_PREFIX2}: Failed to trigger conversation:`, errorMsg);
|
|
10450
10812
|
return null;
|
|
10451
10813
|
}
|
|
10452
10814
|
}
|
|
@@ -10455,17 +10817,17 @@ var SimulationHttpClient = class {
|
|
|
10455
10817
|
*/
|
|
10456
10818
|
async reportFailure(runId, runItemId, error) {
|
|
10457
10819
|
if (!this.client) {
|
|
10458
|
-
Logger.error(`${
|
|
10820
|
+
Logger.error(`${LOG_PREFIX2}: Client not initialized`);
|
|
10459
10821
|
return;
|
|
10460
10822
|
}
|
|
10461
10823
|
try {
|
|
10462
10824
|
const url = `/evaluations/run/${runId}/item/${runItemId}/status`;
|
|
10463
10825
|
const payload = { status: "failed", failureReason: error };
|
|
10464
10826
|
await this.client.patch(url, payload);
|
|
10465
|
-
Logger.info(`${
|
|
10827
|
+
Logger.info(`${LOG_PREFIX2}: Reported failure - ${error}`);
|
|
10466
10828
|
} catch (err) {
|
|
10467
10829
|
const errorMsg = this._extractErrorMessage(err);
|
|
10468
|
-
Logger.error(`${
|
|
10830
|
+
Logger.error(`${LOG_PREFIX2}: Failed to report failure:`, errorMsg);
|
|
10469
10831
|
}
|
|
10470
10832
|
}
|
|
10471
10833
|
/**
|
|
@@ -10474,7 +10836,7 @@ var SimulationHttpClient = class {
|
|
|
10474
10836
|
async postRunStatus(runId, status) {
|
|
10475
10837
|
if (!this.client) {
|
|
10476
10838
|
Logger.error(
|
|
10477
|
-
`${
|
|
10839
|
+
`${LOG_PREFIX2}: Client not initialized; cannot post run status`
|
|
10478
10840
|
);
|
|
10479
10841
|
return { success: false };
|
|
10480
10842
|
}
|
|
@@ -10484,14 +10846,14 @@ var SimulationHttpClient = class {
|
|
|
10484
10846
|
const response = await this.client.post(url, payload);
|
|
10485
10847
|
const data = response.data;
|
|
10486
10848
|
if (data && typeof data === "object" && "data" in data) {
|
|
10487
|
-
Logger.info(`${
|
|
10849
|
+
Logger.info(`${LOG_PREFIX2}: Completed test run successfully`);
|
|
10488
10850
|
return data.data || {};
|
|
10489
10851
|
}
|
|
10490
10852
|
return data;
|
|
10491
10853
|
} catch (error) {
|
|
10492
10854
|
const errorMsg = this._extractErrorMessage(error);
|
|
10493
10855
|
Logger.error(
|
|
10494
|
-
`${
|
|
10856
|
+
`${LOG_PREFIX2}: Failed to post run status for run '${runId}':`,
|
|
10495
10857
|
errorMsg
|
|
10496
10858
|
);
|
|
10497
10859
|
return { success: false };
|
|
@@ -10515,34 +10877,6 @@ var SimulationHttpClient = class {
|
|
|
10515
10877
|
}
|
|
10516
10878
|
};
|
|
10517
10879
|
|
|
10518
|
-
// src/simulation/task.ts
|
|
10519
|
-
var BaseTask = class {
|
|
10520
|
-
};
|
|
10521
|
-
|
|
10522
|
-
// src/simulation/utils.ts
|
|
10523
|
-
var LOG_PREFIX2 = "netra.simulation";
|
|
10524
|
-
function validateSimulationInputs(datasetId, task2) {
|
|
10525
|
-
if (!datasetId) {
|
|
10526
|
-
Logger.error(`${LOG_PREFIX2}: dataset_id is required`);
|
|
10527
|
-
return false;
|
|
10528
|
-
}
|
|
10529
|
-
if (!(task2 instanceof BaseTask)) {
|
|
10530
|
-
Logger.error(`${LOG_PREFIX2}: task must be a BaseTask instance`);
|
|
10531
|
-
return false;
|
|
10532
|
-
}
|
|
10533
|
-
return true;
|
|
10534
|
-
}
|
|
10535
|
-
async function executeTask2(task2, message, sessionId) {
|
|
10536
|
-
const result = task2.run(message, sessionId);
|
|
10537
|
-
const resolvedResult = result instanceof Promise ? await result : result;
|
|
10538
|
-
if (typeof resolvedResult === "object" && resolvedResult !== null && "message" in resolvedResult && "sessionId" in resolvedResult) {
|
|
10539
|
-
return [resolvedResult.message, resolvedResult.sessionId];
|
|
10540
|
-
}
|
|
10541
|
-
throw new Error(
|
|
10542
|
-
`Task must return TaskResult, got ${typeof resolvedResult}`
|
|
10543
|
-
);
|
|
10544
|
-
}
|
|
10545
|
-
|
|
10546
10880
|
// src/simulation/api.ts
|
|
10547
10881
|
var LOG_PREFIX3 = "netra.simulation";
|
|
10548
10882
|
var SPAN_NAME = "Netra.Simulation.TestRun";
|
|
@@ -10562,14 +10896,14 @@ var Simulation = class {
|
|
|
10562
10896
|
name,
|
|
10563
10897
|
datasetId,
|
|
10564
10898
|
task: task2,
|
|
10565
|
-
context:
|
|
10899
|
+
context: context16,
|
|
10566
10900
|
maxConcurrency = 5
|
|
10567
10901
|
} = options;
|
|
10568
10902
|
if (!validateSimulationInputs(datasetId, task2)) {
|
|
10569
10903
|
return null;
|
|
10570
10904
|
}
|
|
10571
10905
|
const startTime = Date.now();
|
|
10572
|
-
const runResult = await this._client.createRun(name, datasetId,
|
|
10906
|
+
const runResult = await this._client.createRun(name, datasetId, context16);
|
|
10573
10907
|
if (!runResult) {
|
|
10574
10908
|
return null;
|
|
10575
10909
|
}
|
|
@@ -10676,29 +11010,29 @@ var Simulation = class {
|
|
|
10676
11010
|
* Execute a multi-turn conversation for a single simulation item.
|
|
10677
11011
|
*/
|
|
10678
11012
|
async _executeConversation(runId, runItem, task2) {
|
|
10679
|
-
const { runItemId, message: initialMessage, turnId: initialTurnId } = runItem;
|
|
11013
|
+
const { runItemId, message: initialMessage, turnId: initialTurnId, files: initialFiles } = runItem;
|
|
10680
11014
|
let message = initialMessage;
|
|
10681
11015
|
let turnId = initialTurnId;
|
|
10682
11016
|
let sessionId = null;
|
|
11017
|
+
let rawFiles = initialFiles ?? [];
|
|
10683
11018
|
while (true) {
|
|
11019
|
+
const span2 = new SpanWrapper(SPAN_NAME, {}, LOG_PREFIX3);
|
|
11020
|
+
span2.start();
|
|
10684
11021
|
try {
|
|
10685
|
-
const span2 = new SpanWrapper(SPAN_NAME, {}, LOG_PREFIX3);
|
|
10686
|
-
span2.start();
|
|
10687
11022
|
const traceId = span2.getCurrentSpan()?.spanContext().traceId ?? "";
|
|
10688
|
-
const [responseMessage, taskSessionId] = await
|
|
10689
|
-
task2,
|
|
10690
|
-
message,
|
|
10691
|
-
sessionId
|
|
11023
|
+
const [responseMessage, taskSessionId] = await span2.withActive(
|
|
11024
|
+
() => executeTask2(task2, message, sessionId, rawFiles)
|
|
10692
11025
|
);
|
|
10693
11026
|
if (taskSessionId) {
|
|
10694
11027
|
sessionId = taskSessionId;
|
|
10695
11028
|
}
|
|
10696
|
-
span2.
|
|
10697
|
-
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
|
|
10701
|
-
|
|
11029
|
+
const response = await span2.withActive(
|
|
11030
|
+
() => this._client.triggerConversation(
|
|
11031
|
+
responseMessage,
|
|
11032
|
+
turnId,
|
|
11033
|
+
sessionId || "",
|
|
11034
|
+
traceId
|
|
11035
|
+
)
|
|
10702
11036
|
);
|
|
10703
11037
|
if (response === null) {
|
|
10704
11038
|
const errorMsg = "Failed to get conversation response";
|
|
@@ -10721,6 +11055,7 @@ var Simulation = class {
|
|
|
10721
11055
|
}
|
|
10722
11056
|
message = response.nextUserMessage;
|
|
10723
11057
|
turnId = response.nextTurnId;
|
|
11058
|
+
rawFiles = response.nextFiles || [];
|
|
10724
11059
|
} catch (error) {
|
|
10725
11060
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
10726
11061
|
Logger.error(
|
|
@@ -10733,6 +11068,8 @@ var Simulation = class {
|
|
|
10733
11068
|
error: errorMsg,
|
|
10734
11069
|
turnId
|
|
10735
11070
|
};
|
|
11071
|
+
} finally {
|
|
11072
|
+
span2.end();
|
|
10736
11073
|
}
|
|
10737
11074
|
}
|
|
10738
11075
|
}
|
|
@@ -11279,6 +11616,6 @@ Netra._metricsEnabled = false;
|
|
|
11279
11616
|
Netra.withBlockedSpansLocal = withBlockedSpansLocal;
|
|
11280
11617
|
var index_default = Netra;
|
|
11281
11618
|
|
|
11282
|
-
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 };
|
|
11619
|
+
export { Aggregation, BaseTask, ChartType, Config, ConversationType, DEFAULT_INSTRUMENTS, DEFAULT_INSTRUMENTS_FOR_ROOT, Dashboard, DimensionField, EntryStatus, Evaluation, FilterField, FilterType, FilteringSpanExporter, GroupBy, InstrumentationSpanProcessor, Measure, Netra, NetraAgentsTracingProcessor, NetraInstruments, NetraOpenAIAgentsInstrumentor, Operator, Prompts, RunEntryContext, RunStatus, Scope, ScrubbingSpanProcessor, SessionSpanProcessor, Simulation, SpanIOProcessor, SpanType, TrialAwareOTLPExporter, Usage, agent, index_default as default, metadataField, mistralAIInstrumentor, netraExpressMiddleware, openaiAgentsInstrumentor, runWithExtractedContext, span, task, workflow };
|
|
11283
11620
|
//# sourceMappingURL=index.js.map
|
|
11284
11621
|
//# sourceMappingURL=index.js.map
|