@juspay/neurolink 12.48.2 → 12.49.1

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 (106) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/dist/browser/neurolink.min.js +616 -595
  3. package/dist/cli/commands/serve.d.ts +0 -3
  4. package/dist/cli/commands/serve.js +85 -3
  5. package/dist/cli/commands/transcribe.d.ts +24 -0
  6. package/dist/cli/commands/transcribe.js +718 -0
  7. package/dist/cli/factories/commandFactory.d.ts +10 -0
  8. package/dist/cli/factories/commandFactory.js +13 -0
  9. package/dist/cli/parser.js +3 -0
  10. package/dist/factories/mediaHandlerCatalog.js +11 -9
  11. package/dist/factories/providerDescriptors.js +5 -4
  12. package/dist/factories/sttDescriptors.d.ts +63 -0
  13. package/dist/factories/sttDescriptors.js +286 -0
  14. package/dist/index.d.ts +4 -1
  15. package/dist/index.js +7 -1
  16. package/dist/neurolink.d.ts +68 -1
  17. package/dist/neurolink.js +202 -4
  18. package/dist/processors/media/AudioProcessor.d.ts +15 -56
  19. package/dist/processors/media/AudioProcessor.js +105 -276
  20. package/dist/processors/media/VideoProcessor.d.ts +3 -5
  21. package/dist/processors/media/VideoProcessor.js +52 -51
  22. package/dist/providers/cloudflareClef.js +9 -1
  23. package/dist/server/abstract/baseServerAdapter.d.ts +7 -0
  24. package/dist/server/abstract/baseServerAdapter.js +13 -1
  25. package/dist/server/adapters/expressAdapter.d.ts +1 -0
  26. package/dist/server/adapters/expressAdapter.js +48 -4
  27. package/dist/server/adapters/fastifyAdapter.d.ts +1 -0
  28. package/dist/server/adapters/fastifyAdapter.js +38 -1
  29. package/dist/server/adapters/honoAdapter.d.ts +1 -4
  30. package/dist/server/adapters/honoAdapter.js +83 -1
  31. package/dist/server/adapters/koaAdapter.d.ts +1 -0
  32. package/dist/server/adapters/koaAdapter.js +43 -0
  33. package/dist/server/index.d.ts +3 -2
  34. package/dist/server/index.js +3 -2
  35. package/dist/server/routes/index.d.ts +1 -0
  36. package/dist/server/routes/index.js +3 -0
  37. package/dist/server/routes/transcribeRoutes.d.ts +23 -0
  38. package/dist/server/routes/transcribeRoutes.js +506 -0
  39. package/dist/server/utils/rawBody.d.ts +32 -0
  40. package/dist/server/utils/rawBody.js +76 -0
  41. package/dist/server/utils/validation.d.ts +192 -0
  42. package/dist/server/utils/validation.js +100 -0
  43. package/dist/server/websocket/transcribeWebSocket.d.ts +42 -0
  44. package/dist/server/websocket/transcribeWebSocket.js +264 -0
  45. package/dist/types/cli.d.ts +46 -0
  46. package/dist/types/index.d.ts +1 -0
  47. package/dist/types/index.js +1 -0
  48. package/dist/types/providers.d.ts +7 -1
  49. package/dist/types/server.d.ts +117 -1
  50. package/dist/types/stt.d.ts +160 -7
  51. package/dist/types/transcribe.d.ts +506 -0
  52. package/dist/types/transcribe.js +29 -0
  53. package/dist/utils/speakerTurns.d.ts +28 -0
  54. package/dist/utils/speakerTurns.js +93 -0
  55. package/dist/utils/sttProcessor.d.ts +20 -2
  56. package/dist/utils/sttProcessor.js +73 -5
  57. package/dist/voice/correction/dictionary.d.ts +49 -0
  58. package/dist/voice/correction/dictionary.js +134 -0
  59. package/dist/voice/correction/guard.d.ts +35 -0
  60. package/dist/voice/correction/guard.js +161 -0
  61. package/dist/voice/correction/index.d.ts +47 -0
  62. package/dist/voice/correction/index.js +211 -0
  63. package/dist/voice/correction/rewrite.d.ts +92 -0
  64. package/dist/voice/correction/rewrite.js +322 -0
  65. package/dist/voice/errors.d.ts +15 -0
  66. package/dist/voice/errors.js +45 -0
  67. package/dist/voice/index.d.ts +20 -2
  68. package/dist/voice/index.js +75 -9
  69. package/dist/voice/providers/AzureSTT.d.ts +10 -7
  70. package/dist/voice/providers/AzureSTT.js +23 -75
  71. package/dist/voice/providers/DeepgramSTT.d.ts +17 -2
  72. package/dist/voice/providers/DeepgramSTT.js +109 -13
  73. package/dist/voice/providers/ElevenLabsSTT.d.ts +12 -2
  74. package/dist/voice/providers/ElevenLabsSTT.js +34 -8
  75. package/dist/voice/providers/GoogleSTT.d.ts +10 -8
  76. package/dist/voice/providers/GoogleSTT.js +21 -75
  77. package/dist/voice/providers/OpenAISTT.d.ts +30 -9
  78. package/dist/voice/providers/OpenAISTT.js +196 -21
  79. package/dist/voice/providers/WhistleSTT.d.ts +87 -0
  80. package/dist/voice/providers/WhistleSTT.js +313 -0
  81. package/dist/voice/streaming/chunkedStreamAdapter.d.ts +19 -0
  82. package/dist/voice/streaming/chunkedStreamAdapter.js +519 -0
  83. package/dist/voice/streaming/endpointer.d.ts +81 -0
  84. package/dist/voice/streaming/endpointer.js +247 -0
  85. package/dist/voice/streaming/localAgreement.d.ts +30 -0
  86. package/dist/voice/streaming/localAgreement.js +44 -0
  87. package/dist/voice/sttEnvCredentials.d.ts +12 -0
  88. package/dist/voice/sttEnvCredentials.js +12 -0
  89. package/dist/voice/transcribe.d.ts +47 -0
  90. package/dist/voice/transcribe.js +519 -0
  91. package/dist/voice/transcribeStream.d.ts +4 -0
  92. package/dist/voice/transcribeStream.js +584 -0
  93. package/dist/voice/whistle/assets.d.ts +47 -0
  94. package/dist/voice/whistle/assets.js +270 -0
  95. package/dist/voice/whistle/audio.d.ts +32 -0
  96. package/dist/voice/whistle/audio.js +267 -0
  97. package/dist/voice/whistle/engine.d.ts +32 -0
  98. package/dist/voice/whistle/engine.js +193 -0
  99. package/dist/voice/whistle/worker.d.ts +18 -0
  100. package/dist/voice/whistle/worker.js +294 -0
  101. package/docs-site/static/search-index.json +71 -12
  102. package/models/whistle/README.md +18 -0
  103. package/models/whistle/needle.js +2 -0
  104. package/models/whistle/needle.wasm +0 -0
  105. package/models/whistle/whistle.cact +0 -0
  106. package/package.json +7 -3
