@juspay/neurolink 9.61.2 → 9.63.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.
Files changed (150) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +132 -103
  3. package/dist/adapters/tts/googleTTSHandler.js +1 -1
  4. package/dist/browser/neurolink.min.js +373 -355
  5. package/dist/cli/commands/auth.d.ts +19 -0
  6. package/dist/cli/commands/auth.js +266 -0
  7. package/dist/cli/commands/proxy.js +77 -2
  8. package/dist/cli/commands/serve.js +9 -0
  9. package/dist/cli/commands/voiceServer.d.ts +7 -0
  10. package/dist/cli/commands/voiceServer.js +9 -1
  11. package/dist/cli/factories/authCommandFactory.d.ts +8 -0
  12. package/dist/cli/factories/authCommandFactory.js +41 -0
  13. package/dist/cli/factories/commandFactory.js +136 -11
  14. package/dist/cli/loop/optionsSchema.d.ts +1 -1
  15. package/dist/cli/utils/audioFileUtils.d.ts +3 -3
  16. package/dist/cli/utils/audioFileUtils.js +5 -1
  17. package/dist/core/baseProvider.js +29 -6
  18. package/dist/factories/providerRegistry.d.ts +14 -0
  19. package/dist/factories/providerRegistry.js +141 -2
  20. package/dist/lib/adapters/tts/googleTTSHandler.js +1 -1
  21. package/dist/lib/core/baseProvider.js +29 -6
  22. package/dist/lib/factories/providerRegistry.d.ts +14 -0
  23. package/dist/lib/factories/providerRegistry.js +141 -2
  24. package/dist/lib/neurolink.d.ts +19 -0
  25. package/dist/lib/neurolink.js +248 -12
  26. package/dist/lib/observability/exporters/laminarExporter.js +1 -0
  27. package/dist/lib/observability/exporters/posthogExporter.js +1 -0
  28. package/dist/lib/observability/utils/spanSerializer.js +1 -0
  29. package/dist/lib/proxy/proxyConfig.js +14 -0
  30. package/dist/lib/server/routes/claudeProxyRoutes.d.ts +24 -2
  31. package/dist/lib/server/routes/claudeProxyRoutes.js +61 -9
  32. package/dist/lib/server/voice/tokenCompare.d.ts +14 -0
  33. package/dist/lib/server/voice/tokenCompare.js +23 -0
  34. package/dist/lib/server/voice/voiceServerApp.js +62 -3
  35. package/dist/lib/server/voice/voiceWebSocketHandler.d.ts +20 -3
  36. package/dist/lib/server/voice/voiceWebSocketHandler.js +555 -435
  37. package/dist/lib/types/cli.d.ts +4 -0
  38. package/dist/lib/types/generate.d.ts +47 -0
  39. package/dist/lib/types/index.d.ts +1 -1
  40. package/dist/lib/types/index.js +1 -1
  41. package/dist/lib/types/proxy.d.ts +23 -1
  42. package/dist/lib/types/realtime.d.ts +243 -0
  43. package/dist/lib/types/realtime.js +70 -0
  44. package/dist/lib/types/server.d.ts +68 -0
  45. package/dist/lib/types/span.d.ts +2 -0
  46. package/dist/lib/types/span.js +2 -0
  47. package/dist/lib/types/stream.d.ts +36 -14
  48. package/dist/lib/types/stt.d.ts +585 -0
  49. package/dist/lib/types/stt.js +90 -0
  50. package/dist/lib/types/subscription.d.ts +5 -0
  51. package/dist/lib/types/tts.d.ts +23 -11
  52. package/dist/lib/types/tts.js +7 -0
  53. package/dist/lib/types/voice.d.ts +272 -0
  54. package/dist/lib/types/voice.js +137 -0
  55. package/dist/lib/utils/audioFormatDetector.d.ts +15 -0
  56. package/dist/lib/utils/audioFormatDetector.js +34 -0
  57. package/dist/lib/utils/sttProcessor.d.ts +115 -0
  58. package/dist/lib/utils/sttProcessor.js +295 -0
  59. package/dist/lib/voice/RealtimeVoiceAPI.d.ts +183 -0
  60. package/dist/lib/voice/RealtimeVoiceAPI.js +439 -0
  61. package/dist/lib/voice/audio-utils.d.ts +135 -0
  62. package/dist/lib/voice/audio-utils.js +435 -0
  63. package/dist/lib/voice/errors.d.ts +123 -0
  64. package/dist/lib/voice/errors.js +386 -0
  65. package/dist/lib/voice/index.d.ts +26 -0
  66. package/dist/lib/voice/index.js +55 -0
  67. package/dist/lib/voice/providers/AzureSTT.d.ts +47 -0
  68. package/dist/lib/voice/providers/AzureSTT.js +345 -0
  69. package/dist/lib/voice/providers/AzureTTS.d.ts +59 -0
  70. package/dist/lib/voice/providers/AzureTTS.js +349 -0
  71. package/dist/lib/voice/providers/DeepgramSTT.d.ts +40 -0
  72. package/dist/lib/voice/providers/DeepgramSTT.js +550 -0
  73. package/dist/lib/voice/providers/ElevenLabsTTS.d.ts +53 -0
  74. package/dist/lib/voice/providers/ElevenLabsTTS.js +311 -0
  75. package/dist/lib/voice/providers/GeminiLive.d.ts +52 -0
  76. package/dist/lib/voice/providers/GeminiLive.js +372 -0
  77. package/dist/lib/voice/providers/GoogleSTT.d.ts +60 -0
  78. package/dist/lib/voice/providers/GoogleSTT.js +454 -0
  79. package/dist/lib/voice/providers/OpenAIRealtime.d.ts +47 -0
  80. package/dist/lib/voice/providers/OpenAIRealtime.js +412 -0
  81. package/dist/lib/voice/providers/OpenAISTT.d.ts +41 -0
  82. package/dist/lib/voice/providers/OpenAISTT.js +286 -0
  83. package/dist/lib/voice/providers/OpenAITTS.d.ts +49 -0
  84. package/dist/lib/voice/providers/OpenAITTS.js +271 -0
  85. package/dist/lib/voice/stream-handler.d.ts +166 -0
  86. package/dist/lib/voice/stream-handler.js +514 -0
  87. package/dist/neurolink.d.ts +19 -0
  88. package/dist/neurolink.js +248 -12
  89. package/dist/observability/exporters/laminarExporter.js +1 -0
  90. package/dist/observability/exporters/posthogExporter.js +1 -0
  91. package/dist/observability/utils/spanSerializer.js +1 -0
  92. package/dist/proxy/proxyConfig.js +14 -0
  93. package/dist/server/routes/claudeProxyRoutes.d.ts +24 -2
  94. package/dist/server/routes/claudeProxyRoutes.js +61 -9
  95. package/dist/server/voice/tokenCompare.d.ts +14 -0
  96. package/dist/server/voice/tokenCompare.js +22 -0
  97. package/dist/server/voice/voiceServerApp.js +62 -3
  98. package/dist/server/voice/voiceWebSocketHandler.d.ts +20 -3
  99. package/dist/server/voice/voiceWebSocketHandler.js +555 -435
  100. package/dist/types/cli.d.ts +4 -0
  101. package/dist/types/generate.d.ts +47 -0
  102. package/dist/types/index.d.ts +1 -1
  103. package/dist/types/index.js +1 -1
  104. package/dist/types/proxy.d.ts +23 -1
  105. package/dist/types/realtime.d.ts +243 -0
  106. package/dist/types/realtime.js +69 -0
  107. package/dist/types/server.d.ts +68 -0
  108. package/dist/types/span.d.ts +2 -0
  109. package/dist/types/span.js +2 -0
  110. package/dist/types/stream.d.ts +36 -14
  111. package/dist/types/stt.d.ts +585 -0
  112. package/dist/types/stt.js +89 -0
  113. package/dist/types/subscription.d.ts +5 -0
  114. package/dist/types/tts.d.ts +23 -11
  115. package/dist/types/tts.js +7 -0
  116. package/dist/types/voice.d.ts +272 -0
  117. package/dist/types/voice.js +136 -0
  118. package/dist/utils/audioFormatDetector.d.ts +15 -0
  119. package/dist/utils/audioFormatDetector.js +33 -0
  120. package/dist/utils/sttProcessor.d.ts +115 -0
  121. package/dist/utils/sttProcessor.js +294 -0
  122. package/dist/voice/RealtimeVoiceAPI.d.ts +183 -0
  123. package/dist/voice/RealtimeVoiceAPI.js +438 -0
  124. package/dist/voice/audio-utils.d.ts +135 -0
  125. package/dist/voice/audio-utils.js +434 -0
  126. package/dist/voice/errors.d.ts +123 -0
  127. package/dist/voice/errors.js +385 -0
  128. package/dist/voice/index.d.ts +26 -0
  129. package/dist/voice/index.js +54 -0
  130. package/dist/voice/providers/AzureSTT.d.ts +47 -0
  131. package/dist/voice/providers/AzureSTT.js +344 -0
  132. package/dist/voice/providers/AzureTTS.d.ts +59 -0
  133. package/dist/voice/providers/AzureTTS.js +348 -0
  134. package/dist/voice/providers/DeepgramSTT.d.ts +40 -0
  135. package/dist/voice/providers/DeepgramSTT.js +549 -0
  136. package/dist/voice/providers/ElevenLabsTTS.d.ts +53 -0
  137. package/dist/voice/providers/ElevenLabsTTS.js +310 -0
  138. package/dist/voice/providers/GeminiLive.d.ts +52 -0
  139. package/dist/voice/providers/GeminiLive.js +371 -0
  140. package/dist/voice/providers/GoogleSTT.d.ts +60 -0
  141. package/dist/voice/providers/GoogleSTT.js +453 -0
  142. package/dist/voice/providers/OpenAIRealtime.d.ts +47 -0
  143. package/dist/voice/providers/OpenAIRealtime.js +411 -0
  144. package/dist/voice/providers/OpenAISTT.d.ts +41 -0
  145. package/dist/voice/providers/OpenAISTT.js +285 -0
  146. package/dist/voice/providers/OpenAITTS.d.ts +49 -0
  147. package/dist/voice/providers/OpenAITTS.js +270 -0
  148. package/dist/voice/stream-handler.d.ts +166 -0
  149. package/dist/voice/stream-handler.js +513 -0
  150. package/package.json +23 -2
