@infersec/conduit 1.98.0 → 1.98.2

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/cli.js CHANGED
@@ -122307,16 +122307,17 @@ const DOWNLOAD_PROGRESS_TIMEOUT = 60000;
122307
122307
  const DOWNLOAD_RETRY_ATTEMPTS_FULL = 3;
122308
122308
  const DOWNLOAD_RETRY_ATTEMPTS_RANGE = 10;
122309
122309
  const ALLOWED_EXTENSIONS = new Set([
122310
+ ".bin",
122311
+ ".gguf",
122310
122312
  ".gitattributes",
122313
+ ".jinja",
122311
122314
  ".json",
122312
122315
  ".merges",
122313
122316
  ".model",
122314
122317
  ".py",
122315
122318
  ".safetensors",
122316
122319
  ".tiktoken",
122317
- ".txt",
122318
- ".bin",
122319
- ".gguf"
122320
+ ".txt"
122320
122321
  ]);
122321
122322
  function isAllowedFile(filePath) {
122322
122323
  const lower = filePath.toLowerCase();
@@ -124186,12 +124187,17 @@ function serializeRequestBody$1(body) {
124186
124187
  };
124187
124188
  }
124188
124189
  const requestPayload = { ...body };
124189
- const streamOptions = requestPayload.stream_options;
124190
- const normalizedStreamOptions = isPlainObject$3(streamOptions)
124191
- ? { ...streamOptions }
124192
- : {};
124193
- normalizedStreamOptions.include_usage = true;
124194
- requestPayload.stream_options = normalizedStreamOptions;
124190
+ if (requestPayload.stream === true) {
124191
+ const streamOptions = requestPayload.stream_options;
124192
+ const normalizedStreamOptions = isPlainObject$3(streamOptions)
124193
+ ? { ...streamOptions }
124194
+ : {};
124195
+ normalizedStreamOptions.include_usage = true;
124196
+ requestPayload.stream_options = normalizedStreamOptions;
124197
+ }
124198
+ else {
124199
+ delete requestPayload.stream_options;
124200
+ }
124195
124201
  if (requestPayload.repetition_penalty === undefined) {
124196
124202
  requestPayload.repetition_penalty = 1.1;
124197
124203
  }
@@ -124201,11 +124207,17 @@ function serializeRequestBody$1(body) {
124201
124207
  payload
124202
124208
  };
124203
124209
  }
