@absolutejs/voice 0.0.22-beta.482 → 0.0.22-beta.483
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/index.d.ts +2 -0
- package/dist/index.js +84 -0
- package/dist/semanticTurn.d.ts +27 -0
- package/dist/testing/index.js +12 -0
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -77,6 +77,8 @@ export { DEFAULT_VOICE_REDACTION_PATTERNS, createVoiceTranscriptRedactor, redact
|
|
|
77
77
|
export type { CreateVoiceTranscriptRedactorOptions, VoiceRedactionPattern, VoiceTranscriptRedactor, } from "./redaction";
|
|
78
78
|
export { DEFAULT_VOICE_PRICE_BOOK, createVoiceCostAccountant, } from "./costAccounting";
|
|
79
79
|
export type { CreateVoiceCostAccountantOptions, VoiceCostAccountant, VoiceCostBreakdown, VoiceCostLLMRecord, VoiceCostSTTRecord, VoiceCostTTSRecord, VoiceCostTelephonyRecord, VoicePriceBook, VoiceProviderRates, } from "./costAccounting";
|
|
80
|
+
export { createPunctuationSemanticTurnDetector, createRegexSemanticTurnDetector, } from "./semanticTurn";
|
|
81
|
+
export type { CreatePunctuationSemanticTurnDetectorOptions, CreateRegexSemanticTurnDetectorOptions, VoiceSemanticTurnDetector, VoiceSemanticTurnInput, VoiceSemanticTurnVerdict, } from "./semanticTurn";
|
|
80
82
|
export { createMonologueAMDDetector } from "./amdDetector";
|
|
81
83
|
export type { MonologueAMDDetectorOptions, VoiceAMDDetector, VoiceAMDDetectorInput, VoiceAMDVerdict, } from "./amdDetector";
|
|
82
84
|
export { createVoiceRAGTool } from "./ragTool";
|
package/dist/index.js
CHANGED
|
@@ -4786,6 +4786,18 @@ var createVoiceSession = (options) => {
|
|
|
4786
4786
|
session,
|
|
4787
4787
|
type: "turn.transcript"
|
|
4788
4788
|
});
|
|
4789
|
+
if (options.semanticTurnDetector) {
|
|
4790
|
+
const verdict = await Promise.resolve(options.semanticTurnDetector.evaluate({
|
|
4791
|
+
lastFinalTranscript: transcript,
|
|
4792
|
+
partialText: session.currentTurn.partialText,
|
|
4793
|
+
silenceMs: session.currentTurn.silenceStartedAt !== undefined ? Date.now() - session.currentTurn.silenceStartedAt : 0,
|
|
4794
|
+
transcripts: session.currentTurn.transcripts
|
|
4795
|
+
}));
|
|
4796
|
+
if (verdict.endOfTurn) {
|
|
4797
|
+
clearSilenceTimer();
|
|
4798
|
+
await requestTurnCommit("vendor");
|
|
4799
|
+
}
|
|
4800
|
+
}
|
|
4789
4801
|
};
|
|
4790
4802
|
const resumePendingTurnCommit = (session) => {
|
|
4791
4803
|
const pendingText = buildTurnText(session.currentTurn.transcripts, session.currentTurn.partialText, {
|
|
@@ -35292,6 +35304,76 @@ var createVoiceCostAccountant = (options = {}) => {
|
|
|
35292
35304
|
})
|
|
35293
35305
|
};
|
|
35294
35306
|
};
|
|
35307
|
+
// src/semanticTurn.ts
|
|
35308
|
+
var DEFAULT_END_PUNCTUATION = [".", "?", "!"];
|
|
35309
|
+
var DEFAULT_FILLER_WORDS = [
|
|
35310
|
+
"uh",
|
|
35311
|
+
"um",
|
|
35312
|
+
"er",
|
|
35313
|
+
"ah",
|
|
35314
|
+
"like",
|
|
35315
|
+
"you know",
|
|
35316
|
+
"i mean",
|
|
35317
|
+
"well",
|
|
35318
|
+
"so"
|
|
35319
|
+
];
|
|
35320
|
+
var stripTerminalPunctuation = (text) => text.replace(/[\s.?!]+$/u, "").trim();
|
|
35321
|
+
var createPunctuationSemanticTurnDetector = (options = {}) => {
|
|
35322
|
+
const endPunctuation = options.endPunctuation ?? DEFAULT_END_PUNCTUATION;
|
|
35323
|
+
const fillerWords = (options.fillerWords ?? DEFAULT_FILLER_WORDS).map((word) => word.toLowerCase());
|
|
35324
|
+
const minPartialWords = options.minPartialWords ?? 2;
|
|
35325
|
+
return {
|
|
35326
|
+
evaluate: ({ lastFinalTranscript, partialText }) => {
|
|
35327
|
+
const candidate = partialText.trim().length > 0 ? partialText : lastFinalTranscript?.text ?? "";
|
|
35328
|
+
const trimmed = candidate.trim();
|
|
35329
|
+
if (!trimmed) {
|
|
35330
|
+
return { endOfTurn: false, reason: "empty" };
|
|
35331
|
+
}
|
|
35332
|
+
const wordCount = trimmed.split(/\s+/u).filter(Boolean).length;
|
|
35333
|
+
if (wordCount < minPartialWords) {
|
|
35334
|
+
return { endOfTurn: false, reason: "below-min-words" };
|
|
35335
|
+
}
|
|
35336
|
+
const lastChar = trimmed.at(-1);
|
|
35337
|
+
const endsWithTerminal = typeof lastChar === "string" && endPunctuation.includes(lastChar);
|
|
35338
|
+
if (!endsWithTerminal) {
|
|
35339
|
+
return { endOfTurn: false, reason: "no-terminal-punctuation" };
|
|
35340
|
+
}
|
|
35341
|
+
const lastWord = stripTerminalPunctuation(trimmed).split(/\s+/u).at(-1)?.toLowerCase();
|
|
35342
|
+
if (lastWord && fillerWords.includes(lastWord)) {
|
|
35343
|
+
return { endOfTurn: false, reason: "trailing-filler" };
|
|
35344
|
+
}
|
|
35345
|
+
return {
|
|
35346
|
+
confidence: 0.9,
|
|
35347
|
+
endOfTurn: true,
|
|
35348
|
+
reason: "terminal-punctuation"
|
|
35349
|
+
};
|
|
35350
|
+
}
|
|
35351
|
+
};
|
|
35352
|
+
};
|
|
35353
|
+
var createRegexSemanticTurnDetector = (options) => {
|
|
35354
|
+
const minPartialWords = options.minPartialWords ?? 2;
|
|
35355
|
+
return {
|
|
35356
|
+
evaluate: ({ lastFinalTranscript, partialText }) => {
|
|
35357
|
+
const candidate = partialText.trim().length > 0 ? partialText : lastFinalTranscript?.text ?? "";
|
|
35358
|
+
const trimmed = candidate.trim();
|
|
35359
|
+
if (!trimmed) {
|
|
35360
|
+
return { endOfTurn: false, reason: "empty" };
|
|
35361
|
+
}
|
|
35362
|
+
const wordCount = trimmed.split(/\s+/u).filter(Boolean).length;
|
|
35363
|
+
if (wordCount < minPartialWords) {
|
|
35364
|
+
return { endOfTurn: false, reason: "below-min-words" };
|
|
35365
|
+
}
|
|
35366
|
+
const match = options.endPattern.exec(trimmed);
|
|
35367
|
+
if (!match) {
|
|
35368
|
+
return { endOfTurn: false, reason: "pattern-miss" };
|
|
35369
|
+
}
|
|
35370
|
+
return {
|
|
35371
|
+
endOfTurn: true,
|
|
35372
|
+
reason: "pattern-match"
|
|
35373
|
+
};
|
|
35374
|
+
}
|
|
35375
|
+
};
|
|
35376
|
+
};
|
|
35295
35377
|
// src/amdDetector.ts
|
|
35296
35378
|
var createMonologueAMDDetector = (options = {}) => {
|
|
35297
35379
|
const minMonologueMs = options.minMonologueMs ?? 8000;
|
|
@@ -46489,6 +46571,8 @@ export {
|
|
|
46489
46571
|
createStoredVoiceExternalObjectMap,
|
|
46490
46572
|
createStoredVoiceCallReviewArtifact,
|
|
46491
46573
|
createRiskyTurnCorrectionHandler,
|
|
46574
|
+
createRegexSemanticTurnDetector,
|
|
46575
|
+
createPunctuationSemanticTurnDetector,
|
|
46492
46576
|
createPlivoVoiceRoutes,
|
|
46493
46577
|
createPlivoVoiceResponse,
|
|
46494
46578
|
createPlivoMediaStreamBridge,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Transcript } from "./types";
|
|
2
|
+
export type VoiceSemanticTurnInput = {
|
|
3
|
+
audioLevel?: number;
|
|
4
|
+
lastFinalTranscript?: Transcript;
|
|
5
|
+
partialText: string;
|
|
6
|
+
silenceMs: number;
|
|
7
|
+
transcripts: Transcript[];
|
|
8
|
+
};
|
|
9
|
+
export type VoiceSemanticTurnVerdict = {
|
|
10
|
+
confidence?: number;
|
|
11
|
+
endOfTurn: boolean;
|
|
12
|
+
reason?: string;
|
|
13
|
+
};
|
|
14
|
+
export type VoiceSemanticTurnDetector = {
|
|
15
|
+
evaluate: (input: VoiceSemanticTurnInput) => Promise<VoiceSemanticTurnVerdict> | VoiceSemanticTurnVerdict;
|
|
16
|
+
};
|
|
17
|
+
export type CreatePunctuationSemanticTurnDetectorOptions = {
|
|
18
|
+
endPunctuation?: ReadonlyArray<string>;
|
|
19
|
+
fillerWords?: ReadonlyArray<string>;
|
|
20
|
+
minPartialWords?: number;
|
|
21
|
+
};
|
|
22
|
+
export declare const createPunctuationSemanticTurnDetector: (options?: CreatePunctuationSemanticTurnDetectorOptions) => VoiceSemanticTurnDetector;
|
|
23
|
+
export type CreateRegexSemanticTurnDetectorOptions = {
|
|
24
|
+
endPattern: RegExp;
|
|
25
|
+
minPartialWords?: number;
|
|
26
|
+
};
|
|
27
|
+
export declare const createRegexSemanticTurnDetector: (options: CreateRegexSemanticTurnDetectorOptions) => VoiceSemanticTurnDetector;
|
package/dist/testing/index.js
CHANGED
|
@@ -6754,6 +6754,18 @@ var createVoiceSession = (options) => {
|
|
|
6754
6754
|
session,
|
|
6755
6755
|
type: "turn.transcript"
|
|
6756
6756
|
});
|
|
6757
|
+
if (options.semanticTurnDetector) {
|
|
6758
|
+
const verdict = await Promise.resolve(options.semanticTurnDetector.evaluate({
|
|
6759
|
+
lastFinalTranscript: transcript,
|
|
6760
|
+
partialText: session.currentTurn.partialText,
|
|
6761
|
+
silenceMs: session.currentTurn.silenceStartedAt !== undefined ? Date.now() - session.currentTurn.silenceStartedAt : 0,
|
|
6762
|
+
transcripts: session.currentTurn.transcripts
|
|
6763
|
+
}));
|
|
6764
|
+
if (verdict.endOfTurn) {
|
|
6765
|
+
clearSilenceTimer();
|
|
6766
|
+
await requestTurnCommit("vendor");
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
6757
6769
|
};
|
|
6758
6770
|
const resumePendingTurnCommit = (session) => {
|
|
6759
6771
|
const pendingText = buildTurnText(session.currentTurn.transcripts, session.currentTurn.partialText, {
|
package/dist/types.d.ts
CHANGED
|
@@ -731,6 +731,7 @@ export type CreateVoiceSessionOptions<TContext = unknown, TSession extends Voice
|
|
|
731
731
|
provider?: string;
|
|
732
732
|
};
|
|
733
733
|
redact?: import("./redaction").VoiceTranscriptRedactor;
|
|
734
|
+
semanticTurnDetector?: import("./semanticTurn").VoiceSemanticTurnDetector;
|
|
734
735
|
reconnect: Required<VoiceReconnectConfig>;
|
|
735
736
|
phraseHints?: VoicePhraseHint[];
|
|
736
737
|
sessionMetadata?: Record<string, unknown>;
|