@@ -4,6 +4,7 @@ import http from "http";
4
4
  import path from "path";
5
5
  import { fileURLToPath } from "url";
6
6
  import { setupWebSocket } from "./voiceWebSocketHandler.js";
7
+ import { timingSafeEqualString } from "./tokenCompare.js";
7
8
  import { NeuroLink } from "../../neurolink.js";
8
9
  import { logger } from "../../utils/logger.js";
9
10
  import { withTimeout } from "../../utils/async/withTimeout.js";
@@ -30,6 +31,50 @@ function resolvePublicPath() {
30
31
  }
31
32
  export async function startVoiceServer(port = 3000) {
32
33
  const app = express();
34
+ // NEW11: refuse to bind to non-loopback interfaces unless the operator
35
+ // has explicitly opted in. The voice server has minimal hardening and
36
+ // exposing it publicly without a token leaks Soniox / Cartesia / LLM
37
+ // credit usage to anyone who can reach the listener.
38
+ const allowPublic = process.env.VOICE_SERVER_ALLOW_PUBLIC === "1";
39
+ const host = allowPublic
40
+ ? (process.env.VOICE_SERVER_HOST ?? "0.0.0.0")
41
+ : "127.0.0.1";
42
+ // NEW11: optional shared-secret bearer token for both HTTP and WebSocket
43
+ // upgrade. When VOICE_SERVER_AUTH_TOKEN is set, every HTTP request must
44
+ // carry `Authorization: Bearer <token>`. The WS upgrade additionally
45
+ // accepts `?token=<token>` because browser WebSocket constructors cannot
46
+ // set custom headers — see voiceWebSocketHandler.verifyClient. HTTP routes
47
+ // intentionally reject `?token=` (would leak via Referer + access logs).
48
+ const authToken = process.env.VOICE_SERVER_AUTH_TOKEN;
49
+ /* ---------- BODY LIMITS + AUTH ---------- */
50
+ // NEW11: cap JSON / urlencoded body to 100kb. Express's default is 100kb
51
+ // for json() but only when explicitly registered; without this any future
52
+ // body parser would default to whatever its own limit is.
53
+ app.use(express.json({ limit: "100kb" }));
54
+ app.use(express.urlencoded({ limit: "100kb", extended: false }));
55
+ // NEW11: minimal HTTP auth middleware. Skips when no token is configured
56
+ // (back-compat — local-only dev keeps working). Skips for /health so
57
+ // load-balancers can probe without credentials.
58
+ if (authToken) {
59
+ app.use((req, res, next) => {
60
+ if (req.path === "/health") {
61
+ return next();
62
+ }
63
+ const header = req.header("authorization");
64
+ // Bug 3 fix: HTTP routes only accept the bearer header. The `?token=`
65
+ // fallback exists only on the WS upgrade where the browser API cannot
66
+ // attach headers — using it on regular HTTP would leak credentials via
67
+ // Referer headers, browser history, server access logs, and proxies.
68
+ const provided = header?.startsWith("Bearer ")
69
+ ? header.slice(7)
70
+ : undefined;
71
+ if (!provided || !timingSafeEqualString(provided, authToken)) {
72
+ res.status(401).json({ error: "Unauthorized" });
73
+ return;
74
+ }
75
+ next();
76
+ });
77
+ }
33
78
  /* ---------- STATIC FILES ---------- */
34
79
  const publicPath = resolvePublicPath();
35
80
  logger.info("[SERVER] Serving static from:", publicPath);
@@ -41,15 +86,29 @@ export async function startVoiceServer(port = 3000) {
41
86
  app.get("/health", (_, res) => {
42
87
  res.json({ status: "ok" });
43
88
  });
89
+ /* ---------- ERROR HANDLER ---------- */
90
+ // NEW11: global Express error handler so synchronous and async errors are
91
+ // caught instead of crashing the process or leaking stack traces.
92
+ app.use((err, _req, res, _next) => {
93
+ logger.error(`[SERVER] Unhandled error: ${err instanceof Error ? err.message : String(err)}`);
94
+ if (!res.headersSent) {
95
+ res.status(500).json({ error: "Internal server error" });
96
+ }
97
+ });
44
98
  const server = http.createServer(app);
45
99
  /* ---------- WS ---------- */
46
- setupWebSocket(server);
100
+ // NEW11: pass the auth token + allow-public flag through to the WS handler
101
+ // so it can verify clients on upgrade and apply maxPayload caps.
102
+ setupWebSocket(server, { authToken, maxPayload: 1_048_576 });
47
103
  /* ---------- START ---------- */
48
104
  await new Promise((resolve, reject) => {
49
105
  server.once("error", reject);
50
- server.listen(port, () => {
106
+ server.listen(port, host, () => {
51
107
  server.removeListener("error", reject);
52
- logger.info(`[SERVER] Voice server running at http://localhost:${port}`);
108
+ const exposure = allowPublic
109
+ ? `bound publicly on ${host}:${port} (VOICE_SERVER_ALLOW_PUBLIC=1)`
110
+ : `bound to loopback ${host}:${port} (set VOICE_SERVER_ALLOW_PUBLIC=1 to expose externally)`;
111
+ logger.info(`[SERVER] Voice server running — ${exposure}${authToken ? " (auth required)" : " (no auth — token via VOICE_SERVER_AUTH_TOKEN recommended)"}`);
53
112
  resolve();
54
113
  });
55
114
  });
@@ -1,7 +1,24 @@
1
1
  import type { Server as HttpServer } from "http";
2
2
  /**
3
- * Call from the voice-server command handler BEFORE importing anything else
4
- * so the env change is scoped to voice mode only.
3
+ * Voice-server-mode environment configuration.
4
+ *
5
+ * @deprecated NEW12 — this used to mutate `process.env.NEUROLINK_DISABLE_MCP_TOOLS`
6
+ * which is process-wide. That broke any embedder that called this function in
7
+ * a process which ALSO used NeuroLink for non-voice work. The disable-tools
8
+ * intent is now passed explicitly via `disableTools: true` on every NeuroLink
9
+ * `generate()` / `stream()` call inside this server (see line ~167). Calling
10
+ * this function is now a no-op kept for backwards compatibility.
5
11
  */
6
12
  export declare function configureVoiceServerEnvironment(): void;
7
- export declare function setupWebSocket(server: HttpServer): void;
13
+ /**
14
+ * Returns a copy of an outbound Soniox payload with the API key redacted.
15
+ *
16
+ * Use this whenever debug logging the auth frame — never JSON.stringify the
17
+ * raw object. (C3 mitigation: prevents the Soniox API key from leaking into
18
+ * any aggregated log sink even if a future debug statement serialises the
19
+ * outbound payload.)
20
+ */
21
+ export declare function redactSonioxAuth<T extends {
22
+ api_key?: string;
23
+ }>(payload: T): T;
24
+ export declare function setupWebSocket(server: HttpServer, options?: import("../../types/index.js").ServerVoiceWebSocketOptions): void;