@juspay/neurolink 12.17.1 → 12.17.2

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 (68) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/dist/browser/neurolink.min.js +421 -412
  3. package/dist/cli/commands/proxy.js +455 -259
  4. package/dist/constants/contextWindows.d.ts +2 -0
  5. package/dist/constants/contextWindows.js +4 -0
  6. package/dist/proxy/anthropicBudgetResponse.d.ts +3 -0
  7. package/dist/proxy/anthropicBudgetResponse.js +153 -0
  8. package/dist/proxy/bodyCaptureProcessing.d.ts +1 -0
  9. package/dist/proxy/bodyCaptureProcessing.js +23 -4
  10. package/dist/proxy/bodyCaptureWorker.js +20 -2
  11. package/dist/proxy/codexFallback.d.ts +10 -0
  12. package/dist/proxy/codexFallback.js +108 -24
  13. package/dist/proxy/codexUsage.js +2 -0
  14. package/dist/proxy/globalInstaller.d.ts +32 -1
  15. package/dist/proxy/globalInstaller.js +386 -3
  16. package/dist/proxy/otelLogSink.d.ts +3 -3
  17. package/dist/proxy/otelLogSink.js +137 -144
  18. package/dist/proxy/otlpLogTransport.d.ts +3 -0
  19. package/dist/proxy/otlpLogTransport.js +334 -0
  20. package/dist/proxy/proxyActivity.d.ts +22 -2
  21. package/dist/proxy/proxyActivity.js +114 -9
  22. package/dist/proxy/proxyAnalysis.js +82 -52
  23. package/dist/proxy/proxyClientCancellation.d.ts +7 -0
  24. package/dist/proxy/proxyClientCancellation.js +23 -0
  25. package/dist/proxy/proxyContextPreflight.d.ts +25 -0
  26. package/dist/proxy/proxyContextPreflight.js +337 -0
  27. package/dist/proxy/proxyFailureDetails.d.ts +19 -0
  28. package/dist/proxy/proxyFailureDetails.js +96 -0
  29. package/dist/proxy/proxyLifecycle.js +7 -0
  30. package/dist/proxy/proxyRouteBodyCapture.d.ts +13 -0
  31. package/dist/proxy/proxyRouteBodyCapture.js +112 -0
  32. package/dist/proxy/proxyTokenBudget.d.ts +40 -0
  33. package/dist/proxy/proxyTokenBudget.js +523 -0
  34. package/dist/proxy/proxyTracer.d.ts +3 -2
  35. package/dist/proxy/proxyTracer.js +46 -20
  36. package/dist/proxy/proxyTranslationEngine.d.ts +8 -10
  37. package/dist/proxy/proxyTranslationEngine.js +736 -376
  38. package/dist/proxy/requestLogger.d.ts +1 -0
  39. package/dist/proxy/requestLogger.js +107 -5
  40. package/dist/proxy/restartControl.js +9 -4
  41. package/dist/proxy/rollingWorkerProcess.js +65 -0
  42. package/dist/proxy/rollingWorkerSupervisor.js +7 -0
  43. package/dist/proxy/updateCoordinator.d.ts +14 -1
  44. package/dist/proxy/updateCoordinator.js +57 -2
  45. package/dist/server/routes/claudeProxyRoutes.d.ts +4 -5
  46. package/dist/server/routes/claudeProxyRoutes.js +809 -577
  47. package/dist/server/routes/codexProxyRoutes.js +191 -9
  48. package/dist/server/routes/openaiProxyRoutes.d.ts +1 -1
  49. package/dist/server/routes/openaiProxyRoutes.js +261 -69
  50. package/dist/types/cli.d.ts +3 -0
  51. package/dist/types/codex.d.ts +5 -1
  52. package/dist/types/index.d.ts +2 -0
  53. package/dist/types/index.js +2 -0
  54. package/dist/types/proxy.d.ts +148 -3
  55. package/dist/types/proxy.js +0 -15
  56. package/dist/types/proxyBudget.d.ts +74 -0
  57. package/dist/types/proxyBudget.js +1 -0
  58. package/dist/types/proxyContext.d.ts +35 -0
  59. package/dist/types/proxyContext.js +1 -0
  60. package/docs/assets/dashboards/README.md +37 -0
  61. package/docs/assets/dashboards/neurolink-proxy-observability-dashboard.json +197 -89
  62. package/docs-site/static/search-index.json +1 -1
  63. package/package.json +3 -1
  64. package/scripts/observability/NATIVE-DURABLE.md +63 -0
  65. package/scripts/observability/otel-collector.proxy-native-durable.yaml +93 -0
  66. package/scripts/observability/proxy-telemetry-backend.mjs +32 -5
  67. package/scripts/observability/proxy-telemetry-check.mjs +396 -61
  68. package/scripts/observability/query-proxy-history.mjs +34 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "12.17.1",
