@absolutejs/voice 0.0.22-beta.82 → 0.0.22-beta.83

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 CHANGED
@@ -15,6 +15,7 @@ export { applyVoiceTelephonyOutcome, createMemoryVoiceTelephonyWebhookIdempotenc
15
15
  export { createStoredVoiceCallReviewArtifact, createStoredVoiceExternalObjectMap, createStoredVoiceIntegrationEvent, createStoredVoiceOpsTask, createVoiceFileExternalObjectMapStore, createVoiceFileAssistantMemoryStore, createVoiceFileIntegrationEventStore, createVoiceFileReviewStore, createVoiceFileRuntimeStorage, createVoiceFileSessionStore, createVoiceFileTaskStore, createVoiceFileTraceSinkDeliveryStore, createVoiceFileTraceEventStore } from './fileStore';
16
16
  export { createVoiceAssistantMemoryHandle, createVoiceAssistantMemoryRecord, createVoiceMemoryAssistantMemoryStore, resolveVoiceAssistantMemoryNamespace } from './assistantMemory';
17
17
  export { createAnthropicVoiceAssistantModel, createGeminiVoiceAssistantModel, createJSONVoiceAssistantModel, createOpenAIVoiceAssistantModel, resolveVoiceProviderRoutingPolicyPreset, createVoiceProviderRouter } from './modelAdapters';
18
+ export { createOpenAIVoiceTTS } from './openaiTTS';
18
19
  export { createVoiceProviderHealthHTMLHandler, createVoiceProviderHealthJSONHandler, createVoiceProviderHealthRoutes, renderVoiceProviderHealthHTML, summarizeVoiceProviderHealth } from './providerHealth';
19
20
  export { createVoiceProviderCapabilityHTMLHandler, createVoiceProviderCapabilityJSONHandler, createVoiceProviderCapabilityRoutes, renderVoiceProviderCapabilityHTML, summarizeVoiceProviderCapabilities } from './providerCapabilities';
20
21
  export { buildVoiceOpsConsoleReport, createVoiceOpsConsoleRoutes, renderVoiceOpsConsoleHTML } from './opsConsoleRoutes';
@@ -53,6 +54,7 @@ export type { VoiceEvalBaselineComparison, VoiceEvalBaselineComparisonOptions, V
53
54
  export type { VoiceWorkflowContract, VoiceWorkflowContractDefinition, VoiceWorkflowContractField, VoiceWorkflowContractFieldMatch, VoiceWorkflowContractPresetName, VoiceWorkflowContractPresetOptions, VoiceWorkflowContractTracePayload, VoiceWorkflowContractValidation, VoiceWorkflowContractValidationIssue, VoiceWorkflowOutcome } from './workflowContract';
54
55
  export type { VoiceSessionListHTMLHandlerOptions, VoiceSessionListItem, VoiceSessionListOptions, VoiceSessionListRoutesOptions, VoiceSessionListStatus, VoiceSessionReplay, VoiceSessionReplayHTMLHandlerOptions, VoiceSessionReplayOptions, VoiceSessionReplayRoutesOptions, VoiceSessionReplayTurn } from './sessionReplay';
55
56
  export type { AnthropicVoiceAssistantModelOptions, GeminiVoiceAssistantModelOptions, OpenAIVoiceAssistantModelOptions, VoiceProviderRouterEvent, VoiceProviderRouterFallbackMode, VoiceProviderRouterHealthOptions, VoiceProviderRouterOptions, VoiceProviderRouterPolicy, VoiceProviderRouterPolicyPreset, VoiceProviderRouterPolicyWeights, VoiceProviderRouterProviderHealth, VoiceProviderRouterProviderProfile, VoiceProviderRouterStrategy, VoiceJSONAssistantModelHandler, VoiceJSONAssistantModelOptions } from './modelAdapters';
57
+ export type { OpenAIVoiceTTSOptions, OpenAIVoiceTTSVoice } from './openaiTTS';
56
58
  export type { VoiceProviderHealthStatus, VoiceProviderHealthSummary, VoiceProviderHealthSummaryOptions } from './providerHealth';
57
59
  export type { VoiceProviderCapabilityDefinition, VoiceProviderCapabilityHandlerOptions, VoiceProviderCapabilityHTMLHandlerOptions, VoiceProviderCapabilityKind, VoiceProviderCapabilityOptions, VoiceProviderCapabilityReport, VoiceProviderCapabilityRoutesOptions, VoiceProviderCapabilitySummary } from './providerCapabilities';
58
60
  export type { VoiceTurnQualityHTMLHandlerOptions, VoiceTurnQualityItem, VoiceTurnQualityOptions, VoiceTurnQualityReport, VoiceTurnQualityRoutesOptions, VoiceTurnQualityStatus } from './turnQuality';
package/dist/index.js CHANGED
@@ -12424,6 +12424,136 @@ var createGeminiVoiceAssistantModel = (options) => {
12424
12424
  }
12425
12425
  };
12426
12426
  };
