@juspay/neurolink 10.4.2 → 10.4.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/CHANGELOG.md +6 -0
- package/dist/browser/neurolink.min.js +333 -336
- package/dist/cli/commands/proxy.d.ts +1 -1
- package/dist/cli/commands/proxy.js +124 -56
- package/dist/cli/commands/proxyAnalyze.js +10 -1
- package/dist/lib/proxy/proxyAnalysis.js +136 -12
- package/dist/lib/proxy/requestLogger.d.ts +2 -0
- package/dist/lib/proxy/requestLogger.js +72 -13
- package/dist/lib/proxy/rollingProxyServer.js +79 -8
- package/dist/lib/proxy/rollingWorkerProcess.js +20 -15
- package/dist/lib/proxy/rollingWorkerProtocol.js +3 -0
- package/dist/lib/proxy/rollingWorkerSupervisor.d.ts +1 -0
- package/dist/lib/proxy/rollingWorkerSupervisor.js +31 -11
- package/dist/lib/proxy/runtimeConfig.d.ts +1 -0
- package/dist/lib/proxy/runtimeConfig.js +20 -5
- package/dist/lib/proxy/socketWorkerRuntime.js +41 -13
- package/dist/lib/server/routes/claudeProxyRoutes.js +63 -75
- package/dist/lib/types/proxy.d.ts +31 -1
- package/dist/proxy/proxyAnalysis.js +136 -12
- package/dist/proxy/requestLogger.d.ts +2 -0
- package/dist/proxy/requestLogger.js +72 -13
- package/dist/proxy/rollingProxyServer.js +79 -8
- package/dist/proxy/rollingWorkerProcess.js +20 -15
- package/dist/proxy/rollingWorkerProtocol.js +3 -0
- package/dist/proxy/rollingWorkerSupervisor.d.ts +1 -0
- package/dist/proxy/rollingWorkerSupervisor.js +31 -11
- package/dist/proxy/runtimeConfig.d.ts +1 -0
- package/dist/proxy/runtimeConfig.js +20 -5
- package/dist/proxy/socketWorkerRuntime.js +41 -13
- package/dist/server/routes/claudeProxyRoutes.js +63 -75
- package/dist/types/proxy.d.ts +31 -1
- package/package.json +1 -1
|
@@ -8,6 +8,7 @@ function isTransferableProxySocket(handle) {
|
|
|
8
8
|
typeof candidate.resume === "function" &&
|
|
9
9
|
typeof candidate.destroy === "function" &&
|
|
10
10
|
typeof candidate.end === "function" &&
|
|
11
|
+
typeof candidate.off === "function" &&
|
|
11
12
|
typeof candidate.once === "function");
|
|
12
13
|
}
|
|
13
14
|
function destroyTransferredHandle(handle) {
|
|
@@ -153,6 +154,16 @@ export function attachSocketWorkerProcess(server, input) {
|
|
|
153
154
|
// synchronously here would truncate that in-flight request.
|
|
154
155
|
setImmediate(() => runtime.drain());
|
|
155
156
|
};
|
|
157
|
+
const takePendingSocket = (socketId) => {
|
|
158
|
+
const pending = pendingSockets.get(socketId);
|
|
159
|
+
if (!pending) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
pendingSockets.delete(socketId);
|
|
163
|
+
pending.socket.off("error", pending.onError);
|
|
164
|
+
pending.socket.off("close", pending.onClose);
|
|
165
|
+
return pending.socket;
|
|
166
|
+
};
|
|
156
167
|
const onMessage = (message, handle) => {
|
|
157
168
|
if (message &&
|
|
158
169
|
typeof message === "object" &&
|
|
@@ -176,7 +187,27 @@ export function attachSocketWorkerProcess(server, input) {
|
|
|
176
187
|
socket.destroy();
|
|
177
188
|
return;
|
|
178
189
|
}
|
|
179
|
-
|
|
190
|
+
// A client can reset while the transferred handle is paused between
|
|
191
|
+
// acceptance and commit. The HTTP server has not seen the socket yet,
|
|
192
|
+
// so it cannot install its normal transport-error handler for us.
|
|
193
|
+
const onError = () => {
|
|
194
|
+
if (pendingSockets.get(socketId)?.socket !== socket) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
takePendingSocket(socketId);
|
|
198
|
+
socket.destroy();
|
|
199
|
+
drainWhenPendingSettled();
|
|
200
|
+
};
|
|
201
|
+
const onClose = () => {
|
|
202
|
+
if (pendingSockets.get(socketId)?.socket !== socket) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
takePendingSocket(socketId);
|
|
206
|
+
drainWhenPendingSettled();
|
|
207
|
+
};
|
|
208
|
+
pendingSockets.set(socketId, { socket, onError, onClose });
|
|
209
|
+
socket.once("error", onError);
|
|
210
|
+
socket.once("close", onClose);
|
|
180
211
|
try {
|
|
181
212
|
process.send({
|
|
182
213
|
type: "proxy-worker:socket-accepted",
|
|
@@ -185,14 +216,14 @@ export function attachSocketWorkerProcess(server, input) {
|
|
|
185
216
|
socketId,
|
|
186
217
|
}, (error) => {
|
|
187
218
|
if (error) {
|
|
188
|
-
|
|
189
|
-
|
|
219
|
+
takePendingSocket(socketId)?.destroy();
|
|
220
|
+
drainWhenPendingSettled();
|
|
190
221
|
}
|
|
191
222
|
});
|
|
192
223
|
}
|
|
193
224
|
catch {
|
|
194
|
-
|
|
195
|
-
|
|
225
|
+
takePendingSocket(socketId)?.destroy();
|
|
226
|
+
drainWhenPendingSettled();
|
|
196
227
|
}
|
|
197
228
|
}
|
|
198
229
|
else {
|
|
@@ -229,11 +260,10 @@ export function attachSocketWorkerProcess(server, input) {
|
|
|
229
260
|
}
|
|
230
261
|
else if (message.type === "proxy-worker:socket-commit" ||
|
|
231
262
|
message.type === "proxy-worker:socket-cancel") {
|
|
232
|
-
const socket =
|
|
263
|
+
const socket = takePendingSocket(message.socketId);
|
|
233
264
|
if (!socket) {
|
|
234
265
|
return;
|
|
235
266
|
}
|
|
236
|
-
pendingSockets.delete(message.socketId);
|
|
237
267
|
if (message.type === "proxy-worker:socket-commit") {
|
|
238
268
|
runtime.acceptSocket(socket);
|
|
239
269
|
}
|
|
@@ -259,10 +289,9 @@ export function attachSocketWorkerProcess(server, input) {
|
|
|
259
289
|
// is exiting. The zero-downtime guarantee applies to the rolling handoff
|
|
260
290
|
// (control-message) path, not to process termination.
|
|
261
291
|
const drain = () => {
|
|
262
|
-
for (const
|
|
263
|
-
|
|
292
|
+
for (const socketId of [...pendingSockets.keys()]) {
|
|
293
|
+
takePendingSocket(socketId)?.destroy();
|
|
264
294
|
}
|
|
265
|
-
pendingSockets.clear();
|
|
266
295
|
runtime.drain();
|
|
267
296
|
};
|
|
268
297
|
const onTerminationSignal = () => drain();
|
|
@@ -283,10 +312,9 @@ export function attachSocketWorkerProcess(server, input) {
|
|
|
283
312
|
process.off("disconnect", drain);
|
|
284
313
|
process.off("SIGTERM", onTerminationSignal);
|
|
285
314
|
process.off("SIGINT", onTerminationSignal);
|
|
286
|
-
for (const
|
|
287
|
-
|
|
315
|
+
for (const socketId of [...pendingSockets.keys()]) {
|
|
316
|
+
takePendingSocket(socketId)?.destroy();
|
|
288
317
|
}
|
|
289
|
-
pendingSockets.clear();
|
|
290
318
|
runtime.close();
|
|
291
319
|
},
|
|
292
320
|
};
|
|
@@ -2241,6 +2241,7 @@ async function handleAnthropicSuccessfulResponse(args) {
|
|
|
2241
2241
|
attemptNumber,
|
|
2242
2242
|
finalBodyStr,
|
|
2243
2243
|
upstreamSpan,
|
|
2244
|
+
logAttempt,
|
|
2244
2245
|
logProxyBody,
|
|
2245
2246
|
logFinalRequest,
|
|
2246
2247
|
});
|
|
@@ -2248,6 +2249,8 @@ async function handleAnthropicSuccessfulResponse(args) {
|
|
|
2248
2249
|
async function handleAnthropicStreamingSuccessResponse(args) {
|
|
2249
2250
|
const { account, accountState, response, responseHeaders, tracer, requestStartTime, fetchStartMs, attemptNumber, finalBodyStr, upstreamSpan, logAttempt, logProxyBody, logFinalRequest, } = args;
|
|
2250
2251
|
if (!response.body) {
|
|
2252
|
+
recordAttemptError(account.label, account.type, 502);
|
|
2253
|
+
logAttempt(502, "stream_error", "No response body from upstream");
|
|
2251
2254
|
upstreamSpan?.end();
|
|
2252
2255
|
tracer?.setError("stream_error", "No response body from upstream");
|
|
2253
2256
|
tracer?.end(502, Date.now() - requestStartTime);
|
|
@@ -2386,6 +2389,9 @@ async function handleAnthropicStreamingSuccessResponse(args) {
|
|
|
2386
2389
|
failure: { message: preflight.message, rateLimit: isRateLimit },
|
|
2387
2390
|
};
|
|
2388
2391
|
}
|
|
2392
|
+
logAttempt(response.status, undefined, undefined, {
|
|
2393
|
+
attemptDurationMs: Date.now() - fetchStartMs,
|
|
2394
|
+
});
|
|
2389
2395
|
const streamOutcomeTracker = createStreamTerminalOutcomeTracker();
|
|
2390
2396
|
let mainStreamClosed = false;
|
|
2391
2397
|
const remainingStream = new ReadableStream({
|
|
@@ -2693,8 +2699,11 @@ function attachAnthropicSuccessStreamTelemetry(args) {
|
|
|
2693
2699
|
});
|
|
2694
2700
|
}
|
|
2695
2701
|
async function handleAnthropicJsonSuccessResponse(args) {
|
|
2696
|
-
const { account, response, responseHeaders, tracer, requestStartTime, fetchStartMs, attemptNumber, finalBodyStr, upstreamSpan, logProxyBody, logFinalRequest, } = args;
|
|
2702
|
+
const { account, response, responseHeaders, tracer, requestStartTime, fetchStartMs, attemptNumber, finalBodyStr, upstreamSpan, logAttempt, logProxyBody, logFinalRequest, } = args;
|
|
2697
2703
|
const responseText = await response.text();
|
|
2704
|
+
logAttempt(response.status, undefined, undefined, {
|
|
2705
|
+
attemptDurationMs: Date.now() - fetchStartMs,
|
|
2706
|
+
});
|
|
2698
2707
|
tracer?.logUpstreamResponseBody(responseText);
|
|
2699
2708
|
logProxyBody({
|
|
2700
2709
|
phase: "upstream_response",
|
|
@@ -2779,8 +2788,8 @@ async function handleAnthropicJsonSuccessResponse(args) {
|
|
|
2779
2788
|
}
|
|
2780
2789
|
return { response: responseJson };
|
|
2781
2790
|
}
|
|
2782
|
-
async function
|
|
2783
|
-
const {
|
|
2791
|
+
async function handleAnthropicSuccessfulNonStreamRetryResponse(args) {
|
|
2792
|
+
const { account, accountState, retryResp, tracer, requestStartTime, fetchStartMs, attemptNumber, finalBodyStr, upstreamSpan, logAttempt, logProxyBody, logFinalRequest, } = args;
|
|
2784
2793
|
const retryQuota = parseQuotaHeaders(retryResp.headers);
|
|
2785
2794
|
if (retryQuota) {
|
|
2786
2795
|
// Keep the auth-retry success path in parity with the main success path:
|
|
@@ -2802,63 +2811,11 @@ async function handleAnthropicSuccessfulRetryResponse(args) {
|
|
|
2802
2811
|
});
|
|
2803
2812
|
});
|
|
2804
2813
|
}
|
|
2805
|
-
if (body.stream && retryResp.body) {
|
|
2806
|
-
const retryReader = retryResp.body.getReader();
|
|
2807
|
-
const streamOutcomeTracker = createStreamTerminalOutcomeTracker();
|
|
2808
|
-
let retryStreamClosed = false;
|
|
2809
|
-
const retryStream = new ReadableStream({
|
|
2810
|
-
async pull(controller) {
|
|
2811
|
-
if (retryStreamClosed) {
|
|
2812
|
-
return;
|
|
2813
|
-
}
|
|
2814
|
-
try {
|
|
2815
|
-
const { done, value } = await retryReader.read();
|
|
2816
|
-
if (retryStreamClosed) {
|
|
2817
|
-
return;
|
|
2818
|
-
}
|
|
2819
|
-
if (done) {
|
|
2820
|
-
retryStreamClosed = true;
|
|
2821
|
-
streamOutcomeTracker.complete();
|
|
2822
|
-
controller.close();
|
|
2823
|
-
return;
|
|
2824
|
-
}
|
|
2825
|
-
controller.enqueue(value);
|
|
2826
|
-
}
|
|
2827
|
-
catch (streamErr) {
|
|
2828
|
-
const errMsg = describeTransportError(streamErr);
|
|
2829
|
-
logger.always(`[proxy] mid-stream error (auth-retry) account=${account.label}: ${errMsg}`);
|
|
2830
|
-
streamOutcomeTracker.fail(errMsg);
|
|
2831
|
-
if (!retryStreamClosed) {
|
|
2832
|
-
retryStreamClosed = true;
|
|
2833
|
-
const errorEvent = `event: error\ndata: ${JSON.stringify({ type: "error", error: { type: "api_error", message: `Upstream stream interrupted: ${errMsg}` } })}\n\n`;
|
|
2834
|
-
controller.enqueue(new TextEncoder().encode(errorEvent));
|
|
2835
|
-
controller.close();
|
|
2836
|
-
}
|
|
2837
|
-
}
|
|
2838
|
-
},
|
|
2839
|
-
cancel() {
|
|
2840
|
-
retryStreamClosed = true;
|
|
2841
|
-
streamOutcomeTracker.cancel();
|
|
2842
|
-
return retryReader.cancel();
|
|
2843
|
-
},
|
|
2844
|
-
});
|
|
2845
|
-
return attachAnthropicSuccessStreamTelemetry({
|
|
2846
|
-
account,
|
|
2847
|
-
response: retryResp,
|
|
2848
|
-
responseHeaders: Object.fromEntries([...retryResp.headers.entries()]),
|
|
2849
|
-
remainingStream: retryStream,
|
|
2850
|
-
streamOutcome: streamOutcomeTracker.outcome,
|
|
2851
|
-
tracer,
|
|
2852
|
-
requestStartTime,
|
|
2853
|
-
attemptNumber,
|
|
2854
|
-
finalBodyStr,
|
|
2855
|
-
upstreamSpan,
|
|
2856
|
-
logProxyBody,
|
|
2857
|
-
logFinalRequest,
|
|
2858
|
-
});
|
|
2859
|
-
}
|
|
2860
2814
|
const retryRespHeaders = Object.fromEntries([...retryResp.headers.entries()]);
|
|
2861
2815
|
const retryText = await retryResp.text();
|
|
2816
|
+
logAttempt(retryResp.status, undefined, undefined, {
|
|
2817
|
+
attemptDurationMs: Date.now() - fetchStartMs,
|
|
2818
|
+
});
|
|
2862
2819
|
tracer?.logUpstreamResponseHeaders(retryRespHeaders);
|
|
2863
2820
|
tracer?.logUpstreamResponseBody(retryText);
|
|
2864
2821
|
logProxyBody({
|
|
@@ -2960,7 +2917,7 @@ async function handleAnthropicAuthRetry(args) {
|
|
|
2960
2917
|
const retryLogAttempt = (status, errorType, errorMessage, extra) => logAttempt(status, errorType, errorMessage, {
|
|
2961
2918
|
...extra,
|
|
2962
2919
|
attempt: retryAttemptNumber,
|
|
2963
|
-
attemptDurationMs: Date.now() - retryAttemptStartedAt,
|
|
2920
|
+
attemptDurationMs: extra?.attemptDurationMs ?? Date.now() - retryAttemptStartedAt,
|
|
2964
2921
|
});
|
|
2965
2922
|
const retryBodyStr = buildUpstreamBody(account.token).bodyStr;
|
|
2966
2923
|
const retryFetchStartMs = Date.now();
|
|
@@ -2986,23 +2943,54 @@ async function handleAnthropicAuthRetry(args) {
|
|
|
2986
2943
|
authRetrySucceeded = true;
|
|
2987
2944
|
accountState.consecutiveRefreshFailures = 0;
|
|
2988
2945
|
logger.always(`[proxy] ← 200 account=${account.label} (after ${authRetry + 1} refresh(es))`);
|
|
2989
|
-
const
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
2946
|
+
const successResult = body.stream
|
|
2947
|
+
? await handleAnthropicSuccessfulResponse({
|
|
2948
|
+
ctx,
|
|
2949
|
+
body,
|
|
2950
|
+
account,
|
|
2951
|
+
accountState,
|
|
2952
|
+
response: retryResp,
|
|
2953
|
+
tracer,
|
|
2954
|
+
requestStartTime,
|
|
2955
|
+
fetchStartMs: retryFetchStartMs,
|
|
2956
|
+
attemptNumber: retryAttemptNumber,
|
|
2957
|
+
finalBodyStr: retryBodyStr,
|
|
2958
|
+
upstreamSpan: currentUpstreamSpan,
|
|
2959
|
+
logAttempt: retryLogAttempt,
|
|
2960
|
+
logProxyBody,
|
|
2961
|
+
logFinalRequest,
|
|
2962
|
+
})
|
|
2963
|
+
: {
|
|
2964
|
+
response: await handleAnthropicSuccessfulNonStreamRetryResponse({
|
|
2965
|
+
account,
|
|
2966
|
+
accountState,
|
|
2967
|
+
retryResp,
|
|
2968
|
+
tracer,
|
|
2969
|
+
requestStartTime,
|
|
2970
|
+
fetchStartMs: retryFetchStartMs,
|
|
2971
|
+
attemptNumber: retryAttemptNumber,
|
|
2972
|
+
finalBodyStr: retryBodyStr,
|
|
2973
|
+
upstreamSpan: currentUpstreamSpan,
|
|
2974
|
+
logAttempt: retryLogAttempt,
|
|
2975
|
+
logProxyBody,
|
|
2976
|
+
logFinalRequest,
|
|
2977
|
+
}),
|
|
2978
|
+
};
|
|
2979
|
+
if ("retryNextAccount" in successResult) {
|
|
2980
|
+
const failure = successResult.failure;
|
|
2981
|
+
return {
|
|
2982
|
+
continueLoop: true,
|
|
2983
|
+
lastError: failure?.message ?? currentLastError,
|
|
2984
|
+
authFailureMessage: currentAuthFailureMessage,
|
|
2985
|
+
sawRateLimit: currentSawRateLimit || Boolean(failure?.rateLimit),
|
|
2986
|
+
sawTransientFailure: currentSawTransientFailure ||
|
|
2987
|
+
Boolean(failure && !failure.rateLimit),
|
|
2988
|
+
sawNetworkError: currentSawNetworkError,
|
|
2989
|
+
upstreamSpan: undefined,
|
|
2990
|
+
};
|
|
2991
|
+
}
|
|
3004
2992
|
return {
|
|
3005
|
-
response:
|
|
2993
|
+
response: successResult.response,
|
|
3006
2994
|
continueLoop: false,
|
|
3007
2995
|
lastError: currentLastError,
|
|
3008
2996
|
authFailureMessage: currentAuthFailureMessage,
|
package/dist/types/proxy.d.ts
CHANGED
|
@@ -1121,6 +1121,7 @@ export type ProxyAnalysisAccount = {
|
|
|
1121
1121
|
unclassifiedRateLimits: number;
|
|
1122
1122
|
};
|
|
1123
1123
|
/** Offline report generated from proxy request, attempt, and lifecycle logs. */
|
|
1124
|
+
export type ProxyAnalysisStreamName = "lifecycle" | "requests" | "attempts" | "debug";
|
|
1124
1125
|
export type ProxyAnalysisReport = {
|
|
1125
1126
|
generatedAt: string;
|
|
1126
1127
|
since: string;
|
|
@@ -1129,6 +1130,7 @@ export type ProxyAnalysisReport = {
|
|
|
1129
1130
|
lifecycle: number;
|
|
1130
1131
|
requests: number;
|
|
1131
1132
|
attempts: number;
|
|
1133
|
+
debug: number;
|
|
1132
1134
|
};
|
|
1133
1135
|
coverage: {
|
|
1134
1136
|
lifecycle: boolean;
|
|
@@ -1143,6 +1145,20 @@ export type ProxyAnalysisReport = {
|
|
|
1143
1145
|
unsupportedLifecycleLines: number;
|
|
1144
1146
|
lifecycleSequenceGaps: number;
|
|
1145
1147
|
lifecycleSequenceDuplicates: number;
|
|
1148
|
+
streams: Record<ProxyAnalysisStreamName, {
|
|
1149
|
+
observedFrom: string | null;
|
|
1150
|
+
observedTo: string | null;
|
|
1151
|
+
startsAtOrBeforeRequestedWindow: boolean;
|
|
1152
|
+
}>;
|
|
1153
|
+
bodyArtifacts: {
|
|
1154
|
+
capturesIndexed: number;
|
|
1155
|
+
artifactsReferenced: number;
|
|
1156
|
+
artifactsPresent: number;
|
|
1157
|
+
artifactsMissing: number;
|
|
1158
|
+
invalidPaths: number;
|
|
1159
|
+
writeFailures: number;
|
|
1160
|
+
truncatedCaptures: number;
|
|
1161
|
+
};
|
|
1146
1162
|
};
|
|
1147
1163
|
lifecycle: {
|
|
1148
1164
|
accepted: number;
|
|
@@ -1392,6 +1408,7 @@ export type StoredBodyArtifact = {
|
|
|
1392
1408
|
storedFileBytes?: number;
|
|
1393
1409
|
redactedBody?: string;
|
|
1394
1410
|
bodyTruncated?: boolean;
|
|
1411
|
+
bodyWriteFailed?: boolean;
|
|
1395
1412
|
};
|
|
1396
1413
|
/** File the proxy logger tracks for rotation and cleanup. */
|
|
1397
1414
|
export type ManagedLogFile = {
|
|
@@ -1653,6 +1670,11 @@ export type ProxyWorkerStatusMessage = {
|
|
|
1653
1670
|
generation: number;
|
|
1654
1671
|
pid: number;
|
|
1655
1672
|
socketId: string;
|
|
1673
|
+
} | {
|
|
1674
|
+
type: "proxy-worker:replacement-requested";
|
|
1675
|
+
generation: number;
|
|
1676
|
+
pid: number;
|
|
1677
|
+
reason: "environment";
|
|
1656
1678
|
};
|
|
1657
1679
|
export type ProxyWorkerSocketMessage = {
|
|
1658
1680
|
type: "proxy-worker:socket";
|
|
@@ -1661,6 +1683,8 @@ export type ProxyWorkerSocketMessage = {
|
|
|
1661
1683
|
};
|
|
1662
1684
|
export type ProxyWorkerIpcMessage = ProxyWorkerControlMessage | ProxyWorkerStatusMessage | ProxyWorkerSocketMessage;
|
|
1663
1685
|
export type TransferableProxySocket = Pick<import("node:net").Socket, "destroy" | "end" | "pause" | "resume" | "once">;
|
|
1686
|
+
/** A transferred socket whose temporary handoff listeners can be detached. */
|
|
1687
|
+
export type DetachableTransferableProxySocket = TransferableProxySocket & Pick<import("node:net").Socket, "off">;
|
|
1664
1688
|
export type RollingWorkerHandle = {
|
|
1665
1689
|
pid: number;
|
|
1666
1690
|
sendControl: (message: ProxyWorkerControlMessage) => void;
|
|
@@ -1714,6 +1738,11 @@ export type RollingWorkerSupervisorOptions = {
|
|
|
1714
1738
|
socketQueueTimeoutMs?: number;
|
|
1715
1739
|
shutdownTimeoutMs?: number;
|
|
1716
1740
|
onStateChange?: (snapshot: RollingWorkerSupervisorSnapshot) => void;
|
|
1741
|
+
onReplacementRequested?: (request: {
|
|
1742
|
+
generation: number;
|
|
1743
|
+
pid: number;
|
|
1744
|
+
reason: "environment";
|
|
1745
|
+
}) => void;
|
|
1717
1746
|
log?: (message: string) => void;
|
|
1718
1747
|
};
|
|
1719
1748
|
export type RollingProxyServerOptions = {
|
|
@@ -1854,6 +1883,7 @@ export type ProxyRuntimeConfigReloadResult = {
|
|
|
1854
1883
|
applied: boolean;
|
|
1855
1884
|
changed: boolean;
|
|
1856
1885
|
generation: number;
|
|
1886
|
+
environmentChanged?: boolean;
|
|
1857
1887
|
error?: string;
|
|
1858
1888
|
};
|
|
1859
1889
|
/** Safe runtime configuration diagnostics exposed through proxy status. */
|
|
@@ -1933,7 +1963,7 @@ export type StatusStats = {
|
|
|
1933
1963
|
transientRateLimits?: number;
|
|
1934
1964
|
quotaRateLimits?: number;
|
|
1935
1965
|
cooling: boolean;
|
|
1936
|
-
status?: "active" | "cooling" | "disabled" | "excluded" | "removed";
|
|
1966
|
+
status?: "active" | "cooling" | "disabled" | "excluded" | "removed" | "unattributed";
|
|
1937
1967
|
}[];
|
|
1938
1968
|
persistence?: ProxyStatsPersistenceStatus;
|
|
1939
1969
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "10.4.
|
|
3
|
+
"version": "10.4.3",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "TypeScript AI SDK with 24+ LLM providers behind one consistent API. MCP-native (connect any MCP server), voice TTS/STT/realtime, RAG, agents, memory, context compaction. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · DeepSeek · NVIDIA NIM and more.",
|
|
6
6
|
"author": {
|