@infersec/conduit 1.26.5 → 1.28.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.
@@ -1,6 +1,7 @@
1
1
  import { InferenceAgentConfiguration, InferenceAgentLLMMetricsPayload, InferenceAgentMachineReportPayload, ULID, type ConduitState } from "@infersec/definitions";
2
2
  import { Logger } from "@infersec/logger";
3
3
  export interface APIClient {
4
+ cycleInferenceSourceEngine: () => Promise<void>;
4
5
  getConduitConfiguration: () => Promise<InferenceAgentConfiguration>;
5
6
  reportConduitState: (state: ConduitState) => Promise<void>;
6
7
  reportMachineMetadata: (payload: InferenceAgentMachineReportPayload) => Promise<void>;
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ const __dirname = __pathDirname(__filename);
6
6
 
7
7
  import { parseArgs } from 'node:util';
8
8
  import 'node:crypto';
9
- import { a as asError, s as startInferenceAgent } from './start-D4bpW8Ix.js';
9
+ import { a as asError, s as startInferenceAgent } from './start-DtAR3bT0.js';
10
10
  import 'argon2';
11
11
  import 'node:child_process';
12
12
  import 'node:stream';
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ const __filename = __fileURLToPath(import.meta.url);
5
5
  const __dirname = __pathDirname(__filename);
6
6
 
7
7
  import 'node:crypto';
8
- import { s as startInferenceAgent, a as asError } from './start-D4bpW8Ix.js';
8
+ import { s as startInferenceAgent, a as asError } from './start-DtAR3bT0.js';
9
9
  import 'argon2';
10
10
  import 'node:child_process';
11
11
  import 'node:stream';
@@ -14932,6 +14932,22 @@ const API_SERVICE_CONDUIT_API_REFERENCE = {
14932
14932
  }
14933
14933
  }
14934
14934
  },
14935
+ "/conduit/api/v1/source/:sourceID/engine/cycle": {
14936
+ POST: {
14937
+ auth: {
14938
+ type: "api-key"
14939
+ },
14940
+ parameters: {
14941
+ sourceID: ULIDSchema
14942
+ },
14943
+ response: {
14944
+ schema: object({
14945
+ acknowledged: literal(true)
14946
+ }),
14947
+ type: "rest"
14948
+ }
14949
+ }
14950
+ },
14935
14951
  "/conduit/api/v1/source/:sourceID/requests/:requestID/chunk": {
14936
14952
  POST: {
14937
14953
  auth: {
@@ -15237,6 +15253,19 @@ const API_CLIENT_CONDUIT_GENERAL_REFERENCE = {
15237
15253
  type: "rest"
15238
15254
  }
15239
15255
  }
15256
+ },
15257
+ "/conduit/engine/cycle": {
15258
+ POST: {
15259
+ auth: {
15260
+ type: "none"
15261
+ },
15262
+ response: {
15263
+ schema: object({
15264
+ acknowledged: literal(true)
15265
+ }),
15266
+ type: "rest"
15267
+ }
15268
+ }
15240
15269
  }
15241
15270
  };
15242
15271
  const API_CLIENT_CONDUIT_OPENAI_REFERENCE = {
@@ -15301,6 +15330,32 @@ object({
15301
15330
  email: string$1().email(),
15302
15331
  password: RawPasswordForLoginSchema
15303
15332
  });
15333
+ object({
15334
+ ok: literal(true)
15335
+ })
15336
+ .or(object({
15337
+ ok: literal(false),
15338
+ requiresPasswordChange: literal(false)
15339
+ }))
15340
+ .or(object({
15341
+ ok: literal(false),
15342
+ requiresPasswordChange: literal(true)
15343
+ }));
15344
+ object({
15345
+ accountID: ULIDSchema.optional(),
15346
+ currentPassword: RawPasswordForLoginSchema,
15347
+ email: string$1().email(),
15348
+ newPassword: RawPasswordSchema,
15349
+ newPasswordConfirm: RawPasswordSchema
15350
+ })
15351
+ .refine(data => data.newPassword === data.newPasswordConfirm, {
15352
+ message: "New passwords do not match",
15353
+ path: ["newPasswordConfirm"]
15354
+ })
15355
+ .refine(data => data.newPassword !== data.currentPassword, {
15356
+ message: "New password must differ from current password",
15357
+ path: ["newPassword"]
15358
+ });
15304
15359
  object({
15305
15360
  ok: literal(true)
15306
15361
  })
@@ -98187,6 +98242,18 @@ function createAPIClient({ apiKey, apiURL, inferenceSourceID, logger }) {
98187
98242
  });
98188
98243
  return result.configuration;
98189
98244
  },
