@absolutejs/voice 0.0.22-beta.542 → 0.0.22-beta.543

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,30 @@
1
+ import type { TTSAdapter, TTSAdapterOpenOptions } from './types';
2
+ export type CachedTTSOptions = {
3
+ /**
4
+ * Return a stable cache key for an utterance whose synthesized audio should
5
+ * be rendered once and replayed verbatim on later calls (typically a
6
+ * greeting / fixed prompt), or `null`/`undefined` to synthesize it live every
7
+ * time (dynamic turn replies).
8
+ *
9
+ * The key must encode everything that affects the audio — the text, the
10
+ * voice, the model, and the output format. Because the cache is
11
+ * content-addressed, editing any of those naturally produces a new key, so a
12
+ * stale rendering is never replayed: the first call after a change re-renders
13
+ * (and re-caches) while the old entry is simply orphaned.
14
+ */
15
+ keyFor: (text: string, openOptions: TTSAdapterOpenOptions) => string | null | undefined;
16
+ /** Max distinct utterances to retain (LRU by insertion). Default 32. */
17
+ maxEntries?: number;
18
+ };
19
+ /**
20
+ * Wrap a TTS adapter so selected utterances are synthesized once and replayed
21
+ * from memory on subsequent `send()`s — eliminating provider latency for fixed
22
+ * prompts like a call greeting. Utterances are selected (and keyed) by
23
+ * `options.keyFor`; everything else passes straight through to the inner
24
+ * adapter, so dynamic replies are unaffected.
25
+ *
26
+ * The cache lives for the lifetime of the wrapper (one per adapter), so it is
27
+ * shared across every session/call the adapter serves. Warm it ahead of the
28
+ * first call by opening a session and `send()`ing the cacheable text once.
29
+ */
30
+ export declare const createCachedTTS: (inner: TTSAdapter, options: CachedTTSOptions) => TTSAdapter<TTSAdapterOpenOptions>;
package/dist/index.d.ts CHANGED
@@ -159,6 +159,7 @@ export { computePcmDurationMs, createVoiceMemoryRecordingStore, createVoiceWavRe
159
159
  export type { EncodeStereoWavInput, InterleavePcmInput, StoredVoiceRecordingArtifact, VoiceRecordingArtifact, VoiceRecordingChannel, VoiceRecordingEncoder, VoiceRecordingEncoderInput, VoiceRecordingEncoderResult, VoiceRecordingStore, } from "./core/recordingStore";
160
160
  export { createVoiceAssistantMemoryHandle, createVoiceAssistantMemoryRecord, createVoiceMemoryAssistantMemoryStore, resolveVoiceAssistantMemoryNamespace, } from "./core/assistantMemory";
161
161
  export { createAnthropicVoiceAssistantModel, createGeminiVoiceAssistantModel, createJSONVoiceAssistantModel, createOpenAIVoiceAssistantModel, createVoiceProviderOrchestrationProfile, resolveVoiceProviderRoutingPolicyPreset, createVoiceProviderRouter, } from "./core/modelAdapters";
162
+ export { createCachedTTS } from "./core/cachedTTS";
162
163
  export { createOpenAIVoiceTTS } from "./core/openaiTTS";
163
164
  export { createVoiceProviderHealthHTMLHandler, createVoiceProviderHealthJSONHandler, createVoiceProviderHealthRoutes, renderVoiceProviderHealthHTML, summarizeVoiceProviderHealth, } from "./core/providerHealth";
164
165
  export { createVoiceProviderCapabilityHTMLHandler, createVoiceProviderCapabilityJSONHandler, createVoiceProviderCapabilityRoutes, renderVoiceProviderCapabilityHTML, summarizeVoiceProviderCapabilities, } from "./core/providerCapabilities";
@@ -220,6 +221,7 @@ export type { VoiceSimulationSuiteAssertionInput, VoiceSimulationSuiteAssertionR
220
221
  export type { VoiceWorkflowContract, VoiceWorkflowContractDefinition, VoiceWorkflowContractField, VoiceWorkflowContractFieldMatch, VoiceWorkflowContractPresetName, VoiceWorkflowContractPresetOptions, VoiceWorkflowContractTracePayload, VoiceWorkflowContractValidation, VoiceWorkflowContractValidationIssue, VoiceWorkflowOutcome, } from "./core/workflowContract";
221
222
  export type { VoiceSessionListHTMLHandlerOptions, VoiceSessionListItem, VoiceSessionListOptions, VoiceSessionListRoutesOptions, VoiceSessionListStatus, VoiceProviderFallbackRecoverySummary, VoiceSessionReplay, VoiceSessionReplayHTMLHandlerOptions, VoiceSessionReplayOptions, VoiceSessionReplayRoutesOptions, VoiceSessionReplayTurn, } from "./core/sessionReplay";
222
223
  export type { AnthropicVoiceAssistantModelOptions, GeminiVoiceAssistantModelOptions, OpenAIVoiceAssistantModelOptions, VoiceProviderRouterEvent, VoiceProviderRouterFallbackMode, VoiceProviderRouterHealthOptions, VoiceProviderRouterOptions, VoiceProviderOrchestrationProfile, VoiceProviderOrchestrationProfileOptions, VoiceProviderOrchestrationResolvedSurface, VoiceProviderOrchestrationSurface, VoiceProviderRouterPolicy, VoiceProviderRouterPolicyPreset, VoiceProviderRouterPolicyWeights, VoiceProviderRouterProviderHealth, VoiceProviderRouterProviderProfile, VoiceProviderRouterStrategy, VoiceJSONAssistantModelHandler, VoiceJSONAssistantModelOptions, } from "./core/modelAdapters";
224
+ export type { CachedTTSOptions } from "./core/cachedTTS";
223
225
  export type { OpenAIVoiceTTSOptions, OpenAIVoiceTTSVoice, } from "./core/openaiTTS";
224
226
  export type { VoiceProviderHealthStatus, VoiceProviderHealthSummary, VoiceProviderHealthSummaryOptions, } from "./core/providerHealth";
225
227
  export type { VoiceProviderCapabilityDefinition, VoiceProviderCapabilityHandlerOptions, VoiceProviderCapabilityHTMLHandlerOptions, VoiceProviderCapabilityKind, VoiceProviderCapabilityOptions, VoiceProviderCapabilityReport, VoiceProviderCapabilityRoutesOptions, VoiceProviderCapabilitySummary, } from "./core/providerCapabilities";
package/dist/index.js CHANGED
@@ -44998,6 +44998,74 @@ var createGeminiVoiceAssistantModel = (options) => {
44998
44998
  }
44999
44999
  };
45000
45000
  };