3
+ "version": "12.17.2",
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": {
@@ -153,6 +153,7 @@
153
153
  "test:dynamic": "pnpm exec tsx test/continuous-test-suite-dynamic.ts",
154
154
  "test:proxy": "pnpm exec tsx test/continuous-test-suite-proxy.ts",
155
155
  "test:proxy-connect-retry": "pnpm exec tsx test/continuous-test-suite-proxy-connect-retry.ts",
156
+ "test:proxy-reliability": "node scripts/run-proxy-reliability.mjs",
156
157
  "test:proxy-telemetry": "pnpm exec tsx test/continuous-test-suite-proxy-telemetry.ts",
157
158
  "test:proxy-restart": "pnpm exec tsx test/continuous-test-suite-proxy-restart.ts",
158
159
  "test:codex": "pnpm exec tsx test/continuous-test-suite-codex.ts",
@@ -391,6 +392,7 @@
391
392
  "@opentelemetry/exporter-logs-otlp-http": "^0.214.0",
392
393
  "@opentelemetry/exporter-metrics-otlp-http": "^0.214.0",
393
394
  "@opentelemetry/exporter-trace-otlp-http": "^0.214.0",
395
+ "@opentelemetry/otlp-transformer": "^0.214.0",
394
396
  "@opentelemetry/resources": "^2.6.0",
395
397
  "@opentelemetry/sdk-logs": "^0.214.0",
396
398
  "@opentelemetry/sdk-metrics": "^2.6.1",