98245
+ cycleInferenceSourceEngine: async () => {
98246
+ await fetchByReference({
98247
+ baseURL: apiURL,
98248
+ fetch: fetchWithAPIKey,
98249
+ method: "POST",
98250
+ parameters: {
98251
+ sourceID: inferenceSourceID
98252
+ },
98253
+ reference: API_SERVICE_CONDUIT_API_REFERENCE,
98254
+ route: "/conduit/api/v1/source/:sourceID/engine/cycle"
98255
+ });
98256
+ },
98190
98257
  reportMachineMetadata: async (payload) => {
98191
98258
  await fetchByReference({
98192
98259
  baseURL: apiURL,
@@ -118895,7 +118962,7 @@ async function proxyOpenAIStreamingRoute({ body, configuration, logger, modelID,
118895
118962
  async function createApplication({ abortController, apiClient, configuration, logger }) {
118896
118963
  // Fetch configuration
118897
118964
  logger.info("Fetching conduit configuration");
118898
- const conduitConfiguration = await apiClient.getConduitConfiguration();
118965
+ let conduitConfiguration = await apiClient.getConduitConfiguration();
118899
118966
  logger.info("Received configuration", {
118900
118967
  modelID: conduitConfiguration.targetModel.id
118901
118968
  });
@@ -118916,11 +118983,11 @@ async function createApplication({ abortController, apiClient, configuration, lo
118916
118983
  state: "initialising"
118917
118984
  }
118918
118985
  });
118919
- const modelFileName = getConduitModelFileName(conduitConfiguration);
118920
- const modelName = getConduitModelName(conduitConfiguration);
118986
+ let modelFileName = getConduitModelFileName(conduitConfiguration);
118987
+ let modelName = getConduitModelName(conduitConfiguration);
118921
118988
  const startup = Date.now();
118922
118989
  // Initialise model manager
118923
- const modelManager = new ModelManager({
118990
+ let modelManager = new ModelManager({
118924
118991
  contextLength: conduitConfiguration.contextLength ?? null,
118925
118992
  engine: configuration.agentEngineType,
118926
118993
  logger,
@@ -118960,6 +119027,30 @@ async function createApplication({ abortController, apiClient, configuration, lo
118960
119027
  });
118961
119028
  conduitStateReportManager.reportStateChange();
118962
119029
  };
119030
+ const attachLifecycleListeners = () => {
119031
+ modelManager.on("engineError", err => {
119032
+ logger.error("LLM engine error", {
119033
+ error: err
119034
+ });
119035
+ stopRequestedByControl = false;
119036
+ setErrorState({ error: err.message });
119037
+ });
119038
+ modelManager.on("engineTerminated", () => {
119039
+ if (stopRequestedByControl) {
119040
+ stopRequestedByControl = false;
119041
+ setIdleState({ reason: "Remote shutdown requested" });
119042
+ return;
119043
+ }
119044
+ conduitStateManager.setState({
119045
+ state: "offline"
119046
+ });
119047
+ conduitStateReportManager.reportStateChange();
119048
+ });
119049
+ modelManager.on("engineReady", () => {
119050
+ setOnlineState();
119051
+ });
119052
+ };
119053
+ attachLifecycleListeners();
118963
119054
  let lastDownloadKey = "";
118964
119055
  const reportDownloadProgress = (update) => {
118965
119056
  const filePercent = update.file.total > 0 ? Math.floor((update.file.bytes / update.file.total) * 100) : 0;
@@ -119143,6 +119234,74 @@ async function createApplication({ abortController, apiClient, configuration, lo
119143
119234
  };
119144
119235
  }
119145
119236
  }
119237
+ },
119238
+ "/conduit/engine/cycle": {
119239
+ POST: async ({ body }) => {
119240
+ const sourceState = conduitStateManager.getState().state;
119241
+ if (sourceState !== "bootingEngine" &&
119242
+ sourceState !== "online" &&
119243
+ sourceState !== "idle") {
119244
+ return {
119245
+ status: 409,
119246
+ statusText: "Engine can only be cycled while booting, online, or idle"
119247
+ };
119248
+ }
119249
+ if (sourceState !== "idle" && !modelManager.canStop) {
119250
+ return {
119251
+ status: 409,
119252
+ statusText: `Engine cannot be cycled from current state: ${modelManager.state}`
119253
+ };
119254
+ }
119255
+ try {
119256
+ logger.info("Received remote engine cycle request");
119257
+ const sourceState = conduitStateManager.getState().state;
119258
+ if (sourceState !== "idle") {
119259
+ await stopEngine({
119260
+ reason: "Remote cycle requested"
119261
+ });
119262
+ }
119263
+ logger.info("Fetching new configuration");
119264
+ const newConduitConfiguration = await apiClient.getConduitConfiguration();
119265
+ logger.info("Received new configuration", {
119266
+ modelID: newConduitConfiguration.targetModel.id
119267
+ });
119268
+ logger.info("Updating configuration and model manager");
119269
+ conduitConfiguration = newConduitConfiguration;
119270
+ modelFileName = getConduitModelFileName(conduitConfiguration);
119271
+ modelName = getConduitModelName(conduitConfiguration);
119272
+ modelManager = new ModelManager({
119273
+ contextLength: conduitConfiguration.contextLength ?? null,
119274
+ engine: configuration.agentEngineType,
119275
+ logger,
119276
+ model: conduitConfiguration.targetModel,
119277
+ parallelism: conduitConfiguration.parallelism ?? null,
119278
+ root: configuration.rootDirectory
119279
+ });
119280
+ attachLifecycleListeners();
119281
+ if (sourceState === "idle") {
119282
+ logger.info("Restarting engine from idle");
119283
+ await startEngine();
119284
+ }
119285
+ else {
119286
+ logger.info("Restarting engine");
119287
+ await startEngine();
119288
+ }
119289
+ return {
119290
+ body: {
119291
+ acknowledged: true
119292
+ },
119293
+ status: 202
119294
+ };
119295
+ }
119296
+ catch (error) {
119297
+ const parsedError = asError(error);
119298
+ setErrorState({ error: parsedError.message });
119299
+ return {
119300
+ status: 500,
119301
+ statusText: parsedError.message
119302
+ };
119303
+ }
119304
+ }
119146
119305
  }
119147
119306
  },
119148
119307
  logger,
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.26.5",
4
+ "version": "1.28.0",
5
5
  "bin": {
6
6
  "infersec-conduit": "./dist/cli.js"
7
7
  },