@juspay/neurolink 12.58.0 → 12.59.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 CHANGED
@@ -1,13 +1,8 @@
1
- ## [12.58.0](https://github.com/juspay/neurolink/compare/v12.57.0...v12.58.0) (2026-10-15)
1
+ ## [12.59.0](https://github.com/juspay/neurolink/compare/v12.58.1...v12.59.0) (2026-10-15)
2
2
 
3
3
  ### Features
4
4
 
5
- - **(decide):** add OpenAI's Decisions API as a catalog provider ([9bdc342](https://github.com/juspay/neurolink/commit/9bdc3428097ab44917aad65239bb28386570b971))
6
-
7
- ### Bug Fixes
8
-
9
- - **(observability):** keep the user's question in trimmed span inputs and make the cap configurable ([2d39413](https://github.com/juspay/neurolink/commit/2d394138094c3b89015975ea3fdce69e4a75a5c9))
10
- - **(security):** make the gitleaks secret scan run, and fail when it cannot ([467c19f](https://github.com/juspay/neurolink/commit/467c19f5e16bac64d7ad00606c32186448386621)), closes [PKCS#8](https://github.com/juspay/PKCS/issues/8)
5
+ - **(voice):** export the energy endpointer as @juspay/neurolink/voice/endpointer ([7bf7d39](https://github.com/juspay/neurolink/commit/7bf7d398cb39678d9a92e16a9b7f0dccf9177672))
11
6
 
12
7
  ## [11.2.3](https://github.com/juspay/neurolink/compare/v11.2.2...v11.2.3) (2026-08-19)
13
8
 
@@ -44,7 +44,7 @@
44
44
  * ```
45
45
  */
46
46
  import { BaseFileProcessor } from "../base/BaseFileProcessor.js";
47
- import type { FileInfo, ProcessedVideo, ProcessorFileProcessingResult, ProcessOptions, VideoProcessorOptions } from "../../types/index.js";
47
+ import type { FileInfo, ProcessedVideo, ProcessorFileProcessingResult, ProcessorFluentFfmpegModule, ProcessOptions, VideoProcessorOptions } from "../../types/index.js";
48
48
  /**
49
49
  * Narrow a loaded `fluent-ffmpeg` export to the shape this file actually uses:
50
50
  * a callable carrying the `ffprobe` and `setFfmpegPath` statics.
@@ -55,7 +55,7 @@ import type { FileInfo, ProcessedVideo, ProcessorFileProcessingResult, ProcessOp
55
55
  * "Cannot read properties of undefined (reading 'ffprobe')" from inside
56
56
  * probeVideo — blaming the call site instead of the package that is wrong.
57
57
  */
58
- export declare function assertFluentFfmpegShape(mod: unknown): asserts mod is typeof import("fluent-ffmpeg");
58
+ export declare function assertFluentFfmpegShape(mod: unknown): asserts mod is ProcessorFluentFfmpegModule;
59
59
  /**
60
60
  * Video Processor - extracts metadata, keyframes, and subtitles from video files.
61
61
  *
@@ -570,6 +570,16 @@ export type FfprobeData = {
570
570
  [key: string]: unknown;
571
571
  };
572
572
  };
573
+ /**
574
+ * Structural shape of the `fluent-ffmpeg` export: a callable carrying the
575
+ * `ffprobe` and `setFfmpegPath` statics. Public declarations use this instead of
576
+ * `typeof import("fluent-ffmpeg")`, whose types live in a devDependency that
577
+ * consumers do not install.
578
+ */
579
+ export type ProcessorFluentFfmpegModule = ((...args: never[]) => unknown) & {
580
+ ffprobe: (...args: never[]) => unknown;
581
+ setFfmpegPath: (...args: never[]) => unknown;
582
+ };
573
583
  /**
574
584
  * Structural types for exceljs objects.
575
585
  * Defined here so the optional exceljs package is not required at typecheck time.
@@ -4542,6 +4542,7 @@
4542
4542
  {"objectID":"7c55169273332aab63f54e94bae343516bd630e062d60a4d427d004b72ee287e","title":"Nothing is ever dropped","url":"/docs/features/transcribe#nothing-is-ever-dropped","content":"Every layer fails open, and none may lose words:\nA rewrite that drops more than maxDropRatio of the words is discarded and\n the dictionary-applied text is kept.\nA rewrite that times out, fails or returns nothing keeps the text it was\n given.\nA guard that times out or fails applies the dictionary as is.\nWhen streaming, a final pass that returns less than the live text keeps the\n live text, and an utterance no engine could read is reported as a silence\n event with its length rather than disappearing.\nraw always holds the engine's own text, so a caller can show or diff it.\n\nEach of those outcomes is written to steps, so a degraded path is visible\nrather than silent.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"Nothing is ever dropped","lvl3":""}},
4543
4543
  {"objectID":"c0207627f5f88b7914c2fbe84a641879ece05ae20f7e2194a9f0bc29c24cfd65","title":"Fallback and second opinion","url":"/docs/features/transcribe#fallback-and-second-opinion","content":"Fallback takes the request (or, when streaming, the utterance) when the\n primary engine cannot read it: when defaults to [\"unsure\", \"empty\"] — a\n low language-detection score, or no text — and \"error\" adds engine\n failures. engine.fallbackUsed says when it ran.\nSecond opinion runs a second engine on the same audio in parallel; the\n rewrite reconciles the two transcripts, taking each language's words from the\n engine that reads it better. When the primary reports an unsure language,\n or no text, the second opinion's text leads. With rewrite: false that is\n all it does — there is no reconciliation without the rewrite.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"Fallback and second opinion","lvl3":""}},
4544
4544
  {"objectID":"c903ddf3ec717cab3ff063e2bbb762f634ff09b05e5199c35d95283aba82f2f6","title":"Streaming","url":"/docs/features/transcribe#streaming","content":"Engines with a native stream use it; every other engine is streamed on the\nclient by a chunked adapter (an energy gate finds utterances, the current\nutterance is re-transcribed every intervalMs, and the prefix two passes agree\non is committed). streaming.mode: \"chunked\" forces the adapter.\n\n| Event | Carries |\n| ------------ | ---------------------------------------------------------------------------------------------- |\n| interim | The utterance's current text, split into committed (stable) and tail (may still change). |\n| language | The detected language and whether the engine was sure. |\n| final | The utterance's final text, segment and words, the engine, and whether the fallback took it. |\n| correcting | Partial text of the streamed rewrite. |\n| corrected | The corrected text, its raw, decisions, steps and timings. |\n| silence | An utterance no engine could read, with its length. |\n| error | A message, and recoverable: true when the stream carries on with the next utterance. |\n\nTuning (streaming): sampleRate (16000), endSilenceMs (750), intervalMs\n(900), softCutSeconds (16), maxUtteranceSeconds (28), onsetRms (0.006),\nprerollMs (350), minSpeechMs (250).","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"Streaming","lvl3":""}},
4545
+ {"objectID":"336d246e949117f5c2b68c49a693582dd2395b7515979d6566e5d07a7a65fd75","title":"Finding the end of a spoken turn in a browser","url":"/docs/features/transcribe#finding-the-end-of-a-spoken-turn-in-a-browser","content":"@juspay/neurolink/voice/endpointer exports the energy gate the chunked adapter\nuses. It is a self-contained module (no Node built-ins, no other imports), so a\nbrowser app can ask where a spoken turn starts and ends without running a speech\nengine and without bundling the voice entry.\nstart is tentative: a click also starts an utterance, and a drop follows\n about endSilenceMs later. end carries a reason: silence, softCut,\n hardCut or flush.\nFeed it a continuous stream of samples. The noise floor and every timer count\n samples, so polling an AnalyserNode on a timer gives wrong timings.\nThe noise floor starts at a fixed value and rises by at most about 2x per\n second. In a loud room the first two seconds can produce an utterance made of\n noise, so keep the gate running for about two seconds before trusting events.\nA signal that never dips (a fan, a steady hum) is absorbed as noise after a\n few seconds. It measures energy, not speech: background talk keeps a turn open\n until a cut.\nsoftCutSeconds (16) ends a turn at the first gap of 320 ms or more once it is\n that long. Raise it, together with maxUtteranceSeconds, when you want one\n recording per turn.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"Finding the end of a spoken turn in a browser","lvl3":""}},
4545
4546
  {"objectID":"dee2eadc8e2a8712fe874329eae3639423ba11bb01631e21956abde47b3c7a3f","title":"CLI","url":"/docs/features/transcribe#cli","content":"The text output is the transcript, then a dim line with the engine, the\nlanguage (detected or unsure), the audio length, each layer's time and the\nsteps. --format json prints the whole TranscribeResult (one event per line\nwith --stream); --format srt|vtt builds subtitle cues from the segments, or\nfrom the word timings. --stream decodes the file to 16 kHz mono PCM16 (WAV in\nprocess, anything else through ffmpeg) and runs it through\ntranscribeStream(). Credentials are env-only, as for every CLI command. The\nfull flag table is in the CLI reference.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"CLI","lvl3":""}},
4546
4547
  {"objectID":"3529c7278a91963a4075c1f8b880ed143b9276ea52089e84639f7c658685bae8","title":"Server routes","url":"/docs/features/transcribe#server-routes","content":"createAllRoutes() / registerAllRoutes() mount two routes on every adapter\n(Hono, Express, Fastify, Koa); createTranscribeRoutes(basePath, options)\nmounts them on their own. Neither accepts credentials: engines use the\nserver's own configuration, and a credentials field in a body is ignored.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"Server routes","lvl3":""}},
4547
4548
  {"objectID":"081502d8e5cd1a1c0f622a7d6118ac263dc88c9d07d8ef96402d71b4957a7172","title":"POST /api/agent/transcribe","url":"/docs/features/transcribe#post-apiagenttranscribe","content":"JSON body with exactly one audio source:\n\n| Source | Rules |\n| ----------- | ------------------------------------------------------------------------------------------------------------------------------- |\n| audio | Base64, or a data:audio/...;base64, URL. Bounded by the adapter's JSON body limit (bodyParser.jsonLimit, 10 MB by default). |\n| audioUrl | An http(s) URL the server downloads through the SSRF guard (private addresses and redirects refused), capped in size. |\n| audioPath | A path on the server. Refused by default; allowed only inside the directories in transcribe.allowedAudioRoots. |\n\nThe response is the TranscribeResult, in the adapters' usual\n{ data, metadata } envelope. Errors use the usual error shape: 400 for an\ninvalid body or an unsupported provider, language or format, 403 for a refused\naudioPath, 413 for audio over the limit, 500 for an engine failure.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"POST /api/agent/transcribe","lvl3":""}},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "12.58.0",
3
+ "version": "12.59.0",
4
4
  "packageManager": "pnpm@10.15.1",
5
5
  "description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
6
6
  "author": {
@@ -150,6 +150,7 @@
150
150
  "test:decide-contract": "pnpm exec tsx test/continuous-test-suite-decide-provider-contract.ts",
151
151
  "test:acceptance-gate": "pnpm exec tsx test/continuous-test-suite-acceptance-gate.ts",
152
152
  "test:cli-fallback": "pnpm exec tsx test/continuous-test-suite-cli-fallback.ts",
153
+ "test:package-declarations": "pnpm exec tsx test/continuous-test-suite-package-declarations.ts",
153
154
  "scaffold:provider": "pnpm exec tsx tools/scaffold-provider.ts",
154
155
  "verify:provider-onboarding": "pnpm exec tsx tools/verify-provider-onboarding.ts",
155
156
  "test:openai-compat-catalog": "pnpm exec tsx test/continuous-test-suite-openai-compat-catalog.ts",
@@ -229,7 +230,7 @@
229
230
  "// CI tier — fast, no live AI calls, safe for every commit (test:unit; also see the separate provider-safety-net CI job, which runs build + test:providers-mocked + test:provider-structure + test:error-classifier-contract on every PR)": "",
230
231
  "test:tool-routing": "pnpm exec tsx test/continuous-test-suite-tool-routing.ts",
231
232
  "test:tool-routing-semantic": "pnpm exec tsx test/continuous-test-suite-tool-routing-semantic.ts",
232
- "test:unit": "pnpm run test:bugfixes && pnpm run test:mcp:infra && pnpm run test:mcp:spans && pnpm run test:tool-routing && pnpm run test:tool-routing-cli && pnpm run test:tool-dedup && pnpm run test:model-pool && pnpm run test:classifier-router && pnpm run test:tool-routing-semantic && pnpm run test:mcp-result-cache && pnpm run test:mcp-direct-name-repair && pnpm run test:mcp-breaker-resolved-errors && pnpm run test:archive:security && pnpm run test:office:security && pnpm run test:image-exif && pnpm run test:vector-chroma && pnpm run test:vector-pgvector && pnpm run test:vector-pinecone && pnpm run test:provider-wiring && pnpm run test:docs-mcp && pnpm run test:retired-model-defaults && pnpm run test:cli-fallback && pnpm run test:embedding-response-validation && pnpm run test:xiaomi-mimo-pilot && pnpm run test:rag-bounds && pnpm run test:longcat-pilot && pnpm run test:runinfra-pilot",
233
+ "test:unit": "pnpm run test:bugfixes && pnpm run test:mcp:infra && pnpm run test:mcp:spans && pnpm run test:tool-routing && pnpm run test:tool-routing-cli && pnpm run test:tool-dedup && pnpm run test:model-pool && pnpm run test:classifier-router && pnpm run test:tool-routing-semantic && pnpm run test:mcp-result-cache && pnpm run test:mcp-direct-name-repair && pnpm run test:mcp-breaker-resolved-errors && pnpm run test:archive:security && pnpm run test:office:security && pnpm run test:image-exif && pnpm run test:vector-chroma && pnpm run test:vector-pgvector && pnpm run test:vector-pinecone && pnpm run test:provider-wiring && pnpm run test:docs-mcp && pnpm run test:retired-model-defaults && pnpm run test:cli-fallback && pnpm run test:embedding-response-validation && pnpm run test:xiaomi-mimo-pilot && pnpm run test:rag-bounds && pnpm run test:longcat-pilot && pnpm run test:runinfra-pilot && pnpm run test:package-declarations",
233
234
  "// CI tier — live providers, runs only when API keys are present (test:credentials and test:dynamic make real provider calls when keys are set, so they live here, not in test:unit; test:matrix, a different suite covering the full provider capability matrix, runs nightly via .github/workflows/live-matrix.yml — test:providers itself is still only wired into test:live, not any GitHub Actions workflow)": "",
234
235
  "test:live": "pnpm run test:providers && pnpm run test:mcp:http && pnpm run test:mcp:sdk && pnpm run test:mcp:cli && pnpm run test:observability && pnpm run test:context && pnpm run test:memory && pnpm run test:tool-reliability && pnpm run test:evaluation && pnpm run test:autoresearch && pnpm run test:credentials && pnpm run test:dynamic && pnpm run test:model-not-found-retryable",
235
236
  "// CI tier — product output (image/video/TTS/PPT) — costs $$ per run (not wired into any GitHub Actions workflow as of this comment; run manually or add to live-matrix.yml if nightly coverage is needed)": "",
@@ -335,6 +336,7 @@
335
336
  "dist",
336
337
  "!dist/**/*.test.*",
337
338
  "!dist/**/*.spec.*",
339
+ "!dist/**/*.tsx",
338
340
  "!dist/**/*.map",
339
341
  "docs/assets/dashboards/*.json",
340
342
  "docs-site/mcp-server/*.js",
@@ -397,6 +399,11 @@
397
399
  "import": "./dist/voice/index.js",
398
400
  "default": "./dist/voice/index.js"
399
401
  },
402
+ "./voice/endpointer": {
403
+ "types": "./dist/voice/streaming/endpointer.d.ts",
404
+ "import": "./dist/voice/streaming/endpointer.js",
405
+ "default": "./dist/voice/streaming/endpointer.js"
406
+ },
400
407
  "./music": {
401
408
  "types": "./dist/music/index.d.ts",
402
409
  "import": "./dist/music/index.js",