@@ -0,0 +1,63 @@
1
+ # Native collector queues and body separation
2
+
3
+ `otel-collector.proxy-native-durable.yaml` is an opt-in profile for
4
+ `otelcol-contrib >= 0.160.0`. It does not install, replace, or restart a service.
5
+ Application logs remain OTLP-only. Collector retry storage writes a bounded
6
+ queue to disk so records accepted into that queue survive a collector restart.
7
+
8
+ Configure these variables in the collector service environment:
9
+
10
+ - `NEUROLINK_OPENOBSERVE_OTLP_ENDPOINT`: backend API endpoint, for example
11
+ `http://127.0.0.1:5080/api/default` (use TLS outside loopback).
12
+ - `NEUROLINK_OPENOBSERVE_BASIC_AUTH`: backend authorization, supplied privately.
13
+ - `NEUROLINK_OTEL_QUEUE_DIRECTORY` and `NEUROLINK_OTEL_COMPACTION_DIRECTORY`:
14
+ private directories on a volume with an operator-managed disk quota.
15
+ - `NEUROLINK_PROXY_STREAM_HEADER=neurolink_proxy` and
16
+ `NEUROLINK_PROXY_BODY_STREAM_HEADER=neurolink_proxy_bodies`.
17
+
18
+ Configure the proxy service with `NEUROLINK_PROXY_LOG_SINK=otel`,
19
+ `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://127.0.0.1:14318/v1/logs` and
20
+ `NEUROLINK_PROXY_OTLP_BODIES_ENDPOINT=http://127.0.0.1:14319/v1/logs`.
21
+ Configure the doctor's environment with the same two stream variables, or point
22
+ `NEUROLINK_OTEL_COLLECTOR_CONFIG` at this collector's resolved configuration.
23
+ Without a separate body endpoint/stream, existing single-stream deployments
24
+ continue to work.
25
+
26
+ The profile isolates metadata and bulk body queues and backend streams. There is
27
+ no volatile batch processor before the persistent exporter queue: receiver
28
+ success follows persistent enqueue rather than a timer-buffered batch. Proxy
29
+ chunk batching still reduces transport calls. Queues use a 32 MiB metadata byte
30
+ limit per signal and a 256 MiB body byte limit, plus in-flight requests and
31
+ storage/index overhead. Compaction reclaims consumed pages. These are payload
32
+ bounds, not a hard filesystem size cap; apply a volume quota and monitor free
33
+ space. Backend retention should be configured separately for each stream.
34
+
35
+ Disk-full errors, queue saturation, invalid records, process crashes before
36
+ persistent enqueue, and permanent backend rejection can still lose records.
37
+ Retry queues retry transient errors indefinitely until delivered or storage
38
+ limits are reached. A transport acknowledgment is not proof of backend
39
+ persistence or exactly-once delivery; use stable event IDs to deduplicate
40
+ retries. Retrying after ambiguous network acknowledgment can create duplicates.
41
+
42
+ Validate a profile before an authorized activation:
43
+
44
+ ```sh
45
+ otelcol-contrib validate --config scripts/observability/otel-collector.proxy-native-durable.yaml
46
+ ```
47
+
48
+ The isolated recovery test starts its own collector on random loopback ports,
49
+ uses a temporary queue directory and a fake backend, forces an outage, kills
50
+ only that test-owned collector process, restarts it with the same directory,
51
+ and verifies replay. It never operates an installed service:
52
+
53
+ ```sh
54
+ NEUROLINK_TEST_OTELCOL_BIN=/absolute/path/to/otelcol-contrib \
55
+ pnpm exec tsx test/continuous-test-suite-proxy-capture-pipeline.ts
56
+ ```
57
+
58
+ The doctor's admission reconciliation searches a bounded lookback (24 hours by
59
+ default), applies per-request deadlines where logged, and gives late ingestion
60
+ 120 seconds before flagging missing endings. Use `--admission-lookback-minutes`
61
+ and `--max-rows` to select an explicit wider proof; exceeding row/query budgets
62
+ is incomplete evidence, never a green result. Request success remains separate
63
+ from capture admission, worker processing, publication and exporter transport.
@@ -0,0 +1,93 @@
1
+ # Opt-in native collector profile (otelcol-contrib >= 0.160.0).
2
+ # This persists collector retry queues, never application log files. Configure a
3
+ # private directory and a filesystem quota; queue byte bounds exclude DB overhead.
4
+ receivers:
5
+ otlp/metadata:
6
+ protocols:
7
+ http:
8
+ endpoint: ${env:NEUROLINK_OTEL_METADATA_LISTEN:-127.0.0.1:14318}
9
+ otlp/bodies:
10
+ protocols:
11
+ http:
12
+ endpoint: ${env:NEUROLINK_OTEL_BODIES_LISTEN:-127.0.0.1:14319}
13
+ processors:
14
+ memory_limiter:
15
+ check_interval: 1s
16
+ limit_mib: 256
17
+ spike_limit_mib: 64
18
+ exporters:
19
+ otlphttp/openobserve:
20
+ endpoint: ${env:NEUROLINK_OPENOBSERVE_OTLP_ENDPOINT}
21
+ encoding: json
22
+ headers:
23
+ Authorization: ${env:NEUROLINK_OPENOBSERVE_BASIC_AUTH}
24
+ stream-name: ${env:NEUROLINK_PROXY_STREAM_HEADER:-neurolink_proxy}
25
+ retry_on_failure:
26
+ enabled: true
27
+ initial_interval: 1s
28
+ max_interval: 30s
29
+ max_elapsed_time: 0s
30
+ sending_queue:
31
+ enabled: true
32
+ num_consumers: 2
33
+ sizer: bytes
34
+ queue_size: 33554432
35
+ storage: file_storage
36
+ otlphttp/openobserve-bodies:
37
+ endpoint: ${env:NEUROLINK_OPENOBSERVE_OTLP_ENDPOINT}
38
+ encoding: json
39
+ headers:
40
+ Authorization: ${env:NEUROLINK_OPENOBSERVE_BASIC_AUTH}
41
+ stream-name: ${env:NEUROLINK_PROXY_BODY_STREAM_HEADER:-neurolink_proxy_bodies}
42
+ retry_on_failure:
43
+ enabled: true
44
+ initial_interval: 1s
45
+ max_interval: 30s
46
+ max_elapsed_time: 0s
47
+ sending_queue:
48
+ enabled: true
49
+ num_consumers: 2
50
+ sizer: bytes
51
+ queue_size: 268435456
52
+ storage: file_storage
53
+ extensions:
54
+ file_storage:
55
+ directory: ${env:NEUROLINK_OTEL_QUEUE_DIRECTORY}
56
+ create_directory: true
57
+ fsync: true
58
+ compaction:
59
+ on_start: true
60
+ on_rebound: true
61
+ directory: ${env:NEUROLINK_OTEL_COMPACTION_DIRECTORY}
62
+ health_check:
63
+ endpoint: ${env:NEUROLINK_OTEL_HEALTH_LISTEN:-127.0.0.1:14333}
64
+ service:
65
+ extensions: [file_storage, health_check]
66
+ pipelines:
67
+ logs/metadata:
68
+ receivers: [otlp/metadata]
69
+ processors: [memory_limiter]
70
+ exporters: [otlphttp/openobserve]
71
+ logs/bodies:
72
+ receivers: [otlp/bodies]
73
+ processors: [memory_limiter]
74
+ exporters: [otlphttp/openobserve-bodies]
75
+ traces:
76
+ receivers: [otlp/metadata]
77
+ processors: [memory_limiter]
78
+ exporters: [otlphttp/openobserve]
79
+ metrics:
80
+ receivers: [otlp/metadata]
81
+ processors: [memory_limiter]
82
+ exporters: [otlphttp/openobserve]
83
+ telemetry:
84
+ logs:
85
+ level: warn
86
+ metrics:
87
+ level: detailed
88
+ readers:
89
+ - pull:
90
+ exporter:
91
+ prometheus:
92
+ host: "127.0.0.1"
93
+ port: ${env:NEUROLINK_OTEL_METRICS_PORT:-14388}
@@ -37,9 +37,25 @@ export async function resolveProxyTelemetryBackend(env = process.env) {
37
37
  }
