@infersec/conduit 1.26.1 → 1.26.3
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/apiClient/index.d.ts +3 -1
- package/dist/cli.js +2 -2
- package/dist/index.js +2 -2
- package/dist/{start-PzV0cQI5.js → start-D4bpW8Ix.js} +140 -10
- package/dist/utils/network.d.ts +8 -0
- package/package.json +1 -1
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { InferenceAgentConfiguration, InferenceAgentLLMMetricsPayload, InferenceAgentMachineReportPayload, ULID, type ConduitState } from "@infersec/definitions";
|
|
2
|
+
import { Logger } from "@infersec/logger";
|
|
2
3
|
export interface APIClient {
|
|
3
4
|
getConduitConfiguration: () => Promise<InferenceAgentConfiguration>;
|
|
4
5
|
reportConduitState: (state: ConduitState) => Promise<void>;
|
|
5
6
|
reportMachineMetadata: (payload: InferenceAgentMachineReportPayload) => Promise<void>;
|
|
6
7
|
reportPromptMetrics: (payload: InferenceAgentLLMMetricsPayload) => Promise<void>;
|
|
7
8
|
}
|
|
8
|
-
export declare function createAPIClient({ apiKey, apiURL, inferenceSourceID }: {
|
|
9
|
+
export declare function createAPIClient({ apiKey, apiURL, inferenceSourceID, logger }: {
|
|
9
10
|
apiKey: string;
|
|
10
11
|
apiURL: string;
|
|
11
12
|
inferenceSourceID: ULID;
|
|
13
|
+
logger: Logger;
|
|
12
14
|
}): APIClient;
|
package/dist/cli.js
CHANGED
|
@@ -6,10 +6,11 @@ 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-D4bpW8Ix.js';
|
|
10
10
|
import 'argon2';
|
|
11
11
|
import 'node:child_process';
|
|
12
12
|
import 'node:stream';
|
|
13
|
+
import 'node:dns';
|
|
13
14
|
import 'os';
|
|
14
15
|
import 'fs';
|
|
15
16
|
import 'util';
|
|
@@ -34,7 +35,6 @@ import 'node:console';
|
|
|
34
35
|
import 'node:fs/promises';
|
|
35
36
|
import 'node:path';
|
|
36
37
|
import 'node:timers';
|
|
37
|
-
import 'node:dns';
|
|
38
38
|
import 'path';
|
|
39
39
|
import 'tty';
|
|
40
40
|
import 'net';
|
package/dist/index.js
CHANGED
|
@@ -5,10 +5,11 @@ 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-D4bpW8Ix.js';
|
|
9
9
|
import 'argon2';
|
|
10
10
|
import 'node:child_process';
|
|
11
11
|
import 'node:stream';
|
|
12
|
+
import 'node:dns';
|
|
12
13
|
import 'os';
|
|
13
14
|
import 'fs';
|
|
14
15
|
import 'util';
|
|
@@ -34,7 +35,6 @@ import 'node:console';
|
|
|
34
35
|
import 'node:fs/promises';
|
|
35
36
|
import 'node:path';
|
|
36
37
|
import 'node:timers';
|
|
37
|
-
import 'node:dns';
|
|
38
38
|
import 'path';
|
|
39
39
|
import 'tty';
|
|
40
40
|
import 'net';
|
|
@@ -4,6 +4,7 @@ import { dirname as __pathDirname } from 'node:path';
|
|
|
4
4
|
const __filename = __fileURLToPath(import.meta.url);
|
|
5
5
|
const __dirname = __pathDirname(__filename);
|
|
6
6
|
|
|
7
|
+
import require$$1$6, { setDefaultResultOrder } from 'node:dns';
|
|
7
8
|
import require$$0$5 from 'os';
|
|
8
9
|
import require$$1$2, { realpathSync as realpathSync$1, readlinkSync, readdirSync, readdir as readdir$1, lstatSync } from 'fs';
|
|
9
10
|
import require$$2$2 from 'util';
|
|
@@ -33,7 +34,6 @@ import require$$1$5 from 'node:console';
|
|
|
33
34
|
import require$$0$b, { mkdir, readFile, writeFile, stat, unlink, rename, realpath, readlink, readdir, lstat } from 'node:fs/promises';
|
|
34
35
|
import path$1, { join, dirname, win32, posix } from 'node:path';
|
|
35
36
|
import require$$2$5 from 'node:timers';
|
|
36
|
-
import require$$1$6 from 'node:dns';
|
|
37
37
|
import require$$0$c from 'path';
|
|
38
38
|
import require$$0$d from 'tty';
|
|
39
39
|
import require$$4$3 from 'net';
|
|
@@ -98039,8 +98039,136 @@ function implementAPIReference({ api, logger, mount, reference }) {
|
|
|
98039
98039
|
}
|
|
98040
98040
|
}
|
|
98041
98041
|
|
|
98042
|
-
function
|
|
98042
|
+
function sleep(ms) {
|
|
98043
|
+
return new Promise(resolve => {
|
|
98044
|
+
setTimeout(() => resolve(), ms);
|
|
98045
|
+
});
|
|
98046
|
+
}
|
|
98047
|
+
|
|
98048
|
+
async function fetchWithRetry(input, init, { baseDelayMs = 250, maxAttempts = 4, maxDelayMs = 2000, signal, timeoutMs = 10000 } = {}) {
|
|
98049
|
+
let lastError = null;
|
|
98050
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
98051
|
+
if (signal?.aborted) {
|
|
98052
|
+
throw asError(signal.reason);
|
|
98053
|
+
}
|
|
98054
|
+
const attemptController = new AbortController();
|
|
98055
|
+
const timeout = setTimeout(() => {
|
|
98056
|
+
attemptController.abort(new Error(`Request timeout (${timeoutMs}ms)`));
|
|
98057
|
+
}, timeoutMs);
|
|
98058
|
+
const composedSignal = composeAbortSignals({
|
|
98059
|
+
primary: signal,
|
|
98060
|
+
secondary: attemptController.signal
|
|
98061
|
+
});
|
|
98062
|
+
try {
|
|
98063
|
+
return await fetch(input, {
|
|
98064
|
+
...init,
|
|
98065
|
+
signal: composedSignal
|
|
98066
|
+
});
|
|
98067
|
+
}
|
|
98068
|
+
catch (error) {
|
|
98069
|
+
const parsedError = asError(error);
|
|
98070
|
+
lastError = parsedError;
|
|
98071
|
+
if (!isRetryableNetworkError(parsedError) || attempt >= maxAttempts) {
|
|
98072
|
+
throw parsedError;
|
|
98073
|
+
}
|
|
98074
|
+
const delayMs = Math.min(maxDelayMs, baseDelayMs * 2 ** (attempt - 1));
|
|
98075
|
+
const jitterMs = Math.floor(Math.random() * 100);
|
|
98076
|
+
await sleep(delayMs + jitterMs);
|
|
98077
|
+
}
|
|
98078
|
+
finally {
|
|
98079
|
+
clearTimeout(timeout);
|
|
98080
|
+
}
|
|
98081
|
+
}
|
|
98082
|
+
throw lastError ?? new Error("Request failed");
|
|
98083
|
+
}
|
|
98084
|
+
function getNetworkErrorAttributes(error) {
|
|
98085
|
+
const parsedError = asError(error);
|
|
98086
|
+
const attributes = {};
|
|
98087
|
+
let cursor = parsedError;
|
|
98088
|
+
let depth = 0;
|
|
98089
|
+
while (cursor && depth < 3) {
|
|
98090
|
+
const networkCursor = cursor;
|
|
98091
|
+
if (depth === 0) {
|
|
98092
|
+
attributes.errorMessage = cursor.message;
|
|
98093
|
+
attributes.errorName = cursor.name;
|
|
98094
|
+
}
|
|
98095
|
+
const prefix = depth === 0 ? "error" : `cause${String(depth)}`;
|
|
98096
|
+
if (typeof networkCursor.code === "string") {
|
|
98097
|
+
attributes[`${prefix}Code`] = networkCursor.code;
|
|
98098
|
+
}
|
|
98099
|
+
if (typeof networkCursor.errno === "string" || typeof networkCursor.errno === "number") {
|
|
98100
|
+
attributes[`${prefix}Errno`] = networkCursor.errno;
|
|
98101
|
+
}
|
|
98102
|
+
if (typeof networkCursor.syscall === "string") {
|
|
98103
|
+
attributes[`${prefix}Syscall`] = networkCursor.syscall;
|
|
98104
|
+
}
|
|
98105
|
+
if (typeof networkCursor.address === "string") {
|
|
98106
|
+
attributes[`${prefix}Address`] = networkCursor.address;
|
|
98107
|
+
}
|
|
98108
|
+
if (typeof networkCursor.port === "number") {
|
|
98109
|
+
attributes[`${prefix}Port`] = networkCursor.port;
|
|
98110
|
+
}
|
|
98111
|
+
cursor = cursor.cause instanceof Error ? cursor.cause : undefined;
|
|
98112
|
+
depth += 1;
|
|
98113
|
+
}
|
|
98114
|
+
return attributes;
|
|
98115
|
+
}
|
|
98116
|
+
function composeAbortSignals({ primary, secondary }) {
|
|
98117
|
+
if (!primary) {
|
|
98118
|
+
return secondary;
|
|
98119
|
+
}
|
|
98120
|
+
if (primary.aborted) {
|
|
98121
|
+
return primary;
|
|
98122
|
+
}
|
|
98123
|
+
const composedController = new AbortController();
|
|
98124
|
+
const abort = (reason) => {
|
|
98125
|
+
if (!composedController.signal.aborted) {
|
|
98126
|
+
composedController.abort(reason);
|
|
98127
|
+
}
|
|
98128
|
+
};
|
|
98129
|
+
const primaryListener = () => {
|
|
98130
|
+
abort(primary.reason);
|
|
98131
|
+
};
|
|
98132
|
+
const secondaryListener = () => {
|
|
98133
|
+
abort(secondary.reason);
|
|
98134
|
+
};
|
|
98135
|
+
primary.addEventListener("abort", primaryListener, { once: true });
|
|
98136
|
+
secondary.addEventListener("abort", secondaryListener, { once: true });
|
|
98137
|
+
return composedController.signal;
|
|
98138
|
+
}
|
|
98139
|
+
function isRetryableNetworkError(error) {
|
|
98140
|
+
if (error.name === "AbortError") {
|
|
98141
|
+
return true;
|
|
98142
|
+
}
|
|
98143
|
+
const message = error.message.toLowerCase();
|
|
98144
|
+
if (message.includes("fetch failed") || message.includes("timeout")) {
|
|
98145
|
+
return true;
|
|
98146
|
+
}
|
|
98147
|
+
const errorCode = error.code;
|
|
98148
|
+
return (errorCode === "ECONNRESET" ||
|
|
98149
|
+
errorCode === "ECONNREFUSED" ||
|
|
98150
|
+
errorCode === "ETIMEDOUT" ||
|
|
98151
|
+
errorCode === "EHOSTUNREACH" ||
|
|
98152
|
+
errorCode === "ENETUNREACH" ||
|
|
98153
|
+
errorCode === "ENOTFOUND" ||
|
|
98154
|
+
errorCode === "EAI_AGAIN");
|
|
98155
|
+
}
|
|
98156
|
+
|
|
98157
|
+
function createAPIClient({ apiKey, apiURL, inferenceSourceID, logger }) {
|
|
98158
|
+
async function retryingFetch(input, init) {
|
|
98159
|
+
try {
|
|
98160
|
+
return await fetchWithRetry(input, init, {
|
|
98161
|
+
maxAttempts: 4,
|
|
98162
|
+
timeoutMs: 10000
|
|
98163
|
+
});
|
|
98164
|
+
}
|
|
98165
|
+
catch (error) {
|
|
98166
|
+
logger.warn("API request failed after retries", getNetworkErrorAttributes(error));
|
|
98167
|
+
throw error;
|
|
98168
|
+
}
|
|
98169
|
+
}
|
|
98043
98170
|
const fetchWithAPIKey = createFetchWithHeaders({
|
|
98171
|
+
fetchFn: retryingFetch,
|
|
98044
98172
|
headers: {
|
|
98045
98173
|
"x-api-key": apiKey
|
|
98046
98174
|
}
|
|
@@ -108454,12 +108582,6 @@ class ModelManager extends EventEmitter {
|
|
|
108454
108582
|
}
|
|
108455
108583
|
}
|
|
108456
108584
|
|
|
108457
|
-
function sleep(ms) {
|
|
108458
|
-
return new Promise(resolve => {
|
|
108459
|
-
setTimeout(() => resolve(), ms);
|
|
108460
|
-
});
|
|
108461
|
-
}
|
|
108462
|
-
|
|
108463
108585
|
async function handleSSERequests({ apiURL, configuration, logger, modelID, onRequest, onRequestEnd, onRequestStart, reportMetrics, signal }) {
|
|
108464
108586
|
const streamURL = `${apiURL}/conduit/api/v1/source/${configuration.inferenceSourceID}/requests/stream`;
|
|
108465
108587
|
const maxReconnectDelayMs = 30000;
|
|
@@ -108509,6 +108631,7 @@ async function handleSSERequests({ apiURL, configuration, logger, modelID, onReq
|
|
|
108509
108631
|
const isTerminated = isTerminatedError(error);
|
|
108510
108632
|
if (!isTerminated) {
|
|
108511
108633
|
logger.error("SSE connection failed", {
|
|
108634
|
+
...getNetworkErrorAttributes(error),
|
|
108512
108635
|
error: asError(error)
|
|
108513
108636
|
});
|
|
108514
108637
|
}
|
|
@@ -108736,7 +108859,7 @@ async function sendChunkStream({ apiURL, configuration, requestID, logger }) {
|
|
|
108736
108859
|
for (let attempt = 1; attempt <= maxFlushAttempts; attempt += 1) {
|
|
108737
108860
|
try {
|
|
108738
108861
|
activeAbortController = new AbortController();
|
|
108739
|
-
const response = await
|
|
108862
|
+
const response = await fetchWithRetry(streamURL, {
|
|
108740
108863
|
body: body.toString(),
|
|
108741
108864
|
headers: {
|
|
108742
108865
|
"content-type": "application/json",
|
|
@@ -108744,6 +108867,9 @@ async function sendChunkStream({ apiURL, configuration, requestID, logger }) {
|
|
|
108744
108867
|
},
|
|
108745
108868
|
method: "POST",
|
|
108746
108869
|
signal: activeAbortController.signal
|
|
108870
|
+
}, {
|
|
108871
|
+
maxAttempts: 2,
|
|
108872
|
+
timeoutMs: 15000
|
|
108747
108873
|
});
|
|
108748
108874
|
if (!response.ok) {
|
|
108749
108875
|
throw new Error(`Chunk stream flush failed with status ${response.status}`);
|
|
@@ -108759,6 +108885,7 @@ async function sendChunkStream({ apiURL, configuration, requestID, logger }) {
|
|
|
108759
108885
|
throw asError(error);
|
|
108760
108886
|
}
|
|
108761
108887
|
logger.warn("Failed to send chunk batch", {
|
|
108888
|
+
...getNetworkErrorAttributes(error),
|
|
108762
108889
|
error: asError(error)
|
|
108763
108890
|
});
|
|
108764
108891
|
await sleep(100 * attempt);
|
|
@@ -108911,6 +109038,7 @@ class ConduitStateReportManager {
|
|
|
108911
109038
|
}
|
|
108912
109039
|
catch (error) {
|
|
108913
109040
|
this.logger.error("Conduit state update failed", {
|
|
109041
|
+
...getNetworkErrorAttributes(error),
|
|
108914
109042
|
error: asError(error)
|
|
108915
109043
|
});
|
|
108916
109044
|
}
|
|
@@ -119191,6 +119319,7 @@ function getConfiguration({ overrides } = {}) {
|
|
|
119191
119319
|
}
|
|
119192
119320
|
|
|
119193
119321
|
async function startInferenceAgent({ configurationOverrides }) {
|
|
119322
|
+
setDefaultResultOrder("ipv4first");
|
|
119194
119323
|
const abortController = new AbortController();
|
|
119195
119324
|
const configuration = getConfiguration({ overrides: configurationOverrides });
|
|
119196
119325
|
const logger = createLogger({
|
|
@@ -119202,7 +119331,8 @@ async function startInferenceAgent({ configurationOverrides }) {
|
|
|
119202
119331
|
const apiClient = createAPIClient({
|
|
119203
119332
|
apiKey: configuration.apiKey,
|
|
119204
119333
|
apiURL: configuration.apiURL,
|
|
119205
|
-
inferenceSourceID: configuration.inferenceSourceID
|
|
119334
|
+
inferenceSourceID: configuration.inferenceSourceID,
|
|
119335
|
+
logger
|
|
119206
119336
|
});
|
|
119207
119337
|
logger.info("Starting web server");
|
|
119208
119338
|
const { app, shutdown } = await createApplication({
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function fetchWithRetry(input: URL | string, init: RequestInit, { baseDelayMs, maxAttempts, maxDelayMs, signal, timeoutMs }?: {
|
|
2
|
+
baseDelayMs?: number;
|
|
3
|
+
maxAttempts?: number;
|
|
4
|
+
maxDelayMs?: number;
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
timeoutMs?: number;
|
|
7
|
+
}): Promise<Response>;
|
|
8
|
+
export declare function getNetworkErrorAttributes(error: unknown): Record<string, unknown>;
|