netra-sdk 1.1.0 → 1.3.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
@@ -610,7 +610,8 @@ var DEFAULT_INSTRUMENTS_FOR_ROOT = /* @__PURE__ */ new Set([
610
610
  // AI frameworks
611
611
  "langchain" /* LANGCHAIN */,
612
612
  "langgraph" /* LANGGRAPH */,
613
- "llama_index" /* LLAMA_INDEX */
613
+ "llama_index" /* LLAMA_INDEX */,
614
+ "openai_agents" /* OPENAI_AGENTS */
614
615
  ]);
615
616
  var DEFAULT_INSTRUMENTS = /* @__PURE__ */ new Set([
616
617
  ...DEFAULT_INSTRUMENTS_FOR_ROOT,
@@ -3626,6 +3627,13 @@ var SpanAttributes2 = {
3626
3627
  };
3627
3628
 
3628
3629
  // src/instrumentation/utils.ts
3630
+ var VALID_NATIVE_TRACING_MODES = /* @__PURE__ */ new Set(["both", "netra", "netra-strict"]);
3631
+ function parseNativeTracingEnv(name) {
3632
+ const val = process.env[name];
3633
+ if (val === void 0 || val === "") return void 0;
3634
+ if (VALID_NATIVE_TRACING_MODES.has(val)) return val;
3635
+ return void 0;
3636
+ }
3629
3637
  var SUPPRESS_INSTRUMENTATION_KEY = /* @__PURE__ */ Symbol("netra.suppress_instrumentation");
3630
3638
  function shouldSuppressInstrumentation() {
3631
3639
  const ctx = context.active();
@@ -9132,6 +9140,8 @@ var cachedAgentsModule = null;
9132
9140
  var isInstrumented6 = false;
9133
9141
  var activeTracer = null;
9134
9142
  var activeProcessor = null;
9143
+ var originalProcessors = null;
9144
+ var didReplaceProcessors = false;
9135
9145
  async function resolveAgentsModule() {
9136
9146
  if (cachedAgentsModule) return cachedAgentsModule;
9137
9147
  try {
@@ -9184,20 +9194,51 @@ var NetraOpenAIAgentsInstrumentor = class {
9184
9194
  }
9185
9195
  const systemName = options.systemName ?? DEFAULT_LLM_SYSTEM;
9186
9196
  activeProcessor = new NetraAgentsTracingProcessor(activeTracer, systemName);
9197
+ const mode = options.nativeTracing ?? parseNativeTracingEnv("NATIVE_TRACING_MODE") ?? "netra-strict";
9198
+ const canSet = typeof agentsModule.setTraceProcessors === "function";
9199
+ const canAdd = typeof agentsModule.addTraceProcessor === "function";
9200
+ let strategy;
9201
+ if (mode === "both" || mode === "netra" && !canSet) {
9202
+ strategy = "append";
9203
+ } else if (canSet) {
9204
+ strategy = "replace";
9205
+ } else {
9206
+ strategy = "skip";
9207
+ }
9187
9208
  try {
9188
- if (typeof agentsModule.addTraceProcessor === "function") {
9189
- agentsModule.addTraceProcessor(activeProcessor);
9190
- } else if (typeof agentsModule.setTraceProcessors === "function") {
9191
- const existing = typeof agentsModule.getTraceProcessors === "function" ? agentsModule.getTraceProcessors() : [];
9192
- agentsModule.setTraceProcessors([...existing, activeProcessor]);
9193
- } else {
9194
- Logger.warn(
9195
- "OpenAI Agents SDK does not expose addTraceProcessor or setTraceProcessors.",
9196
- "Tracing integration may not work."
9197
- );
9198
- activeProcessor = null;
9199
- activeTracer = null;
9200
- return this;
9209
+ switch (strategy) {
9210
+ case "replace":
9211
+ if (typeof agentsModule.getTraceProcessors === "function") {
9212
+ originalProcessors = agentsModule.getTraceProcessors();
9213
+ }
9214
+ agentsModule.setTraceProcessors([activeProcessor]);
9215
+ didReplaceProcessors = true;
9216
+ Logger.debug("OpenAI Agents native tracing disabled \u2014 traces will only be sent to Netra.");
9217
+ break;
9218
+ case "append":
9219
+ if (canAdd) {
9220
+ agentsModule.addTraceProcessor(activeProcessor);
9221
+ } else {
9222
+ Logger.warn("OpenAI Agents SDK does not expose addTraceProcessor or setTraceProcessors.");
9223
+ activeProcessor = null;
9224
+ activeTracer = null;
9225
+ return this;
9226
+ }
9227
+ if (mode === "netra") {
9228
+ Logger.warn(
9229
+ "Cannot exclusively replace native trace processors in this @openai/agents version.",
9230
+ "Traces may still be sent to OpenAI."
9231
+ );
9232
+ }
9233
+ break;
9234
+ case "skip":
9235
+ Logger.warn(
9236
+ 'nativeTracing is "netra-strict" but the installed @openai/agents version',
9237
+ "does not support processor replacement. Skipping instrumentation."
9238
+ );
9239
+ activeProcessor = null;
9240
+ activeTracer = null;
9241
+ return this;
9201
9242
  }
9202
9243
  } catch (error) {
9203
9244
  Logger.warn("Failed to register trace processor with @openai/agents:", error);
@@ -9217,6 +9258,21 @@ var NetraOpenAIAgentsInstrumentor = class {
9217
9258
  activeProcessor.shutdown();
9218
9259
  activeProcessor = null;
9219
9260
  }
9261
+ if (didReplaceProcessors && cachedAgentsModule) {
9262
+ try {
9263
+ if (originalProcessors && typeof cachedAgentsModule.setTraceProcessors === "function") {
9264
+ cachedAgentsModule.setTraceProcessors(originalProcessors);
9265
+ Logger.debug("Restored original OpenAI Agents trace processors");
9266
+ } else if (typeof cachedAgentsModule.setDefaultOpenAITracingExporter === "function") {
9267
+ cachedAgentsModule.setDefaultOpenAITracingExporter();
9268
+ Logger.debug("Restored default OpenAI Agents tracing exporter");
9269
+ }
9270
+ } catch (error) {
9271
+ Logger.debug("Failed to restore original trace processors:", error);
9272
+ }
9273
+ }
9274
+ originalProcessors = null;
9275
+ didReplaceProcessors = false;
9220
9276
  activeTracer = null;
9221
9277
  cachedAgentsModule = null;
9222
9278
  isInstrumented6 = false;
@@ -10099,7 +10155,9 @@ function initInstrumentations(config2, instruments, blockInstruments, rootInstru
10099
10155
  mistral: false,
10100
10156
  langgraph: false,
10101
10157
  googleGenAI: false,
10102
- anthropic: false};
10158
+ anthropic: false,
10159
+ openAiAgents: false
10160
+ };
10103
10161
  const resolved = enableAll ? new Set(Object.values(NetraInstruments).filter((v) => v !== "__all__" /* ALL */)) : instruments && instruments.size > 0 ? instruments : DEFAULT_INSTRUMENTS;
10104
10162
  instrumentModules.google_vertexai = false;
10105
10163
  instrumentModules.langchain = false;
@@ -10147,6 +10205,9 @@ function initInstrumentations(config2, instruments, blockInstruments, rootInstru
10147
10205
  if (resolved.has("anthropic" /* ANTHROPIC */)) {
10148
10206
  customInstrumentModules.anthropic = true;
10149
10207
  }
10208
+ if (resolved.has("openai_agents" /* OPENAI_AGENTS */)) {
10209
+ customInstrumentModules.openAiAgents = true;
10210
+ }
10150
10211
  if (blockInstruments && blockInstruments.size > 0) {
10151
10212
  const blockAll = blockInstruments.has("__all__" /* ALL */);
10152
10213
  if (blockAll || blockInstruments.has("openai" /* OPENAI */)) customInstrumentModules.openai = false;
@@ -10155,6 +10216,7 @@ function initInstrumentations(config2, instruments, blockInstruments, rootInstru
10155
10216
  if (blockAll || blockInstruments.has("langgraph" /* LANGGRAPH */)) customInstrumentModules.langgraph = false;
10156
10217
  if (blockAll || blockInstruments.has("google_genai" /* GOOGLE_GENERATIVE_AI */)) customInstrumentModules.googleGenAI = false;
10157
10218
  if (blockAll || blockInstruments.has("anthropic" /* ANTHROPIC */)) customInstrumentModules.anthropic = false;
10219
+ if (blockAll || blockInstruments.has("openai_agents" /* OPENAI_AGENTS */)) customInstrumentModules.openAiAgents = false;
10158
10220
  if (blockAll || blockInstruments.has("vertexai" /* VERTEX_AI */)) instrumentModules.google_vertexai = false;
10159
10221
  if (blockAll || blockInstruments.has("langchain" /* LANGCHAIN */)) instrumentModules.langchain = false;
10160
10222
  if (blockAll || blockInstruments.has("llama_index" /* LLAMA_INDEX */)) instrumentModules.llamaIndex = false;
@@ -10277,7 +10339,7 @@ async function initCustomInstrumentationsAsync(config2, tracerProvider, customIn
10277
10339
  Logger.debug("Failed to initialize custom Anthropic instrumentation:", e);
10278
10340
  }
10279
10341
  }
10280
- if (customInstrumentModules.openaiAgents && !blockInstruments?.has("openai_agents" /* OPENAI_AGENTS */)) {
10342
+ if (customInstrumentModules.openAiAgents && !blockInstruments?.has("openai_agents" /* OPENAI_AGENTS */)) {
10281
10343
  try {
10282
10344
  await openaiAgentsInstrumentor.instrument({ tracerProvider });
10283
10345
  Logger.debug("Custom OpenAI Agents SDK instrumentation enabled");
@@ -10526,7 +10588,130 @@ async function uninstrumentAll() {
10526
10588
  Logger.debug("Failed to uninstrument undici:", e);
10527
10589
  }
10528
10590
  }
10591
+
10592
+ // src/simulation/task.ts
10593
+ var BaseTask = class {
10594
+ };
10595
+
10596
+ // src/simulation/utils.ts
10529
10597
  var LOG_PREFIX = "netra.simulation";
10598
+ var DEFAULT_FILE_DOWNLOAD_TIMEOUT_S = 30;
10599
+ var MAX_FILE_DOWNLOAD_WORKERS = 8;
10600
+ var _cachedFileDownloadTimeoutMs = null;
10601
+ function validateSimulationInputs(datasetId, task2) {
10602
+ if (!datasetId) {
10603
+ Logger.error(`${LOG_PREFIX}: dataset_id is required`);
10604
+ return false;
10605
+ }
10606
+ if (!(task2 instanceof BaseTask)) {
10607
+ Logger.error(`${LOG_PREFIX}: task must be a BaseTask instance`);
10608
+ return false;
10609
+ }
10610
+ return true;
10611
+ }
10612
+ function _getFileDownloadTimeout() {
10613
+ if (_cachedFileDownloadTimeoutMs !== null) {
10614
+ return _cachedFileDownloadTimeoutMs;
10615
+ }
10616
+ const envVal = process.env.NETRA_SIMULATION_FILE_DOWNLOAD_TIMEOUT;
10617
+ if (envVal) {
10618
+ const parsed = parseFloat(envVal);
10619
+ if (!isNaN(parsed) && parsed > 0) {
10620
+ _cachedFileDownloadTimeoutMs = parsed * 1e3;
10621
+ return _cachedFileDownloadTimeoutMs;
10622
+ }
10623
+ Logger.warn(
10624
+ `${LOG_PREFIX}: Invalid file download timeout '${envVal}', using default ${DEFAULT_FILE_DOWNLOAD_TIMEOUT_S}s`
10625
+ );
10626
+ }
10627
+ _cachedFileDownloadTimeoutMs = DEFAULT_FILE_DOWNLOAD_TIMEOUT_S * 1e3;
10628
+ return _cachedFileDownloadTimeoutMs;
10629
+ }
10630
+ async function _downloadSingleFile(fileData, timeoutMs, signal) {
10631
+ try {
10632
+ const response = await axios.get(fileData.downloadUrl, {
10633
+ responseType: "arraybuffer",
10634
+ timeout: timeoutMs,
10635
+ signal
10636
+ });
10637
+ const encoded = Buffer.from(response.data).toString("base64");
10638
+ return {
10639
+ fileName: fileData.fileName,
10640
+ contentType: fileData.contentType,
10641
+ description: fileData.description,
10642
+ data: encoded
10643
+ };
10644
+ } catch (error) {
10645
+ if (axios.isCancel(error)) {
10646
+ throw new Error(
10647
+ `Download of '${fileData.fileName}' was cancelled`
10648
+ );
10649
+ }
10650
+ const status = axios.isAxiosError(error) ? error.response?.status : void 0;
10651
+ const reason = status ? `HTTP ${status}` : error instanceof Error ? error.message : String(error);
10652
+ Logger.error(
10653
+ `${LOG_PREFIX}: Failed to download file '${fileData.fileName}': ${reason}`
10654
+ );
10655
+ throw new Error(
10656
+ `Failed to download file '${fileData.fileName}': ${reason}`
10657
+ );
10658
+ }
10659
+ }
10660
+ function parseFiles(rawFiles) {
10661
+ if (!rawFiles) {
10662
+ return [];
10663
+ }
10664
+ const parsed = [];
10665
+ for (const entry of rawFiles) {
10666
+ const fileName = entry.fileName || "";
10667
+ const downloadUrl = entry.downloadUrl || "";
10668
+ if (!fileName || !downloadUrl) {
10669
+ Logger.warn(
10670
+ `${LOG_PREFIX}: Skipping malformed file attachment (missing fileName or downloadUrl)`
10671
+ );
10672
+ continue;
10673
+ }
10674
+ parsed.push({
10675
+ fileName,
10676
+ contentType: entry.contentType || "",
10677
+ description: entry.description || void 0,
10678
+ downloadUrl
10679
+ });
10680
+ }
10681
+ return parsed;
10682
+ }
10683
+ async function processFiles(files) {
10684
+ if (!files || files.length === 0) {
10685
+ return null;
10686
+ }
10687
+ const timeoutMs = _getFileDownloadTimeout();
10688
+ const limit = pLimit(MAX_FILE_DOWNLOAD_WORKERS);
10689
+ const controller = new AbortController();
10690
+ const downloadPromises = files.map(
10691
+ (file) => limit(() => _downloadSingleFile(file, timeoutMs, controller.signal))
10692
+ );
10693
+ try {
10694
+ return await Promise.all(downloadPromises);
10695
+ } catch (error) {
10696
+ controller.abort();
10697
+ limit.clearQueue();
10698
+ throw error;
10699
+ }
10700
+ }
10701
+ async function executeTask2(task2, message, sessionId, rawFiles) {
10702
+ const processedFiles = rawFiles && rawFiles.length > 0 ? await processFiles(rawFiles) : null;
10703
+ const result = task2.run(message, sessionId, processedFiles);
10704
+ const resolvedResult = result instanceof Promise ? await result : result;
10705
+ if (typeof resolvedResult === "object" && resolvedResult !== null && "message" in resolvedResult && "sessionId" in resolvedResult) {
10706
+ return [resolvedResult.message, resolvedResult.sessionId];
10707
+ }
10708
+ throw new Error(
10709
+ `Task must return TaskResult, got ${typeof resolvedResult}`
10710
+ );
10711
+ }
10712
+
10713
+ // src/simulation/client.ts
10714
+ var LOG_PREFIX2 = "netra.simulation";
10530
10715
  var DEFAULT_TIMEOUT = 1e4;
10531
10716
  var SimulationHttpClient = class {
10532
10717
  constructor(config2) {
@@ -10539,7 +10724,7 @@ var SimulationHttpClient = class {
10539
10724
  _createClient(config2) {
10540
10725
  const endpoint = (config2.otlpEndpoint || "").trim();
10541
10726
  if (!endpoint) {
10542
- Logger.error(`${LOG_PREFIX}: NETRA_OTLP_ENDPOINT is required`);
10727
+ Logger.error(`${LOG_PREFIX2}: NETRA_OTLP_ENDPOINT is required`);
10543
10728
  return null;
10544
10729
  }
10545
10730
  const baseURL = this._resolveBaseUrl(endpoint);
@@ -10561,7 +10746,7 @@ var SimulationHttpClient = class {
10561
10746
  );
10562
10747
  return instance;
10563
10748
  } catch (error) {
10564
- Logger.error(`${LOG_PREFIX}: Failed to create HTTP client:`, error);
10749
+ Logger.error(`${LOG_PREFIX2}: Failed to create HTTP client:`, error);
10565
10750
  return null;
10566
10751
  }
10567
10752
  }
@@ -10596,7 +10781,7 @@ var SimulationHttpClient = class {
10596
10781
  const timeout = parseFloat(timeoutStr);
10597
10782
  if (isNaN(timeout)) {
10598
10783
  Logger.warn(
10599
- `${LOG_PREFIX}: Invalid timeout '${timeoutStr}', using default ${DEFAULT_TIMEOUT}ms`
10784
+ `${LOG_PREFIX2}: Invalid timeout '${timeoutStr}', using default ${DEFAULT_TIMEOUT}ms`
10600
10785
  );
10601
10786
  return DEFAULT_TIMEOUT;
10602
10787
  }
@@ -10607,7 +10792,7 @@ var SimulationHttpClient = class {
10607
10792
  */
10608
10793
  async createRun(name, datasetId, context16) {
10609
10794
  if (!this.client) {
10610
- Logger.error(`${LOG_PREFIX}: Client not initialized`);
10795
+ Logger.error(`${LOG_PREFIX2}: Client not initialized`);
10611
10796
  return null;
10612
10797
  }
10613
10798
  try {
@@ -10622,7 +10807,7 @@ var SimulationHttpClient = class {
10622
10807
  const responseData = data.data || {};
10623
10808
  const userMessages = responseData.userMessages || [];
10624
10809
  if (userMessages.length === 0) {
10625
- Logger.warn(`${LOG_PREFIX}: No user messages returned from create_run`);
10810
+ Logger.warn(`${LOG_PREFIX2}: No user messages returned from create_run`);
10626
10811
  return null;
10627
10812
  }
10628
10813
  const runId = responseData.id || "";
@@ -10630,7 +10815,8 @@ var SimulationHttpClient = class {
10630
10815
  (msg) => ({
10631
10816
  runItemId: msg.testRunItemId || "",
10632
10817
  message: msg.userMessage || "",
10633
- turnId: msg.turnId || ""
10818
+ turnId: msg.turnId || "",
10819
+ files: parseFiles(msg.attachments)
10634
10820
  })
10635
10821
  );
10636
10822
  return {
@@ -10639,7 +10825,7 @@ var SimulationHttpClient = class {
10639
10825
  };
10640
10826
  } catch (error) {
10641
10827
  const errorMsg = this._extractErrorMessage(error);
10642
- Logger.error(`${LOG_PREFIX}: Failed to create simulation run:`, errorMsg);
10828
+ Logger.error(`${LOG_PREFIX2}: Failed to create simulation run:`, errorMsg);
10643
10829
  return null;
10644
10830
  }
10645
10831
  }
@@ -10648,7 +10834,7 @@ var SimulationHttpClient = class {
10648
10834
  */
10649
10835
  async triggerConversation(message, turnId, sessionId, traceId) {
10650
10836
  if (!this.client) {
10651
- Logger.error(`${LOG_PREFIX}: Client not initialized`);
10837
+ Logger.error(`${LOG_PREFIX2}: Client not initialized`);
10652
10838
  return null;
10653
10839
  }
10654
10840
  try {
@@ -10671,7 +10857,7 @@ var SimulationHttpClient = class {
10671
10857
  }
10672
10858
  const userMessages = responseData.userMessages || [];
10673
10859
  if (userMessages.length === 0) {
10674
- Logger.warn(`${LOG_PREFIX}: No user messages in continue response`);
10860
+ Logger.warn(`${LOG_PREFIX2}: No user messages in continue response`);
10675
10861
  return null;
10676
10862
  }
10677
10863
  const nextMsg = userMessages[0];
@@ -10679,11 +10865,12 @@ var SimulationHttpClient = class {
10679
10865
  decision,
10680
10866
  nextTurnId: nextMsg.turnId || "",
10681
10867
  nextUserMessage: nextMsg.userMessage || "",
10682
- nextRunItemId: nextMsg.testRunItemId || ""
10868
+ nextRunItemId: nextMsg.testRunItemId || "",
10869
+ nextFiles: parseFiles(nextMsg.attachments)
10683
10870
  };
10684
10871
  } catch (error) {
10685
10872
  const errorMsg = this._extractErrorMessage(error);
10686
- Logger.error(`${LOG_PREFIX}: Failed to trigger conversation:`, errorMsg);
10873
+ Logger.error(`${LOG_PREFIX2}: Failed to trigger conversation:`, errorMsg);
10687
10874
  return null;
10688
10875
  }
10689
10876
  }
@@ -10692,17 +10879,17 @@ var SimulationHttpClient = class {
10692
10879
  */
10693
10880
  async reportFailure(runId, runItemId, error) {
10694
10881
  if (!this.client) {
10695
- Logger.error(`${LOG_PREFIX}: Client not initialized`);
10882
+ Logger.error(`${LOG_PREFIX2}: Client not initialized`);
10696
10883
  return;
10697
10884
  }
10698
10885
  try {
10699
10886
  const url = `/evaluations/run/${runId}/item/${runItemId}/status`;
10700
10887
  const payload = { status: "failed", failureReason: error };
10701
10888
  await this.client.patch(url, payload);
10702
- Logger.info(`${LOG_PREFIX}: Reported failure - ${error}`);
10889
+ Logger.info(`${LOG_PREFIX2}: Reported failure - ${error}`);
10703
10890
  } catch (err) {
10704
10891
  const errorMsg = this._extractErrorMessage(err);
10705
- Logger.error(`${LOG_PREFIX}: Failed to report failure:`, errorMsg);
10892
+ Logger.error(`${LOG_PREFIX2}: Failed to report failure:`, errorMsg);
10706
10893
  }
10707
10894
  }
10708
10895
  /**
@@ -10711,7 +10898,7 @@ var SimulationHttpClient = class {
10711
10898
  async postRunStatus(runId, status) {
10712
10899
  if (!this.client) {
10713
10900
  Logger.error(
10714
- `${LOG_PREFIX}: Client not initialized; cannot post run status`
10901
+ `${LOG_PREFIX2}: Client not initialized; cannot post run status`
10715
10902
  );
10716
10903
  return { success: false };
10717
10904
  }
@@ -10721,14 +10908,14 @@ var SimulationHttpClient = class {
10721
10908
  const response = await this.client.post(url, payload);
10722
10909
  const data = response.data;
10723
10910
  if (data && typeof data === "object" && "data" in data) {
10724
- Logger.info(`${LOG_PREFIX}: Completed test run successfully`);
10911
+ Logger.info(`${LOG_PREFIX2}: Completed test run successfully`);
10725
10912
  return data.data || {};
10726
10913
  }
10727
10914
  return data;
10728
10915
  } catch (error) {
10729
10916
  const errorMsg = this._extractErrorMessage(error);
10730
10917
  Logger.error(
10731
- `${LOG_PREFIX}: Failed to post run status for run '${runId}':`,
10918
+ `${LOG_PREFIX2}: Failed to post run status for run '${runId}':`,
10732
10919
  errorMsg
10733
10920
  );
10734
10921
  return { success: false };
@@ -10752,34 +10939,6 @@ var SimulationHttpClient = class {
10752
10939
  }
10753
10940
  };
10754
10941
 
10755
- // src/simulation/task.ts
10756
- var BaseTask = class {
10757
- };
10758
-
10759
- // src/simulation/utils.ts
10760
- var LOG_PREFIX2 = "netra.simulation";
10761
- function validateSimulationInputs(datasetId, task2) {
10762
- if (!datasetId) {
10763
- Logger.error(`${LOG_PREFIX2}: dataset_id is required`);
10764
- return false;
10765
- }
10766
- if (!(task2 instanceof BaseTask)) {
10767
- Logger.error(`${LOG_PREFIX2}: task must be a BaseTask instance`);
10768
- return false;
10769
- }
10770
- return true;
10771
- }
10772
- async function executeTask2(task2, message, sessionId) {
10773
- const result = task2.run(message, sessionId);
10774
- const resolvedResult = result instanceof Promise ? await result : result;
10775
- if (typeof resolvedResult === "object" && resolvedResult !== null && "message" in resolvedResult && "sessionId" in resolvedResult) {
10776
- return [resolvedResult.message, resolvedResult.sessionId];
10777
- }
10778
- throw new Error(
10779
- `Task must return TaskResult, got ${typeof resolvedResult}`
10780
- );
10781
- }
10782
-
10783
10942
  // src/simulation/api.ts
10784
10943
  var LOG_PREFIX3 = "netra.simulation";
10785
10944
  var SPAN_NAME = "Netra.Simulation.TestRun";
@@ -10913,17 +11072,18 @@ var Simulation = class {
10913
11072
  * Execute a multi-turn conversation for a single simulation item.
10914
11073
  */
10915
11074
  async _executeConversation(runId, runItem, task2) {
10916
- const { runItemId, message: initialMessage, turnId: initialTurnId } = runItem;
11075
+ const { runItemId, message: initialMessage, turnId: initialTurnId, files: initialFiles } = runItem;
10917
11076
  let message = initialMessage;
10918
11077
  let turnId = initialTurnId;
10919
11078
  let sessionId = null;
11079
+ let rawFiles = initialFiles ?? [];
10920
11080
  while (true) {
10921
11081
  const span2 = new SpanWrapper(SPAN_NAME, {}, LOG_PREFIX3);
10922
11082
  span2.start();
10923
11083
  try {
10924
11084
  const traceId = span2.getCurrentSpan()?.spanContext().traceId ?? "";
10925
11085
  const [responseMessage, taskSessionId] = await span2.withActive(
10926
- () => executeTask2(task2, message, sessionId)
11086
+ () => executeTask2(task2, message, sessionId, rawFiles)
10927
11087
  );
10928
11088
  if (taskSessionId) {
10929
11089
  sessionId = taskSessionId;
@@ -10957,6 +11117,7 @@ var Simulation = class {
10957
11117
  }
10958
11118
  message = response.nextUserMessage;
10959
11119
  turnId = response.nextTurnId;
11120
+ rawFiles = response.nextFiles || [];
10960
11121
  } catch (error) {
10961
11122
  const errorMsg = error instanceof Error ? error.message : String(error);
10962
11123
  Logger.error(