38
38
  }
39
39
  }
40
+ /** Resolve collector environment substitutions without logging their values.
41
+ * @param {string | undefined} value
42
+ */
43
+ const resolveCollectorValue = (value) =>
44
+ value?.replace(
45
+ /\$\{env:([A-Za-z_][A-Za-z0-9_]*)(?::-([^}]*))?\}/g,
46
+ (_match, name, fallback) => {
47
+ const resolved = env[name] ?? fallback;
48
+ if (resolved === undefined)
49
+ {throw new Error(
50
+ `Collector environment variable ${name} is not configured`,
51
+ );}
52
+ return resolved;
53
+ },
54
+ );
40
55
  const exporter = native?.exporters?.["otlphttp/openobserve"];
41
- const destination = exporter?.endpoint
42
- ? new URL(exporter.endpoint)
56
+ const configuredEndpoint = resolveCollectorValue(exporter?.endpoint);
57
+ const destination = configuredEndpoint
58
+ ? new URL(configuredEndpoint)
43
59
  : undefined;
44
60
  const nativeOrg = destination?.pathname.match(
45
61
  /^\/api\/([a-zA-Z0-9_-]+)\/?$/,
@@ -48,7 +64,9 @@ export async function resolveProxyTelemetryBackend(env = process.env) {
48
64
  env.NEUROLINK_OPENOBSERVE_BASIC_AUTH ??
49
65
  (env.NEUROLINK_OPENOBSERVE_USER && env.NEUROLINK_OPENOBSERVE_PASSWORD
50
66
  ? `Basic ${Buffer.from(`${env.NEUROLINK_OPENOBSERVE_USER}:${env.NEUROLINK_OPENOBSERVE_PASSWORD}`).toString("base64")}`
51
- : (exporter?.headers?.Authorization ?? exporter?.headers?.authorization));
67
+ : resolveCollectorValue(
68
+ exporter?.headers?.Authorization ?? exporter?.headers?.authorization,
69
+ ));
52
70
  return {
53
71
  baseUrl:
54
72
  env.NEUROLINK_OPENOBSERVE_URL ??
@@ -57,8 +75,15 @@ export async function resolveProxyTelemetryBackend(env = process.env) {
57
75
  organization: env.NEUROLINK_OPENOBSERVE_ORG ?? nativeOrg ?? "default",
58
76
  stream:
59
77
  env.NEUROLINK_PROXY_STREAM_HEADER ??
60
- exporter?.headers?.["stream-name"] ??
78
+ resolveCollectorValue(exporter?.headers?.["stream-name"]) ??
61
79
  "neurolink_proxy",
80
+ bodyStream:
81
+ env.NEUROLINK_PROXY_BODY_STREAM_HEADER ??
82
+ resolveCollectorValue(
83
+ native?.exporters?.["otlphttp/openobserve-bodies"]?.headers?.[
84
+ "stream-name"
85
+ ],
86
+ ),
62
87
  authorization,
63
88
  collectorMetricsUrl:
64
89
  env.NEUROLINK_OTEL_COLLECTOR_METRICS_URL ??
@@ -72,7 +97,9 @@ export async function resolveProxyTelemetryBackend(env = process.env) {
72
97
  export function validateProxyTelemetryBackend(backend) {
73
98
  if (
74
99
  !/^[a-zA-Z0-9_-]+$/.test(backend.organization) ||
75
- !/^[a-zA-Z0-9_]+$/.test(backend.stream)
100
+ !/^[a-zA-Z0-9_]+$/.test(backend.stream) ||
101
+ (backend.bodyStream !== undefined &&
102
+ !/^[a-zA-Z0-9_]+$/.test(backend.bodyStream))
76
103
  ) {
77
104
  throw new Error("Invalid telemetry organization or stream");
78
105
  }