@juspay/neurolink 10.0.1 → 10.1.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/CHANGELOG.md +6 -0
- package/dist/browser/neurolink.min.js +305 -305
- package/dist/cli/commands/proxyReplay.d.ts +3 -0
- package/dist/cli/commands/proxyReplay.js +175 -0
- package/dist/cli/parser.js +3 -1
- package/dist/lib/proxy/proxyReplay.d.ts +10 -0
- package/dist/lib/proxy/proxyReplay.js +765 -0
- package/dist/lib/proxy/requestLogger.d.ts +13 -0
- package/dist/lib/proxy/requestLogger.js +13 -0
- package/dist/lib/server/routes/claudeProxyRoutes.d.ts +1 -0
- package/dist/lib/server/routes/claudeProxyRoutes.js +9 -2
- package/dist/lib/types/cli.d.ts +16 -0
- package/dist/lib/types/proxy.d.ts +121 -0
- package/dist/proxy/proxyReplay.d.ts +10 -0
- package/dist/proxy/proxyReplay.js +764 -0
- package/dist/proxy/requestLogger.d.ts +13 -0
- package/dist/proxy/requestLogger.js +13 -0
- package/dist/server/routes/claudeProxyRoutes.d.ts +1 -0
- package/dist/server/routes/claudeProxyRoutes.js +9 -2
- package/dist/types/cli.d.ts +16 -0
- package/dist/types/proxy.d.ts +121 -0
- package/package.json +1 -1
|
@@ -15,6 +15,19 @@ export declare function logRequest(entry: RequestLogEntry): Promise<void>;
|
|
|
15
15
|
*/
|
|
16
16
|
export declare function logRequestAttempt(entry: RequestAttemptLogEntry): Promise<void>;
|
|
17
17
|
export declare function getLogDir(): string | null;
|
|
18
|
+
/** Shared redaction used by offline replay exports and direct comparisons. */
|
|
19
|
+
export declare function redactProxyHeadersForLogging(headers: Record<string, string> | undefined): Record<string, string> | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* Apply the same bounded body redaction used by persisted proxy captures.
|
|
22
|
+
* `value` and `bytes` are omitted only when the input is null or undefined.
|
|
23
|
+
* This performs serialization immediately, so callers must keep it off proxy
|
|
24
|
+
* hot paths unless body processing has already been explicitly requested.
|
|
25
|
+
*/
|
|
26
|
+
export declare function prepareProxyBodyForLogging(body: unknown): {
|
|
27
|
+
value?: string;
|
|
28
|
+
bytes?: number;
|
|
29
|
+
truncated: boolean;
|
|
30
|
+
};
|
|
18
31
|
export declare function logBodyCapture(entry: ProxyBodyCaptureEntry): Promise<void>;
|
|
19
32
|
/**
|
|
20
33
|
* Log the FULL raw request and response for debugging.
|
|
@@ -330,6 +330,19 @@ function prepareRedactedBody(body) {
|
|
|
330
330
|
}
|
|
331
331
|
return truncateUtf8String(redacted, MAX_CAPTURED_BODY_BYTES);
|
|
332
332
|
}
|
|
333
|
+
/** Shared redaction used by offline replay exports and direct comparisons. */
|
|
334
|
+
export function redactProxyHeadersForLogging(headers) {
|
|
335
|
+
return redactHeaders(headers);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Apply the same bounded body redaction used by persisted proxy captures.
|
|
339
|
+
* `value` and `bytes` are omitted only when the input is null or undefined.
|
|
340
|
+
* This performs serialization immediately, so callers must keep it off proxy
|
|
341
|
+
* hot paths unless body processing has already been explicitly requested.
|
|
342
|
+
*/
|
|
343
|
+
export function prepareProxyBodyForLogging(body) {
|
|
344
|
+
return prepareRedactedBody(body);
|
|
345
|
+
}
|
|
333
346
|
function collectManagedLogFiles(rootDir) {
|
|
334
347
|
const managedFiles = [];
|
|
335
348
|
const walk = (directory) => {
|
|
@@ -1011,6 +1011,10 @@ async function handleClaudePassthroughRequest(args) {
|
|
|
1011
1011
|
account: "passthrough",
|
|
1012
1012
|
accountType: "passthrough",
|
|
1013
1013
|
attempt: 1,
|
|
1014
|
+
metadata: {
|
|
1015
|
+
upstreamMethod: "POST",
|
|
1016
|
+
upstreamUrl: "https://api.anthropic.com/v1/messages?beta=true",
|
|
1017
|
+
},
|
|
1014
1018
|
});
|
|
1015
1019
|
let response;
|
|
1016
1020
|
try {
|
|
@@ -2914,7 +2918,7 @@ async function handleAnthropicSuccessfulRetryResponse(args) {
|
|
|
2914
2918
|
return retryJson;
|
|
2915
2919
|
}
|
|
2916
2920
|
async function handleAnthropicAuthRetry(args) {
|
|
2917
|
-
const { ctx, body, account, accountState, headers, buildUpstreamBody, enabledAccounts, orderedAccounts, tracer, requestStartTime, allocateAttemptNumber, upstreamSpan, logAttempt, logProxyBody, logFinalRequest, lastError, authFailureMessage, sawRateLimit, sawTransientFailure, sawNetworkError, } = args;
|
|
2921
|
+
const { ctx, body, account, accountState, headers, buildUpstreamBody, url, enabledAccounts, orderedAccounts, tracer, requestStartTime, allocateAttemptNumber, upstreamSpan, logAttempt, logProxyBody, logFinalRequest, lastError, authFailureMessage, sawRateLimit, sawTransientFailure, sawNetworkError, } = args;
|
|
2918
2922
|
recordAttemptError(account.label, account.type, 401);
|
|
2919
2923
|
logAttempt(401, "authentication_error", "received 401 from Anthropic", {
|
|
2920
2924
|
retryable: true,
|
|
@@ -2969,9 +2973,10 @@ async function handleAnthropicAuthRetry(args) {
|
|
|
2969
2973
|
account: account.label,
|
|
2970
2974
|
accountType: account.type,
|
|
2971
2975
|
attempt: retryAttemptNumber,
|
|
2976
|
+
metadata: { upstreamMethod: "POST", upstreamUrl: url },
|
|
2972
2977
|
});
|
|
2973
2978
|
try {
|
|
2974
|
-
const retryResp = await fetch(
|
|
2979
|
+
const retryResp = await fetch(url, {
|
|
2975
2980
|
method: "POST",
|
|
2976
2981
|
headers,
|
|
2977
2982
|
body: retryBodyStr,
|
|
@@ -3692,6 +3697,7 @@ async function prepareAnthropicAccountAttempt(args) {
|
|
|
3692
3697
|
account: account.label,
|
|
3693
3698
|
accountType: account.type,
|
|
3694
3699
|
attempt: attemptNumber,
|
|
3700
|
+
metadata: { upstreamMethod: "POST", upstreamUrl: url },
|
|
3695
3701
|
});
|
|
3696
3702
|
return {
|
|
3697
3703
|
continueLoop: false,
|
|
@@ -4087,6 +4093,7 @@ async function handleAnthropicRoutedClaudeRequest(args) {
|
|
|
4087
4093
|
accountState,
|
|
4088
4094
|
headers: preparedAttempt.headers,
|
|
4089
4095
|
buildUpstreamBody: preparedAttempt.buildUpstreamBody,
|
|
4096
|
+
url,
|
|
4090
4097
|
enabledAccounts,
|
|
4091
4098
|
orderedAccounts,
|
|
4092
4099
|
tracer,
|
package/dist/types/cli.d.ts
CHANGED
|
@@ -798,6 +798,22 @@ export type ProxyAnalyzeArgs = {
|
|
|
798
798
|
format?: "text" | "json";
|
|
799
799
|
quiet?: boolean;
|
|
800
800
|
};
|
|
801
|
+
/** Arguments accepted by `neurolink proxy replay <export|compare>`. */
|
|
802
|
+
export type ProxyReplayArgs = {
|
|
803
|
+
action?: "export" | "compare";
|
|
804
|
+
requestId?: string;
|
|
805
|
+
attempt?: number;
|
|
806
|
+
logsDir?: string;
|
|
807
|
+
bundle?: string;
|
|
808
|
+
output?: string;
|
|
809
|
+
execute?: boolean;
|
|
810
|
+
headerEnv?: string[];
|
|
811
|
+
bodyFile?: string;
|
|
812
|
+
url?: string;
|
|
813
|
+
timeoutMs?: number;
|
|
814
|
+
format?: "text" | "json";
|
|
815
|
+
quiet?: boolean;
|
|
816
|
+
};
|
|
801
817
|
/** Arguments accepted by hidden `neurolink proxy guard` command */
|
|
802
818
|
export type ProxyGuardArgs = {
|
|
803
819
|
host?: string;
|
package/dist/types/proxy.d.ts
CHANGED
|
@@ -1227,6 +1227,127 @@ export type ProxyBodyCaptureEntry = {
|
|
|
1227
1227
|
spanId?: string;
|
|
1228
1228
|
metadata?: Record<string, unknown>;
|
|
1229
1229
|
};
|
|
1230
|
+
/** JSON object retained in deterministic proxy replay artifacts. */
|
|
1231
|
+
export type ProxyReplayJsonRecord = Record<string, unknown>;
|
|
1232
|
+
/** One verified body-capture record in a proxy replay bundle. */
|
|
1233
|
+
export type ProxyReplayCapture = {
|
|
1234
|
+
timestamp: string;
|
|
1235
|
+
phase: string;
|
|
1236
|
+
attempt: number | null;
|
|
1237
|
+
model: string | null;
|
|
1238
|
+
stream: boolean | null;
|
|
1239
|
+
account: string | null;
|
|
1240
|
+
accountType: string | null;
|
|
1241
|
+
responseStatus: number | null;
|
|
1242
|
+
durationMs: number | null;
|
|
1243
|
+
contentType: string | null;
|
|
1244
|
+
headers: Record<string, string>;
|
|
1245
|
+
body: string | null;
|
|
1246
|
+
bodySha256: string | null;
|
|
1247
|
+
bodyTruncated: boolean;
|
|
1248
|
+
observedBodyBytes: number | null;
|
|
1249
|
+
metadata: ProxyReplayJsonRecord | null;
|
|
1250
|
+
source: {
|
|
1251
|
+
indexFile: string;
|
|
1252
|
+
indexLine: number;
|
|
1253
|
+
artifactPath: string | null;
|
|
1254
|
+
};
|
|
1255
|
+
issues: string[];
|
|
1256
|
+
};
|
|
1257
|
+
/** Deterministic, redacted reconstruction of one captured proxy request. */
|
|
1258
|
+
export type ProxyReplayBundle = {
|
|
1259
|
+
schemaVersion: 1;
|
|
1260
|
+
kind: "neurolink.proxy.replay-bundle";
|
|
1261
|
+
requestId: string;
|
|
1262
|
+
selectedAttempt: number;
|
|
1263
|
+
source: {
|
|
1264
|
+
logsDirectory: string;
|
|
1265
|
+
indexFiles: string[];
|
|
1266
|
+
};
|
|
1267
|
+
completeness: {
|
|
1268
|
+
captures: number;
|
|
1269
|
+
phasesPresent: string[];
|
|
1270
|
+
missingRequiredPhases: string[];
|
|
1271
|
+
truncatedCaptures: number;
|
|
1272
|
+
artifactsWithIssues: number;
|
|
1273
|
+
replayable: boolean;
|
|
1274
|
+
blockers: string[];
|
|
1275
|
+
};
|
|
1276
|
+
request: {
|
|
1277
|
+
method: string;
|
|
1278
|
+
url: string | null;
|
|
1279
|
+
headers: Record<string, string>;
|
|
1280
|
+
requiredHeaderInputs: string[];
|
|
1281
|
+
body: string | null;
|
|
1282
|
+
bodySha256: string | null;
|
|
1283
|
+
bodyTruncated: boolean;
|
|
1284
|
+
contentType: string | null;
|
|
1285
|
+
account: string | null;
|
|
1286
|
+
accountType: string | null;
|
|
1287
|
+
model: string | null;
|
|
1288
|
+
stream: boolean | null;
|
|
1289
|
+
};
|
|
1290
|
+
capturedResponse: ProxyReplayCapture | null;
|
|
1291
|
+
captures: ProxyReplayCapture[];
|
|
1292
|
+
};
|
|
1293
|
+
/** Redacted direct-upstream response and comparison with captured evidence. */
|
|
1294
|
+
export type ProxyReplayComparison = {
|
|
1295
|
+
schemaVersion: 1;
|
|
1296
|
+
kind: "neurolink.proxy.replay-comparison";
|
|
1297
|
+
requestId: string;
|
|
1298
|
+
selectedAttempt: number;
|
|
1299
|
+
endpoint: string;
|
|
1300
|
+
request: {
|
|
1301
|
+
method: string;
|
|
1302
|
+
headers: Record<string, string>;
|
|
1303
|
+
bodySha256: string;
|
|
1304
|
+
bodyBytes: number;
|
|
1305
|
+
usedBodyOverride: boolean;
|
|
1306
|
+
};
|
|
1307
|
+
captured: {
|
|
1308
|
+
status: number | null;
|
|
1309
|
+
contentType: string | null;
|
|
1310
|
+
bodySha256: string | null;
|
|
1311
|
+
bodyBytes: number | null;
|
|
1312
|
+
bodyTruncated: boolean;
|
|
1313
|
+
jsonShape: string[] | null;
|
|
1314
|
+
} | null;
|
|
1315
|
+
direct: {
|
|
1316
|
+
status: number;
|
|
1317
|
+
headers: Record<string, string>;
|
|
1318
|
+
contentType: string | null;
|
|
1319
|
+
body: string;
|
|
1320
|
+
bodySha256: string;
|
|
1321
|
+
observedBodyBytes: number;
|
|
1322
|
+
storedBodyBytes: number;
|
|
1323
|
+
bodyTruncated: boolean;
|
|
1324
|
+
timeToHeadersMs: number;
|
|
1325
|
+
totalMs: number;
|
|
1326
|
+
jsonShape: string[] | null;
|
|
1327
|
+
};
|
|
1328
|
+
comparison: {
|
|
1329
|
+
statusMatches: boolean | null;
|
|
1330
|
+
contentTypeMatches: boolean | null;
|
|
1331
|
+
bodyHashMatches: boolean | null;
|
|
1332
|
+
jsonShapeMatches: boolean | null;
|
|
1333
|
+
};
|
|
1334
|
+
};
|
|
1335
|
+
/** Inputs for deterministic proxy replay bundle export. */
|
|
1336
|
+
export type ExportProxyReplayOptions = {
|
|
1337
|
+
requestId: string;
|
|
1338
|
+
logsDir?: string;
|
|
1339
|
+
attempt?: number;
|
|
1340
|
+
};
|
|
1341
|
+
/** Inputs for an explicitly authorized direct-upstream comparison. */
|
|
1342
|
+
export type CompareProxyReplayOptions = {
|
|
1343
|
+
execute: boolean;
|
|
1344
|
+
headerValues?: Record<string, string>;
|
|
1345
|
+
bodyOverride?: string;
|
|
1346
|
+
urlOverride?: string;
|
|
1347
|
+
timeoutMs?: number;
|
|
1348
|
+
now?: () => number;
|
|
1349
|
+
fetchImpl?: typeof fetch;
|
|
1350
|
+
};
|
|
1230
1351
|
/** Persisted artifact produced when a body is stored to disk. */
|
|
1231
1352
|
export type StoredBodyArtifact = {
|
|
1232
1353
|
bodyPath?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "10.0
|
|
3
|
+
"version": "10.1.0",
|
|
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": {
|