@juspay/neurolink 12.14.6 → 12.14.8
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 +2 -2
- package/dist/browser/neurolink.min.js +411 -411
- package/dist/cli/commands/proxy.js +83 -14
- package/dist/proxy/bodyCaptureProcessing.js +47 -3
- package/dist/proxy/bodyCaptureWorker.js +39 -10
- package/dist/proxy/claudeOutputObservation.d.ts +9 -0
- package/dist/proxy/claudeOutputObservation.js +85 -0
- package/dist/proxy/codexUsage.js +86 -3
- package/dist/proxy/otelLogSink.d.ts +13 -0
- package/dist/proxy/otelLogSink.js +63 -2
- package/dist/proxy/processTelemetry.d.ts +3 -0
- package/dist/proxy/processTelemetry.js +25 -0
- package/dist/proxy/proxyTraceContext.d.ts +21 -0
- package/dist/proxy/proxyTraceContext.js +47 -0
- package/dist/proxy/proxyTracer.d.ts +9 -5
- package/dist/proxy/proxyTracer.js +81 -2
- package/dist/proxy/rawStreamCapture.js +17 -26
- package/dist/proxy/requestLogger.d.ts +2 -0
- package/dist/proxy/requestLogger.js +29 -19
- package/dist/proxy/restartControl.d.ts +3 -1
- package/dist/proxy/restartControl.js +118 -1
- package/dist/proxy/sseInterceptor.js +71 -3
- package/dist/server/routes/claudeProxyRoutes.d.ts +0 -11
- package/dist/server/routes/claudeProxyRoutes.js +27 -12
- package/dist/server/routes/codexProxyRoutes.js +496 -333
- package/dist/types/cli.d.ts +7 -1
- package/dist/types/proxy.d.ts +133 -3
- package/dist/types/proxyRestart.d.ts +25 -0
- package/dist/utils/logSanitize.js +1 -1
- package/docs-site/static/search-index.json +1 -1
- package/package.json +1 -1
- package/scripts/observability/check-proxy-telemetry.mjs +29 -241
- package/scripts/observability/proxy-telemetry-backend.mjs +202 -0
- package/scripts/observability/proxy-telemetry-check.mjs +578 -0
- package/scripts/observability/query-proxy-history.mjs +30 -19
package/dist/types/cli.d.ts
CHANGED
|
@@ -834,8 +834,14 @@ export type ProxyGuardArgs = {
|
|
|
834
834
|
};
|
|
835
835
|
/** Arguments accepted by `neurolink proxy telemetry <subcommand>` */
|
|
836
836
|
export type ProxyTelemetryArgs = {
|
|
837
|
-
action?: "setup" | "start" | "stop" | "status" | "logs" | "import-dashboard";
|
|
837
|
+
action?: "setup" | "start" | "stop" | "status" | "logs" | "import-dashboard" | "doctor" | "query";
|
|
838
838
|
quiet?: boolean;
|
|
839
|
+
since?: string;
|
|
840
|
+
until?: string;
|
|
841
|
+
kind?: string;
|
|
842
|
+
format?: "json" | "text";
|
|
843
|
+
maxRows?: number;
|
|
844
|
+
proxyUrl?: string;
|
|
839
845
|
};
|
|
840
846
|
/** A fallback chain entry (serialisable subset of FallbackEntry) */
|
|
841
847
|
export type FallbackInfo = {
|
package/dist/types/proxy.d.ts
CHANGED
|
@@ -555,8 +555,16 @@ export type ProxyAccountSortMetrics = {
|
|
|
555
555
|
scopedSaturated: boolean;
|
|
556
556
|
};
|
|
557
557
|
export type RequestLogEntry = {
|
|
558
|
-
/** First
|
|
558
|
+
/** First text, refusal or populated tool output, excluding SSE control frames. */
|
|
559
559
|
firstUsefulOutputMs?: number;
|
|
560
|
+
/** Why first-useful-output timing is absent; never substitute a zero. */
|
|
561
|
+
firstUsefulOutputStatus?: "observed" | "no_useful_output" | "not_observed";
|
|
562
|
+
/** Native protocol event that established the first useful output. */
|
|
563
|
+
firstUsefulOutputEvent?: string;
|
|
564
|
+
/** Why first-output timing could not be established for this response. */
|
|
565
|
+
firstUsefulOutputUnavailableReason?: string;
|
|
566
|
+
/** Requested reasoning effort retained independently of body capture. */
|
|
567
|
+
reasoningEffort?: string;
|
|
560
568
|
/** Small routing evidence retained even when response bodies are pruned. */
|
|
561
569
|
fallbackPlan?: Array<{
|
|
562
570
|
provider: string;
|
|
@@ -610,6 +618,8 @@ export type RequestLogEntry = {
|
|
|
610
618
|
traceId?: string;
|
|
611
619
|
/** OTel span ID for correlation with distributed traces */
|
|
612
620
|
spanId?: string;
|
|
621
|
+
/** Original OTel sampling flags retained through deferred logging. */
|
|
622
|
+
traceFlags?: number;
|
|
613
623
|
/** Exact secret-free inputs and result of initial account selection. */
|
|
614
624
|
routingDecision?: ProxyAccountRoutingDecision;
|
|
615
625
|
};
|
|
@@ -631,6 +641,18 @@ export type ProcessedProxyBodyCapture = {
|
|
|
631
641
|
error?: string;
|
|
632
642
|
queueWaitMs?: number;
|
|
633
643
|
processingMs?: number;
|
|
644
|
+
admission?: ProxyBodyCaptureAdmission;
|
|
645
|
+
};
|
|
646
|
+
/** Exact bounded-admission state; records no request content. */
|
|
647
|
+
export type ProxyBodyCaptureAdmission = {
|
|
648
|
+
limitingResource: "entry" | "captures" | "bytes" | "worker";
|
|
649
|
+
estimatedBytes?: number;
|
|
650
|
+
/** Per-entry clone ceiling, independent of the aggregate queue ceiling. */
|
|
651
|
+
maxEntryBytes?: number;
|
|
652
|
+
pending: number;
|
|
653
|
+
pendingBytes: number;
|
|
654
|
+
maxPending: number;
|
|
655
|
+
maxPendingBytes: number;
|
|
634
656
|
};
|
|
635
657
|
export type ProxyBodyCaptureWorkerSnapshot = {
|
|
636
658
|
attempted: number;
|
|
@@ -641,9 +663,12 @@ export type ProxyBodyCaptureWorkerSnapshot = {
|
|
|
641
663
|
pendingBytes: number;
|
|
642
664
|
maxPending: number;
|
|
643
665
|
maxPendingBytes: number;
|
|
666
|
+
highWaterPending: number;
|
|
667
|
+
highWaterBytes: number;
|
|
644
668
|
/** Admission failures by exact guard, independent of processing failures. */
|
|
645
669
|
rejectionReasons: Record<string, number>;
|
|
646
670
|
lastError?: string;
|
|
671
|
+
lastRejectedAt?: string;
|
|
647
672
|
};
|
|
648
673
|
/** Collector transport evidence; acknowledgement does not prove backend storage. */
|
|
649
674
|
export type ProxyBodyDeliveryResult = {
|
|
@@ -664,6 +689,82 @@ export type ProxyBodyPublicationProgress = {
|
|
|
664
689
|
emitted: number;
|
|
665
690
|
notify?: () => void;
|
|
666
691
|
};
|
|
692
|
+
/** Bounded metadata-only evidence for an unconfirmed or locally rejected OTLP batch. */
|
|
693
|
+
export type ProxyOtelExportFailure = {
|
|
694
|
+
id: string;
|
|
695
|
+
at: string;
|
|
696
|
+
reason: "export_unconfirmed" | "queue_full";
|
|
697
|
+
error?: string;
|
|
698
|
+
records: Array<{
|
|
699
|
+
eventId: string;
|
|
700
|
+
kind?: string;
|
|
701
|
+
requestId?: string;
|
|
702
|
+
captureId?: string;
|
|
703
|
+
}>;
|
|
704
|
+
};
|
|
705
|
+
/** Read adapter configuration; credentials never appear in diagnostic reports. */
|
|
706
|
+
export type ProxyTelemetryBackend = {
|
|
707
|
+
baseUrl: string;
|
|
708
|
+
organization: string;
|
|
709
|
+
stream: string;
|
|
710
|
+
authorization?: string;
|
|
711
|
+
collectorMetricsUrl?: string;
|
|
712
|
+
};
|
|
713
|
+
export type ProxyTelemetryNativeConfig = {
|
|
714
|
+
exporters?: Record<string, {
|
|
715
|
+
endpoint?: string;
|
|
716
|
+
headers?: Record<string, string>;
|
|
717
|
+
}>;
|
|
718
|
+
};
|
|
719
|
+
export type ProxyTelemetryQueryBudget = {
|
|
720
|
+
used: number;
|
|
721
|
+
limit: number;
|
|
722
|
+
};
|
|
723
|
+
export type ProxyTelemetryQueryOptions = {
|
|
724
|
+
sql: string;
|
|
725
|
+
signal?: string;
|
|
726
|
+
startTime: number;
|
|
727
|
+
endTime: number;
|
|
728
|
+
size?: number;
|
|
729
|
+
offset?: number;
|
|
730
|
+
};
|
|
731
|
+
export type ProxyTelemetryDoctorOptions = {
|
|
732
|
+
backend: ProxyTelemetryBackend;
|
|
733
|
+
startTime: number;
|
|
734
|
+
endTime: number;
|
|
735
|
+
proxyUrl?: string;
|
|
736
|
+
maxRows?: number;
|
|
737
|
+
fetchImpl?: typeof fetch;
|
|
738
|
+
};
|
|
739
|
+
export type ProxyTelemetryCheck = {
|
|
740
|
+
name: string;
|
|
741
|
+
status: "pass" | "fail" | "warn" | "unverified";
|
|
742
|
+
evidence: unknown;
|
|
743
|
+
};
|
|
744
|
+
/** Small stored metadata used by the doctor; bodies are queried separately. */
|
|
745
|
+
export type ProxyTelemetryStoredRecord = Partial<RequestLogEntry> & {
|
|
746
|
+
recordedAtMicroseconds?: number;
|
|
747
|
+
captureId?: string;
|
|
748
|
+
bodySha256?: string;
|
|
749
|
+
redactedBodyBytes?: number;
|
|
750
|
+
bodyDelivery?: {
|
|
751
|
+
status?: string;
|
|
752
|
+
};
|
|
753
|
+
captureError?: string;
|
|
754
|
+
captureAdmission?: ProxyBodyCaptureAdmission;
|
|
755
|
+
bodyTruncated?: boolean;
|
|
756
|
+
phase?: string;
|
|
757
|
+
event?: string;
|
|
758
|
+
telemetryStatus?: string;
|
|
759
|
+
outcomeSource?: string;
|
|
760
|
+
};
|
|
761
|
+
export type ProxyTelemetryFieldCoverage = {
|
|
762
|
+
records: number;
|
|
763
|
+
traceMissing: number;
|
|
764
|
+
durationMissing: number;
|
|
765
|
+
outcomeMissing: number;
|
|
766
|
+
firstOutputUnexplained: number;
|
|
767
|
+
};
|
|
667
768
|
/** Chunk emission stays in the request logger, which owns request attributes. */
|
|
668
769
|
export type ProxyBodyChunkEmitter = (chunk: string, index: number, count: number) => void;
|
|
669
770
|
export type ProxyRequestLoggerSnapshot = {
|
|
@@ -721,9 +822,11 @@ export type RequestAttemptLogEntry = {
|
|
|
721
822
|
traceId?: string;
|
|
722
823
|
/** OTel span ID for correlation with distributed traces */
|
|
723
824
|
spanId?: string;
|
|
825
|
+
/** Original OTel sampling flags retained through deferred logging. */
|
|
826
|
+
traceFlags?: number;
|
|
724
827
|
};
|
|
725
828
|
/** Additional fields recorded when a Codex response becomes client-final. */
|
|
726
|
-
export type CodexFinalLogExtra = Partial<Pick<RequestLogEntry, "errorType" | "errorMessage" | "errorCode" | "transportScope" | "inputTokens" | "outputTokens" | "cacheReadTokens" | "cacheCreationTokens" | "terminalOutcome" | "firstUsefulOutputMs">>;
|
|
829
|
+
export type CodexFinalLogExtra = Partial<Pick<RequestLogEntry, "errorType" | "errorMessage" | "errorCode" | "transportScope" | "inputTokens" | "outputTokens" | "cacheReadTokens" | "cacheCreationTokens" | "terminalOutcome" | "firstUsefulOutputMs" | "firstUsefulOutputStatus" | "firstUsefulOutputEvent">>;
|
|
727
830
|
/** Additional fields recorded for each upstream Codex account attempt. */
|
|
728
831
|
export type CodexAttemptLogExtra = Partial<Pick<RequestAttemptLogEntry, "errorType" | "errorMessage" | "errorCode" | "transportScope" | "retryable" | "rateLimitKind" | "cooldownReason">>;
|
|
729
832
|
/** Minimal persistence contract needed by Codex rotating-token refreshes. */
|
|
@@ -739,6 +842,8 @@ export type CodexTokenRefresher = (refreshToken: string) => Promise<{
|
|
|
739
842
|
}>;
|
|
740
843
|
export type ProxyBodyCaptureInput = {
|
|
741
844
|
phase: string;
|
|
845
|
+
/** The stream observer retained only a bounded prefix. */
|
|
846
|
+
sourceTruncated?: boolean;
|
|
742
847
|
headers?: Record<string, string>;
|
|
743
848
|
body?: unknown;
|
|
744
849
|
bodySize?: number;
|
|
@@ -1562,6 +1667,8 @@ export type ProxyRequestContext = {
|
|
|
1562
1667
|
* every non-Anthropic model prices to $0.
|
|
1563
1668
|
*/
|
|
1564
1669
|
provider?: string;
|
|
1670
|
+
/** An internal fallback is an attempt; its parent owns request/token metrics. */
|
|
1671
|
+
recordRequestMetrics?: boolean;
|
|
1565
1672
|
};
|
|
1566
1673
|
/** Response-side details parsed from the upstream reply (model, finish, tools). */
|
|
1567
1674
|
export type ResponseInfoContext = {
|
|
@@ -1998,7 +2105,10 @@ export type CodexStreamUsage = {
|
|
|
1998
2105
|
export type CodexStreamEvidence = {
|
|
1999
2106
|
completed: boolean;
|
|
2000
2107
|
terminalBytes: number;
|
|
2108
|
+
/** Malformed, oversized or undispatched frames prevent proving output absence. */
|
|
2109
|
+
observationIncomplete?: boolean;
|
|
2001
2110
|
firstUsefulOutputAt?: number;
|
|
2111
|
+
firstUsefulOutputEvent?: string;
|
|
2002
2112
|
errorType?: string;
|
|
2003
2113
|
errorMessage?: string;
|
|
2004
2114
|
errorCode?: string;
|
|
@@ -2017,6 +2127,11 @@ export type RuntimeRequestMetadata = {
|
|
|
2017
2127
|
/** Last dispatched attempt, retained until this HTTP request terminates. */
|
|
2018
2128
|
lastUpstreamAttempt?: RequestAttemptLogEntry;
|
|
2019
2129
|
requestId: string;
|
|
2130
|
+
/** Ingress OTel correlation survives detached stream/error callbacks. */
|
|
2131
|
+
traceId?: string;
|
|
2132
|
+
spanId?: string;
|
|
2133
|
+
/** Original OTel sampling flags retained through deferred logging. */
|
|
2134
|
+
traceFlags?: number;
|
|
2020
2135
|
method: string;
|
|
2021
2136
|
path: string;
|
|
2022
2137
|
startedAt: number;
|
|
@@ -2057,6 +2172,8 @@ export type ProxyBodyCaptureEntry = {
|
|
|
2057
2172
|
headers?: Record<string, string>;
|
|
2058
2173
|
body?: unknown;
|
|
2059
2174
|
bodySize?: number;
|
|
2175
|
+
/** The bounded stream observer omitted a suffix before redaction/processing. */
|
|
2176
|
+
sourceTruncated?: boolean;
|
|
2060
2177
|
contentType?: string;
|
|
2061
2178
|
responseStatus?: number;
|
|
2062
2179
|
durationMs?: number;
|
|
@@ -2065,6 +2182,8 @@ export type ProxyBodyCaptureEntry = {
|
|
|
2065
2182
|
attempt?: number;
|
|
2066
2183
|
traceId?: string;
|
|
2067
2184
|
spanId?: string;
|
|
2185
|
+
/** Original OTel sampling flags retained through deferred logging. */
|
|
2186
|
+
traceFlags?: number;
|
|
2068
2187
|
metadata?: Record<string, unknown>;
|
|
2069
2188
|
};
|
|
2070
2189
|
/** JSON object retained in deterministic proxy replay artifacts. */
|
|
@@ -2225,6 +2344,8 @@ export type SSEContentBlock = {
|
|
|
2225
2344
|
export type SSETelemetry = {
|
|
2226
2345
|
messageStopReceived: boolean;
|
|
2227
2346
|
firstUsefulOutputAt?: number;
|
|
2347
|
+
firstUsefulOutputEvent?: string;
|
|
2348
|
+
observationIncomplete?: boolean;
|
|
2228
2349
|
messageId: string;
|
|
2229
2350
|
model: string;
|
|
2230
2351
|
usage: {
|
|
@@ -2248,6 +2369,7 @@ export type SSETelemetry = {
|
|
|
2248
2369
|
/** Error carried as a terminal SSE `event: error`, if one was observed. */
|
|
2249
2370
|
streamErrorMessage?: string;
|
|
2250
2371
|
rawText?: string;
|
|
2372
|
+
rawTextTruncated?: boolean;
|
|
2251
2373
|
};
|
|
2252
2374
|
/** Terminal outcome of a response body after the HTTP headers were sent. */
|
|
2253
2375
|
export type StreamTerminalOutcome = {
|
|
@@ -2269,6 +2391,8 @@ export type StreamTerminalOutcomeTracker = {
|
|
|
2269
2391
|
export type TelemetryAccumulator = {
|
|
2270
2392
|
messageStopReceived: boolean;
|
|
2271
2393
|
firstUsefulOutputAt?: number;
|
|
2394
|
+
firstUsefulOutputEvent?: string;
|
|
2395
|
+
observationIncomplete?: boolean;
|
|
2272
2396
|
messageId: string;
|
|
2273
2397
|
model: string;
|
|
2274
2398
|
inputTokens: number;
|
|
@@ -2874,7 +2998,7 @@ export type StatusStats = {
|
|
|
2874
2998
|
persistence?: ProxyStatsPersistenceStatus;
|
|
2875
2999
|
};
|
|
2876
3000
|
/** Sub-action of the `proxy telemetry` CLI command. */
|
|
2877
|
-
export type ProxyTelemetryAction = "setup" | "start" | "stop" | "status" | "logs" | "import-dashboard";
|
|
3001
|
+
export type ProxyTelemetryAction = "doctor" | "query" | "setup" | "start" | "stop" | "status" | "logs" | "import-dashboard";
|
|
2878
3002
|
/** Wire format a proxy request is using. */
|
|
2879
3003
|
export type ProxyFormat = "claude" | "openai" | "gemini";
|
|
2880
3004
|
/**
|
|
@@ -3866,3 +3990,9 @@ export type ProxyShareProvisioningBundle = {
|
|
|
3866
3990
|
expiresAt?: number;
|
|
3867
3991
|
};
|
|
3868
3992
|
};
|
|
3993
|
+
/** Log correlation retained independently of the current async context. */
|
|
3994
|
+
export type ProxyLogTraceContext = {
|
|
3995
|
+
traceId: string;
|
|
3996
|
+
spanId: string;
|
|
3997
|
+
traceFlags: number;
|
|
3998
|
+
};
|
|
@@ -44,6 +44,31 @@ export type ProxyRestartControlOptions = {
|
|
|
44
44
|
getInstalledVersion: () => Promise<string | undefined>;
|
|
45
45
|
isUpdatePending: () => boolean;
|
|
46
46
|
getStatus: () => Promise<unknown>;
|
|
47
|
+
/** Current supervisor process evidence; never infer it from a worker/plist. */
|
|
48
|
+
getTelemetry?: () => ProxyProcessTelemetrySnapshot;
|
|
47
49
|
/** Report control-server errors without stopping the serving listener. */
|
|
48
50
|
log?: (message: string) => void;
|
|
49
51
|
};
|
|
52
|
+
/** Small read-only process evidence, excluding environment variables and log content. */
|
|
53
|
+
export type ProxyProcessTelemetrySnapshot = {
|
|
54
|
+
pid: number;
|
|
55
|
+
checkedAt: string;
|
|
56
|
+
configuredSink: "otel" | "file";
|
|
57
|
+
lifecycleSink: string;
|
|
58
|
+
otelInitialized: boolean;
|
|
59
|
+
stdio: {
|
|
60
|
+
stdout: "file" | "non_file" | "unavailable";
|
|
61
|
+
stderr: "file" | "non_file" | "unavailable";
|
|
62
|
+
};
|
|
63
|
+
exportDropped: number;
|
|
64
|
+
exportUnconfirmed: number;
|
|
65
|
+
};
|
|
66
|
+
export type ProxySupervisorTelemetry = {
|
|
67
|
+
status: "available";
|
|
68
|
+
process: ProxyProcessTelemetrySnapshot;
|
|
69
|
+
} | {
|
|
70
|
+
status: "unavailable";
|
|
71
|
+
reason: string;
|
|
72
|
+
} | {
|
|
73
|
+
status: "not_applicable";
|
|
74
|
+
};
|
|
@@ -47,7 +47,7 @@ const SECRET_PATTERN = new RegExp(
|
|
|
47
47
|
// Bare tokens by known prefix (e.g. `sk-abc…`, `r8_xyz…`)
|
|
48
48
|
`|\\b(?:${PREFIX_PATTERN})[_\\-][A-Za-z0-9_\\-\\.]{8,}\\b` +
|
|
49
49
|
// Generic key=value pairs (URL params, JSON bodies, header dumps)
|
|
50
|
-
"|\\b(?:api[_-]?key|access[_-]?token|secret[_-]?key|refresh[_-]?token)
|
|
50
|
+
"|\\b(?:api[_-]?key|access[_-]?token|secret[_-]?key|refresh[_-]?token)['\"]?\\s*[:=]\\s*['\"]?[^\\s,;'\"&]+", "gi");
|
|
51
51
|
/** Header names that should always be redacted regardless of value shape. */
|
|
52
52
|
const SENSITIVE_HEADER_NAMES = [
|
|
53
53
|
"authorization",
|