124204
- function calculateTokensPerSecond$2({ durationMs, totalTokens }) {
124205
- if (durationMs <= 0) {
124210
+ function calculateTokensPerSecond$1({ completionTokens, durationMs, streamRequested, timeToFirstTokenMs }) {
124211
+ if (completionTokens <= 0 || durationMs <= 0) {
124212
+ return 0;
124213
+ }
124214
+ const decodeMs = streamRequested && timeToFirstTokenMs !== null && timeToFirstTokenMs > 0
124215
+ ? Math.max(0, durationMs - timeToFirstTokenMs)
124216
+ : durationMs;
124217
+ if (decodeMs <= 0) {
124206
124218
  return 0;
124207
124219
  }
124208
- const tokensPerSecond = totalTokens / (durationMs / 1000);
124220
+ const tokensPerSecond = completionTokens / (decodeMs / 1000);
124209
124221
  if (!Number.isFinite(tokensPerSecond) || tokensPerSecond <= 0) {
124210
124222
  return 0;
124211
124223
  }
@@ -124255,10 +124267,7 @@ async function proxyEmbeddingsRoute({ body, conduitConfiguration, endpointId, lo
124255
124267
  responseBytes,
124256
124268
  successful: upstreamResponseOk && !error,
124257
124269
  timeToFirstTokenMs: null,
124258
- tokensPerSecond: calculateTokensPerSecond$2({
124259
- durationMs: latencyMs,
124260
- totalTokens
124261
- }),
124270
+ tokensPerSecond: 0,
124262
124271
  totalTokens
124263
124272
  });
124264
124273
  };
@@ -124401,9 +124410,11 @@ async function proxyOpenAIStreamingRoute({ body, conduitConfiguration, endpointI
124401
124410
  responseBytes,
124402
124411
  successful: upstreamResponseOk && !error,
124403
124412
  timeToFirstTokenMs,
124404
- tokensPerSecond: calculateTokensPerSecond$2({
124413
+ tokensPerSecond: calculateTokensPerSecond$1({
124414
+ completionTokens,
124405
124415
  durationMs: latencyMs,
124406
- totalTokens
124416
+ streamRequested,
124417
+ timeToFirstTokenMs
124407
124418
  }),
124408
124419
  totalTokens
124409
124420
  });
@@ -124851,10 +124862,15 @@ function serializeRequestBody(body) {
124851
124862
  payload
124852
124863
  };
124853
124864
  }
124854
- function calculateTokensPerSecond$1({ durationMs, totalTokens }) {
124855
- if (durationMs <= 0)
124865
+ function calculateTokensPerSecond({ completionTokens, durationMs, streamRequested, timeToFirstTokenMs }) {
124866
+ if (completionTokens <= 0 || durationMs <= 0)
124867
+ return 0;
124868
+ const decodeMs = streamRequested && timeToFirstTokenMs !== null && timeToFirstTokenMs > 0
124869
+ ? Math.max(0, durationMs - timeToFirstTokenMs)
124870
+ : durationMs;
124871
+ if (decodeMs <= 0)
124856
124872
  return 0;
124857
- const tokensPerSecond = totalTokens / (durationMs / 1000);
124873
+ const tokensPerSecond = completionTokens / (decodeMs / 1000);
124858
124874
  if (!Number.isFinite(tokensPerSecond) || tokensPerSecond <= 0)
124859
124875
  return 0;
124860
124876
  return Math.round(tokensPerSecond);
@@ -125032,7 +125048,7 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125032
125048
  const targetBody = needsTranslation
125033
125049
  ? translateAnthropicRequestToOpenAI(serializedBody).body
125034
125050
  : serializedBody;
125035
- const onMonitoringComplete = ({ durationMs, error, responseBytes, usage }) => {
125051
+ const onMonitoringComplete = ({ durationMs, error, responseBytes, timeToFirstTokenMs, usage }) => {
125036
125052
  const promptTokens = normalizeTokenCount(usage?.inputTokens);
125037
125053
  const completionTokens = normalizeTokenCount(usage?.outputTokens);
125038
125054
  const totalTokens = promptTokens + completionTokens;
@@ -125051,10 +125067,12 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125051
125067
  requestPath: "/v1/messages",
125052
125068
  responseBytes,
125053
125069
  successful: !error,
125054
- timeToFirstTokenMs: null,
125055
- tokensPerSecond: calculateTokensPerSecond$1({
125070
+ timeToFirstTokenMs,
125071
+ tokensPerSecond: calculateTokensPerSecond({
125072
+ completionTokens,
125056
125073
  durationMs: latencyMs,
125057
- totalTokens
125074
+ streamRequested,
125075
+ timeToFirstTokenMs
125058
125076
  }),
125059
125077
  totalTokens
125060
125078
  });
@@ -125151,6 +125169,7 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125151
125169
  const passThrough = new PassThrough();
125152
125170
  let responseBytes = 0;
125153
125171
  let completed = false;
125172
+ let firstChunkAt = null;
125154
125173
  const usage = { inputTokens: null, outputTokens: null };
125155
125174
  const upstreamError = response.ok
125156
125175
  ? null
@@ -125163,6 +125182,7 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125163
125182
  durationMs: Math.max(0, Date.now() - requestStartedAt),
125164
125183
  error,
125165
125184
  responseBytes,
125185
+ timeToFirstTokenMs: firstChunkAt === null ? null : Math.max(0, firstChunkAt - requestStartedAt),
125166
125186
  usage
125167
125187
  });
125168
125188
  }
@@ -125172,6 +125192,8 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125172
125192
  const chunks = [];
125173
125193
  rawBody.on("data", (chunk) => {
125174
125194
  const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
125195
+ if (firstChunkAt === null)
125196
+ firstChunkAt = Date.now();
125175
125197
  responseBytes += chunkBuffer.length;
125176
125198
  chunks.push(chunkBuffer);
125177
125199
  });
@@ -125254,6 +125276,8 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125254
125276
  let buffer = "";
125255
125277
  rawBody.on("data", (chunk) => {
125256
125278
  const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
125279
+ if (firstChunkAt === null)
125280
+ firstChunkAt = Date.now();
125257
125281
  responseBytes += chunkBuffer.length;
125258
125282
  buffer += chunkBuffer.toString("utf8");
125259
125283
  const lines = buffer.split("\n");
@@ -125324,6 +125348,8 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125324
125348
  const chunks = [];
125325
125349
  rawBody.on("data", (chunk) => {
125326
125350
  const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
125351
+ if (firstChunkAt === null)
125352
+ firstChunkAt = Date.now();
125327
125353
  responseBytes += chunkBuffer.length;
125328
125354
  chunks.push(chunkBuffer);
125329
125355
  });
@@ -125474,7 +125500,7 @@ function createHealthHandler() {
125474
125500
  };
125475
125501
  }
125476
125502
 
125477
- async function handleSSERequests({ apiURL, conduitConfiguration, configuration, logger, modelID, onRequest, onRequestEnd, onRequestStart, reportMetrics, signal }) {
125503
+ async function handleSSERequests({ apiURL, configuration, logger, onRequest, onRequestEnd, onRequestStart, signal }) {
125478
125504
  const streamURL = `${apiURL}/conduit/api/v1/source/${configuration.inferenceSourceID}/requests/stream`;
125479
125505
  const maxReconnectDelayMs = 30000;
125480
125506
  let reconnectAttempt = 0;
@@ -125516,14 +125542,11 @@ async function handleSSERequests({ apiURL, conduitConfiguration, configuration,
125516
125542
  handleRequest({
125517
125543
  activeRequests,
125518
125544
  apiURL,
125519
- conduitConfiguration,
125520
125545
  configuration,
125521
125546
  logger,
125522
- modelID,
125523
125547
  onRequest,
125524
125548
  onRequestEnd,
125525
125549
  onRequestStart,
125526
- reportMetrics,
125527
125550
  request: payload,
125528
125551
  signal: effectiveSignal
125529
125552
  }).catch(error => {
@@ -125560,23 +125583,12 @@ async function handleSSERequests({ apiURL, conduitConfiguration, configuration,
125560
125583
  }
125561
125584
  }
125562
125585
  }
125563
- async function handleRequest({ activeRequests, apiURL, conduitConfiguration, configuration, logger, modelID, onRequest, onRequestEnd, onRequestStart, reportMetrics, request, signal }) {
125564
- function reportMetricsSafe(payload) {
125565
- reportMetrics(payload).catch(error => {
125566
- logger.warn("Failed to upload LLM prompt metrics", {
125567
- error: asError(error),
125568
- requestUrl: request.path
125569
- });
125570
- });
125571
- }
125572
- const engineType = conduitConfiguration().engineConfig?.type ?? null;
125573
- const endpointId = request.parameters?.endpointID ?? null;
125586
+ async function handleRequest({ activeRequests, apiURL, configuration, logger, onRequest, onRequestEnd, onRequestStart, request, signal }) {
125574
125587
  const requestStartedAt = Date.now();
125575
- const requestBytes = calculateRequestBytes(request.body ?? null);
125576
125588
  try {
125577
125589
  await onRequestStart?.(request);
125578
125590
  const response = await onRequest({ request, signal });
125579
- const responseMetrics = await streamResponse({
125591
+ await streamResponse({
125580
125592
  apiURL,
125581
125593
  configuration,
125582
125594
  logger,
@@ -125585,30 +125597,6 @@ async function handleRequest({ activeRequests, apiURL, conduitConfiguration, con
125585
125597
  response,
125586
125598
  signal
125587
125599
  });
125588
- const latencyMs = Math.max(0, Date.now() - requestStartedAt);
125589
- const totalTokens = 0;
125590
- const tokensPerSecond = calculateTokensPerSecond({
125591
- durationMs: latencyMs,
125592
- totalTokens
125593
- });
125594
- reportMetricsSafe({
125595
- bytes: requestBytes + responseMetrics.responseBytes,
125596
- completionTokens: 0,
125597
- engine: engineType,
125598
- endpointId,
125599
- latencyMs,
125600
- modelId: modelID,
125601
- promptTokens: 0,
125602
- requestBytes,
125603
- requestId: request.requestID,
125604
- requestMethod: request.method,
125605
- requestPath: request.path,
125606
- responseBytes: responseMetrics.responseBytes,
125607
- successful: responseMetrics.status < 400,
125608
- timeToFirstTokenMs: responseMetrics.timeToFirstTokenMs,
125609
- tokensPerSecond,
125610
- totalTokens
125611
- });
125612
125600
  }
125613
125601
  catch (error) {
125614
125602
  const isCancelled = signal?.aborted;
@@ -125624,8 +125612,6 @@ async function handleRequest({ activeRequests, apiURL, conduitConfiguration, con
125624
125612
  });
125625
125613
  }
125626
125614
  const failureMessage = "Bad gateway\n\nProxying failed";
125627
- const failureBytes = Buffer.byteLength(failureMessage, "utf8");
125628
- const latencyMs = Math.max(0, Date.now() - requestStartedAt);
125629
125615
  if (!isCancelled) {
125630
125616
  const streamHandler = await sendChunkStream({
125631
125617
  apiURL,
@@ -125645,24 +125631,6 @@ async function handleRequest({ activeRequests, apiURL, conduitConfiguration, con
125645
125631
  });
125646
125632
  await streamHandler.end();
125647
125633
  }
125648
- reportMetricsSafe({
125649
- bytes: isCancelled ? requestBytes : requestBytes + failureBytes,
125650
- completionTokens: 0,
125651
- engine: engineType,
125652
- endpointId,
125653
- latencyMs,
125654
- modelId: modelID,
125655
- promptTokens: 0,
125656
- requestBytes,
125657
- requestId: request.requestID,
125658
- requestMethod: request.method,
125659
- requestPath: request.path,
125660
- responseBytes: isCancelled ? 0 : failureBytes,
125661
- successful: false,
125662
- timeToFirstTokenMs: isCancelled ? null : latencyMs,
125663
- tokensPerSecond: 0,
125664
- totalTokens: 0
125665
- });
125666
125634
  }
125667
125635
  finally {
125668
125636
  activeRequests.delete(request.requestID);
@@ -125850,25 +125818,6 @@ async function sendChunkStream({ apiURL, configuration, requestID, logger }) {
125850
125818
  abort
125851
125819
  };
125852
125820
  }
125853
- function calculateRequestBytes(body) {
125854
- if (body === null || body === undefined) {
125855
- return 0;
125856
- }
125857
- if (typeof body === "string") {
125858
- return Buffer.byteLength(body, "utf8");
125859
- }
125860
- return Buffer.byteLength(JSON.stringify(body), "utf8");
125861
- }
125862
- function calculateTokensPerSecond({ durationMs, totalTokens }) {
125863
- if (durationMs <= 0) {
125864
- return 0;
125865
- }
125866
- const tokensPerSecond = totalTokens / (durationMs / 1000);
125867
- if (!Number.isFinite(tokensPerSecond) || tokensPerSecond <= 0) {
125868
- return 0;
125869
- }
125870
- return Math.round(tokensPerSecond);
125871
- }
125872
125821
 
125873
125822
  const ENGINE_FETCH_TIMEOUT_MS = 7_200_000;
125874
125823
  const LOOPBACK_AGENT = new undiciExports.Agent({
@@ -136041,10 +135990,8 @@ async function createApplication({ abortController, apiClient, configuration, lo
136041
135990
  });
136042
135991
  handleSSERequests({
136043
135992
  apiURL: configuration.apiURL,
136044
- conduitConfiguration: () => conduitConfiguration,
136045
135993
  configuration,
136046
135994
  logger,
136047
- modelID: conduitConfiguration.targetModel.id,
136048
135995
  onRequest: async ({ request, signal }) => {
136049
135996
  return proxyRequest({
136050
135997
  configuration,
@@ -136061,7 +136008,6 @@ async function createApplication({ abortController, apiClient, configuration, lo
136061
136008
  conduitStateManager.incrementActiveRequestCount();
136062
136009
  conduitStateReportManager.reportStateChange();
136063
136010
  },
136064
- reportMetrics: apiClient.reportPromptMetrics,
136065
136011
  signal: abortController.signal
136066
136012
  }).catch(error => {
136067
136013
  logger.error("SSE handler failed", {
package/dist/cli.sea.cjs CHANGED
@@ -122322,16 +122322,17 @@ const DOWNLOAD_PROGRESS_TIMEOUT = 60000;
122322
122322
  const DOWNLOAD_RETRY_ATTEMPTS_FULL = 3;
122323
122323
  const DOWNLOAD_RETRY_ATTEMPTS_RANGE = 10;
122324
122324
  const ALLOWED_EXTENSIONS = new Set([
122325
+ ".bin",
122326
+ ".gguf",
122325
122327
  ".gitattributes",
122328
+ ".jinja",
122326
122329
  ".json",
122327
122330
  ".merges",
122328
122331
  ".model",
122329
122332
  ".py",
122330
122333
  ".safetensors",
122331
122334
  ".tiktoken",
122332
- ".txt",
122333
- ".bin",
122334
- ".gguf"
122335
+ ".txt"
122335
122336
  ]);
122336
122337
  function isAllowedFile(filePath) {
122337
122338
  const lower = filePath.toLowerCase();
@@ -124201,12 +124202,17 @@ function serializeRequestBody$1(body) {
124201
124202
  };
124202
124203
  }
124203
124204
  const requestPayload = { ...body };
124204
- const streamOptions = requestPayload.stream_options;
124205
- const normalizedStreamOptions = isPlainObject$3(streamOptions)
124206
- ? { ...streamOptions }
124207
- : {};
124208
- normalizedStreamOptions.include_usage = true;
124209
- requestPayload.stream_options = normalizedStreamOptions;
124205
+ if (requestPayload.stream === true) {
124206
+ const streamOptions = requestPayload.stream_options;
124207
+ const normalizedStreamOptions = isPlainObject$3(streamOptions)
124208
+ ? { ...streamOptions }
124209
+ : {};
124210
+ normalizedStreamOptions.include_usage = true;
124211
+ requestPayload.stream_options = normalizedStreamOptions;
124212
+ }
124213
+ else {
124214
+ delete requestPayload.stream_options;
124215
+ }
124210
124216
  if (requestPayload.repetition_penalty === undefined) {
124211
124217
  requestPayload.repetition_penalty = 1.1;
124212
124218
  }
@@ -124216,11 +124222,17 @@ function serializeRequestBody$1(body) {
124216
124222
  payload
124217
124223
  };
124218
124224
  }
124219
- function calculateTokensPerSecond$2({ durationMs, totalTokens }) {
124220
- if (durationMs <= 0) {
124225
+ function calculateTokensPerSecond$1({ completionTokens, durationMs, streamRequested, timeToFirstTokenMs }) {
124226
+ if (completionTokens <= 0 || durationMs <= 0) {
124227
+ return 0;
124228
+ }
124229
+ const decodeMs = streamRequested && timeToFirstTokenMs !== null && timeToFirstTokenMs > 0
124230
+ ? Math.max(0, durationMs - timeToFirstTokenMs)
124231
+ : durationMs;
124232
+ if (decodeMs <= 0) {
124221
124233
  return 0;
124222
124234
  }
124223
- const tokensPerSecond = totalTokens / (durationMs / 1000);
124235
+ const tokensPerSecond = completionTokens / (decodeMs / 1000);
124224
124236
  if (!Number.isFinite(tokensPerSecond) || tokensPerSecond <= 0) {
124225
124237
  return 0;
124226
124238
  }
@@ -124270,10 +124282,7 @@ async function proxyEmbeddingsRoute({ body, conduitConfiguration, endpointId, lo
124270
124282
  responseBytes,
124271
124283
  successful: upstreamResponseOk && !error,
124272
124284
  timeToFirstTokenMs: null,
124273
- tokensPerSecond: calculateTokensPerSecond$2({
124274
- durationMs: latencyMs,
124275
- totalTokens
124276
- }),
124285
+ tokensPerSecond: 0,
124277
124286
  totalTokens
124278
124287
  });
124279
124288
  };
@@ -124416,9 +124425,11 @@ async function proxyOpenAIStreamingRoute({ body, conduitConfiguration, endpointI
124416
124425
  responseBytes,
124417
124426
  successful: upstreamResponseOk && !error,
124418
124427
  timeToFirstTokenMs,
124419
- tokensPerSecond: calculateTokensPerSecond$2({
124428
+ tokensPerSecond: calculateTokensPerSecond$1({
124429
+ completionTokens,
124420
124430
  durationMs: latencyMs,
124421
- totalTokens
124431
+ streamRequested,
124432
+ timeToFirstTokenMs
124422
124433
  }),
124423
124434
  totalTokens
124424
124435
  });
@@ -124866,10 +124877,15 @@ function serializeRequestBody(body) {
124866
124877
  payload
124867
124878
  };
124868
124879
  }
124869
- function calculateTokensPerSecond$1({ durationMs, totalTokens }) {
124870
- if (durationMs <= 0)
124880
+ function calculateTokensPerSecond({ completionTokens, durationMs, streamRequested, timeToFirstTokenMs }) {
124881
+ if (completionTokens <= 0 || durationMs <= 0)
124882
+ return 0;
124883
+ const decodeMs = streamRequested && timeToFirstTokenMs !== null && timeToFirstTokenMs > 0
124884
+ ? Math.max(0, durationMs - timeToFirstTokenMs)
124885
+ : durationMs;
124886
+ if (decodeMs <= 0)
124871
124887
  return 0;
124872
- const tokensPerSecond = totalTokens / (durationMs / 1000);
124888
+ const tokensPerSecond = completionTokens / (decodeMs / 1000);
124873
124889
  if (!Number.isFinite(tokensPerSecond) || tokensPerSecond <= 0)
124874
124890
  return 0;
124875
124891
  return Math.round(tokensPerSecond);
@@ -125047,7 +125063,7 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125047
125063
  const targetBody = needsTranslation
125048
125064
  ? translateAnthropicRequestToOpenAI(serializedBody).body
125049
125065
  : serializedBody;
125050
- const onMonitoringComplete = ({ durationMs, error, responseBytes, usage }) => {
125066
+ const onMonitoringComplete = ({ durationMs, error, responseBytes, timeToFirstTokenMs, usage }) => {
125051
125067
  const promptTokens = normalizeTokenCount(usage?.inputTokens);
125052
125068
  const completionTokens = normalizeTokenCount(usage?.outputTokens);
125053
125069
  const totalTokens = promptTokens + completionTokens;
@@ -125066,10 +125082,12 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125066
125082
  requestPath: "/v1/messages",
125067
125083
  responseBytes,
125068
125084
  successful: !error,
125069
- timeToFirstTokenMs: null,
125070
- tokensPerSecond: calculateTokensPerSecond$1({
125085
+ timeToFirstTokenMs,
125086
+ tokensPerSecond: calculateTokensPerSecond({
125087
+ completionTokens,
125071
125088
  durationMs: latencyMs,
125072
- totalTokens
125089
+ streamRequested,
125090
+ timeToFirstTokenMs
125073
125091
  }),
125074
125092
  totalTokens
125075
125093
  });
@@ -125166,6 +125184,7 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125166
125184
  const passThrough = new require$$0$8.PassThrough();
125167
125185
  let responseBytes = 0;
125168
125186
  let completed = false;
125187
+ let firstChunkAt = null;
125169
125188
  const usage = { inputTokens: null, outputTokens: null };
125170
125189
  const upstreamError = response.ok
125171
125190
  ? null
@@ -125178,6 +125197,7 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125178
125197
  durationMs: Math.max(0, Date.now() - requestStartedAt),
125179
125198
  error,
125180
125199
  responseBytes,
125200
+ timeToFirstTokenMs: firstChunkAt === null ? null : Math.max(0, firstChunkAt - requestStartedAt),
125181
125201
  usage
125182
125202
  });
125183
125203
  }
@@ -125187,6 +125207,8 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125187
125207
  const chunks = [];
125188
125208
  rawBody.on("data", (chunk) => {
125189
125209
  const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
125210
+ if (firstChunkAt === null)
125211
+ firstChunkAt = Date.now();
125190
125212
  responseBytes += chunkBuffer.length;
125191
125213
  chunks.push(chunkBuffer);
125192
125214
  });
@@ -125269,6 +125291,8 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125269
125291
  let buffer = "";
125270
125292
  rawBody.on("data", (chunk) => {
125271
125293
  const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
125294
+ if (firstChunkAt === null)
125295
+ firstChunkAt = Date.now();
125272
125296
  responseBytes += chunkBuffer.length;
125273
125297
  buffer += chunkBuffer.toString("utf8");
125274
125298
  const lines = buffer.split("\n");
@@ -125339,6 +125363,8 @@ async function proxyAnthropicStreamingRoute({ body, conduitConfiguration, endpoi
125339
125363
  const chunks = [];
125340
125364
  rawBody.on("data", (chunk) => {
125341
125365
  const chunkBuffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
125366
+ if (firstChunkAt === null)
125367
+ firstChunkAt = Date.now();
125342
125368
  responseBytes += chunkBuffer.length;
125343
125369
  chunks.push(chunkBuffer);
125344
125370
  });
@@ -125489,7 +125515,7 @@ function createHealthHandler() {
125489
125515
  };
125490
125516
  }
125491
125517
 
125492
- async function handleSSERequests({ apiURL, conduitConfiguration, configuration, logger, modelID, onRequest, onRequestEnd, onRequestStart, reportMetrics, signal }) {
125518
+ async function handleSSERequests({ apiURL, configuration, logger, onRequest, onRequestEnd, onRequestStart, signal }) {
125493
125519
  const streamURL = `${apiURL}/conduit/api/v1/source/${configuration.inferenceSourceID}/requests/stream`;
125494
125520
  const maxReconnectDelayMs = 30000;
125495
125521
  let reconnectAttempt = 0;
@@ -125531,14 +125557,11 @@ async function handleSSERequests({ apiURL, conduitConfiguration, configuration,
125531
125557
  handleRequest({
125532
125558
  activeRequests,
125533
125559
  apiURL,
125534
- conduitConfiguration,
125535
125560
  configuration,
125536
125561
  logger,
125537
- modelID,
125538
125562
  onRequest,
125539
125563
  onRequestEnd,
125540
125564
  onRequestStart,
125541
- reportMetrics,
125542
125565
  request: payload,
125543
125566
  signal: effectiveSignal
125544
125567
  }).catch(error => {
@@ -125575,23 +125598,12 @@ async function handleSSERequests({ apiURL, conduitConfiguration, configuration,
125575
125598
  }
125576
125599
  }
125577
125600
  }
125578
- async function handleRequest({ activeRequests, apiURL, conduitConfiguration, configuration, logger, modelID, onRequest, onRequestEnd, onRequestStart, reportMetrics, request, signal }) {
125579
- function reportMetricsSafe(payload) {
125580
- reportMetrics(payload).catch(error => {
125581
- logger.warn("Failed to upload LLM prompt metrics", {
125582
- error: asError(error),
125583
- requestUrl: request.path
125584
- });
125585
- });
125586
- }
125587
- const engineType = conduitConfiguration().engineConfig?.type ?? null;
125588
- const endpointId = request.parameters?.endpointID ?? null;
125601
+ async function handleRequest({ activeRequests, apiURL, configuration, logger, onRequest, onRequestEnd, onRequestStart, request, signal }) {
125589
125602
  const requestStartedAt = Date.now();
125590
- const requestBytes = calculateRequestBytes(request.body ?? null);
125591
125603
  try {
125592
125604
  await onRequestStart?.(request);
125593
125605
  const response = await onRequest({ request, signal });
125594
- const responseMetrics = await streamResponse({
125606
+ await streamResponse({
125595
125607
  apiURL,
125596
125608
  configuration,
125597
125609
  logger,
@@ -125600,30 +125612,6 @@ async function handleRequest({ activeRequests, apiURL, conduitConfiguration, con
125600
125612
  response,
125601
125613
  signal
125602
125614
  });
125603
- const latencyMs = Math.max(0, Date.now() - requestStartedAt);
125604
- const totalTokens = 0;
125605
- const tokensPerSecond = calculateTokensPerSecond({
125606
- durationMs: latencyMs,
125607
- totalTokens
125608
- });
125609
- reportMetricsSafe({
125610
- bytes: requestBytes + responseMetrics.responseBytes,
125611
- completionTokens: 0,
125612
- engine: engineType,
125613
- endpointId,
125614
- latencyMs,
125615
- modelId: modelID,
125616
- promptTokens: 0,
125617
- requestBytes,
125618
- requestId: request.requestID,
125619
- requestMethod: request.method,
125620
- requestPath: request.path,
125621
- responseBytes: responseMetrics.responseBytes,
125622
- successful: responseMetrics.status < 400,
125623
- timeToFirstTokenMs: responseMetrics.timeToFirstTokenMs,
125624
- tokensPerSecond,
125625
- totalTokens
125626
- });
125627
125615
  }
125628
125616
  catch (error) {
125629
125617
  const isCancelled = signal?.aborted;
@@ -125639,8 +125627,6 @@ async function handleRequest({ activeRequests, apiURL, conduitConfiguration, con
125639
125627
  });
125640
125628
  }
125641
125629
  const failureMessage = "Bad gateway\n\nProxying failed";
125642
- const failureBytes = Buffer.byteLength(failureMessage, "utf8");
125643
- const latencyMs = Math.max(0, Date.now() - requestStartedAt);
125644
125630
  if (!isCancelled) {
125645
125631
  const streamHandler = await sendChunkStream({
125646
125632
  apiURL,
@@ -125660,24 +125646,6 @@ async function handleRequest({ activeRequests, apiURL, conduitConfiguration, con
125660
125646
  });
125661
125647
  await streamHandler.end();
125662
125648
  }
125663
- reportMetricsSafe({
125664
- bytes: isCancelled ? requestBytes : requestBytes + failureBytes,
125665
- completionTokens: 0,
125666
- engine: engineType,
125667
- endpointId,
125668
- latencyMs,
125669
- modelId: modelID,
125670
- promptTokens: 0,
125671
- requestBytes,
125672
- requestId: request.requestID,
125673
- requestMethod: request.method,
125674
- requestPath: request.path,
125675
- responseBytes: isCancelled ? 0 : failureBytes,
125676
- successful: false,
125677
- timeToFirstTokenMs: isCancelled ? null : latencyMs,
125678
- tokensPerSecond: 0,
125679
- totalTokens: 0
125680
- });
125681
125649
  }
125682
125650
  finally {
125683
125651
  activeRequests.delete(request.requestID);
@@ -125865,25 +125833,6 @@ async function sendChunkStream({ apiURL, configuration, requestID, logger }) {
125865
125833
  abort
125866
125834
  };
125867
125835
  }
125868
- function calculateRequestBytes(body) {
125869
- if (body === null || body === undefined) {
125870
- return 0;
125871
- }
125872
- if (typeof body === "string") {
125873
- return Buffer.byteLength(body, "utf8");
125874
- }
125875
- return Buffer.byteLength(JSON.stringify(body), "utf8");
125876
- }
125877
- function calculateTokensPerSecond({ durationMs, totalTokens }) {
125878
- if (durationMs <= 0) {
125879
- return 0;
125880
- }
125881
- const tokensPerSecond = totalTokens / (durationMs / 1000);
125882
- if (!Number.isFinite(tokensPerSecond) || tokensPerSecond <= 0) {
125883
- return 0;
125884
- }
125885
- return Math.round(tokensPerSecond);
125886
- }
125887
125836
 
125888
125837
  const ENGINE_FETCH_TIMEOUT_MS = 7_200_000;
125889
125838
  const LOOPBACK_AGENT = new undiciExports.Agent({
@@ -156271,10 +156220,8 @@ async function createApplication({ abortController, apiClient, configuration, lo
156271
156220
  });
156272
156221
  handleSSERequests({
156273
156222
  apiURL: configuration.apiURL,
156274
- conduitConfiguration: () => conduitConfiguration,
156275
156223
  configuration,
156276
156224
  logger,
156277
- modelID: conduitConfiguration.targetModel.id,
156278
156225
  onRequest: async ({ request, signal }) => {
156279
156226
  return proxyRequest({
156280
156227
  configuration,
@@ -156291,7 +156238,6 @@ async function createApplication({ abortController, apiClient, configuration, lo
156291
156238
  conduitStateManager.incrementActiveRequestCount();
156292
156239
  conduitStateReportManager.reportStateChange();
156293
156240
  },
156294
- reportMetrics: apiClient.reportPromptMetrics,
156295
156241
  signal: abortController.signal
156296
156242
  }).catch(error => {
156297
156243
  logger.error("SSE handler failed", {
@@ -1,18 +1,15 @@
1
- import { InferenceAgentConfiguration, InferenceAgentLLMMetricsPayload, type ULID, type APIResponse, type ServerToClientAPIRequest } from "@infersec/definitions";
1
+ import { type APIResponse, type ServerToClientAPIRequest } from "@infersec/definitions";
2
2
  import { Logger } from "@infersec/logger";
3
3
  import { Configuration } from "../configuration.js";
4
- export declare function handleSSERequests({ apiURL, conduitConfiguration, configuration, logger, modelID, onRequest, onRequestEnd, onRequestStart, reportMetrics, signal }: {
4
+ export declare function handleSSERequests({ apiURL, configuration, logger, onRequest, onRequestEnd, onRequestStart, signal }: {
5
5
  apiURL: string;
6
- conduitConfiguration: () => InferenceAgentConfiguration;
7
6
  configuration: Configuration;
8
7
  logger: Logger;
9
- modelID: ULID;
10
8
  onRequest: ({ request, signal }: {
11
9
  request: ServerToClientAPIRequest;
12
10
  signal?: AbortSignal;
13
11
  }) => Promise<APIResponse>;
14
12
  onRequestEnd?: (request: ServerToClientAPIRequest) => Promise<void> | void;
15
13
  onRequestStart?: (request: ServerToClientAPIRequest) => Promise<void> | void;
16
- reportMetrics: (payload: InferenceAgentLLMMetricsPayload) => Promise<void>;
17
14
  signal?: AbortSignal;
18
15
  }): Promise<void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@infersec/conduit",
3
3
  "description": "End user conduit agent for connecting local LLMs to the cloud.",
4
- "version": "1.98.0",
4
+ "version": "1.98.2",
5
5
  "bin": {
6
6
  "infersec-conduit": "./dist/cli.js"
7
7
  },