@@ -9,9 +9,6 @@
9
9
  * neurolink serve status
10
10
  */
11
11
  import type { CommandModule } from "yargs";
12
- /**
13
- * Serve CLI command factory
14
- */
15
12
  export declare class ServeCommandFactory {
16
13
  /**
17
14
  * Create the main serve command
@@ -134,6 +134,50 @@ function createFileWatcher(onRestart, quiet) {
134
134
  /**
135
135
  * Serve CLI command factory
136
136
  */
137
+ /** A Node `http.Server` (or `https.Server`): it can take an `upgrade` listener. */
138
+ function isNodeHttpServer(value) {
139
+ return (typeof value === "object" &&
140
+ value !== null &&
141
+ typeof value.on === "function" &&
142
+ typeof value.listen === "function");
143
+ }
144
+ /**
145
+ * Live transcription streams over a WebSocket upgrade, which the HTTP
146
+ * adapters cannot route; it attaches to the Node server once it listens, on
147
+ * the first start and on every watch-mode restart. Bun and Deno serve
148
+ * without one, and then the route is simply absent. Guarded by the same
149
+ * NEUROLINK_SERVER_API_KEY(s) as the HTTP routes.
150
+ */
151
+ /** `--cors-origin` values, split on commas and trimmed; `undefined` when none were given. */
152
+ function corsOriginsFromArgv(values) {
153
+ if (!values || values.length === 0) {
154
+ return undefined;
155
+ }
156
+ const origins = values
157
+ .flatMap((value) => String(value).split(","))
158
+ .map((origin) => origin.trim())
159
+ .filter((origin) => origin.length > 0);
160
+ return origins.length > 0 ? origins : undefined;
161
+ }
162
+ async function attachTranscriptionWebSocket(server, neurolink, serverConfig) {
163
+ const native = server.getNativeServer?.();
164
+ if (!isNodeHttpServer(native)) {
165
+ return;
166
+ }
167
+ const { attachTranscribeWebSocket } = await import("../../server/websocket/transcribeWebSocket.js");
168
+ const apiKeys = readServerApiKeys();
169
+ // The same origin allow-list as the HTTP routes: with CORS on and a list
170
+ // that is not "*", a page from an unlisted origin cannot open the stream.
171
+ const origins = serverConfig.cors?.origins;
172
+ const allowedOrigins = serverConfig.cors?.enabled !== false && origins && !origins.includes("*")
173
+ ? origins
174
+ : undefined;
175
+ await attachTranscribeWebSocket(native, neurolink, {
176
+ ...(apiKeys.length > 0 ? { authToken: apiKeys } : {}),
177
+ ...(allowedOrigins ? { allowedOrigins } : {}),
178
+ });
179
+ logger.debug("[serve] transcription WebSocket attached at /v1/audio/transcriptions/stream");
180
+ }
137
181
  export class ServeCommandFactory {
138
182
  /**
139
183
  * Create the main serve command
@@ -180,6 +224,13 @@ export class ServeCommandFactory {
180
224
  .option("cors", {
181
225
  type: "boolean",
182
226
  description: "Enable CORS middleware (default: true)",
227
+ })
228
+ .option("cors-origin", {
229
+ type: "array",
230
+ string: true,
231
+ alias: "corsOrigin",
232
+ description: "Browser origin allowed by CORS (repeat or comma-separate; '*' for any). " +
233
+ "Default: none, so no web page can call the server cross-origin",
183
234
  })
184
235
  .option("rate-limit", {
185
236
  type: "number",
@@ -351,6 +402,9 @@ export class ServeCommandFactory {
351
402
  enabled: argv.cors !== undefined
352
403
  ? argv.cors
353
404
  : (fileConfig.cors?.enabled ?? defaultConfig.cors.enabled),
405
+ ...(corsOriginsFromArgv(argv.corsOrigin)
406
+ ? { origins: corsOriginsFromArgv(argv.corsOrigin) }
407
+ : {}),
354
408
  },
355
409
  rateLimit: {
356
410
  ...defaultConfig.rateLimit,
@@ -366,7 +420,13 @@ export class ServeCommandFactory {
366
420
  },
367
421
  bodyParser: fileConfig.bodyParser,
368
422
  logging: fileConfig.logging,
369
- timeout: fileConfig.timeout,
423
+ // Transcription of a long recording through a remote engine can take
424
+ // longer than the 30 s default, so the request timeout is also
425
+ // settable from the environment (milliseconds); the config file wins.
426
+ timeout: fileConfig.timeout ??
427
+ (Number(process.env.NEUROLINK_SERVER_TIMEOUT_MS) > 0
428
+ ? Number(process.env.NEUROLINK_SERVER_TIMEOUT_MS)
429
+ : undefined),
370
430
  enableMetrics: fileConfig.enableMetrics ?? true,
371
431
  enableSwagger: argv.swagger !== undefined
372
432
  ? argv.swagger
@@ -394,6 +454,7 @@ export class ServeCommandFactory {
394
454
  }
395
455
  await withTimeout(serverRef.current.initialize(), 30000, new ServerStartError("Server initialization timed out after 30 seconds", undefined, opts.port, opts.host));
396
456
  await withTimeout(serverRef.current.start(), 30000, new ServerStartError("Server startup timed out after 30 seconds", undefined, opts.port, opts.host));
457
+ await attachTranscriptionWebSocket(serverRef.current, neurolink, opts.serverConfig);
397
458
  return serverRef;
398
459
  }
399
460
  /**
@@ -426,6 +487,11 @@ export class ServeCommandFactory {
426
487
  }
427
488
  const url = `http://${opts.host === "0.0.0.0" ? "localhost" : opts.host}:${opts.port}`;
428
489
  const corsEnabled = opts.argv.cors ?? opts.serverConfig.cors?.enabled ?? true;
490
+ // The origin list and the API key together decide whether any browser
491
+ // page may call this server; the banner says which case this is.
492
+ const corsOrigins = opts.serverConfig.cors?.origins ?? [];
493
+ const corsWildcard = corsEnabled && corsOrigins.includes("*");
494
+ const corsNoOrigins = corsEnabled && corsOrigins.length === 0;
429
495
  const rateLimitValue = opts.argv.rateLimit ?? opts.serverConfig.rateLimit?.maxRequests ?? 100;
430
496
  const rateLimitEnabled = rateLimitValue > 0;
431
497
  const swaggerEnabled = opts.argv.swagger ?? opts.serverConfig.enableSwagger ?? false;
@@ -436,6 +502,8 @@ export class ServeCommandFactory {
436
502
  pid: state.pid,
437
503
  configFile: opts.argv.config,
438
504
  corsEnabled,
505
+ corsWildcard,
506
+ corsNoOrigins,
439
507
  rateLimitEnabled,
440
508
  rateLimitValue,
441
509
  swaggerEnabled,
@@ -461,7 +529,16 @@ export class ServeCommandFactory {
461
529
  }
462
530
  logger.always("");
463
531
  logger.always(chalk.bold("Middleware:"));
464
- logger.always(` CORS: ${info.corsEnabled ? chalk.green("enabled") : chalk.yellow("disabled")}`);
532
+ logger.always(` CORS: ${!info.corsEnabled
533
+ ? chalk.yellow("disabled")
534
+ : info.corsWildcard
535
+ ? info.authEnabled
536
+ ? chalk.green("enabled (any origin; API key required)")
537
+ : chalk.yellow("enabled for ANY origin and no API key — any web page can call this server; set " +
538
+ SERVER_API_KEY_ENV)
539
+ : info.corsNoOrigins
540
+ ? chalk.yellow("enabled, no origins listed — browsers cannot call this server; pass --cors-origin or set cors.origins")
541
+ : chalk.green("enabled (listed origins)")}`);
465
542
  logger.always(` Rate Limit: ${info.rateLimitEnabled ? chalk.green(`enabled (${info.rateLimitValue} req/15min)`) : chalk.yellow("disabled")}`);
466
543
  logger.always(` Swagger: ${info.swaggerEnabled ? chalk.green("enabled") : chalk.yellow("disabled")}`);
467
544
  if (info.watchEnabled) {
@@ -513,7 +590,8 @@ export class ServeCommandFactory {
513
590
  const timestamp = Date.now();
514
591
  const { createServer: createNewServer, registerAllRoutes: registerNewRoutes, } = await import(`../../server/index.js?t=${timestamp}`);
515
592
  // Create new server
516
- const newServer = await createNewServer(new NeuroLink(), {
593
+ const newNeurolink = new NeuroLink();
594
+ const newServer = await createNewServer(newNeurolink, {
517
595
  framework: ctx.framework,
518
596
  config: ctx.serverConfig,
519
597
  });
@@ -522,6 +600,10 @@ export class ServeCommandFactory {
522
600
  // Initialize and start with timeouts
523
601
  await withTimeout(newServer.initialize(), 30000, new ServerStartError("Server initialization timed out during restart", undefined, ctx.port, ctx.host));
524
602
  await withTimeout(newServer.start(), 30000, new ServerStartError("Server startup timed out during restart", undefined, ctx.port, ctx.host));
603
+ // The upgrade handler lives on the old adapter's http.Server; the
604
+ // restarted one needs its own, or the stream route is gone after the
605
+ // first file change.
606
+ await attachTranscriptionWebSocket(newServer, newNeurolink, ctx.serverConfig);
525
607
  // Update the reference so signal handlers use the new server instance
526
608
  ctx.serverRef.current = newServer;
527
609
  logger.always(chalk.green("Server restarted successfully"));
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * NeuroLink CLI Transcribe Command
4
+ *
5
+ * Calls `NeuroLink.transcribe()` — audio in, text out — or, with `--stream`,
6
+ * `NeuroLink.transcribeStream()` over the file decoded to 16 kHz mono PCM16.
7
+ * See src/lib/types/transcribe.ts for the full vocabulary (dictionary,
8
+ * correction, second opinion, fallback).
9
+ *
10
+ * Credentials are env-only here, exactly as every other CLI command: each STT
11
+ * handler reads its own settings, and `NEUROLINK_STT_PROVIDER`,
12
+ * `NEUROLINK_STT_MODEL` and `NEUROLINK_STT_LANGUAGE` pick the defaults. With
13
+ * nothing configured the built-in local engine (Whistle) is used.
14
+ */
15
+ import type { CommandModule } from "yargs";
16
+ import type { CliTranscribeArgs } from "../../types/index.js";
17
+ export declare const transcribeCommand: CommandModule<object, CliTranscribeArgs>;
18
+ /**
19
+ * Create transcribe command factory for CLICommandFactory-style registration,
20
+ * matching the DecideCommandFactory pattern.
21
+ */
22
+ export declare class TranscribeCommandFactory {
23
+ static createTranscribeCommand(): CommandModule;
24
+ }