@absolutejs/voice 0.0.22-beta.10 → 0.0.22-beta.12
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 -2
- package/dist/index.js +107 -2
- package/dist/modelAdapters.d.ts +35 -0
- package/package.json +1 -1
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, VoiceProviderRouterFallbackMode, VoiceProviderRouterOptions, VoiceProviderRouterPolicy, VoiceProviderRouterProviderProfile, 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,108 @@ 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 policy = typeof options.policy === "string" ? {
|
|
7245
|
+
strategy: options.policy
|
|
7246
|
+
} : options.policy;
|
|
7247
|
+
const strategy = policy?.strategy ?? "prefer-selected";
|
|
7248
|
+
const fallbackMode = policy?.fallbackMode ?? options.fallbackMode ?? "provider-error";
|
|
7249
|
+
const resolveAllowedProviders = async (input) => {
|
|
7250
|
+
const allowProviders = policy?.allowProviders ?? options.allowProviders;
|
|
7251
|
+
const allowed = typeof allowProviders === "function" ? await allowProviders(input) : allowProviders;
|
|
7252
|
+
return new Set(allowed ?? providerIds);
|
|
7253
|
+
};
|
|
7254
|
+
const sortProviders = (providers) => {
|
|
7255
|
+
if (strategy !== "prefer-cheapest" && strategy !== "prefer-fastest") {
|
|
7256
|
+
return providers;
|
|
7257
|
+
}
|
|
7258
|
+
return [...providers].sort((left, right) => {
|
|
7259
|
+
const leftProfile = options.providerProfiles?.[left];
|
|
7260
|
+
const rightProfile = options.providerProfiles?.[right];
|
|
7261
|
+
const leftValue = strategy === "prefer-cheapest" ? leftProfile?.cost ?? Number.MAX_SAFE_INTEGER : leftProfile?.latencyMs ?? Number.MAX_SAFE_INTEGER;
|
|
7262
|
+
const rightValue = strategy === "prefer-cheapest" ? rightProfile?.cost ?? Number.MAX_SAFE_INTEGER : rightProfile?.latencyMs ?? Number.MAX_SAFE_INTEGER;
|
|
7263
|
+
return leftValue - rightValue || (leftProfile?.priority ?? Number.MAX_SAFE_INTEGER) - (rightProfile?.priority ?? Number.MAX_SAFE_INTEGER);
|
|
7264
|
+
});
|
|
7265
|
+
};
|
|
7266
|
+
const resolveOrder = async (input) => {
|
|
7267
|
+
const selectedProvider = await options.selectProvider?.(input);
|
|
7268
|
+
const allowedProviders = await resolveAllowedProviders(input);
|
|
7269
|
+
const fallbackOrder = typeof options.fallback === "function" ? await options.fallback(input) : options.fallback;
|
|
7270
|
+
const rankedProviders = sortProviders([
|
|
7271
|
+
...fallbackOrder ?? providerIds
|
|
7272
|
+
]).filter((provider) => allowedProviders.has(provider));
|
|
7273
|
+
const preferred = selectedProvider && allowedProviders.has(selectedProvider) ? selectedProvider : rankedProviders[0] ?? firstProvider;
|
|
7274
|
+
const seen = new Set;
|
|
7275
|
+
const order = [];
|
|
7276
|
+
const candidates = strategy === "ordered" ? rankedProviders : [preferred, ...rankedProviders, ...providerIds];
|
|
7277
|
+
for (const provider of candidates) {
|
|
7278
|
+
if (!provider || seen.has(provider) || !allowedProviders.has(provider) || !options.providers[provider]) {
|
|
7279
|
+
continue;
|
|
7280
|
+
}
|
|
7281
|
+
seen.add(provider);
|
|
7282
|
+
order.push(provider);
|
|
7283
|
+
}
|
|
7284
|
+
return {
|
|
7285
|
+
order,
|
|
7286
|
+
selectedProvider: preferred
|
|
7287
|
+
};
|
|
7288
|
+
};
|
|
7289
|
+
const emit = async (event, input) => {
|
|
7290
|
+
await options.onProviderEvent?.(event, input);
|
|
7291
|
+
};
|
|
7292
|
+
return {
|
|
7293
|
+
generate: async (input) => {
|
|
7294
|
+
const { order, selectedProvider } = await resolveOrder(input);
|
|
7295
|
+
if (!selectedProvider || order.length === 0) {
|
|
7296
|
+
throw new Error("Voice provider router has no available providers.");
|
|
7297
|
+
}
|
|
7298
|
+
let lastError;
|
|
7299
|
+
for (const [index, provider] of order.entries()) {
|
|
7300
|
+
const model = options.providers[provider];
|
|
7301
|
+
if (!model) {
|
|
7302
|
+
continue;
|
|
7303
|
+
}
|
|
7304
|
+
const startedAt = Date.now();
|
|
7305
|
+
try {
|
|
7306
|
+
const output = await model.generate(input);
|
|
7307
|
+
await emit({
|
|
7308
|
+
at: Date.now(),
|
|
7309
|
+
elapsedMs: Date.now() - startedAt,
|
|
7310
|
+
fallbackProvider: provider === selectedProvider ? undefined : provider,
|
|
7311
|
+
provider,
|
|
7312
|
+
recovered: provider !== selectedProvider,
|
|
7313
|
+
selectedProvider,
|
|
7314
|
+
status: provider === selectedProvider ? "success" : "fallback"
|
|
7315
|
+
}, input);
|
|
7316
|
+
return output;
|
|
7317
|
+
} catch (error) {
|
|
7318
|
+
lastError = error;
|
|
7319
|
+
const hasNextProvider = index < order.length - 1;
|
|
7320
|
+
const isProviderError = options.isProviderError?.(error, provider) ?? true;
|
|
7321
|
+
const rateLimited = options.isRateLimitError?.(error, provider) ?? defaultIsRateLimitError(error);
|
|
7322
|
+
const shouldFallback = fallbackMode === "provider-error" ? isProviderError : fallbackMode === "rate-limit" ? isProviderError && rateLimited : false;
|
|
7323
|
+
const nextProvider = hasNextProvider ? order[index + 1] : undefined;
|
|
7324
|
+
await emit({
|
|
7325
|
+
at: Date.now(),
|
|
7326
|
+
elapsedMs: Date.now() - startedAt,
|
|
7327
|
+
error: errorMessage(error),
|
|
7328
|
+
fallbackProvider: shouldFallback ? nextProvider : undefined,
|
|
7329
|
+
provider,
|
|
7330
|
+
rateLimited,
|
|
7331
|
+
selectedProvider,
|
|
7332
|
+
status: "error"
|
|
7333
|
+
}, input);
|
|
7334
|
+
if (!hasNextProvider || !shouldFallback) {
|
|
7335
|
+
throw error;
|
|
7336
|
+
}
|
|
7337
|
+
}
|
|
7338
|
+
}
|
|
7339
|
+
throw lastError ?? new Error("Voice provider router did not run a provider.");
|
|
7340
|
+
}
|
|
7341
|
+
};
|
|
7342
|
+
};
|
|
7239
7343
|
var messageToOpenAIInput = (message) => {
|
|
7240
7344
|
if (message.role === "tool") {
|
|
7241
7345
|
return [
|
|
@@ -8868,10 +8972,10 @@ var createVoiceOpsTaskProcessorWorker = (options) => ({
|
|
|
8868
8972
|
result.completed += 1;
|
|
8869
8973
|
} catch (error) {
|
|
8870
8974
|
await options.onError?.(error, task);
|
|
8871
|
-
const
|
|
8975
|
+
const errorMessage2 = error instanceof Error ? error.message : String(error);
|
|
8872
8976
|
const failedTask = failVoiceOpsTask(task, {
|
|
8873
8977
|
actor: task.claimedBy ?? "ops-worker",
|
|
8874
|
-
error:
|
|
8978
|
+
error: errorMessage2
|
|
8875
8979
|
});
|
|
8876
8980
|
if (shouldDeadLetterTask(failedTask, options.maxFailures)) {
|
|
8877
8981
|
const deadLetterTask = deadLetterVoiceOpsTask(failedTask, {
|
|
@@ -10198,6 +10302,7 @@ export {
|
|
|
10198
10302
|
createVoiceReviewSavedEvent,
|
|
10199
10303
|
createVoiceRedisTaskLeaseCoordinator,
|
|
10200
10304
|
createVoiceRedisIdempotencyStore,
|
|
10305
|
+
createVoiceProviderRouter,
|
|
10201
10306
|
createVoicePostgresTraceSinkDeliveryStore,
|
|
10202
10307
|
createVoicePostgresTraceEventStore,
|
|
10203
10308
|
createVoicePostgresTaskStore,
|
package/dist/modelAdapters.d.ts
CHANGED
|
@@ -34,7 +34,42 @@ 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 VoiceProviderRouterFallbackMode = 'never' | 'provider-error' | 'rate-limit';
|
|
49
|
+
export type VoiceProviderRouterPolicy<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TProvider extends string = string> = 'ordered' | 'prefer-cheapest' | 'prefer-fastest' | 'prefer-selected' | {
|
|
50
|
+
allowProviders?: readonly TProvider[] | ((input: VoiceAgentModelInput<TContext, TSession>) => readonly TProvider[] | Promise<readonly TProvider[]>);
|
|
51
|
+
fallbackMode?: VoiceProviderRouterFallbackMode;
|
|
52
|
+
strategy?: 'ordered' | 'prefer-cheapest' | 'prefer-fastest' | 'prefer-selected';
|
|
53
|
+
};
|
|
54
|
+
export type VoiceProviderRouterProviderProfile = {
|
|
55
|
+
cost?: number;
|
|
56
|
+
latencyMs?: number;
|
|
57
|
+
priority?: number;
|
|
58
|
+
};
|
|
59
|
+
export type VoiceProviderRouterOptions<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown, TProvider extends string = string> = {
|
|
60
|
+
allowProviders?: readonly TProvider[] | ((input: VoiceAgentModelInput<TContext, TSession>) => readonly TProvider[] | Promise<readonly TProvider[]>);
|
|
61
|
+
fallback?: TProvider[] | ((input: VoiceAgentModelInput<TContext, TSession>) => readonly TProvider[] | Promise<readonly TProvider[]>);
|
|
62
|
+
fallbackMode?: VoiceProviderRouterFallbackMode;
|
|
63
|
+
isProviderError?: (error: unknown, provider: TProvider) => boolean;
|
|
64
|
+
isRateLimitError?: (error: unknown, provider: TProvider) => boolean;
|
|
65
|
+
onProviderEvent?: (event: VoiceProviderRouterEvent<TProvider>, input: VoiceAgentModelInput<TContext, TSession>) => Promise<void> | void;
|
|
66
|
+
policy?: VoiceProviderRouterPolicy<TContext, TSession, TProvider>;
|
|
67
|
+
providerProfiles?: Partial<Record<TProvider, VoiceProviderRouterProviderProfile>>;
|
|
68
|
+
providers: Partial<Record<TProvider, VoiceAgentModel<TContext, TSession, TResult>>>;
|
|
69
|
+
selectProvider?: (input: VoiceAgentModelInput<TContext, TSession>) => TProvider | undefined | Promise<TProvider | undefined>;
|
|
70
|
+
};
|
|
37
71
|
export declare const createJSONVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: VoiceJSONAssistantModelOptions<TContext, TSession, TResult>) => VoiceAgentModel<TContext, TSession, TResult>;
|
|
72
|
+
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
73
|
export declare const createOpenAIVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: OpenAIVoiceAssistantModelOptions) => VoiceAgentModel<TContext, TSession, TResult>;
|
|
39
74
|
export declare const createAnthropicVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: AnthropicVoiceAssistantModelOptions) => VoiceAgentModel<TContext, TSession, TResult>;
|
|
40
75
|
export declare const createGeminiVoiceAssistantModel: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown>(options: GeminiVoiceAssistantModelOptions) => VoiceAgentModel<TContext, TSession, TResult>;
|