@absolutejs/voice 0.0.22-beta.632 → 0.0.22-beta.634
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/dist/core/types.d.ts +34 -0
- package/dist/index.js +46 -14
- package/dist/manifest.d.ts +2 -0
- package/dist/manifest.js +8865 -0
- package/dist/manifest.json +385 -0
- package/dist/testing/index.js +49 -15
- package/package.json +17 -4
package/dist/core/types.d.ts
CHANGED
|
@@ -78,6 +78,18 @@ export type VoiceTranscriptSentiment = {
|
|
|
78
78
|
metadata?: Record<string, unknown>;
|
|
79
79
|
score?: number;
|
|
80
80
|
};
|
|
81
|
+
/** A provider-normalized word hypothesis. Keeping this evidence attached to the
|
|
82
|
+
* transcript lets applications detect a single risky name or number that would
|
|
83
|
+
* otherwise disappear inside a high turn-level average confidence. */
|
|
84
|
+
export type TranscriptWord = {
|
|
85
|
+
confidence?: number;
|
|
86
|
+
endedAtMs?: number;
|
|
87
|
+
language?: string;
|
|
88
|
+
punctuatedText?: string;
|
|
89
|
+
speaker?: string | number;
|
|
90
|
+
startedAtMs?: number;
|
|
91
|
+
text: string;
|
|
92
|
+
};
|
|
81
93
|
export type Transcript = {
|
|
82
94
|
id: string;
|
|
83
95
|
text: string;
|
|
@@ -89,6 +101,7 @@ export type Transcript = {
|
|
|
89
101
|
startedAtMs?: number;
|
|
90
102
|
endedAtMs?: number;
|
|
91
103
|
vendor?: string;
|
|
104
|
+
words?: TranscriptWord[];
|
|
92
105
|
};
|
|
93
106
|
export type VoiceTranscriptQuality = {
|
|
94
107
|
averageConfidence?: number;
|
|
@@ -101,6 +114,8 @@ export type VoiceTranscriptQuality = {
|
|
|
101
114
|
partialTranscriptCount: number;
|
|
102
115
|
selectedTranscriptCount: number;
|
|
103
116
|
source: "fallback" | "primary";
|
|
117
|
+
lowestWordConfidence?: number;
|
|
118
|
+
wordConfidenceSampleCount?: number;
|
|
104
119
|
};
|
|
105
120
|
export type VoiceTurnCorrectionDiagnostics = {
|
|
106
121
|
attempted: boolean;
|
|
@@ -130,6 +145,7 @@ export type VoiceFallbackDiagnostics = {
|
|
|
130
145
|
selected: boolean;
|
|
131
146
|
selectionReason: VoiceFallbackSelectionReason;
|
|
132
147
|
trigger: "empty-turn" | "low-confidence" | "empty-or-low-confidence" | "always";
|
|
148
|
+
triggerReason?: VoiceFallbackTriggerReason;
|
|
133
149
|
};
|
|
134
150
|
export type VoicePartialEvent = {
|
|
135
151
|
type: "partial";
|
|
@@ -417,6 +433,16 @@ export type VoiceSTTLifecycle = "continuous" | "turn-scoped";
|
|
|
417
433
|
export type VoiceTurnProfile = "fast" | "balanced" | "long-form";
|
|
418
434
|
export type VoiceTurnQualityProfile = "general" | "accent-heavy" | "noisy-room" | "short-command";
|
|
419
435
|
export type VoiceTurnFallbackTrigger = "empty-turn" | "low-confidence" | "empty-or-low-confidence" | "always";
|
|
436
|
+
export type VoiceFallbackTriggerReason = "always" | "empty-turn" | "risk-policy" | "transcript-confidence" | "word-confidence";
|
|
437
|
+
export type VoiceSTTFallbackCandidate = {
|
|
438
|
+
averageConfidence: number;
|
|
439
|
+
lowestWordConfidence?: number;
|
|
440
|
+
text: string;
|
|
441
|
+
transcripts: Transcript[];
|
|
442
|
+
wordCount: number;
|
|
443
|
+
words: TranscriptWord[];
|
|
444
|
+
};
|
|
445
|
+
export type VoiceSTTFallbackRiskPolicy = (candidate: VoiceSTTFallbackCandidate) => boolean;
|
|
420
446
|
export type VoiceSTTFallbackConfig = {
|
|
421
447
|
adapter: STTAdapter;
|
|
422
448
|
trigger?: VoiceTurnFallbackTrigger;
|
|
@@ -426,6 +452,12 @@ export type VoiceSTTFallbackConfig = {
|
|
|
426
452
|
settleMs?: number;
|
|
427
453
|
completionTimeoutMs?: number;
|
|
428
454
|
maxAttemptsPerTurn?: number;
|
|
455
|
+
/** Run the fallback when any provider word falls below this value. */
|
|
456
|
+
wordConfidenceThreshold?: number;
|
|
457
|
+
/** Application-specific routing for high-value turns, entities, or correction
|
|
458
|
+
* language that should receive a second transcription pass regardless of the
|
|
459
|
+
* aggregate confidence. */
|
|
460
|
+
riskPolicy?: VoiceSTTFallbackRiskPolicy;
|
|
429
461
|
};
|
|
430
462
|
export type VoiceResolvedSTTFallbackConfig = {
|
|
431
463
|
adapter: STTAdapter;
|
|
@@ -436,6 +468,8 @@ export type VoiceResolvedSTTFallbackConfig = {
|
|
|
436
468
|
settleMs: number;
|
|
437
469
|
completionTimeoutMs: number;
|
|
438
470
|
maxAttemptsPerTurn: number;
|
|
471
|
+
wordConfidenceThreshold?: number;
|
|
472
|
+
riskPolicy?: VoiceSTTFallbackRiskPolicy;
|
|
439
473
|
};
|
|
440
474
|
export type VoiceTurnDetectionConfig = {
|
|
441
475
|
profile?: VoiceTurnProfile;
|
package/dist/index.js
CHANGED
|
@@ -4025,7 +4025,10 @@ var createEmptyCurrentTurn = () => ({
|
|
|
4025
4025
|
silenceStartedAt: undefined,
|
|
4026
4026
|
transcripts: []
|
|
4027
4027
|
});
|
|
4028
|
-
var cloneTranscript = (transcript) => ({
|
|
4028
|
+
var cloneTranscript = (transcript) => ({
|
|
4029
|
+
...transcript,
|
|
4030
|
+
words: transcript.words?.map((word) => ({ ...word }))
|
|
4031
|
+
});
|
|
4029
4032
|
var encodeBase64 = (chunk) => Buffer2.from(chunk).toString("base64");
|
|
4030
4033
|
var countWords2 = (text) => text.trim().split(/\s+/).filter(Boolean).length;
|
|
4031
4034
|
var normalizeText2 = (text) => text.trim().replace(/\s+/g, " ");
|
|
@@ -4070,9 +4073,12 @@ var calculateMeanConfidence = (transcripts) => {
|
|
|
4070
4073
|
}
|
|
4071
4074
|
return sum / total;
|
|
4072
4075
|
};
|
|
4076
|
+
var collectTranscriptWords = (transcripts) => transcripts.flatMap((transcript) => transcript.words ?? []);
|
|
4077
|
+
var collectWordConfidences = (transcripts) => collectTranscriptWords(transcripts).map((word) => word.confidence).filter((confidence) => typeof confidence === "number" && Number.isFinite(confidence));
|
|
4073
4078
|
var createTurnQuality = (transcripts, source, fallbackUsed, fallbackDiagnostics, correctionDiagnostics, costEstimate) => {
|
|
4074
4079
|
const sampledTranscripts = transcripts.filter((transcript) => typeof transcript.confidence === "number");
|
|
4075
4080
|
const confidenceSampleCount = sampledTranscripts.length;
|
|
4081
|
+
const wordConfidences = collectWordConfidences(transcripts);
|
|
4076
4082
|
return {
|
|
4077
4083
|
averageConfidence: confidenceSampleCount > 0 ? sampledTranscripts.reduce((sum, transcript) => sum + transcript.confidence, 0) / confidenceSampleCount : undefined,
|
|
4078
4084
|
confidenceSampleCount,
|
|
@@ -4083,7 +4089,9 @@ var createTurnQuality = (transcripts, source, fallbackUsed, fallbackDiagnostics,
|
|
|
4083
4089
|
finalTranscriptCount: transcripts.filter((transcript) => transcript.isFinal).length,
|
|
4084
4090
|
partialTranscriptCount: transcripts.filter((transcript) => !transcript.isFinal).length,
|
|
4085
4091
|
selectedTranscriptCount: transcripts.length,
|
|
4086
|
-
source
|
|
4092
|
+
source,
|
|
4093
|
+
lowestWordConfidence: wordConfidences.length > 0 ? Math.min(...wordConfidences) : undefined,
|
|
4094
|
+
wordConfidenceSampleCount: wordConfidences.length
|
|
4087
4095
|
};
|
|
4088
4096
|
};
|
|
4089
4097
|
var createTurnCostEstimate = (input) => {
|
|
@@ -4100,20 +4108,38 @@ var createTurnCostEstimate = (input) => {
|
|
|
4100
4108
|
};
|
|
4101
4109
|
};
|
|
4102
4110
|
var normalizeCorrectionText = (text) => normalizeText2(text);
|
|
4103
|
-
var
|
|
4111
|
+
var evaluateFallbackNeed = (candidate, config) => {
|
|
4104
4112
|
const trimmed = normalizeText2(candidate.text);
|
|
4105
4113
|
const wordCount = countWords2(trimmed);
|
|
4114
|
+
const averageConfidence = calculateMeanConfidence(candidate.transcripts);
|
|
4115
|
+
const words = collectTranscriptWords(candidate.transcripts);
|
|
4116
|
+
const wordConfidences = collectWordConfidences(candidate.transcripts);
|
|
4117
|
+
const lowestWordConfidence = wordConfidences.length > 0 ? Math.min(...wordConfidences) : undefined;
|
|
4118
|
+
const resolvedCandidate = {
|
|
4119
|
+
averageConfidence,
|
|
4120
|
+
lowestWordConfidence,
|
|
4121
|
+
text: candidate.text,
|
|
4122
|
+
transcripts: candidate.transcripts,
|
|
4123
|
+
wordCount,
|
|
4124
|
+
words
|
|
4125
|
+
};
|
|
4106
4126
|
if (config.trigger === "always") {
|
|
4107
|
-
return true;
|
|
4127
|
+
return { needed: true, reason: "always" };
|
|
4108
4128
|
}
|
|
4109
|
-
if (config.trigger === "empty-turn") {
|
|
4110
|
-
return
|
|
4129
|
+
if (wordCount < config.minTextLength && (config.trigger === "empty-turn" || config.trigger === "empty-or-low-confidence")) {
|
|
4130
|
+
return { needed: true, reason: "empty-turn" };
|
|
4111
4131
|
}
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4132
|
+
if (config.riskPolicy?.(resolvedCandidate)) {
|
|
4133
|
+
return { needed: true, reason: "risk-policy" };
|
|
4134
|
+
}
|
|
4135
|
+
if (config.wordConfidenceThreshold !== undefined && lowestWordConfidence !== undefined && lowestWordConfidence < config.wordConfidenceThreshold) {
|
|
4136
|
+
return { needed: true, reason: "word-confidence" };
|
|
4115
4137
|
}
|
|
4116
|
-
|
|
4138
|
+
const checksConfidence = config.trigger === "low-confidence" || config.trigger === "empty-or-low-confidence";
|
|
4139
|
+
if (checksConfidence && averageConfidence > 0 && averageConfidence < config.confidenceThreshold) {
|
|
4140
|
+
return { needed: true, reason: "transcript-confidence" };
|
|
4141
|
+
}
|
|
4142
|
+
return { needed: false, reason: undefined };
|
|
4117
4143
|
};
|
|
4118
4144
|
var selectBetterTurnText = (candidate, fallback) => {
|
|
4119
4145
|
if (!fallback.text) {
|
|
@@ -4232,7 +4258,9 @@ var createVoiceSession = (options) => {
|
|
|
4232
4258
|
minTextLength: options.sttFallback.minTextLength ?? DEFAULT_FALLBACK_MIN_TEXT_LENGTH,
|
|
4233
4259
|
replayWindowMs: options.sttFallback.replayWindowMs ?? DEFAULT_FALLBACK_REPLAY_MS,
|
|
4234
4260
|
settleMs: options.sttFallback.settleMs ?? DEFAULT_FALLBACK_SETTLE_MS,
|
|
4235
|
-
trigger: options.sttFallback.trigger ?? "empty-or-low-confidence"
|
|
4261
|
+
trigger: options.sttFallback.trigger ?? "empty-or-low-confidence",
|
|
4262
|
+
wordConfidenceThreshold: options.sttFallback.wordConfidenceThreshold,
|
|
4263
|
+
riskPolicy: options.sttFallback.riskPolicy
|
|
4236
4264
|
} : undefined;
|
|
4237
4265
|
const appendTrace = async (input) => {
|
|
4238
4266
|
await options.trace?.append({
|
|
@@ -5379,7 +5407,8 @@ var createVoiceSession = (options) => {
|
|
|
5379
5407
|
text: primaryText,
|
|
5380
5408
|
transcripts: primaryTranscripts
|
|
5381
5409
|
};
|
|
5382
|
-
|
|
5410
|
+
const fallbackNeed = evaluateFallbackNeed(candidate, sttFallback);
|
|
5411
|
+
if (!fallbackNeed.needed) {
|
|
5383
5412
|
return null;
|
|
5384
5413
|
}
|
|
5385
5414
|
fallbackAttemptsForCurrentTurn += 1;
|
|
@@ -5506,7 +5535,8 @@ var createVoiceSession = (options) => {
|
|
|
5506
5535
|
primaryWordCount: primaryCandidate.wordCount,
|
|
5507
5536
|
selected: selection.winner.text === fallbackCandidate.text,
|
|
5508
5537
|
selectionReason: selection.reason,
|
|
5509
|
-
trigger: sttFallback.trigger
|
|
5538
|
+
trigger: sttFallback.trigger,
|
|
5539
|
+
triggerReason: fallbackNeed.reason
|
|
5510
5540
|
};
|
|
5511
5541
|
if (selection.winner.text === primaryCandidate.text) {
|
|
5512
5542
|
return {
|
|
@@ -25397,7 +25427,9 @@ var resolveSTTFallbackConfig = (config) => {
|
|
|
25397
25427
|
minTextLength: config.minTextLength ?? 2,
|
|
25398
25428
|
replayWindowMs: config.replayWindowMs ?? 8000,
|
|
25399
25429
|
settleMs: config.settleMs ?? 220,
|
|
25400
|
-
trigger: config.trigger ?? "empty-or-low-confidence"
|
|
25430
|
+
trigger: config.trigger ?? "empty-or-low-confidence",
|
|
25431
|
+
wordConfidenceThreshold: config.wordConfidenceThreshold,
|
|
25432
|
+
riskPolicy: config.riskPolicy
|
|
25401
25433
|
};
|
|
25402
25434
|
};
|
|
25403
25435
|
var normalizePhraseHints = (hints) => (hints ?? []).map((hint) => ({
|