@infersec/conduit 1.93.0 → 1.95.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/cli.js CHANGED
@@ -112706,6 +112706,8 @@ function requireExpressPromiseRouter () {
112706
112706
  var expressPromiseRouterExports = requireExpressPromiseRouter();
112707
112707
  var createRouter = /*@__PURE__*/getDefaultExportFromCjs(expressPromiseRouterExports);
112708
112708
 
112709
+ const SERVED_MODEL_NAME = "default";
112710
+
112709
112711
  const SECRET_FLAGS = new Set([
112710
112712
  "api-key",
112711
112713
  "auth-token",
@@ -121201,7 +121203,7 @@ async function startVLLM({ enginePort, targetDirectory }) {
121201
121203
  "--model",
121202
121204
  modelPath,
121203
121205
  "--served-model-name",
121204
- this.model.id,
121206
+ SERVED_MODEL_NAME,
121205
121207
  "--max-model-len",
121206
121208
  String(contextLength),
121207
121209
  "--tensor-parallel-size",
@@ -123017,7 +123019,7 @@ async function startSGLang({ enginePort, targetDirectory }) {
123017
123019
  "--model-path",
123018
123020
  targetDirectory,
123019
123021
  "--served-model-name",
123020
- this.model.id,
123022
+ SERVED_MODEL_NAME,
123021
123023
  "--context-length",
123022
123024
  String(contextLength),
123023
123025
  "--tp-size",
@@ -123091,6 +123093,7 @@ class ModelManager extends EventEmitter {
123091
123093
  logger;
123092
123094
  engineProcess = null;
123093
123095
  healthPollInterval = null;
123096
+ lastEngineError = null;
123094
123097
  lifecycleState = "stopped";
123095
123098
  stopRequested = false;
123096
123099
  modelsDirectory;
@@ -123198,6 +123201,7 @@ class ModelManager extends EventEmitter {
123198
123201
  });
123199
123202
  }
123200
123203
  this.lifecycleState = "starting";
123204
+ this.lastEngineError = null;
123201
123205
  this.stopRequested = false;
123202
123206
  this.logger.info("Starting LLM engine", {
123203
123207
  agentEngineType: this.engine
@@ -123211,12 +123215,18 @@ class ModelManager extends EventEmitter {
123211
123215
  await this.waitForEngineReady();
123212
123216
  }
123213
123217
  catch (error) {
123214
- const err = error instanceof Error ? error : new Error(String(error));
123218
+ let err = error instanceof Error ? error : new Error(String(error));
123215
123219
  if (this.stopRequested) {
123216
123220
  throw err;
123217
123221
  }
123222
+ if (this.lastEngineError) {
123223
+ err = this.lastEngineError;
123224
+ }
123225
+ const alreadyEmitted = this.lastEngineError !== null;
123218
123226
  this.lifecycleState = "errored";
123219
- this.emit("engineError", err);
123227
+ if (!alreadyEmitted) {
123228
+ this.emit("engineError", err);
123229
+ }
123220
123230
  if (this.engineProcess) {
123221
123231
  this.startHealthPoll();
123222
123232
  }
@@ -123351,7 +123361,10 @@ class ModelManager extends EventEmitter {
123351
123361
  }
123352
123362
  await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
123353
123363
  }
123354
- throw new Error("LLM engine failed readiness checks within timeout");
123364
+ const stderrTail = this.engineProcess?.stderr?.slice(-1e3);
123365
+ throw new Error(stderrTail
123366
+ ? `LLM engine failed readiness checks within timeout. Last engine output:\n${stderrTail}`
123367
+ : "LLM engine failed readiness checks within timeout");
123355
123368
  }
123356
123369
  clearHealthPoll() {
123357
123370
  if (this.healthPollInterval) {
@@ -123414,6 +123427,11 @@ class ModelManager extends EventEmitter {
123414
123427
  return null;
123415
123428
  }
123416
123429
  }
123430
+ recordEngineError(err) {
123431
+ this.lifecycleState = "errored";
123432
+ this.lastEngineError = err;
123433
+ this.emit("engineError", err);
123434
+ }
123417
123435
  async releaseDownloadLock() {
123418
123436
  try {
123419
123437
  await unlink(this.lockFilePath);
@@ -123459,8 +123477,7 @@ class ModelManager extends EventEmitter {
123459
123477
  return;
123460
123478
  }
123461
123479
  this.engineProcess = null;
123462
- this.lifecycleState = "errored";
123463
- this.emit("engineError", new ProcessExecutionError({
123480
+ this.recordEngineError(new ProcessExecutionError({
123464
123481
  code: null,
123465
123482
  error: err,
123466
123483
  message: `Process error: ${this.engine}: ${processManager.stderr}`,
@@ -123485,8 +123502,7 @@ class ModelManager extends EventEmitter {
123485
123502
  this.emit("engineTerminated");
123486
123503
  return;
123487
123504
  }
123488
- this.lifecycleState = "errored";
123489
- this.emit("engineError", new ProcessExecutionError({
123505
+ this.recordEngineError(new ProcessExecutionError({
123490
123506
  code,
123491
123507
  message: `Process stopped: ${this.engine}: ${processManager.stderr}`,
123492
123508
  signal
@@ -123536,6 +123552,47 @@ class ModelManager extends EventEmitter {
123536
123552
  }
123537
123553
  }
123538
123554
 
123555
+ const EXCEPTION_LINE_PATTERN = /([A-Za-z_][A-Za-z0-9_]*(?:Error|Exception)):\s*(.+)/;
123556
+ const FALLBACK_DETAIL_MAX_LENGTH = 300;
123557
+ const FALLBACK_RAW_MAX_LENGTH = 500;
123558
+ const PATTERNS = [
123559
+ {
123560
+ message: () => "GPU memory insufficient to reserve the KV cache. Raise --gpu-memory-utilization, or reduce --max-model-len / context length.",
123561
+ pattern: /No available memory for the cache blocks/
123562
+ },
123563
+ {
123564
+ message: match => `Context length requires more KV cache memory than is available. Lower the source's context length to at most ${match[1]} tokens (the engine's computed ceiling), or raise --gpu-memory-utilization.`,
123565
+ pattern: /larger than the available KV cache memory[\s\S]*?estimated maximum model length is (\d+)/
123566
+ },
123567
+ {
123568
+ message: () => "The GPU ran out of memory (CUDA OOM). Reduce --max-model-len / --max-num-seqs, lower --gpu-memory-utilization, or use a smaller or more aggressively quantized model.",
123569
+ pattern: /CUDA out of memory/i
123570
+ }
123571
+ ];
123572
+ function normalizeEngineError(input) {
123573
+ const source = typeof input === "string" ? input : String(input ?? "");
123574
+ for (const { message, pattern } of PATTERNS) {
123575
+ const match = source.match(pattern);
123576
+ if (match) {
123577
+ return message(match);
123578
+ }
123579
+ }
123580
+ const lines = source.split(/\r?\n/);
123581
+ for (let index = lines.length - 1; index >= 0; index -= 1) {
123582
+ const exceptionMatch = lines[index].match(EXCEPTION_LINE_PATTERN);
123583
+ if (exceptionMatch) {
123584
+ return `Engine failed to start: ${truncate(exceptionMatch[0], FALLBACK_DETAIL_MAX_LENGTH)}`;
123585
+ }
123586
+ }
123587
+ return `Engine failed to start: ${truncate(source, FALLBACK_RAW_MAX_LENGTH)}`;
123588
+ }
123589
+ function truncate(value, max) {
123590
+ if (value.length <= max) {
123591
+ return value;
123592
+ }
123593
+ return `${value.slice(0, max)}…`;
123594
+ }
123595
+
123539
123596
  function createConduitGeneralAPIReferenceHandlers({ cycleEngine, conduitStateManager, getModelManager, logger, setErrorState, startEngine, stopEngine, stopRequestedByControl }) {
123540
123597
  return {
123541
123598
  "/conduit/engine/start": {
@@ -124563,7 +124620,7 @@ function createConduitOpenAIAPIReferenceHandlers({ apiClient, conduitConfigurati
124563
124620
  data: [
124564
124621
  {
124565
124622
  created: startup / 1000,
124566
- id: "default",
124623
+ id: SERVED_MODEL_NAME,
124567
124624
  limit: {
124568
124625
  context: effectiveContextLength
124569
124626
  },
@@ -135738,7 +135795,7 @@ async function createApplication({ abortController, apiClient, configuration, lo
135738
135795
  error: err
135739
135796
  });
135740
135797
  stopRequestedByControl = false;
135741
- setErrorState({ error: err.message });
135798
+ setErrorState({ error: normalizeEngineError(err.message) });
135742
135799
  });
135743
135800
  modelManager.on("engineReady", () => {
135744
135801
  setOnlineState();
@@ -135855,7 +135912,7 @@ async function createApplication({ abortController, apiClient, configuration, lo
135855
135912
  logger.error("Failed starting LLM engine", {
135856
135913
  error: parsedError
135857
135914
  });
135858
- setErrorState({ error: parsedError.message });
135915
+ setErrorState({ error: normalizeEngineError(parsedError.message) });
135859
135916
  });
135860
135917
  }
135861
135918
  const app = express();
package/dist/cli.sea.cjs CHANGED
@@ -112721,6 +112721,8 @@ function requireExpressPromiseRouter () {
112721
112721
  var expressPromiseRouterExports = requireExpressPromiseRouter();
112722
112722
  var createRouter = /*@__PURE__*/getDefaultExportFromCjs(expressPromiseRouterExports);
112723
112723
 
112724
+ const SERVED_MODEL_NAME = "default";
112725
+
112724
112726
  const SECRET_FLAGS = new Set([
112725
112727
  "api-key",
112726
112728
  "auth-token",
@@ -121216,7 +121218,7 @@ async function startVLLM({ enginePort, targetDirectory }) {
121216
121218
  "--model",
121217
121219
  modelPath,
121218
121220
  "--served-model-name",
121219
- this.model.id,
121221
+ SERVED_MODEL_NAME,
121220
121222
  "--max-model-len",
121221
121223
  String(contextLength),
121222
121224
  "--tensor-parallel-size",
@@ -123032,7 +123034,7 @@ async function startSGLang({ enginePort, targetDirectory }) {
123032
123034
  "--model-path",
123033
123035
  targetDirectory,
123034
123036
  "--served-model-name",
123035
- this.model.id,
123037
+ SERVED_MODEL_NAME,
123036
123038
  "--context-length",
123037
123039
  String(contextLength),
123038
123040
  "--tp-size",
@@ -123106,6 +123108,7 @@ class ModelManager extends EventEmitter {
123106
123108
  logger;
123107
123109
  engineProcess = null;
123108
123110
  healthPollInterval = null;
123111
+ lastEngineError = null;
123109
123112
  lifecycleState = "stopped";
123110
123113
  stopRequested = false;
123111
123114
  modelsDirectory;
@@ -123213,6 +123216,7 @@ class ModelManager extends EventEmitter {
123213
123216
  });
123214
123217
  }
123215
123218
  this.lifecycleState = "starting";
123219
+ this.lastEngineError = null;
123216
123220
  this.stopRequested = false;
123217
123221
  this.logger.info("Starting LLM engine", {
123218
123222
  agentEngineType: this.engine
@@ -123226,12 +123230,18 @@ class ModelManager extends EventEmitter {
123226
123230
  await this.waitForEngineReady();
123227
123231
  }
123228
123232
  catch (error) {
123229
- const err = error instanceof Error ? error : new Error(String(error));
123233
+ let err = error instanceof Error ? error : new Error(String(error));
123230
123234
  if (this.stopRequested) {
123231
123235
  throw err;
123232
123236
  }
123237
+ if (this.lastEngineError) {
123238
+ err = this.lastEngineError;
123239
+ }
123240
+ const alreadyEmitted = this.lastEngineError !== null;
123233
123241
  this.lifecycleState = "errored";
123234
- this.emit("engineError", err);
123242
+ if (!alreadyEmitted) {
123243
+ this.emit("engineError", err);
123244
+ }
123235
123245
  if (this.engineProcess) {
123236
123246
  this.startHealthPoll();
123237
123247
  }
@@ -123366,7 +123376,10 @@ class ModelManager extends EventEmitter {
123366
123376
  }
123367
123377
  await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
123368
123378
  }
123369
- throw new Error("LLM engine failed readiness checks within timeout");
123379
+ const stderrTail = this.engineProcess?.stderr?.slice(-1e3);
123380
+ throw new Error(stderrTail
123381
+ ? `LLM engine failed readiness checks within timeout. Last engine output:\n${stderrTail}`
123382
+ : "LLM engine failed readiness checks within timeout");
123370
123383
  }
123371
123384
  clearHealthPoll() {
123372
123385
  if (this.healthPollInterval) {
@@ -123429,6 +123442,11 @@ class ModelManager extends EventEmitter {
123429
123442
  return null;
123430
123443
  }
123431
123444
  }
123445
+ recordEngineError(err) {
123446
+ this.lifecycleState = "errored";
123447
+ this.lastEngineError = err;
123448
+ this.emit("engineError", err);
123449
+ }
123432
123450
  async releaseDownloadLock() {
123433
123451
  try {
123434
123452
  await require$$0$d.unlink(this.lockFilePath);
@@ -123474,8 +123492,7 @@ class ModelManager extends EventEmitter {
123474
123492
  return;
123475
123493
  }
123476
123494
  this.engineProcess = null;
123477
- this.lifecycleState = "errored";
123478
- this.emit("engineError", new ProcessExecutionError({
123495
+ this.recordEngineError(new ProcessExecutionError({
123479
123496
  code: null,
123480
123497
  error: err,
123481
123498
  message: `Process error: ${this.engine}: ${processManager.stderr}`,
@@ -123500,8 +123517,7 @@ class ModelManager extends EventEmitter {
123500
123517
  this.emit("engineTerminated");
123501
123518
  return;
123502
123519
  }
123503
- this.lifecycleState = "errored";
123504
- this.emit("engineError", new ProcessExecutionError({
123520
+ this.recordEngineError(new ProcessExecutionError({
123505
123521
  code,
123506
123522
  message: `Process stopped: ${this.engine}: ${processManager.stderr}`,
123507
123523
  signal
@@ -123551,6 +123567,47 @@ class ModelManager extends EventEmitter {
123551
123567
  }
123552
123568
  }
123553
123569
 
123570
+ const EXCEPTION_LINE_PATTERN = /([A-Za-z_][A-Za-z0-9_]*(?:Error|Exception)):\s*(.+)/;
123571
+ const FALLBACK_DETAIL_MAX_LENGTH = 300;
123572
+ const FALLBACK_RAW_MAX_LENGTH = 500;
123573
+ const PATTERNS = [
123574
+ {
123575
+ message: () => "GPU memory insufficient to reserve the KV cache. Raise --gpu-memory-utilization, or reduce --max-model-len / context length.",
123576
+ pattern: /No available memory for the cache blocks/
123577
+ },
123578
+ {
123579
+ message: match => `Context length requires more KV cache memory than is available. Lower the source's context length to at most ${match[1]} tokens (the engine's computed ceiling), or raise --gpu-memory-utilization.`,
123580
+ pattern: /larger than the available KV cache memory[\s\S]*?estimated maximum model length is (\d+)/
123581
+ },
123582
+ {
123583
+ message: () => "The GPU ran out of memory (CUDA OOM). Reduce --max-model-len / --max-num-seqs, lower --gpu-memory-utilization, or use a smaller or more aggressively quantized model.",
123584
+ pattern: /CUDA out of memory/i
123585
+ }
123586
+ ];
123587
+ function normalizeEngineError(input) {
123588
+ const source = typeof input === "string" ? input : String(input ?? "");
123589
+ for (const { message, pattern } of PATTERNS) {
123590
+ const match = source.match(pattern);
123591
+ if (match) {
123592
+ return message(match);
123593
+ }
123594
+ }
123595
+ const lines = source.split(/\r?\n/);
123596
+ for (let index = lines.length - 1; index >= 0; index -= 1) {
123597
+ const exceptionMatch = lines[index].match(EXCEPTION_LINE_PATTERN);
123598
+ if (exceptionMatch) {
123599
+ return `Engine failed to start: ${truncate(exceptionMatch[0], FALLBACK_DETAIL_MAX_LENGTH)}`;
123600
+ }
123601
+ }
123602
+ return `Engine failed to start: ${truncate(source, FALLBACK_RAW_MAX_LENGTH)}`;
123603
+ }
123604
+ function truncate(value, max) {
123605
+ if (value.length <= max) {
123606
+ return value;
123607
+ }
123608
+ return `${value.slice(0, max)}…`;
123609
+ }
123610
+
123554
123611
  function createConduitGeneralAPIReferenceHandlers({ cycleEngine, conduitStateManager, getModelManager, logger, setErrorState, startEngine, stopEngine, stopRequestedByControl }) {
123555
123612
  return {
123556
123613
  "/conduit/engine/start": {
@@ -124578,7 +124635,7 @@ function createConduitOpenAIAPIReferenceHandlers({ apiClient, conduitConfigurati
124578
124635
  data: [
124579
124636
  {
124580
124637
  created: startup / 1000,
124581
- id: "default",
124638
+ id: SERVED_MODEL_NAME,
124582
124639
  limit: {
124583
124640
  context: effectiveContextLength
124584
124641
  },
@@ -155968,7 +156025,7 @@ async function createApplication({ abortController, apiClient, configuration, lo
155968
156025
  error: err
155969
156026
  });
155970
156027
  stopRequestedByControl = false;
155971
- setErrorState({ error: err.message });
156028
+ setErrorState({ error: normalizeEngineError(err.message) });
155972
156029
  });
155973
156030
  modelManager.on("engineReady", () => {
155974
156031
  setOnlineState();
@@ -156085,7 +156142,7 @@ async function createApplication({ abortController, apiClient, configuration, lo
156085
156142
  logger.error("Failed starting LLM engine", {
156086
156143
  error: parsedError
156087
156144
  });
156088
- setErrorState({ error: parsedError.message });
156145
+ setErrorState({ error: normalizeEngineError(parsedError.message) });
156089
156146
  });
156090
156147
  }
156091
156148
  const app = express();
@@ -0,0 +1 @@
1
+ export declare const SERVED_MODEL_NAME = "default";
@@ -20,6 +20,7 @@ export declare class ModelManager extends EventEmitter<ModelManagerEvents> {
20
20
  protected readonly logger: Logger;
21
21
  private engineProcess;
22
22
  private healthPollInterval;
23
+ private lastEngineError;
23
24
  private lifecycleState;
24
25
  private stopRequested;
25
26
  protected readonly modelsDirectory: string;
@@ -51,6 +52,7 @@ export declare class ModelManager extends EventEmitter<ModelManagerEvents> {
51
52
  private get lockFilePath();
52
53
  private acquireDownloadLock;
53
54
  private getLockAge;
55
+ private recordEngineError;
54
56
  private releaseDownloadLock;
55
57
  private waitForDownloadLock;
56
58
  private bindEngineProcessEvents;
@@ -0,0 +1 @@
1
+ export declare function normalizeEngineError(input: string): string;
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.93.0",
4
+ "version": "1.95.0",
5
5
  "bin": {
6
6
  "infersec-conduit": "./dist/cli.js"
7
7
  },