@infersec/conduit 1.8.0 → 1.8.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
|
@@ -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-
|
|
9
|
+
import { a as asError, s as startInferenceAgent } from './start-LWLy96m_.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-
|
|
8
|
+
import { s as startInferenceAgent, a as asError } from './start-LWLy96m_.js';
|
|
9
9
|
import 'argon2';
|
|
10
10
|
import 'node:child_process';
|
|
11
11
|
import 'node:stream';
|
|
@@ -30,5 +30,7 @@ export declare class ModelManager extends EventEmitter<ModelManagerEvents> {
|
|
|
30
30
|
onDownloadProgress?: (update: ModelDownloadProgressUpdate) => void;
|
|
31
31
|
}): Promise<void>;
|
|
32
32
|
start(): Promise<void>;
|
|
33
|
+
private isEngineReady;
|
|
34
|
+
private waitForEngineReady;
|
|
33
35
|
}
|
|
34
36
|
export {};
|
package/dist/sse/handler.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
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, configuration, logger, onRequest, onRequestEnd, onRequestStart }: {
|
|
4
|
+
export declare function handleSSERequests({ apiURL, configuration, logger, onRequest, onRequestEnd, onRequestStart, signal }: {
|
|
5
5
|
apiURL: string;
|
|
6
6
|
configuration: Configuration;
|
|
7
7
|
logger: Logger;
|
|
8
8
|
onRequest: (request: ServerToClientAPIRequest) => Promise<APIResponse>;
|
|
9
9
|
onRequestEnd?: (request: ServerToClientAPIRequest) => Promise<void> | void;
|
|
10
10
|
onRequestStart?: (request: ServerToClientAPIRequest) => Promise<void> | void;
|
|
11
|
+
signal?: AbortSignal;
|
|
11
12
|
}): Promise<void>;
|
|
@@ -105091,42 +105091,112 @@ class ModelManager extends EventEmitter {
|
|
|
105091
105091
|
this.logger.info("Started LLM engine", {
|
|
105092
105092
|
agentEngineType: this.engine
|
|
105093
105093
|
});
|
|
105094
|
+
try {
|
|
105095
|
+
await this.waitForEngineReady();
|
|
105096
|
+
}
|
|
105097
|
+
catch (error) {
|
|
105098
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
105099
|
+
this.emit("engineError", err);
|
|
105100
|
+
throw err;
|
|
105101
|
+
}
|
|
105094
105102
|
this.emit("engineReady");
|
|
105095
105103
|
}
|
|
105104
|
+
async isEngineReady() {
|
|
105105
|
+
switch (this.engine) {
|
|
105106
|
+
case "llama.cpp":
|
|
105107
|
+
case "vllm": {
|
|
105108
|
+
try {
|
|
105109
|
+
const response = await this.fetchOpenAI("/v1/models", {
|
|
105110
|
+
method: "GET",
|
|
105111
|
+
signal: AbortSignal.timeout(5000)
|
|
105112
|
+
});
|
|
105113
|
+
return response.ok;
|
|
105114
|
+
}
|
|
105115
|
+
catch (_error) {
|
|
105116
|
+
return false;
|
|
105117
|
+
}
|
|
105118
|
+
}
|
|
105119
|
+
default:
|
|
105120
|
+
return true;
|
|
105121
|
+
}
|
|
105122
|
+
}
|
|
105123
|
+
async waitForEngineReady() {
|
|
105124
|
+
const maxWaitMs = 5 * 60 * 1000;
|
|
105125
|
+
const pollIntervalMs = 2000;
|
|
105126
|
+
const start = Date.now();
|
|
105127
|
+
while (Date.now() - start < maxWaitMs) {
|
|
105128
|
+
const ready = await this.isEngineReady();
|
|
105129
|
+
if (ready) {
|
|
105130
|
+
return;
|
|
105131
|
+
}
|
|
105132
|
+
await new Promise(resolve => setTimeout(resolve, pollIntervalMs));
|
|
105133
|
+
}
|
|
105134
|
+
throw new Error("LLM engine failed readiness checks within timeout");
|
|
105135
|
+
}
|
|
105136
|
+
}
|
|
105137
|
+
|
|
105138
|
+
function sleep(ms) {
|
|
105139
|
+
return new Promise(resolve => {
|
|
105140
|
+
setTimeout(() => resolve(), ms);
|
|
105141
|
+
});
|
|
105096
105142
|
}
|
|
105097
105143
|
|
|
105098
|
-
async function handleSSERequests({ apiURL, configuration, logger, onRequest, onRequestEnd, onRequestStart }) {
|
|
105144
|
+
async function handleSSERequests({ apiURL, configuration, logger, onRequest, onRequestEnd, onRequestStart, signal }) {
|
|
105099
105145
|
const streamURL = `${apiURL}/conduit/api/v1/source/${configuration.inferenceSourceID}/requests/stream`;
|
|
105100
|
-
|
|
105101
|
-
|
|
105102
|
-
|
|
105103
|
-
|
|
105104
|
-
|
|
105105
|
-
|
|
105106
|
-
|
|
105146
|
+
const maxReconnectDelayMs = 30000;
|
|
105147
|
+
let reconnectAttempt = 0;
|
|
105148
|
+
while (!signal?.aborted) {
|
|
105149
|
+
const connectionStartedAt = Date.now();
|
|
105150
|
+
try {
|
|
105151
|
+
await connectSSE(streamURL, {
|
|
105152
|
+
headers: {
|
|
105153
|
+
"x-api-key": configuration.apiKey
|
|
105154
|
+
},
|
|
105155
|
+
onError: (error) => {
|
|
105156
|
+
logger.error("SSE connection error", {
|
|
105157
|
+
error
|
|
105158
|
+
});
|
|
105159
|
+
},
|
|
105160
|
+
onMessage: (message) => {
|
|
105161
|
+
if (message.event !== "request") {
|
|
105162
|
+
return;
|
|
105163
|
+
}
|
|
105164
|
+
const payload = ServerToClientAPIRequestSchema.parse(JSON.parse(message.data));
|
|
105165
|
+
handleRequest({
|
|
105166
|
+
apiURL,
|
|
105167
|
+
configuration,
|
|
105168
|
+
logger,
|
|
105169
|
+
onRequest,
|
|
105170
|
+
onRequestEnd,
|
|
105171
|
+
onRequestStart,
|
|
105172
|
+
request: payload
|
|
105173
|
+
}).catch(error => {
|
|
105174
|
+
logger.error("SSE request handler failed", {
|
|
105175
|
+
error: asError(error),
|
|
105176
|
+
requestMethod: payload.requestID
|
|
105177
|
+
});
|
|
105178
|
+
});
|
|
105179
|
+
},
|
|
105180
|
+
signal
|
|
105107
105181
|
});
|
|
105108
|
-
}
|
|
105109
|
-
|
|
105110
|
-
if (
|
|
105182
|
+
}
|
|
105183
|
+
catch (error) {
|
|
105184
|
+
if (signal?.aborted) {
|
|
105111
105185
|
return;
|
|
105112
105186
|
}
|
|
105113
|
-
|
|
105114
|
-
|
|
105115
|
-
apiURL,
|
|
105116
|
-
configuration,
|
|
105117
|
-
logger,
|
|
105118
|
-
onRequestEnd,
|
|
105119
|
-
onRequestStart,
|
|
105120
|
-
onRequest,
|
|
105121
|
-
request: payload
|
|
105122
|
-
}).catch(error => {
|
|
105123
|
-
logger.error("SSE request handler failed", {
|
|
105124
|
-
error: asError(error),
|
|
105125
|
-
requestMethod: payload.requestID
|
|
105126
|
-
});
|
|
105187
|
+
logger.error("SSE connection failed", {
|
|
105188
|
+
error: asError(error)
|
|
105127
105189
|
});
|
|
105128
105190
|
}
|
|
105129
|
-
|
|
105191
|
+
if (signal?.aborted) {
|
|
105192
|
+
return;
|
|
105193
|
+
}
|
|
105194
|
+
const connectionDurationMs = Date.now() - connectionStartedAt;
|
|
105195
|
+
reconnectAttempt = connectionDurationMs > 10000 ? 0 : reconnectAttempt + 1;
|
|
105196
|
+
const reconnectDelayMs = Math.min(maxReconnectDelayMs, Math.max(1000, 1000 * 2 ** Math.min(6, reconnectAttempt)));
|
|
105197
|
+
logger.warn("SSE disconnected, retrying");
|
|
105198
|
+
await sleep(reconnectDelayMs);
|
|
105199
|
+
}
|
|
105130
105200
|
}
|
|
105131
105201
|
async function handleRequest({ apiURL, configuration, logger, onRequest, onRequestEnd, onRequestStart, request }) {
|
|
105132
105202
|
try {
|
|
@@ -114784,7 +114854,6 @@ async function createApplication({ abortController, apiClient, configuration, lo
|
|
|
114784
114854
|
});
|
|
114785
114855
|
const modelFileName = getConduitModelFileName(conduitConfiguration);
|
|
114786
114856
|
const modelName = getConduitModelName(conduitConfiguration);
|
|
114787
|
-
const idleReason = "Awaiting requests";
|
|
114788
114857
|
const startup = Date.now();
|
|
114789
114858
|
// Initialise model manager
|
|
114790
114859
|
const modelManager = new ModelManager({
|
|
@@ -114795,28 +114864,6 @@ async function createApplication({ abortController, apiClient, configuration, lo
|
|
|
114795
114864
|
parallelism: conduitConfiguration.parallelism ?? null,
|
|
114796
114865
|
root: configuration.rootDirectory
|
|
114797
114866
|
});
|
|
114798
|
-
modelManager.on("engineError", err => {
|
|
114799
|
-
logger.error("LLM engine error", {
|
|
114800
|
-
error: err
|
|
114801
|
-
});
|
|
114802
|
-
conduitStateManager.setState({
|
|
114803
|
-
error: err.message,
|
|
114804
|
-
state: "error"
|
|
114805
|
-
});
|
|
114806
|
-
abortController.abort(err);
|
|
114807
|
-
});
|
|
114808
|
-
modelManager.on("engineTerminated", () => {
|
|
114809
|
-
conduitStateManager.setState({
|
|
114810
|
-
state: "offline"
|
|
114811
|
-
});
|
|
114812
|
-
abortController.abort();
|
|
114813
|
-
});
|
|
114814
|
-
modelManager.on("engineReady", () => {
|
|
114815
|
-
conduitStateManager.setState({
|
|
114816
|
-
reason: idleReason,
|
|
114817
|
-
state: "idle"
|
|
114818
|
-
});
|
|
114819
|
-
});
|
|
114820
114867
|
conduitStateManager.setState({
|
|
114821
114868
|
modelFileName,
|
|
114822
114869
|
modelName,
|
|
@@ -114931,40 +114978,54 @@ async function createApplication({ abortController, apiClient, configuration, lo
|
|
|
114931
114978
|
});
|
|
114932
114979
|
}, CONDUIT_STATE_INTERVAL_MS);
|
|
114933
114980
|
let activeRequests = 0;
|
|
114934
|
-
const setIdleState = () => {
|
|
114935
|
-
conduitStateManager.setState({
|
|
114936
|
-
reason: idleReason,
|
|
114937
|
-
state: "idle"
|
|
114938
|
-
});
|
|
114939
|
-
};
|
|
114940
114981
|
const setOnlineState = () => {
|
|
114941
114982
|
conduitStateManager.setState({
|
|
114942
114983
|
modelName,
|
|
114943
114984
|
state: "online"
|
|
114944
114985
|
});
|
|
114945
114986
|
};
|
|
114987
|
+
modelManager.on("engineError", err => {
|
|
114988
|
+
logger.error("LLM engine error", {
|
|
114989
|
+
error: err
|
|
114990
|
+
});
|
|
114991
|
+
conduitStateManager.setState({
|
|
114992
|
+
error: err.message,
|
|
114993
|
+
state: "error"
|
|
114994
|
+
});
|
|
114995
|
+
abortController.abort(err);
|
|
114996
|
+
});
|
|
114997
|
+
modelManager.on("engineTerminated", () => {
|
|
114998
|
+
conduitStateManager.setState({
|
|
114999
|
+
state: "offline"
|
|
115000
|
+
});
|
|
115001
|
+
abortController.abort();
|
|
115002
|
+
});
|
|
115003
|
+
modelManager.on("engineReady", () => {
|
|
115004
|
+
setOnlineState();
|
|
115005
|
+
});
|
|
114946
115006
|
handleSSERequests({
|
|
114947
115007
|
apiURL: configuration.apiURL,
|
|
114948
115008
|
configuration,
|
|
114949
115009
|
logger,
|
|
114950
|
-
onRequestEnd: () => {
|
|
114951
|
-
activeRequests = Math.max(0, activeRequests - 1);
|
|
114952
|
-
if (activeRequests === 0) {
|
|
114953
|
-
setIdleState();
|
|
114954
|
-
}
|
|
114955
|
-
},
|
|
114956
115010
|
onRequest: async (request) => {
|
|
114957
115011
|
return proxyRequest({
|
|
114958
115012
|
configuration,
|
|
114959
115013
|
request
|
|
114960
115014
|
});
|
|
114961
115015
|
},
|
|
115016
|
+
onRequestEnd: () => {
|
|
115017
|
+
activeRequests = Math.max(0, activeRequests - 1);
|
|
115018
|
+
if (activeRequests === 0) {
|
|
115019
|
+
setOnlineState();
|
|
115020
|
+
}
|
|
115021
|
+
},
|
|
114962
115022
|
onRequestStart: () => {
|
|
114963
115023
|
activeRequests += 1;
|
|
114964
115024
|
if (activeRequests === 1) {
|
|
114965
115025
|
setOnlineState();
|
|
114966
115026
|
}
|
|
114967
|
-
}
|
|
115027
|
+
},
|
|
115028
|
+
signal: abortController.signal
|
|
114968
115029
|
}).catch(error => {
|
|
114969
115030
|
logger.error("SSE handler failed", {
|
|
114970
115031
|
error: asError(error)
|
|
@@ -115004,12 +115065,6 @@ function getConfiguration({ overrides } = {}) {
|
|
|
115004
115065
|
};
|
|
115005
115066
|
}
|
|
115006
115067
|
|
|
115007
|
-
function sleep(ms) {
|
|
115008
|
-
return new Promise(resolve => {
|
|
115009
|
-
setTimeout(() => resolve(), ms);
|
|
115010
|
-
});
|
|
115011
|
-
}
|
|
115012
|
-
|
|
115013
115068
|
async function startInferenceAgent({ configurationOverrides }) {
|
|
115014
115069
|
const abortController = new AbortController();
|
|
115015
115070
|
const configuration = getConfiguration({ overrides: configurationOverrides });
|