@absolutejs/voice 0.0.22-beta.10 → 0.0.22-beta.11

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
@@ -3,7 +3,7 @@ export { createVoiceAssistant, createVoiceExperiment, summarizeVoiceAssistantRun
3
3
  export { createVoiceAgent, createVoiceAgentSquad, createVoiceAgentTool } from './agent';
4
4
  export { createStoredVoiceCallReviewArtifact, createStoredVoiceExternalObjectMap, createStoredVoiceIntegrationEvent, createStoredVoiceOpsTask, createVoiceFileExternalObjectMapStore, createVoiceFileAssistantMemoryStore, createVoiceFileIntegrationEventStore, createVoiceFileReviewStore, createVoiceFileRuntimeStorage, createVoiceFileSessionStore, createVoiceFileTaskStore, createVoiceFileTraceSinkDeliveryStore, createVoiceFileTraceEventStore } from './fileStore';
5
5
  export { createVoiceAssistantMemoryHandle, createVoiceAssistantMemoryRecord, createVoiceMemoryAssistantMemoryStore, resolveVoiceAssistantMemoryNamespace } from './assistantMemory';
6
- export { createAnthropicVoiceAssistantModel, createGeminiVoiceAssistantModel, createJSONVoiceAssistantModel, createOpenAIVoiceAssistantModel } from './modelAdapters';
6
+ export { createAnthropicVoiceAssistantModel, createGeminiVoiceAssistantModel, createJSONVoiceAssistantModel, createOpenAIVoiceAssistantModel, createVoiceProviderRouter } from './modelAdapters';
7
7
  export { buildVoiceTraceReplay, createVoiceMemoryTraceSinkDeliveryStore, createVoiceTraceHTTPSink, createVoiceMemoryTraceEventStore, createVoiceTraceSinkDeliveryId, createVoiceTraceSinkDeliveryRecord, createVoiceTraceSinkStore, createVoiceTraceEvent, createVoiceTraceEventId, deliverVoiceTraceEventsToSinks, evaluateVoiceTrace, exportVoiceTrace, filterVoiceTraceEvents, pruneVoiceTraceEvents, redactVoiceTraceEvent, redactVoiceTraceEvents, redactVoiceTraceText, renderVoiceTraceHTML, renderVoiceTraceMarkdown, resolveVoiceTraceRedactionOptions, selectVoiceTraceEventsForPrune, summarizeVoiceTrace } from './trace';
8
8
  export { createVoiceSQLiteExternalObjectMapStore, createVoiceSQLiteIntegrationEventStore, createVoiceSQLiteReviewStore, createVoiceSQLiteRuntimeStorage, createVoiceSQLiteSessionStore, createVoiceSQLiteTaskStore, createVoiceSQLiteTraceSinkDeliveryStore, createVoiceSQLiteTraceEventStore } from './sqliteStore';
9
9
  export { createVoicePostgresExternalObjectMapStore, createVoicePostgresIntegrationEventStore, createVoicePostgresReviewStore, createVoicePostgresRuntimeStorage, createVoicePostgresSessionStore, createVoicePostgresTaskStore, createVoicePostgresTraceSinkDeliveryStore, createVoicePostgresTraceEventStore } from './postgresStore';
@@ -26,7 +26,7 @@ export { resolveTurnDetectionConfig, TURN_PROFILE_DEFAULTS } from './turnProfile
26
26
  export { createVoiceCallReviewFromLiveTelephonyReport, createVoiceCallReviewRecorder, renderVoiceCallReviewHTML, renderVoiceCallReviewMarkdown } from './testing/review';
27
27
  export type { VoiceAssistant, VoiceAssistantArtifactPlan, VoiceAssistantExperiment, VoiceAssistantExperimentOptions, VoiceAssistantGuardrailInput, VoiceAssistantGuardrails, VoiceAssistantMemoryLifecycle, VoiceAssistantMemoryLifecycleInput, VoiceAssistantOptions, VoiceAssistantOutputGuardrailInput, VoiceAssistantPreset, VoiceAssistantRunsSummary, VoiceAssistantRunSummary, VoiceAssistantVariant } from './assistant';
28
28
  export type { VoiceAssistantMemoryBinding, VoiceAssistantMemoryHandle, VoiceAssistantMemoryOptions, VoiceAssistantMemoryRecord, VoiceAssistantMemoryStore } from './assistantMemory';
29
- export type { AnthropicVoiceAssistantModelOptions, GeminiVoiceAssistantModelOptions, OpenAIVoiceAssistantModelOptions, VoiceJSONAssistantModelHandler, VoiceJSONAssistantModelOptions } from './modelAdapters';
29
+ export type { AnthropicVoiceAssistantModelOptions, GeminiVoiceAssistantModelOptions, OpenAIVoiceAssistantModelOptions, VoiceProviderRouterEvent, VoiceProviderRouterOptions, VoiceJSONAssistantModelHandler, VoiceJSONAssistantModelOptions } from './modelAdapters';
30
30
  export type { VoiceAgent, VoiceAgentMessage, VoiceAgentMessageRole, VoiceAgentModel, VoiceAgentModelInput, VoiceAgentModelOutput, VoiceAgentOptions, VoiceAgentRunResult, VoiceAgentSquadOptions, VoiceAgentTool, VoiceAgentToolCall, VoiceAgentToolResult } from './agent';
31
31
  export type { VoiceOpsRuntime, VoiceOpsRuntimeConfig, VoiceOpsRuntimeSummary, VoiceOpsRuntimeSinkWorkerConfig, VoiceOpsRuntimeTaskWorkerConfig, VoiceOpsRuntimeTickResult, VoiceOpsRuntimeWebhookWorkerConfig } from './opsRuntime';
32
32
  export type { VoiceOpsPresetName, VoiceOpsPresetOverrides, VoiceResolvedOpsPreset } from './opsPresets';
package/dist/index.js CHANGED
@@ -7183,6 +7183,8 @@ var createHTTPError = (provider, response) => new Error(`${provider} voice assis
7183
7183
  var sleep4 = (ms) => new Promise((resolve2) => {
7184
7184
  setTimeout(resolve2, ms);
7185
7185
  });
7186
+ var errorMessage = (error) => error instanceof Error ? error.message : String(error);
7187
+ var defaultIsRateLimitError = (error) => /(\b429\b|rate limit|quota|too many requests)/i.test(errorMessage(error));
7186
7188
  var normalizeRouteOutput = (output) => {
7187
7189
  const result = {};
7188
7190
  if (typeof output.assistantText === "string") {
@@ -7236,6 +7238,83 @@ var createJSONVoiceAssistantModel = (options) => ({
7236
7238
  return options.mapOutput?.(output) ?? normalizeRouteOutput(output);
7237
7239
  }
7238
7240
  });
7241
+ var createVoiceProviderRouter = (options) => {
7242
+ const providerIds = Object.keys(options.providers);
7243
+ const firstProvider = providerIds[0];
7244
+ const resolveOrder = async (input) => {
7245
+ const selectedProvider = await options.selectProvider?.(input);
7246
+ const fallbackOrder = typeof options.fallback === "function" ? await options.fallback(input) : options.fallback;
7247
+ const preferred = selectedProvider ?? fallbackOrder?.[0] ?? firstProvider;
7248
+ const seen = new Set;
7249
+ const order = [];
7250
+ for (const provider of [
7251
+ preferred,
7252
+ ...fallbackOrder ?? [],
7253
+ ...providerIds
7254
+ ]) {
7255
+ if (!provider || seen.has(provider) || !options.providers[provider]) {
7256
+ continue;
7257
+ }
7258
+ seen.add(provider);
7259
+ order.push(provider);
7260
+ }
7261
+ return {
7262
+ order,
7263
+ selectedProvider: preferred
7264
+ };
7265
+ };
7266
+ const emit = async (event, input) => {
7267
+ await options.onProviderEvent?.(event, input);
7268
+ };
7269
+ return {
7270
+ generate: async (input) => {
7271
+ const { order, selectedProvider } = await resolveOrder(input);
7272
+ if (!selectedProvider || order.length === 0) {
7273
+ throw new Error("Voice provider router has no available providers.");
7274
+ }
7275
+ let lastError;
7276
+ for (const [index, provider] of order.entries()) {
7277
+ const model = options.providers[provider];
7278
+ if (!model) {
7279
+ continue;
7280
+ }
7281
+ const startedAt = Date.now();
7282
+ try {
7283
+ const output = await model.generate(input);
7284
+ await emit({
7285
+ at: Date.now(),
7286
+ elapsedMs: Date.now() - startedAt,
7287
+ fallbackProvider: provider === selectedProvider ? undefined : provider,
7288
+ provider,
7289
+ recovered: provider !== selectedProvider,
7290
+ selectedProvider,
7291
+ status: provider === selectedProvider ? "success" : "fallback"
7292
+ }, input);
7293
+ return output;
7294
+ } catch (error) {
7295
+ lastError = error;
7296
+ const hasNextProvider = index < order.length - 1;
7297
+ const isProviderError = options.isProviderError?.(error, provider) ?? true;
7298
+ const nextProvider = hasNextProvider ? order[index + 1] : undefined;
7299
+ await emit({
7300
+ at: Date.now(),
7301
+ elapsedMs: Date.now() - startedAt,
7302
+ error: errorMessage(error),
7303
+ fallbackProvider: isProviderError ? nextProvider : undefined,
7304
+ provider,
7305
+ rateLimited: options.isRateLimitError?.(error, provider) ?? defaultIsRateLimitError(error),
7306
+ selectedProvider,
7307
+ status: "error"
7308
+ }, input);
7309
+ if (!hasNextProvider || !isProviderError) {
7310
+ throw error;
7311
+ }
7312
+ }
7313
+ }
7314
+ throw lastError ?? new Error("Voice provider router did not run a provider.");
7315
+ }
7316
+ };
7317
+ };
7239
7318
  var messageToOpenAIInput = (message) => {
7240
7319
  if (message.role === "tool") {
7241
7320
  return [
@@ -8868,10 +8947,10 @@ var createVoiceOpsTaskProcessorWorker = (options) => ({
8868
8947
  result.completed += 1;
8869
8948
  } catch (error) {
8870
8949
  await options.onError?.(error, task);
8871
- const errorMessage = error instanceof Error ? error.message : String(error);
8950
+ const errorMessage2 = error instanceof Error ? error.message : String(error);
8872
8951
  const failedTask = failVoiceOpsTask(task, {
8873
8952
  actor: task.claimedBy ?? "ops-worker",
8874
- error: errorMessage
8953
+ error: errorMessage2
8875
8954
  });
8876
8955
  if (shouldDeadLetterTask(failedTask, options.maxFailures)) {
8877
8956
  const deadLetterTask = deadLetterVoiceOpsTask(failedTask, {
@@ -10198,6 +10277,7 @@ export {
10198
10277
  createVoiceReviewSavedEvent,
10199
10278
  createVoiceRedisTaskLeaseCoordinator,
10200
10279
  createVoiceRedisIdempotencyStore,
10280
+ createVoiceProviderRouter,
10201
10281
  createVoicePostgresTraceSinkDeliveryStore,
10202
10282
  createVoicePostgresTraceEventStore,
10203
10283
  createVoicePostgresTaskStore,
@@ -34,7 +34,27 @@ export type GeminiVoiceAssistantModelOptions = {
34
34
  onUsage?: (usage: Record<string, unknown>) => Promise<void> | void;
35
35
  temperature?: number;
36
36
  };
37
+ export type VoiceProviderRouterEvent<TProvider extends string = string> = {
38
+ at: number;
39
+ elapsedMs: number;
40
+ error?: string;
41
+ fallbackProvider?: TProvider;
42
+ provider: TProvider;
43
+ rateLimited?: boolean;
44
+ recovered?: boolean;
45
+ selectedProvider: TProvider;
46
+ status: 'error' | 'fallback' | 'success';
47
+ };
48
+ export type VoiceProviderRouterOptions<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown, TProvider extends string = string> = {
49
+ fallback?: TProvider[] | ((input: VoiceAgentModelInput<TContext, TSession>) => readonly TProvider[] | Promise<readonly TProvider[]>);
50
+ isProviderError?: (error: unknown, provider: TProvider) => boolean;
51
+ isRateLimitError?: (error: unknown, provider: TProvider) => boolean;
52
+ onProviderEvent?: (event: VoiceProviderRouterEvent<TProvider>, input: VoiceAgentModelInput<TContext, TSession>) => Promise<void> | void;
53
+ providers: Partial<Record<TProvider, VoiceAgentModel<TContext, TSession, TResult>>>;
54
+ selectProvider?: (input: VoiceAgentModelInput<TContext, TSession>) => TProvider | undefined | Promise<TProvider | undefined>;
55
+ };
37
56
  export declare const createJSONVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: VoiceJSONAssistantModelOptions<TContext, TSession, TResult>) => VoiceAgentModel<TContext, TSession, TResult>;
57
+ export declare const createVoiceProviderRouter: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown, TProvider extends string = string>(options: VoiceProviderRouterOptions<TContext, TSession, TResult, TProvider>) => VoiceAgentModel<TContext, TSession, TResult>;
38
58
  export declare const createOpenAIVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: OpenAIVoiceAssistantModelOptions) => VoiceAgentModel<TContext, TSession, TResult>;
39
59
  export declare const createAnthropicVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: AnthropicVoiceAssistantModelOptions) => VoiceAgentModel<TContext, TSession, TResult>;
40
60
  export declare const createGeminiVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: GeminiVoiceAssistantModelOptions) => VoiceAgentModel<TContext, TSession, TResult>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.10",
3
+ "version": "0.0.22-beta.11",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",