12427
+ // src/openaiTTS.ts
12428
+ var OPENAI_PCM24_FORMAT = {
12429
+ channels: 1,
12430
+ container: "raw",
12431
+ encoding: "pcm_s16le",
12432
+ sampleRateHz: 24000
12433
+ };
12434
+ var resolveInstructions = async (instructions, input) => {
12435
+ if (typeof instructions === "function") {
12436
+ return instructions(input);
12437
+ }
12438
+ return instructions;
12439
+ };
12440
+ var createTTSHTTPError = (response) => new Error(`OpenAI voice TTS failed: HTTP ${response.status}`);
12441
+ var emit = async (listeners, event, payload) => {
12442
+ for (const handler of listeners[event]) {
12443
+ await Promise.resolve(handler(payload));
12444
+ }
12445
+ };
12446
+ var createOpenAIVoiceTTS = (options) => {
12447
+ const fetchImpl = options.fetch ?? globalThis.fetch;
12448
+ const baseUrl = options.baseUrl ?? "https://api.openai.com/v1";
12449
+ const model = options.model ?? "gpt-4o-mini-tts";
12450
+ const voice2 = options.voice ?? "coral";
12451
+ return {
12452
+ kind: "tts",
12453
+ open: (openOptions) => {
12454
+ const listeners = {
12455
+ audio: new Set,
12456
+ close: new Set,
12457
+ error: new Set
12458
+ };
12459
+ const abortController = new AbortController;
12460
+ const signalAbort = () => abortController.abort();
12461
+ openOptions.signal?.addEventListener("abort", signalAbort, { once: true });
12462
+ let closed = false;
12463
+ return {
12464
+ close: async (reason) => {
12465
+ if (closed) {
12466
+ return;
12467
+ }
12468
+ closed = true;
12469
+ abortController.abort();
12470
+ openOptions.signal?.removeEventListener("abort", signalAbort);
12471
+ await emit(listeners, "close", {
12472
+ reason,
12473
+ type: "close"
12474
+ });
12475
+ },
12476
+ on: (event, handler) => {
12477
+ listeners[event].add(handler);
12478
+ return () => {
12479
+ listeners[event].delete(handler);
12480
+ };
12481
+ },
12482
+ send: async (text) => {
12483
+ if (closed || !text.trim()) {
12484
+ return;
12485
+ }
12486
+ try {
12487
+ const instructions = await resolveInstructions(options.instructions, {
12488
+ lexicon: openOptions.lexicon,
12489
+ sessionId: openOptions.sessionId,
12490
+ text
12491
+ });
12492
+ const response = await fetchImpl(`${baseUrl.replace(/\/$/, "")}/audio/speech`, {
12493
+ body: JSON.stringify({
12494
+ input: text,
12495
+ instructions,
12496
+ model,
12497
+ response_format: "pcm",
12498
+ speed: options.speed,
12499
+ voice: voice2
12500
+ }),
12501
+ headers: {
12502
+ authorization: `Bearer ${options.apiKey}`,
12503
+ "content-type": "application/json"
12504
+ },
12505
+ method: "POST",
12506
+ signal: abortController.signal
12507
+ });
12508
+ if (!response.ok) {
12509
+ throw createTTSHTTPError(response);
12510
+ }
12511
+ if (!response.body) {
12512
+ const chunk = new Uint8Array(await response.arrayBuffer());
12513
+ if (!closed && chunk.byteLength > 0) {
12514
+ await emit(listeners, "audio", {
12515
+ chunk,
12516
+ format: OPENAI_PCM24_FORMAT,
12517
+ receivedAt: Date.now(),
12518
+ type: "audio"
12519
+ });
12520
+ }
12521
+ return;
12522
+ }
12523
+ const reader = response.body.getReader();
12524
+ try {
12525
+ while (!closed) {
12526
+ const { done, value } = await reader.read();
12527
+ if (done) {
12528
+ break;
12529
+ }
12530
+ if (value.byteLength > 0) {
12531
+ await emit(listeners, "audio", {
12532
+ chunk: new Uint8Array(value),
12533
+ format: OPENAI_PCM24_FORMAT,
12534
+ receivedAt: Date.now(),
12535
+ type: "audio"
12536
+ });
12537
+ }
12538
+ }
12539
+ } finally {
12540
+ reader.releaseLock();
12541
+ }
12542
+ } catch (error) {
12543
+ if (closed || abortController.signal.aborted) {
12544
+ return;
12545
+ }
12546
+ await emit(listeners, "error", {
12547
+ error: error instanceof Error ? error : new Error(String(error)),
12548
+ recoverable: true,
12549
+ type: "error"
12550
+ });
12551
+ }
12552
+ }
12553
+ };
12554
+ }
12555
+ };
12556
+ };
12427
12557
  // src/providerAdapters.ts
