@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.
Files changed (35) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/dist/browser/neurolink.min.js +411 -411
  3. package/dist/cli/commands/proxy.js +83 -14
  4. package/dist/proxy/bodyCaptureProcessing.js +47 -3
  5. package/dist/proxy/bodyCaptureWorker.js +39 -10
  6. package/dist/proxy/claudeOutputObservation.d.ts +9 -0
  7. package/dist/proxy/claudeOutputObservation.js +85 -0
  8. package/dist/proxy/codexUsage.js +86 -3
  9. package/dist/proxy/otelLogSink.d.ts +13 -0
  10. package/dist/proxy/otelLogSink.js +63 -2
  11. package/dist/proxy/processTelemetry.d.ts +3 -0
  12. package/dist/proxy/processTelemetry.js +25 -0
  13. package/dist/proxy/proxyTraceContext.d.ts +21 -0
  14. package/dist/proxy/proxyTraceContext.js +47 -0
  15. package/dist/proxy/proxyTracer.d.ts +9 -5
  16. package/dist/proxy/proxyTracer.js +81 -2
  17. package/dist/proxy/rawStreamCapture.js +17 -26
  18. package/dist/proxy/requestLogger.d.ts +2 -0
  19. package/dist/proxy/requestLogger.js +29 -19
  20. package/dist/proxy/restartControl.d.ts +3 -1
  21. package/dist/proxy/restartControl.js +118 -1
  22. package/dist/proxy/sseInterceptor.js +71 -3
  23. package/dist/server/routes/claudeProxyRoutes.d.ts +0 -11
  24. package/dist/server/routes/claudeProxyRoutes.js +27 -12
  25. package/dist/server/routes/codexProxyRoutes.js +496 -333
  26. package/dist/types/cli.d.ts +7 -1
  27. package/dist/types/proxy.d.ts +133 -3
  28. package/dist/types/proxyRestart.d.ts +25 -0
  29. package/dist/utils/logSanitize.js +1 -1
  30. package/docs-site/static/search-index.json +1 -1
  31. package/package.json +1 -1
  32. package/scripts/observability/check-proxy-telemetry.mjs +29 -241
  33. package/scripts/observability/proxy-telemetry-backend.mjs +202 -0
  34. package/scripts/observability/proxy-telemetry-check.mjs +578 -0
  35. package/scripts/observability/query-proxy-history.mjs +30 -19
@@ -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 = {
@@ -555,8 +555,16 @@ export type ProxyAccountSortMetrics = {
555
555
  scopedSaturated: boolean;
556
556
  };
557
557
  export type RequestLogEntry = {
558
- /** First output text or tool-argument delta, excluding SSE control frames. */
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)\\s*[:=]\\s*['\"]?[^\\s,;'\"&]+", "gi");
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",