@juspay/neurolink 12.48.1 → 12.49.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 +3 -3
- package/dist/browser/neurolink.min.js +616 -595
- package/dist/cli/commands/serve.d.ts +5 -3
- package/dist/cli/commands/serve.js +113 -20
- package/dist/cli/commands/server.js +13 -6
- package/dist/cli/commands/transcribe.d.ts +24 -0
- package/dist/cli/commands/transcribe.js +718 -0
- package/dist/cli/factories/commandFactory.d.ts +10 -0
- package/dist/cli/factories/commandFactory.js +13 -0
- package/dist/cli/parser.js +3 -0
- package/dist/cli/utils/serverUtils.d.ts +28 -0
- package/dist/cli/utils/serverUtils.js +71 -0
- package/dist/factories/mediaHandlerCatalog.js +11 -9
- package/dist/factories/sttDescriptors.d.ts +63 -0
- package/dist/factories/sttDescriptors.js +286 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +7 -1
- package/dist/neurolink.d.ts +68 -1
- package/dist/neurolink.js +202 -4
- package/dist/processors/media/AudioProcessor.d.ts +15 -56
- package/dist/processors/media/AudioProcessor.js +105 -276
- package/dist/processors/media/VideoProcessor.d.ts +3 -5
- package/dist/processors/media/VideoProcessor.js +52 -51
- package/dist/server/abstract/baseServerAdapter.d.ts +28 -1
- package/dist/server/abstract/baseServerAdapter.js +84 -4
- package/dist/server/adapters/expressAdapter.d.ts +1 -0
- package/dist/server/adapters/expressAdapter.js +50 -10
- package/dist/server/adapters/fastifyAdapter.d.ts +1 -0
- package/dist/server/adapters/fastifyAdapter.js +51 -8
- package/dist/server/adapters/honoAdapter.d.ts +1 -4
- package/dist/server/adapters/honoAdapter.js +95 -8
- package/dist/server/adapters/koaAdapter.d.ts +7 -0
- package/dist/server/adapters/koaAdapter.js +71 -10
- package/dist/server/index.d.ts +3 -2
- package/dist/server/index.js +3 -2
- package/dist/server/routes/index.d.ts +1 -0
- package/dist/server/routes/index.js +3 -0
- package/dist/server/routes/transcribeRoutes.d.ts +23 -0
- package/dist/server/routes/transcribeRoutes.js +506 -0
- package/dist/server/utils/rawBody.d.ts +32 -0
- package/dist/server/utils/rawBody.js +76 -0
- package/dist/server/utils/validation.d.ts +192 -0
- package/dist/server/utils/validation.js +100 -0
- package/dist/server/websocket/transcribeWebSocket.d.ts +42 -0
- package/dist/server/websocket/transcribeWebSocket.js +264 -0
- package/dist/types/cli.d.ts +47 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/providers.d.ts +7 -1
- package/dist/types/server.d.ts +117 -1
- package/dist/types/stt.d.ts +160 -7
- package/dist/types/transcribe.d.ts +506 -0
- package/dist/types/transcribe.js +29 -0
- package/dist/utils/speakerTurns.d.ts +28 -0
- package/dist/utils/speakerTurns.js +93 -0
- package/dist/utils/sttProcessor.d.ts +20 -2
- package/dist/utils/sttProcessor.js +73 -5
- package/dist/voice/correction/dictionary.d.ts +49 -0
- package/dist/voice/correction/dictionary.js +134 -0
- package/dist/voice/correction/guard.d.ts +35 -0
- package/dist/voice/correction/guard.js +161 -0
- package/dist/voice/correction/index.d.ts +47 -0
- package/dist/voice/correction/index.js +211 -0
- package/dist/voice/correction/rewrite.d.ts +92 -0
- package/dist/voice/correction/rewrite.js +322 -0
- package/dist/voice/errors.d.ts +15 -0
- package/dist/voice/errors.js +45 -0
- package/dist/voice/index.d.ts +20 -2
- package/dist/voice/index.js +75 -9
- package/dist/voice/providers/AzureSTT.d.ts +10 -7
- package/dist/voice/providers/AzureSTT.js +23 -75
- package/dist/voice/providers/DeepgramSTT.d.ts +17 -2
- package/dist/voice/providers/DeepgramSTT.js +109 -13
- package/dist/voice/providers/ElevenLabsSTT.d.ts +12 -2
- package/dist/voice/providers/ElevenLabsSTT.js +34 -8
- package/dist/voice/providers/GoogleSTT.d.ts +10 -8
- package/dist/voice/providers/GoogleSTT.js +21 -75
- package/dist/voice/providers/OpenAISTT.d.ts +30 -9
- package/dist/voice/providers/OpenAISTT.js +196 -21
- package/dist/voice/providers/WhistleSTT.d.ts +87 -0
- package/dist/voice/providers/WhistleSTT.js +313 -0
- package/dist/voice/streaming/chunkedStreamAdapter.d.ts +19 -0
- package/dist/voice/streaming/chunkedStreamAdapter.js +519 -0
- package/dist/voice/streaming/endpointer.d.ts +81 -0
- package/dist/voice/streaming/endpointer.js +247 -0
- package/dist/voice/streaming/localAgreement.d.ts +30 -0
- package/dist/voice/streaming/localAgreement.js +44 -0
- package/dist/voice/sttEnvCredentials.d.ts +12 -0
- package/dist/voice/sttEnvCredentials.js +12 -0
- package/dist/voice/transcribe.d.ts +47 -0
- package/dist/voice/transcribe.js +519 -0
- package/dist/voice/transcribeStream.d.ts +4 -0
- package/dist/voice/transcribeStream.js +584 -0
- package/dist/voice/whistle/assets.d.ts +47 -0
- package/dist/voice/whistle/assets.js +270 -0
- package/dist/voice/whistle/audio.d.ts +32 -0
- package/dist/voice/whistle/audio.js +267 -0
- package/dist/voice/whistle/engine.d.ts +32 -0
- package/dist/voice/whistle/engine.js +193 -0
- package/dist/voice/whistle/worker.d.ts +18 -0
- package/dist/voice/whistle/worker.js +294 -0
- package/docs-site/static/search-index.json +69 -10
- package/models/whistle/README.md +18 -0
- package/models/whistle/needle.js +2 -0
- package/models/whistle/needle.wasm +0 -0
- package/models/whistle/whistle.cact +0 -0
- package/package.json +7 -3
package/dist/neurolink.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ import type { DynamicOptions } from "./types/index.js";
|
|
|
15
15
|
import { SkillsManager } from "./skills/skillsManager.js";
|
|
16
16
|
import type { CostAnalysisOptions, CostAnalysisResult, ProviderMetricsOptions, ProviderMetricsResult, TeamAnalyticsOptions, TeamAnalyticsResult } from "./types/index.js";
|
|
17
17
|
import { TaskManager } from "./tasks/taskManager.js";
|
|
18
|
-
import type { SessionExport, SessionListItem } from "./types/index.js";
|
|
18
|
+
import type { TranscribeOptions, TranscribeResult, TranscribeStreamEvent, TranscribeStreamOptions, SessionExport, SessionListItem } from "./types/index.js";
|
|
19
19
|
/**
|
|
20
20
|
* Curator P2-4 dedup (concurrency-safe): native providers emit
|
|
21
21
|
* `generation:end` on the shared SDK emitter. We attach a fresh
|
|
@@ -2689,6 +2689,73 @@ export declare class NeuroLink {
|
|
|
2689
2689
|
* `decisionHooks` and emits `decision:before` / `decision:after`.
|
|
2690
2690
|
*/
|
|
2691
2691
|
tryDecide(options: DecisionCallerOptions): Promise<DecisionResult | null>;
|
|
2692
|
+
/**
|
|
2693
|
+
* Transcribe a recording to text through any STT provider, with the
|
|
2694
|
+
* optional layers that make self-hosted engines usable: a dictionary of
|
|
2695
|
+
* names and jargon (sent to the engine as context, then repaired after the
|
|
2696
|
+
* fact behind a `tryDecide` guard), an LLM rewrite, a second-opinion
|
|
2697
|
+
* engine, and a fallback engine for audio the primary cannot read.
|
|
2698
|
+
*
|
|
2699
|
+
* The provider defaults to `NEUROLINK_STT_PROVIDER`, then the first
|
|
2700
|
+
* configured STT provider, then the built-in local engine, so an instance
|
|
2701
|
+
* with no STT configuration still transcribes. Per-call
|
|
2702
|
+
* `credentials.stt` beats the instance's, which beats the environment.
|
|
2703
|
+
*
|
|
2704
|
+
* @example
|
|
2705
|
+
* ```typescript
|
|
2706
|
+
* const result = await neurolink.transcribe({
|
|
2707
|
+
* audio: "./meeting.wav",
|
|
2708
|
+
* dictionary: [{ term: "NeuroLink", heardAs: ["neural link"] }],
|
|
2709
|
+
* });
|
|
2710
|
+
* console.log(result.text, result.engine.provider, result.steps);
|
|
2711
|
+
* ```
|
|
2712
|
+
*
|
|
2713
|
+
* @throws STTError when the audio cannot be read, the provider is unknown,
|
|
2714
|
+
* or the engine fails with no fallback that covers errors
|
|
2715
|
+
*/
|
|
2716
|
+
transcribe(options: TranscribeOptions): Promise<TranscribeResult>;
|
|
2717
|
+
/**
|
|
2718
|
+
* Transcribe a live stream of PCM16LE frames. Engines with a native stream
|
|
2719
|
+
* use it; every other engine is streamed through the chunked adapter
|
|
2720
|
+
* (energy-gated utterances, rolling re-transcription, LocalAgreement
|
|
2721
|
+
* commits). Emits `interim`, `final`, `corrected` and the other
|
|
2722
|
+
* {@link TranscribeStreamEvent}s; the same correction, fallback and
|
|
2723
|
+
* provider rules as {@link NeuroLink.transcribe} apply per utterance.
|
|
2724
|
+
*
|
|
2725
|
+
* @example
|
|
2726
|
+
* ```typescript
|
|
2727
|
+
* for await (const event of neurolink.transcribeStream({ audio: micFrames })) {
|
|
2728
|
+
* if (event.type === "final") console.log(event.text);
|
|
2729
|
+
* }
|
|
2730
|
+
* ```
|
|
2731
|
+
*/
|
|
2732
|
+
transcribeStream(options: TranscribeStreamOptions): AsyncIterable<TranscribeStreamEvent>;
|
|
2733
|
+
/**
|
|
2734
|
+
* Instance `credentials.stt` with a per-call `stt` slice merged on top,
|
|
2735
|
+
* provider by provider and field by field (a per-call `apiKey` keeps the
|
|
2736
|
+
* instance's `baseURL`). Undefined when neither has one.
|
|
2737
|
+
*/
|
|
2738
|
+
private resolveSTTCredentials;
|
|
2739
|
+
/**
|
|
2740
|
+
* The STT provider for a call: an explicit name (or alias) as its
|
|
2741
|
+
* canonical name, a name only a caller-registered handler knows as is, and
|
|
2742
|
+
* no name as the default provider for these credentials.
|
|
2743
|
+
*/
|
|
2744
|
+
private resolveSTTProvider;
|
|
2745
|
+
/**
|
|
2746
|
+
* Everything the transcribe orchestration needs from this instance: STT
|
|
2747
|
+
* handlers with the request's credentials applied, provider resolution,
|
|
2748
|
+
* the fail-open decision model and a rewrite model.
|
|
2749
|
+
*/
|
|
2750
|
+
private buildTranscribeDeps;
|
|
2751
|
+
/**
|
|
2752
|
+
* The correction layer's two model calls: `decide` is {@link tryDecide}
|
|
2753
|
+
* (fail-open — `null` on any failure), `rewrite` a plain text call with
|
|
2754
|
+
* tools and memory off (`onPartial`, when given, receives the finished
|
|
2755
|
+
* text once — see the note inside on why it is not streamed) and aborted
|
|
2756
|
+
* at its timeout.
|
|
2757
|
+
*/
|
|
2758
|
+
private buildSTTCorrectionDeps;
|
|
2692
2759
|
/**
|
|
2693
2760
|
* `tryDecide` without the site handling: the try/catch around the call.
|
|
2694
2761
|
* Dispatches through `this.decide`, so a subclass override or an instance
|
package/dist/neurolink.js
CHANGED
|
@@ -31,6 +31,7 @@ import { ToolRoutingCache } from "./core/toolRoutingCache.js";
|
|
|
31
31
|
import { DEFAULT_RECENT_TURNS, KnowledgeGroundingEngine, } from "./knowledge/index.js";
|
|
32
32
|
import { AIProviderFactory } from "./core/factory.js";
|
|
33
33
|
import { describeDecisionProviderKeys, PROVIDER_ALIAS_INDEX, PROVIDER_DESCRIPTORS_BY_NAME, resolveDefaultDecisionProvider, } from "./factories/providerDescriptors.js";
|
|
34
|
+
import { describeSTTProviderKeys, getSTTProviderDescriptor, listConfiguredSTTProviders, resolveCallSTTEndpoints, resolveDefaultSTTProvider, resolveSTTProviderName, } from "./factories/sttDescriptors.js";
|
|
34
35
|
import { MAX_PARALLEL_DECISION_BATCHES, mergeDecisionResults, splitDecisionRequest, } from "./utils/decisionBatches.js";
|
|
35
36
|
import { decisionKey, HOST_DECISION_NAMESPACE, isHostDecisionKey, snapshotDecisionQuestion, stripHostAnswers, } from "./utils/decisionAnswers.js";
|
|
36
37
|
import { resolveDecisionLimitsReading } from "./utils/decisionLimits.js";
|
|
@@ -4238,8 +4239,9 @@ Current user's request: ${currentInput}`;
|
|
|
4238
4239
|
// registration failed silently after AI providers were registered.
|
|
4239
4240
|
await ProviderRegistry.registerAllProviders();
|
|
4240
4241
|
const { STTProcessor } = await import("./utils/sttProcessor.js");
|
|
4241
|
-
const
|
|
4242
|
-
|
|
4242
|
+
const sttCredentials = this.resolveSTTCredentials(options.credentials?.stt);
|
|
4243
|
+
const sttProvider = this.resolveSTTProvider(options.stt.provider, sttCredentials);
|
|
4244
|
+
sttTranscription = await STTProcessor.transcribe(options.stt.audio, sttProvider, options.stt, sttCredentials);
|
|
4243
4245
|
// Inject transcription into the LLM prompt
|
|
4244
4246
|
if (sttTranscription.text) {
|
|
4245
4247
|
const existingText = textOptions.prompt || textOptions.input?.text || "";
|
|
@@ -7606,8 +7608,9 @@ Current user's request: ${currentInput}`;
|
|
|
7606
7608
|
// registerAllProviders() is idempotent; always call.
|
|
7607
7609
|
await ProviderRegistry.registerAllProviders();
|
|
7608
7610
|
const { STTProcessor } = await import("./utils/sttProcessor.js");
|
|
7609
|
-
const
|
|
7610
|
-
|
|
7611
|
+
const sttCredentials = this.resolveSTTCredentials(options.credentials?.stt);
|
|
7612
|
+
const sttProvider = this.resolveSTTProvider(sttOptions.provider, sttCredentials);
|
|
7613
|
+
streamSttTranscription = await STTProcessor.transcribe(sttAudio, sttProvider, sttOptions, sttCredentials);
|
|
7611
7614
|
if (streamSttTranscription.text) {
|
|
7612
7615
|
const existingText = options.input.text || "";
|
|
7613
7616
|
options.input.text = existingText
|
|
@@ -13979,6 +13982,201 @@ Current user's request: ${currentInput}`;
|
|
|
13979
13982
|
async tryDecide(options) {
|
|
13980
13983
|
return this.siteDecide(options);
|
|
13981
13984
|
}
|
|
13985
|
+
// ==========================================================================
|
|
13986
|
+
// TRANSCRIBE — the speech-to-text inference type
|
|
13987
|
+
// ==========================================================================
|
|
13988
|
+
/**
|
|
13989
|
+
* Transcribe a recording to text through any STT provider, with the
|
|
13990
|
+
* optional layers that make self-hosted engines usable: a dictionary of
|
|
13991
|
+
* names and jargon (sent to the engine as context, then repaired after the
|
|
13992
|
+
* fact behind a `tryDecide` guard), an LLM rewrite, a second-opinion
|
|
13993
|
+
* engine, and a fallback engine for audio the primary cannot read.
|
|
13994
|
+
*
|
|
13995
|
+
* The provider defaults to `NEUROLINK_STT_PROVIDER`, then the first
|
|
13996
|
+
* configured STT provider, then the built-in local engine, so an instance
|
|
13997
|
+
* with no STT configuration still transcribes. Per-call
|
|
13998
|
+
* `credentials.stt` beats the instance's, which beats the environment.
|
|
13999
|
+
*
|
|
14000
|
+
* @example
|
|
14001
|
+
* ```typescript
|
|
14002
|
+
* const result = await neurolink.transcribe({
|
|
14003
|
+
* audio: "./meeting.wav",
|
|
14004
|
+
* dictionary: [{ term: "NeuroLink", heardAs: ["neural link"] }],
|
|
14005
|
+
* });
|
|
14006
|
+
* console.log(result.text, result.engine.provider, result.steps);
|
|
14007
|
+
* ```
|
|
14008
|
+
*
|
|
14009
|
+
* @throws STTError when the audio cannot be read, the provider is unknown,
|
|
14010
|
+
* or the engine fails with no fallback that covers errors
|
|
14011
|
+
*/
|
|
14012
|
+
async transcribe(options) {
|
|
14013
|
+
const [deps, { runTranscribe }] = await Promise.all([
|
|
14014
|
+
this.buildTranscribeDeps(options.credentials?.stt),
|
|
14015
|
+
import("./voice/transcribe.js"),
|
|
14016
|
+
]);
|
|
14017
|
+
return runTranscribe(options, deps);
|
|
14018
|
+
}
|
|
14019
|
+
/**
|
|
14020
|
+
* Transcribe a live stream of PCM16LE frames. Engines with a native stream
|
|
14021
|
+
* use it; every other engine is streamed through the chunked adapter
|
|
14022
|
+
* (energy-gated utterances, rolling re-transcription, LocalAgreement
|
|
14023
|
+
* commits). Emits `interim`, `final`, `corrected` and the other
|
|
14024
|
+
* {@link TranscribeStreamEvent}s; the same correction, fallback and
|
|
14025
|
+
* provider rules as {@link NeuroLink.transcribe} apply per utterance.
|
|
14026
|
+
*
|
|
14027
|
+
* @example
|
|
14028
|
+
* ```typescript
|
|
14029
|
+
* for await (const event of neurolink.transcribeStream({ audio: micFrames })) {
|
|
14030
|
+
* if (event.type === "final") console.log(event.text);
|
|
14031
|
+
* }
|
|
14032
|
+
* ```
|
|
14033
|
+
*/
|
|
14034
|
+
async *transcribeStream(options) {
|
|
14035
|
+
const [deps, { runTranscribeStream }] = await Promise.all([
|
|
14036
|
+
this.buildTranscribeDeps(options.credentials?.stt),
|
|
14037
|
+
import("./voice/transcribeStream.js"),
|
|
14038
|
+
]);
|
|
14039
|
+
yield* runTranscribeStream(options, deps);
|
|
14040
|
+
}
|
|
14041
|
+
/**
|
|
14042
|
+
* Instance `credentials.stt` with a per-call `stt` slice merged on top,
|
|
14043
|
+
* provider by provider and field by field (a per-call `apiKey` keeps the
|
|
14044
|
+
* instance's `baseURL`). Undefined when neither has one.
|
|
14045
|
+
*/
|
|
14046
|
+
resolveSTTCredentials(callCredentials) {
|
|
14047
|
+
const instance = this.credentials?.stt;
|
|
14048
|
+
if (!instance || !callCredentials) {
|
|
14049
|
+
return callCredentials ?? instance;
|
|
14050
|
+
}
|
|
14051
|
+
const merged = { ...instance };
|
|
14052
|
+
for (const [key, callSlice] of Object.entries(callCredentials)) {
|
|
14053
|
+
const instanceSlice = merged[key];
|
|
14054
|
+
merged[key] =
|
|
14055
|
+
instanceSlice &&
|
|
14056
|
+
typeof instanceSlice === "object" &&
|
|
14057
|
+
callSlice &&
|
|
14058
|
+
typeof callSlice === "object"
|
|
14059
|
+
? { ...instanceSlice, ...callSlice }
|
|
14060
|
+
: (callSlice ?? instanceSlice);
|
|
14061
|
+
}
|
|
14062
|
+
return merged;
|
|
14063
|
+
}
|
|
14064
|
+
/**
|
|
14065
|
+
* The STT provider for a call: an explicit name (or alias) as its
|
|
14066
|
+
* canonical name, a name only a caller-registered handler knows as is, and
|
|
14067
|
+
* no name as the default provider for these credentials.
|
|
14068
|
+
*/
|
|
14069
|
+
resolveSTTProvider(name, credentials) {
|
|
14070
|
+
const trimmed = name?.trim();
|
|
14071
|
+
if (!trimmed) {
|
|
14072
|
+
return resolveDefaultSTTProvider(credentials);
|
|
14073
|
+
}
|
|
14074
|
+
return resolveSTTProviderName(trimmed) ?? trimmed;
|
|
14075
|
+
}
|
|
14076
|
+
/**
|
|
14077
|
+
* Everything the transcribe orchestration needs from this instance: STT
|
|
14078
|
+
* handlers with the request's credentials applied, provider resolution,
|
|
14079
|
+
* the fail-open decision model and a rewrite model.
|
|
14080
|
+
*/
|
|
14081
|
+
async buildTranscribeDeps(callCredentials) {
|
|
14082
|
+
await ProviderRegistry.registerAllProviders();
|
|
14083
|
+
const [{ STTProcessor }, { createSTTHandler }, { STTError }] = await Promise.all([
|
|
14084
|
+
import("./utils/sttProcessor.js"),
|
|
14085
|
+
import("./voice/index.js"),
|
|
14086
|
+
import("./voice/errors.js"),
|
|
14087
|
+
]);
|
|
14088
|
+
const credentials = this.resolveSTTCredentials(callCredentials);
|
|
14089
|
+
const resolveProvider = (name) => {
|
|
14090
|
+
const resolved = this.resolveSTTProvider(name, credentials);
|
|
14091
|
+
if (resolveSTTProviderName(resolved) === undefined &&
|
|
14092
|
+
!STTProcessor.supports(resolved) &&
|
|
14093
|
+
!resolveCallSTTEndpoints(credentials)[resolved.trim().toLowerCase()]) {
|
|
14094
|
+
throw STTError.unknownProvider(resolved, listConfiguredSTTProviders(credentials), describeSTTProviderKeys());
|
|
14095
|
+
}
|
|
14096
|
+
return resolved;
|
|
14097
|
+
};
|
|
14098
|
+
// Same precedence as STTProcessor.resolveHandler, synchronously: a
|
|
14099
|
+
// credentials slice for the provider builds a handler from it; else the
|
|
14100
|
+
// registered handler; else, for a shipped provider, one from the env.
|
|
14101
|
+
const getHandler = (name) => {
|
|
14102
|
+
if (resolveCallSTTEndpoints(credentials)[name.trim().toLowerCase()]) {
|
|
14103
|
+
return createSTTHandler(name, credentials);
|
|
14104
|
+
}
|
|
14105
|
+
const descriptor = getSTTProviderDescriptor(name);
|
|
14106
|
+
if (!descriptor) {
|
|
14107
|
+
return STTProcessor.getHandler(name);
|
|
14108
|
+
}
|
|
14109
|
+
if (credentials?.[descriptor.credentialsKey] !== undefined) {
|
|
14110
|
+
return createSTTHandler(descriptor.name, credentials);
|
|
14111
|
+
}
|
|
14112
|
+
return (STTProcessor.getHandler(descriptor.name) ??
|
|
14113
|
+
createSTTHandler(descriptor.name));
|
|
14114
|
+
};
|
|
14115
|
+
return {
|
|
14116
|
+
...this.buildSTTCorrectionDeps(),
|
|
14117
|
+
transcribe: (audio, provider, options) => STTProcessor.transcribe(audio, provider, options, credentials),
|
|
14118
|
+
resolveProvider,
|
|
14119
|
+
getHandler,
|
|
14120
|
+
};
|
|
14121
|
+
}
|
|
14122
|
+
/**
|
|
14123
|
+
* The correction layer's two model calls: `decide` is {@link tryDecide}
|
|
14124
|
+
* (fail-open — `null` on any failure), `rewrite` a plain text call with
|
|
14125
|
+
* tools and memory off (`onPartial`, when given, receives the finished
|
|
14126
|
+
* text once — see the note inside on why it is not streamed) and aborted
|
|
14127
|
+
* at its timeout.
|
|
14128
|
+
*/
|
|
14129
|
+
buildSTTCorrectionDeps() {
|
|
14130
|
+
return {
|
|
14131
|
+
decide: async (o) => {
|
|
14132
|
+
// The correction layer builds plain JSON states and question maps;
|
|
14133
|
+
// the decision provider validates them on its side.
|
|
14134
|
+
const result = await this.tryDecide({
|
|
14135
|
+
state: o.state,
|
|
14136
|
+
questions: o.questions,
|
|
14137
|
+
...(o.timeoutMs !== undefined ? { timeoutMs: o.timeoutMs } : {}),
|
|
14138
|
+
});
|
|
14139
|
+
return result ? { answers: result.answers } : null;
|
|
14140
|
+
},
|
|
14141
|
+
rewrite: async (o) => {
|
|
14142
|
+
const controller = new AbortController();
|
|
14143
|
+
const timer = setTimeout(() => controller.abort(), o.timeoutMs);
|
|
14144
|
+
// A server runs many transcriptions with one rewrite model, so the
|
|
14145
|
+
// model is configurable once, in the environment; a request's own
|
|
14146
|
+
// `correction.rewrite.provider/model` still wins.
|
|
14147
|
+
const provider = o.provider ?? process.env.NEUROLINK_STT_REWRITE_PROVIDER?.trim();
|
|
14148
|
+
const model = o.model ?? process.env.NEUROLINK_STT_REWRITE_MODEL?.trim();
|
|
14149
|
+
const request = {
|
|
14150
|
+
input: { text: o.user },
|
|
14151
|
+
systemPrompt: o.system,
|
|
14152
|
+
...(provider ? { provider } : {}),
|
|
14153
|
+
...(model ? { model } : {}),
|
|
14154
|
+
maxTokens: o.maxTokens,
|
|
14155
|
+
temperature: 0,
|
|
14156
|
+
disableTools: true,
|
|
14157
|
+
memory: { enabled: false },
|
|
14158
|
+
abortSignal: controller.signal,
|
|
14159
|
+
};
|
|
14160
|
+
try {
|
|
14161
|
+
// Always `generate()`. Measured on the same rewrite against the same
|
|
14162
|
+
// model: generate 0.7 s; stream() 3.4 s with the first chunk at
|
|
14163
|
+
// 3.3 s — the stream path's setup costs more than the whole answer
|
|
14164
|
+
// and delivers it in one burst anyway, so a "streamed" rewrite only
|
|
14165
|
+
// risked the 12 s timeout. `onPartial` still fires once with the
|
|
14166
|
+
// full text so a live caller replaces the sentence the same way.
|
|
14167
|
+
const generated = await this.generate(request);
|
|
14168
|
+
const text = generated.content ?? "";
|
|
14169
|
+
if (o.onPartial && text) {
|
|
14170
|
+
o.onPartial(text);
|
|
14171
|
+
}
|
|
14172
|
+
return text;
|
|
14173
|
+
}
|
|
14174
|
+
finally {
|
|
14175
|
+
clearTimeout(timer);
|
|
14176
|
+
}
|
|
14177
|
+
},
|
|
14178
|
+
};
|
|
14179
|
+
}
|
|
13982
14180
|
/**
|
|
13983
14181
|
* `tryDecide` without the site handling: the try/catch around the call.
|
|
13984
14182
|
* Dispatches through `this.decide`, so a subclass override or an instance
|
|
@@ -90,28 +90,22 @@ export declare class AudioProcessor extends BaseFileProcessor<ProcessedAudio> {
|
|
|
90
90
|
*/
|
|
91
91
|
processFile(fileInfo: FileInfo, options?: ProcessOptions & AudioProcessorOptions): Promise<ProcessorFileProcessingResult<ProcessedAudio>>;
|
|
92
92
|
/**
|
|
93
|
-
*
|
|
93
|
+
* Choose the transcription backend for this file (#413).
|
|
94
|
+
*
|
|
95
|
+
* With no `requested` backend, the STT default applies: the provider named
|
|
96
|
+
* by `NEUROLINK_STT_PROVIDER`, else the first configured STT provider in
|
|
97
|
+
* descriptor order, else the built-in local engine when it can run here.
|
|
98
|
+
* With one, it is resolved through the legacy names and the STT aliases and
|
|
99
|
+
* validated for availability — a backend the caller explicitly asked for is
|
|
100
|
+
* never silently swapped for a different one, because a caller who pinned
|
|
101
|
+
* Azure for a data-residency reason would not want OpenAI chosen behind
|
|
102
|
+
* their back. The mismatch is reported instead.
|
|
94
103
|
*
|
|
95
104
|
* Availability is decided from the environment only — no network call — so
|
|
96
105
|
* selection stays cheap and cannot itself fail. A key that is present but
|
|
97
106
|
* rejected upstream surfaces later, as a transcription failure with the
|
|
98
107
|
* provider's own message, not as "unavailable".
|
|
99
108
|
*
|
|
100
|
-
* @param provider - Backend to check
|
|
101
|
-
* @returns True when at least one of the backend's credential vars is set
|
|
102
|
-
*/
|
|
103
|
-
private isProviderAvailable;
|
|
104
|
-
/**
|
|
105
|
-
* Choose the transcription backend for this file (#413).
|
|
106
|
-
*
|
|
107
|
-
* With no `requested` backend, the first configured entry of
|
|
108
|
-
* {@link TRANSCRIPTION_PROVIDER_ORDER} wins (OpenAI, then Google, then
|
|
109
|
-
* Azure). With one, it is normalised through the alias table and validated
|
|
110
|
-
* for availability — a backend the caller explicitly asked for is never
|
|
111
|
-
* silently swapped for a different one, because a caller who pinned Azure
|
|
112
|
-
* for a data-residency reason would not want OpenAI chosen behind their
|
|
113
|
-
* back. The mismatch is reported instead.
|
|
114
|
-
*
|
|
115
109
|
* @param requested - Caller's `AudioProcessorOptions.provider`, if any
|
|
116
110
|
* @returns The chosen backend, or the reason no backend could be chosen
|
|
117
111
|
*/
|
|
@@ -120,10 +114,14 @@ export declare class AudioProcessor extends BaseFileProcessor<ProcessedAudio> {
|
|
|
120
114
|
* Attempt to transcribe audio with whichever backend is configured (#413).
|
|
121
115
|
*
|
|
122
116
|
* Transcription is attempted when:
|
|
123
|
-
* 1. A backend
|
|
117
|
+
* 1. A backend is available (see {@link selectProvider})
|
|
124
118
|
* 2. File size is within the 25MB ceiling
|
|
125
119
|
* 3. The file format is one the backend accepts
|
|
126
120
|
*
|
|
121
|
+
* The call itself goes through `STTProcessor`, the same path as
|
|
122
|
+
* `transcribe()` and `generate({ stt })`, so `OPENAI_STT_*`, the default
|
|
123
|
+
* provider rule and every STT handler apply here too.
|
|
124
|
+
*
|
|
127
125
|
* Gracefully degrades: if transcription fails for any reason, metadata-only
|
|
128
126
|
* output is returned (transcription is additive, never blocks processing).
|
|
129
127
|
*
|
|
@@ -134,45 +132,6 @@ export declare class AudioProcessor extends BaseFileProcessor<ProcessedAudio> {
|
|
|
134
132
|
* @returns Transcription result with transcript text, or the reason there is none
|
|
135
133
|
*/
|
|
136
134
|
private attemptTranscription;
|
|
137
|
-
/**
|
|
138
|
-
* Transcribe via OpenAI Whisper (#416).
|
|
139
|
-
*
|
|
140
|
-
* A native multipart POST to OpenAI's transcription endpoint. This used to
|
|
141
|
-
* go through @ai-sdk/openai's createOpenAI().transcription() plus the ai
|
|
142
|
-
* package's experimental_transcribe; both were dropped, and this is the
|
|
143
|
-
* only wire behaviour of theirs the processor ever depended on. The same
|
|
144
|
-
* request is already made natively by voice/providers/OpenAISTT.ts.
|
|
145
|
-
*
|
|
146
|
-
* `verbose_json` is requested for `language` and `duration` alongside the
|
|
147
|
-
* text — the response was previously parsed for `text` alone, so both were
|
|
148
|
-
* received and discarded, and `FileProcessingResult.metadata.language` had
|
|
149
|
-
* nothing to report (#409).
|
|
150
|
-
*
|
|
151
|
-
* @param buffer - Audio file content
|
|
152
|
-
* @param filename - Original filename, sent as the multipart part name
|
|
153
|
-
* @param mimetype - MIME type used for the upload blob
|
|
154
|
-
* @param options - Caller's language / model / prompt overrides
|
|
155
|
-
* @param skipped - Builds the "no transcript, and here is why" outcome
|
|
156
|
-
* @returns Transcription result, or the reason there is none
|
|
157
|
-
*/
|
|
158
|
-
private transcribeWithOpenAI;
|
|
159
|
-
/**
|
|
160
|
-
* Transcribe via one of the non-OpenAI STT handlers (#413).
|
|
161
|
-
*
|
|
162
|
-
* Google and Azure already have working, tested implementations under
|
|
163
|
-
* `src/lib/voice/providers/`, reached here through a dynamic import so a
|
|
164
|
-
* file-processing run that never transcribes does not pay to load them —
|
|
165
|
-
* the same reason `music-metadata` is loaded lazily above.
|
|
166
|
-
*
|
|
167
|
-
* @param chosen - Backend and display label from {@link selectProvider}
|
|
168
|
-
* @param buffer - Audio file content
|
|
169
|
-
* @param filename - Original filename; its extension picks the wire format
|
|
170
|
-
* @param mimetype - MIME type, used as the fallback format signal
|
|
171
|
-
* @param options - Caller's language / model overrides
|
|
172
|
-
* @param skipped - Builds the "no transcript, and here is why" outcome
|
|
173
|
-
* @returns Transcription result, or the reason there is none
|
|
174
|
-
*/
|
|
175
|
-
private transcribeWithHandler;
|
|
176
135
|
/**
|
|
177
136
|
* Stub implementation required by BaseFileProcessor.
|
|
178
137
|
* Not used because processFile is fully overridden.
|