@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.
- package/CHANGELOG.md +12 -0
- package/README.md +132 -103
- package/dist/adapters/tts/googleTTSHandler.js +1 -1
- package/dist/browser/neurolink.min.js +373 -355
- package/dist/cli/commands/auth.d.ts +19 -0
- package/dist/cli/commands/auth.js +266 -0
- package/dist/cli/commands/proxy.js +77 -2
- package/dist/cli/commands/serve.js +9 -0
- package/dist/cli/commands/voiceServer.d.ts +7 -0
- package/dist/cli/commands/voiceServer.js +9 -1
- package/dist/cli/factories/authCommandFactory.d.ts +8 -0
- package/dist/cli/factories/authCommandFactory.js +41 -0
- package/dist/cli/factories/commandFactory.js +136 -11
- package/dist/cli/loop/optionsSchema.d.ts +1 -1
- package/dist/cli/utils/audioFileUtils.d.ts +3 -3
- package/dist/cli/utils/audioFileUtils.js +5 -1
- package/dist/core/baseProvider.js +29 -6
- package/dist/factories/providerRegistry.d.ts +14 -0
- package/dist/factories/providerRegistry.js +141 -2
- package/dist/lib/adapters/tts/googleTTSHandler.js +1 -1
- package/dist/lib/core/baseProvider.js +29 -6
- package/dist/lib/factories/providerRegistry.d.ts +14 -0
- package/dist/lib/factories/providerRegistry.js +141 -2
- package/dist/lib/neurolink.d.ts +19 -0
- package/dist/lib/neurolink.js +248 -12
- package/dist/lib/observability/exporters/laminarExporter.js +1 -0
- package/dist/lib/observability/exporters/posthogExporter.js +1 -0
- package/dist/lib/observability/utils/spanSerializer.js +1 -0
- package/dist/lib/proxy/proxyConfig.js +14 -0
- package/dist/lib/server/routes/claudeProxyRoutes.d.ts +24 -2
- package/dist/lib/server/routes/claudeProxyRoutes.js +61 -9
- package/dist/lib/server/voice/tokenCompare.d.ts +14 -0
- package/dist/lib/server/voice/tokenCompare.js +23 -0
- package/dist/lib/server/voice/voiceServerApp.js +62 -3
- package/dist/lib/server/voice/voiceWebSocketHandler.d.ts +20 -3
- package/dist/lib/server/voice/voiceWebSocketHandler.js +555 -435
- package/dist/lib/types/cli.d.ts +4 -0
- package/dist/lib/types/generate.d.ts +47 -0
- package/dist/lib/types/index.d.ts +1 -1
- package/dist/lib/types/index.js +1 -1
- package/dist/lib/types/proxy.d.ts +23 -1
- package/dist/lib/types/realtime.d.ts +243 -0
- package/dist/lib/types/realtime.js +70 -0
- package/dist/lib/types/server.d.ts +68 -0
- package/dist/lib/types/span.d.ts +2 -0
- package/dist/lib/types/span.js +2 -0
- package/dist/lib/types/stream.d.ts +36 -14
- package/dist/lib/types/stt.d.ts +585 -0
- package/dist/lib/types/stt.js +90 -0
- package/dist/lib/types/subscription.d.ts +5 -0
- package/dist/lib/types/tts.d.ts +23 -11
- package/dist/lib/types/tts.js +7 -0
- package/dist/lib/types/voice.d.ts +272 -0
- package/dist/lib/types/voice.js +137 -0
- package/dist/lib/utils/audioFormatDetector.d.ts +15 -0
- package/dist/lib/utils/audioFormatDetector.js +34 -0
- package/dist/lib/utils/sttProcessor.d.ts +115 -0
- package/dist/lib/utils/sttProcessor.js +295 -0
- package/dist/lib/voice/RealtimeVoiceAPI.d.ts +183 -0
- package/dist/lib/voice/RealtimeVoiceAPI.js +439 -0
- package/dist/lib/voice/audio-utils.d.ts +135 -0
- package/dist/lib/voice/audio-utils.js +435 -0
- package/dist/lib/voice/errors.d.ts +123 -0
- package/dist/lib/voice/errors.js +386 -0
- package/dist/lib/voice/index.d.ts +26 -0
- package/dist/lib/voice/index.js +55 -0
- package/dist/lib/voice/providers/AzureSTT.d.ts +47 -0
- package/dist/lib/voice/providers/AzureSTT.js +345 -0
- package/dist/lib/voice/providers/AzureTTS.d.ts +59 -0
- package/dist/lib/voice/providers/AzureTTS.js +349 -0
- package/dist/lib/voice/providers/DeepgramSTT.d.ts +40 -0
- package/dist/lib/voice/providers/DeepgramSTT.js +550 -0
- package/dist/lib/voice/providers/ElevenLabsTTS.d.ts +53 -0
- package/dist/lib/voice/providers/ElevenLabsTTS.js +311 -0
- package/dist/lib/voice/providers/GeminiLive.d.ts +52 -0
- package/dist/lib/voice/providers/GeminiLive.js +372 -0
- package/dist/lib/voice/providers/GoogleSTT.d.ts +60 -0
- package/dist/lib/voice/providers/GoogleSTT.js +454 -0
- package/dist/lib/voice/providers/OpenAIRealtime.d.ts +47 -0
- package/dist/lib/voice/providers/OpenAIRealtime.js +412 -0
- package/dist/lib/voice/providers/OpenAISTT.d.ts +41 -0
- package/dist/lib/voice/providers/OpenAISTT.js +286 -0
- package/dist/lib/voice/providers/OpenAITTS.d.ts +49 -0
- package/dist/lib/voice/providers/OpenAITTS.js +271 -0
- package/dist/lib/voice/stream-handler.d.ts +166 -0
- package/dist/lib/voice/stream-handler.js +514 -0
- package/dist/neurolink.d.ts +19 -0
- package/dist/neurolink.js +248 -12
- package/dist/observability/exporters/laminarExporter.js +1 -0
- package/dist/observability/exporters/posthogExporter.js +1 -0
- package/dist/observability/utils/spanSerializer.js +1 -0
- package/dist/proxy/proxyConfig.js +14 -0
- package/dist/server/routes/claudeProxyRoutes.d.ts +24 -2
- package/dist/server/routes/claudeProxyRoutes.js +61 -9
- package/dist/server/voice/tokenCompare.d.ts +14 -0
- package/dist/server/voice/tokenCompare.js +22 -0
- package/dist/server/voice/voiceServerApp.js +62 -3
- package/dist/server/voice/voiceWebSocketHandler.d.ts +20 -3
- package/dist/server/voice/voiceWebSocketHandler.js +555 -435
- package/dist/types/cli.d.ts +4 -0
- package/dist/types/generate.d.ts +47 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/proxy.d.ts +23 -1
- package/dist/types/realtime.d.ts +243 -0
- package/dist/types/realtime.js +69 -0
- package/dist/types/server.d.ts +68 -0
- package/dist/types/span.d.ts +2 -0
- package/dist/types/span.js +2 -0
- package/dist/types/stream.d.ts +36 -14
- package/dist/types/stt.d.ts +585 -0
- package/dist/types/stt.js +89 -0
- package/dist/types/subscription.d.ts +5 -0
- package/dist/types/tts.d.ts +23 -11
- package/dist/types/tts.js +7 -0
- package/dist/types/voice.d.ts +272 -0
- package/dist/types/voice.js +136 -0
- package/dist/utils/audioFormatDetector.d.ts +15 -0
- package/dist/utils/audioFormatDetector.js +33 -0
- package/dist/utils/sttProcessor.d.ts +115 -0
- package/dist/utils/sttProcessor.js +294 -0
- package/dist/voice/RealtimeVoiceAPI.d.ts +183 -0
- package/dist/voice/RealtimeVoiceAPI.js +438 -0
- package/dist/voice/audio-utils.d.ts +135 -0
- package/dist/voice/audio-utils.js +434 -0
- package/dist/voice/errors.d.ts +123 -0
- package/dist/voice/errors.js +385 -0
- package/dist/voice/index.d.ts +26 -0
- package/dist/voice/index.js +54 -0
- package/dist/voice/providers/AzureSTT.d.ts +47 -0
- package/dist/voice/providers/AzureSTT.js +344 -0
- package/dist/voice/providers/AzureTTS.d.ts +59 -0
- package/dist/voice/providers/AzureTTS.js +348 -0
- package/dist/voice/providers/DeepgramSTT.d.ts +40 -0
- package/dist/voice/providers/DeepgramSTT.js +549 -0
- package/dist/voice/providers/ElevenLabsTTS.d.ts +53 -0
- package/dist/voice/providers/ElevenLabsTTS.js +310 -0
- package/dist/voice/providers/GeminiLive.d.ts +52 -0
- package/dist/voice/providers/GeminiLive.js +371 -0
- package/dist/voice/providers/GoogleSTT.d.ts +60 -0
- package/dist/voice/providers/GoogleSTT.js +453 -0
- package/dist/voice/providers/OpenAIRealtime.d.ts +47 -0
- package/dist/voice/providers/OpenAIRealtime.js +411 -0
- package/dist/voice/providers/OpenAISTT.d.ts +41 -0
- package/dist/voice/providers/OpenAISTT.js +285 -0
- package/dist/voice/providers/OpenAITTS.d.ts +49 -0
- package/dist/voice/providers/OpenAITTS.js +270 -0
- package/dist/voice/stream-handler.d.ts +166 -0
- package/dist/voice/stream-handler.js +513 -0
- 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
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
4
|
-
*
|
|
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
|
-
|
|
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;
|