12428
12558
  class VoiceIOProviderTimeoutError extends Error {
12429
12559
  provider;
@@ -12611,11 +12741,11 @@ var createResolver = (options) => {
12611
12741
  selectedProvider: preferred
12612
12742
  };
12613
12743
  };
12614
- const emit = async (event, input) => {
12744
+ const emit2 = async (event, input) => {
12615
12745
  await options.onProviderEvent?.(event, input);
12616
12746
  };
12617
12747
  return {
12618
- emit,
12748
+ emit: emit2,
12619
12749
  getSuppressionRemainingMs,
12620
12750
  providerIds,
12621
12751
  recordError,
@@ -17300,6 +17430,7 @@ export {
17300
17430
  createPlivoVoiceResponse,
17301
17431
  createPlivoMediaStreamBridge,
17302
17432
  createPhraseHintCorrectionHandler,
17433
+ createOpenAIVoiceTTS,
17303
17434
  createOpenAIVoiceAssistantModel,
17304
17435
  createMemoryVoiceTelephonyWebhookIdempotencyStore,
17305
17436
  createJSONVoiceAssistantModel,
@@ -0,0 +1,18 @@
1
+ import type { TTSAdapter, TTSAdapterOpenOptions, VoiceLexiconEntry } from './types';
2
+ export type OpenAIVoiceTTSVoice = 'alloy' | 'ash' | 'ballad' | 'cedar' | 'coral' | 'echo' | 'fable' | 'marin' | 'nova' | 'onyx' | 'sage' | 'shimmer' | 'verse' | (string & {});
3
+ export type OpenAIVoiceTTSOptions = {
4
+ apiKey: string;
5
+ baseUrl?: string;
6
+ fetch?: typeof fetch;
7
+ instructions?: string | ((input: {
8
+ lexicon?: VoiceLexiconEntry[];
9
+ sessionId: string;
10
+ text: string;
11
+ }) => Promise<string | undefined> | string | undefined);
12
+ model?: 'gpt-4o-mini-tts' | 'tts-1' | 'tts-1-hd' | (string & {});
13
+ speed?: number;
14
+ voice?: OpenAIVoiceTTSVoice | {
15
+ id: string;
16
+ };
17
+ };
18
+ export declare const createOpenAIVoiceTTS: (options: OpenAIVoiceTTSOptions) => TTSAdapter<TTSAdapterOpenOptions>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.82",
3
+ "version": "0.0.22-beta.83",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",