45001
+ // src/core/cachedTTS.ts
45002
+ var DEFAULT_MAX_ENTRIES = 32;
45003
+ var createCachedTTS = (inner, options) => {
45004
+ const maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;
45005
+ const cache = new Map;
45006
+ const remember = (key, events) => {
45007
+ cache.delete(key);
45008
+ cache.set(key, events);
45009
+ while (cache.size > maxEntries) {
45010
+ const oldest = cache.keys().next().value;
45011
+ if (oldest === undefined) {
45012
+ break;
45013
+ }
45014
+ cache.delete(oldest);
45015
+ }
45016
+ };
45017
+ return {
45018
+ kind: "tts",
45019
+ open: async (openOptions) => {
45020
+ const session = await inner.open(openOptions);
45021
+ const audioHandlers = new Set;
45022
+ let capture = null;
45023
+ session.on("audio", (event) => {
45024
+ if (capture) {
45025
+ capture.push(event);
45026
+ }
45027
+ });
45028
+ return {
45029
+ cancel: async (reason) => {
45030
+ if (session.cancel) {
45031
+ await session.cancel(reason);
45032
+ }
45033
+ },
45034
+ close: (reason) => session.close(reason),
45035
+ on: (event, handler) => {
45036
+ if (event === "audio") {
45037
+ audioHandlers.add(handler);
45038
+ }
45039
+ return session.on(event, handler);
45040
+ },
45041
+ send: async (text) => {
45042
+ const key = options.keyFor(text, openOptions);
45043
+ if (key === null || key === undefined) {
45044
+ await session.send(text);
45045
+ return;
45046
+ }
45047
+ const cached = cache.get(key);
45048
+ if (cached) {
45049
+ for (const event of cached) {
45050
+ const replay = {
45051
+ ...event,
45052
+ receivedAt: Date.now()
45053
+ };
45054
+ for (const handler of audioHandlers) {
45055
+ await Promise.resolve(handler(replay));
45056
+ }
45057
+ }
45058
+ return;
45059
+ }
45060
+ capture = [];
45061
+ await session.send(text);
45062
+ remember(key, capture);
45063
+ capture = null;
45064
+ }
45065
+ };
45066
+ }
45067
+ };
45068
+ };
45001
45069
  // src/core/openaiTTS.ts
45002
45070
  var OPENAI_PCM24_FORMAT = {
45003
45071
  channels: 1,
@@ -52371,6 +52439,7 @@ export {
52371
52439
  createDomainPhraseHints,
52372
52440
  createDomainLexicon,
52373
52441
  createCoturnIceServers,
52442
+ createCachedTTS,
52374
52443
  createAnthropicVoiceAssistantModel,
52375
52444
  createAIVoiceModel,
52376
52445
  conditionAudioChunk,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.542",
3
+ "version": "0.0.22-beta.543",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",