@absolutejs/voice 0.0.22-beta.488 → 0.0.22-beta.489

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.
@@ -0,0 +1,18 @@
1
+ export type VoiceBackchannelCue = {
2
+ audioUrl?: string;
3
+ metadata?: Record<string, unknown>;
4
+ text?: string;
5
+ };
6
+ export type VoiceBackchannelDriverOptions = {
7
+ cues?: ReadonlyArray<VoiceBackchannelCue>;
8
+ cueIntervalMs?: number;
9
+ cueIndex?: (index: number) => number;
10
+ minSpeechMs?: number;
11
+ onCue: (cue: VoiceBackchannelCue) => Promise<void> | void;
12
+ };
13
+ export type VoiceBackchannelDriver = {
14
+ noteSpeech: (timestampMs?: number) => void;
15
+ noteSilence: (timestampMs?: number) => void;
16
+ reset: () => void;
17
+ };
18
+ export declare const createVoiceBackchannelDriver: (options: VoiceBackchannelDriverOptions) => VoiceBackchannelDriver;
package/dist/index.d.ts CHANGED
@@ -81,6 +81,8 @@ export { describeVoiceAssistantMode, resolveVoiceAssistantMode, } from "./assist
81
81
  export type { VoiceAssistantMode, VoiceAssistantModality, VoiceAssistantModeDescriptor, VoiceSemanticVADConfig, } from "./assistantMode";
82
82
  export { createPunctuationSemanticTurnDetector, createRegexSemanticTurnDetector, } from "./semanticTurn";
83
83
  export { VOICE_WEBHOOK_SIGNATURE_HEADER, VOICE_WEBHOOK_TIMESTAMP_HEADER, extractVoiceWebhookSignatureFromHeaders, signVoiceWebhookBody, verifyVoiceWebhookSignature, } from "./webhookVerification";
84
+ export { createVoiceBackchannelDriver } from "./backchannel";
85
+ export type { VoiceBackchannelCue, VoiceBackchannelDriver, VoiceBackchannelDriverOptions, } from "./backchannel";
84
86
  export { createVoiceIVRSession, describeVoiceIVRPlan, evaluateVoiceIVRPlan, } from "./ivrPlan";
85
87
  export type { VoiceIVRBranch, VoiceIVRDecision, VoiceIVRInput, VoiceIVRMatch, VoiceIVRPlan, VoiceIVRSession, } from "./ivrPlan";
86
88
  export { VOICE_CALLER_MEMORY_KEY, buildVoiceCallerMemoryNamespace, createVoiceCallerMemoryNamespace, summarizeVoiceCallerTranscript, } from "./callerMemory";
package/dist/index.js CHANGED
@@ -35475,6 +35475,70 @@ var extractVoiceWebhookSignatureFromHeaders = (headers) => {
35475
35475
  timestamp: get(VOICE_WEBHOOK_TIMESTAMP_HEADER)
35476
35476
  };
35477
35477
  };
35478
+ // src/backchannel.ts
35479
+ var DEFAULT_CUES = [
35480
+ { text: "mm-hmm" },
35481
+ { text: "I see" },
35482
+ { text: "right" },
35483
+ { text: "go on" }
35484
+ ];
35485
+ var createVoiceBackchannelDriver = (options) => {
35486
+ const cues = options.cues ?? DEFAULT_CUES;
35487
+ const minSpeechMs = options.minSpeechMs ?? 2500;
35488
+ const cueIntervalMs = options.cueIntervalMs ?? 2500;
35489
+ const cueIndexFn = options.cueIndex ?? ((index) => index % Math.max(cues.length, 1));
35490
+ let speechStartedAt;
35491
+ let lastCueAt;
35492
+ let cueCount = 0;
35493
+ let firing = false;
35494
+ const tryFire = async (now) => {
35495
+ if (firing || cues.length === 0) {
35496
+ return;
35497
+ }
35498
+ if (speechStartedAt === undefined) {
35499
+ return;
35500
+ }
35501
+ const elapsed = now - speechStartedAt;
35502
+ if (elapsed < minSpeechMs) {
35503
+ return;
35504
+ }
35505
+ if (lastCueAt !== undefined && now - lastCueAt < cueIntervalMs) {
35506
+ return;
35507
+ }
35508
+ const cue = cues[cueIndexFn(cueCount)];
35509
+ if (!cue) {
35510
+ return;
35511
+ }
35512
+ firing = true;
35513
+ try {
35514
+ await options.onCue(cue);
35515
+ } finally {
35516
+ firing = false;
35517
+ lastCueAt = now;
35518
+ cueCount += 1;
35519
+ }
35520
+ };
35521
+ return {
35522
+ noteSpeech: (timestampMs) => {
35523
+ const now = timestampMs ?? Date.now();
35524
+ if (speechStartedAt === undefined) {
35525
+ speechStartedAt = now;
35526
+ }
35527
+ tryFire(now);
35528
+ },
35529
+ noteSilence: (timestampMs) => {
35530
+ const now = timestampMs ?? Date.now();
35531
+ if (lastCueAt !== undefined && now - lastCueAt > cueIntervalMs * 2) {
35532
+ speechStartedAt = undefined;
35533
+ }
35534
+ },
35535
+ reset: () => {
35536
+ speechStartedAt = undefined;
35537
+ lastCueAt = undefined;
35538
+ cueCount = 0;
35539
+ }
35540
+ };
35541
+ };
35478
35542
  // src/ivrPlan.ts
35479
35543
  var speechMatchesPattern = (pattern, speech) => {
35480
35544
  const normalized = speech.toLowerCase().trim();
@@ -46959,6 +47023,7 @@ export {
46959
47023
  createVoiceBrowserMediaRoutes,
46960
47024
  createVoiceBrowserCallProfileRoutes,
46961
47025
  createVoiceBargeInRoutes,
47026
+ createVoiceBackchannelDriver,
46962
47027
  createVoiceAuditTrailRoutes,
46963
47028
  createVoiceAuditSinkStore,
46964
47029
  createVoiceAuditSinkDeliveryWorkerLoop,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.488",
3
+ "version": "0.0.22-beta.489",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",