@absolutejs/voice 0.0.22-beta.291 → 0.0.22-beta.293
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/README.md +102 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +489 -166
- package/dist/modelAdapters.d.ts +37 -0
- package/dist/productionReadiness.d.ts +15 -0
- package/dist/providerOrchestration.d.ts +109 -0
- package/dist/testing/index.js +87 -12
- package/dist/vue/useVoiceReadinessFailures.d.ts +20 -0
- package/package.json +1 -1
package/dist/modelAdapters.d.ts
CHANGED
|
@@ -92,6 +92,41 @@ export type VoiceProviderRouterProviderHealth<TProvider extends string = string>
|
|
|
92
92
|
status: 'healthy' | 'suppressed';
|
|
93
93
|
suppressedUntil?: number;
|
|
94
94
|
};
|
|
95
|
+
export type VoiceProviderOrchestrationSurface<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TProvider extends string = string> = {
|
|
96
|
+
allowProviders?: readonly TProvider[] | ((input: VoiceAgentModelInput<TContext, TSession>) => readonly TProvider[] | Promise<readonly TProvider[]>);
|
|
97
|
+
fallback?: readonly TProvider[] | ((input: VoiceAgentModelInput<TContext, TSession>) => readonly TProvider[] | Promise<readonly TProvider[]>);
|
|
98
|
+
fallbackMode?: VoiceProviderRouterFallbackMode;
|
|
99
|
+
maxCost?: number;
|
|
100
|
+
maxLatencyMs?: number;
|
|
101
|
+
minQuality?: number;
|
|
102
|
+
policy?: VoiceProviderRouterPolicy<TContext, TSession, TProvider>;
|
|
103
|
+
providerHealth?: boolean | VoiceProviderRouterHealthOptions;
|
|
104
|
+
providerProfiles?: Partial<Record<TProvider, VoiceProviderRouterProviderProfile>>;
|
|
105
|
+
strategy?: VoiceProviderRouterStrategy;
|
|
106
|
+
timeoutMs?: number;
|
|
107
|
+
weights?: VoiceProviderRouterPolicyWeights;
|
|
108
|
+
};
|
|
109
|
+
export type VoiceProviderOrchestrationProfile<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TProvider extends string = string, TSurface extends string = string> = {
|
|
110
|
+
defaultSurface?: TSurface;
|
|
111
|
+
id: string;
|
|
112
|
+
resolve: (surface?: TSurface) => VoiceProviderOrchestrationResolvedSurface<TContext, TSession, TProvider>;
|
|
113
|
+
surfaces: Record<TSurface, VoiceProviderOrchestrationSurface<TContext, TSession, TProvider>>;
|
|
114
|
+
};
|
|
115
|
+
export type VoiceProviderOrchestrationProfileOptions<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TProvider extends string = string, TSurface extends string = string> = {
|
|
116
|
+
defaultSurface?: TSurface;
|
|
117
|
+
id: string;
|
|
118
|
+
surfaces: Record<TSurface, VoiceProviderOrchestrationSurface<TContext, TSession, TProvider>>;
|
|
119
|
+
};
|
|
120
|
+
export type VoiceProviderOrchestrationResolvedSurface<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TProvider extends string = string> = {
|
|
121
|
+
allowProviders?: VoiceProviderOrchestrationSurface<TContext, TSession, TProvider>['allowProviders'];
|
|
122
|
+
fallback?: VoiceProviderOrchestrationSurface<TContext, TSession, TProvider>['fallback'];
|
|
123
|
+
fallbackMode?: VoiceProviderRouterFallbackMode;
|
|
124
|
+
policy?: VoiceProviderRouterPolicy<TContext, TSession, TProvider>;
|
|
125
|
+
providerHealth?: boolean | VoiceProviderRouterHealthOptions;
|
|
126
|
+
providerProfiles?: Partial<Record<TProvider, VoiceProviderRouterProviderProfile>>;
|
|
127
|
+
timeoutMs?: number;
|
|
128
|
+
};
|
|
129
|
+
export declare const createVoiceProviderOrchestrationProfile: <TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TProvider extends string = string, TSurface extends string = string>(options: VoiceProviderOrchestrationProfileOptions<TContext, TSession, TProvider, TSurface>) => VoiceProviderOrchestrationProfile<TContext, TSession, TProvider, TSurface>;
|
|
95
130
|
export type VoiceProviderRouterOptions<TContext = unknown, TSession extends VoiceSessionRecord = VoiceSessionRecord, TResult = unknown, TProvider extends string = string> = {
|
|
96
131
|
allowProviders?: readonly TProvider[] | ((input: VoiceAgentModelInput<TContext, TSession>) => readonly TProvider[] | Promise<readonly TProvider[]>);
|
|
97
132
|
fallback?: TProvider[] | ((input: VoiceAgentModelInput<TContext, TSession>) => readonly TProvider[] | Promise<readonly TProvider[]>);
|
|
@@ -100,6 +135,8 @@ export type VoiceProviderRouterOptions<TContext = unknown, TSession extends Voic
|
|
|
100
135
|
isRateLimitError?: (error: unknown, provider: TProvider) => boolean;
|
|
101
136
|
isTimeoutError?: (error: unknown, provider: TProvider) => boolean;
|
|
102
137
|
onProviderEvent?: (event: VoiceProviderRouterEvent<TProvider>, input: VoiceAgentModelInput<TContext, TSession>) => Promise<void> | void;
|
|
138
|
+
orchestrationProfile?: VoiceProviderOrchestrationProfile<TContext, TSession, TProvider>;
|
|
139
|
+
orchestrationSurface?: string;
|
|
103
140
|
policy?: VoiceProviderRouterPolicy<TContext, TSession, TProvider>;
|
|
104
141
|
providerHealth?: boolean | VoiceProviderRouterHealthOptions;
|
|
105
142
|
providerProfiles?: Partial<Record<TProvider, VoiceProviderRouterProviderProfile>>;
|
|
@@ -15,6 +15,7 @@ import type { VoiceAuditEventStore, VoiceAuditEventType, VoiceAuditOutcome } fro
|
|
|
15
15
|
import { type VoiceAuditSinkDeliveryStore } from './auditSinks';
|
|
16
16
|
import type { VoiceProviderContractMatrixReport, VoiceProviderStackCapabilityGapReport } from './providerStackRecommendations';
|
|
17
17
|
import { type VoiceProviderSloReport, type VoiceProviderSloReportOptions } from './providerSlo';
|
|
18
|
+
import type { VoiceProviderOrchestrationReport } from './providerOrchestration';
|
|
18
19
|
import type { VoiceCampaignReadinessProofReport } from './campaign';
|
|
19
20
|
import { type VoiceOpsRecoveryReport } from './opsRecovery';
|
|
20
21
|
import { type VoiceObservabilityExportDeliveryHistory, type VoiceObservabilityExportDeliveryReceiptStore, type VoiceObservabilityExportReplayReport, type VoiceObservabilityExportReplaySource, type VoiceObservabilityExportReport } from './observabilityExport';
|
|
@@ -136,6 +137,7 @@ export type VoiceProductionReadinessReport = {
|
|
|
136
137
|
phoneAgentSmoke?: string;
|
|
137
138
|
telephonyWebhookSecurity?: string;
|
|
138
139
|
providerContracts?: string;
|
|
140
|
+
providerOrchestration?: string;
|
|
139
141
|
providerRoutingContracts?: string;
|
|
140
142
|
providerSlo?: string;
|
|
141
143
|
quality?: string;
|
|
@@ -243,6 +245,15 @@ export type VoiceProductionReadinessReport = {
|
|
|
243
245
|
};
|
|
244
246
|
providerStack?: VoiceProviderStackCapabilityGapReport;
|
|
245
247
|
providerContractMatrix?: VoiceProviderContractMatrixReport;
|
|
248
|
+
providerOrchestration?: {
|
|
249
|
+
failed: number;
|
|
250
|
+
issues: number;
|
|
251
|
+
passed: number;
|
|
252
|
+
providers: number;
|
|
253
|
+
status: VoiceProductionReadinessStatus;
|
|
254
|
+
surfaces: number;
|
|
255
|
+
warned: number;
|
|
256
|
+
};
|
|
246
257
|
providerRecovery: VoiceProviderFallbackRecoverySummary;
|
|
247
258
|
phoneAgentSmokes?: {
|
|
248
259
|
failed: number;
|
|
@@ -469,6 +480,10 @@ export type VoiceProductionReadinessRoutesOptions = {
|
|
|
469
480
|
query: Record<string, unknown>;
|
|
470
481
|
request: Request;
|
|
471
482
|
}) => Promise<VoiceProviderSloReport | VoiceProviderSloReportOptions> | VoiceProviderSloReport | VoiceProviderSloReportOptions);
|
|
483
|
+
providerOrchestration?: false | VoiceProviderOrchestrationReport | ((input: {
|
|
484
|
+
query: Record<string, unknown>;
|
|
485
|
+
request: Request;
|
|
486
|
+
}) => Promise<VoiceProviderOrchestrationReport> | VoiceProviderOrchestrationReport);
|
|
472
487
|
providerStack?: false | VoiceProviderStackCapabilityGapReport | ((input: {
|
|
473
488
|
query: Record<string, unknown>;
|
|
474
489
|
request: Request;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Elysia } from 'elysia';
|
|
2
|
+
import type { VoiceProviderOrchestrationProfile, VoiceProviderRouterProviderProfile } from './modelAdapters';
|
|
3
|
+
import type { VoiceSessionRecord } from './types';
|
|
4
|
+
export type VoiceProviderOrchestrationStatus = 'fail' | 'pass' | 'warn';
|
|
5
|
+
export type VoiceProviderOrchestrationRequirement = {
|
|
6
|
+
minProviders?: number;
|
|
7
|
+
requireBudgetPolicy?: boolean;
|
|
8
|
+
requireCircuitBreaker?: boolean;
|
|
9
|
+
requireFallback?: boolean;
|
|
10
|
+
requireTimeoutBudget?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type VoiceProviderOrchestrationIssue = {
|
|
13
|
+
code: string;
|
|
14
|
+
message: string;
|
|
15
|
+
status: Exclude<VoiceProviderOrchestrationStatus, 'pass'>;
|
|
16
|
+
surface?: string;
|
|
17
|
+
};
|
|
18
|
+
export type VoiceProviderOrchestrationSurfaceReport = {
|
|
19
|
+
allowProviders: string[];
|
|
20
|
+
budgetPolicy: {
|
|
21
|
+
maxCost?: number;
|
|
22
|
+
maxLatencyMs?: number;
|
|
23
|
+
minQuality?: number;
|
|
24
|
+
};
|
|
25
|
+
circuitBreaker: boolean;
|
|
26
|
+
fallbackMode?: string;
|
|
27
|
+
fallbackProviders: string[];
|
|
28
|
+
issues: VoiceProviderOrchestrationIssue[];
|
|
29
|
+
providerProfiles: Record<string, VoiceProviderRouterProviderProfile>;
|
|
30
|
+
providers: string[];
|
|
31
|
+
status: VoiceProviderOrchestrationStatus;
|
|
32
|
+
strategy?: string;
|
|
33
|
+
surface: string;
|
|
34
|
+
timeoutBudget: boolean;
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
};
|
|
37
|
+
export type VoiceProviderOrchestrationReport = {
|
|
38
|
+
checkedAt: number;
|
|
39
|
+
issues: VoiceProviderOrchestrationIssue[];
|
|
40
|
+
profileId: string;
|
|
41
|
+
status: VoiceProviderOrchestrationStatus;
|
|
42
|
+
summary: {
|
|
43
|
+
failed: number;
|
|
44
|
+
passed: number;
|
|
45
|
+
providers: number;
|
|
46
|
+
surfaces: number;
|
|
47
|
+
warned: number;
|
|
48
|
+
};
|
|
49
|
+
surfaces: VoiceProviderOrchestrationSurfaceReport[];
|
|
50
|
+
};
|
|
51
|
+
export type VoiceProviderOrchestrationReportOptions<TProvider extends string = string, TSurface extends string = string> = {
|
|
52
|
+
defaultRequirement?: VoiceProviderOrchestrationRequirement;
|
|
53
|
+
profile: VoiceProviderOrchestrationProfile<unknown, VoiceSessionRecord, TProvider, TSurface>;
|
|
54
|
+
requirements?: Partial<Record<TSurface, VoiceProviderOrchestrationRequirement>>;
|
|
55
|
+
};
|
|
56
|
+
export type VoiceProviderOrchestrationRoutesOptions<TProvider extends string = string, TSurface extends string = string> = VoiceProviderOrchestrationReportOptions<TProvider, TSurface> & {
|
|
57
|
+
headers?: HeadersInit;
|
|
58
|
+
htmlPath?: false | string;
|
|
59
|
+
markdownPath?: false | string;
|
|
60
|
+
name?: string;
|
|
61
|
+
path?: string;
|
|
62
|
+
render?: (report: VoiceProviderOrchestrationReport) => string | Promise<string>;
|
|
63
|
+
title?: string;
|
|
64
|
+
};
|
|
65
|
+
export declare const buildVoiceProviderOrchestrationReport: <TProvider extends string = string, TSurface extends string = string>(options: VoiceProviderOrchestrationReportOptions<TProvider, TSurface>) => VoiceProviderOrchestrationReport;
|
|
66
|
+
export declare const renderVoiceProviderOrchestrationMarkdown: (report: VoiceProviderOrchestrationReport) => string;
|
|
67
|
+
export declare const renderVoiceProviderOrchestrationHTML: (report: VoiceProviderOrchestrationReport, options?: {
|
|
68
|
+
title?: string;
|
|
69
|
+
}) => string;
|
|
70
|
+
export declare const createVoiceProviderOrchestrationRoutes: <TProvider extends string = string, TSurface extends string = string>(options: VoiceProviderOrchestrationRoutesOptions<TProvider, TSurface>) => Elysia<"", {
|
|
71
|
+
decorator: {};
|
|
72
|
+
store: {};
|
|
73
|
+
derive: {};
|
|
74
|
+
resolve: {};
|
|
75
|
+
}, {
|
|
76
|
+
typebox: {};
|
|
77
|
+
error: {};
|
|
78
|
+
}, {
|
|
79
|
+
schema: {};
|
|
80
|
+
standaloneSchema: {};
|
|
81
|
+
macro: {};
|
|
82
|
+
macroFn: {};
|
|
83
|
+
parser: {};
|
|
84
|
+
response: {};
|
|
85
|
+
}, {
|
|
86
|
+
[x: string]: {
|
|
87
|
+
get: {
|
|
88
|
+
body: unknown;
|
|
89
|
+
params: {};
|
|
90
|
+
query: unknown;
|
|
91
|
+
headers: unknown;
|
|
92
|
+
response: {
|
|
93
|
+
200: VoiceProviderOrchestrationReport;
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
}, {
|
|
98
|
+
derive: {};
|
|
99
|
+
resolve: {};
|
|
100
|
+
schema: {};
|
|
101
|
+
standaloneSchema: {};
|
|
102
|
+
response: {};
|
|
103
|
+
}, {
|
|
104
|
+
derive: {};
|
|
105
|
+
resolve: {};
|
|
106
|
+
schema: {};
|
|
107
|
+
standaloneSchema: {};
|
|
108
|
+
response: {};
|
|
109
|
+
}>;
|
package/dist/testing/index.js
CHANGED
|
@@ -3791,6 +3791,7 @@ var createVoiceIOProviderFailureSimulator = (options) => {
|
|
|
3791
3791
|
};
|
|
3792
3792
|
};
|
|
3793
3793
|
// src/modelAdapters.ts
|
|
3794
|
+
var isVoiceProviderRoutingPolicyPreset = (value) => value === "balanced" || value === "cost-cap" || value === "cost-first" || value === "latency-first" || value === "quality-first";
|
|
3794
3795
|
var resolveVoiceProviderRoutingPolicyPreset = (preset, options = {}) => {
|
|
3795
3796
|
switch (preset) {
|
|
3796
3797
|
case "balanced":
|
|
@@ -3832,6 +3833,75 @@ var resolveVoiceProviderRoutingPolicyPreset = (preset, options = {}) => {
|
|
|
3832
3833
|
};
|
|
3833
3834
|
}
|
|
3834
3835
|
};
|
|
3836
|
+
var resolveVoiceProviderRoutingPolicy = (policy) => {
|
|
3837
|
+
if (!policy) {
|
|
3838
|
+
return;
|
|
3839
|
+
}
|
|
3840
|
+
if (typeof policy === "string") {
|
|
3841
|
+
return isVoiceProviderRoutingPolicyPreset(policy) ? resolveVoiceProviderRoutingPolicyPreset(policy) : {
|
|
3842
|
+
strategy: policy
|
|
3843
|
+
};
|
|
3844
|
+
}
|
|
3845
|
+
return policy;
|
|
3846
|
+
};
|
|
3847
|
+
var mergeDefinedProviderPolicyFields = (base, surface) => {
|
|
3848
|
+
const next = {
|
|
3849
|
+
...base ?? {}
|
|
3850
|
+
};
|
|
3851
|
+
if (surface.allowProviders !== undefined) {
|
|
3852
|
+
next.allowProviders = surface.allowProviders;
|
|
3853
|
+
}
|
|
3854
|
+
if (surface.fallbackMode !== undefined) {
|
|
3855
|
+
next.fallbackMode = surface.fallbackMode;
|
|
3856
|
+
}
|
|
3857
|
+
if (surface.maxCost !== undefined) {
|
|
3858
|
+
next.maxCost = surface.maxCost;
|
|
3859
|
+
}
|
|
3860
|
+
if (surface.maxLatencyMs !== undefined) {
|
|
3861
|
+
next.maxLatencyMs = surface.maxLatencyMs;
|
|
3862
|
+
}
|
|
3863
|
+
if (surface.minQuality !== undefined) {
|
|
3864
|
+
next.minQuality = surface.minQuality;
|
|
3865
|
+
}
|
|
3866
|
+
if (surface.strategy !== undefined) {
|
|
3867
|
+
next.strategy = surface.strategy;
|
|
3868
|
+
}
|
|
3869
|
+
if (surface.weights !== undefined) {
|
|
3870
|
+
next.weights = {
|
|
3871
|
+
...base?.weights ?? {},
|
|
3872
|
+
...surface.weights
|
|
3873
|
+
};
|
|
3874
|
+
}
|
|
3875
|
+
return next;
|
|
3876
|
+
};
|
|
3877
|
+
var createVoiceProviderOrchestrationProfile = (options) => {
|
|
3878
|
+
const surfaceNames = Object.keys(options.surfaces);
|
|
3879
|
+
const defaultSurface = options.defaultSurface ?? surfaceNames[0];
|
|
3880
|
+
if (!defaultSurface || !options.surfaces[defaultSurface]) {
|
|
3881
|
+
throw new Error("Voice provider orchestration profile has no surfaces.");
|
|
3882
|
+
}
|
|
3883
|
+
return {
|
|
3884
|
+
defaultSurface,
|
|
3885
|
+
id: options.id,
|
|
3886
|
+
resolve: (surface = defaultSurface) => {
|
|
3887
|
+
const config = options.surfaces[surface];
|
|
3888
|
+
if (!config) {
|
|
3889
|
+
throw new Error(`Voice provider orchestration profile ${options.id} has no surface "${surface}".`);
|
|
3890
|
+
}
|
|
3891
|
+
const policy = mergeDefinedProviderPolicyFields(resolveVoiceProviderRoutingPolicy(config.policy), config);
|
|
3892
|
+
return {
|
|
3893
|
+
allowProviders: config.allowProviders,
|
|
3894
|
+
fallback: config.fallback,
|
|
3895
|
+
fallbackMode: config.fallbackMode,
|
|
3896
|
+
policy,
|
|
3897
|
+
providerHealth: config.providerHealth,
|
|
3898
|
+
providerProfiles: config.providerProfiles,
|
|
3899
|
+
timeoutMs: config.timeoutMs
|
|
3900
|
+
};
|
|
3901
|
+
},
|
|
3902
|
+
surfaces: options.surfaces
|
|
3903
|
+
};
|
|
3904
|
+
};
|
|
3835
3905
|
var OUTPUT_SCHEMA = {
|
|
3836
3906
|
additionalProperties: false,
|
|
3837
3907
|
properties: {
|
|
@@ -3999,19 +4069,23 @@ var createJSONVoiceAssistantModel = (options) => ({
|
|
|
3999
4069
|
var createVoiceProviderRouter = (options) => {
|
|
4000
4070
|
const providerIds = Object.keys(options.providers);
|
|
4001
4071
|
const firstProvider = providerIds[0];
|
|
4002
|
-
const
|
|
4003
|
-
|
|
4004
|
-
} : options.policy;
|
|
4072
|
+
const orchestrationSurface = options.orchestrationProfile?.resolve(options.orchestrationSurface);
|
|
4073
|
+
const policy = resolveVoiceProviderRoutingPolicy(options.policy) ?? resolveVoiceProviderRoutingPolicy(orchestrationSurface?.policy);
|
|
4005
4074
|
const strategy = policy?.strategy ?? "prefer-selected";
|
|
4006
|
-
const fallbackMode = policy?.fallbackMode ?? options.fallbackMode ?? "provider-error";
|
|
4007
|
-
const
|
|
4075
|
+
const fallbackMode = policy?.fallbackMode ?? options.fallbackMode ?? orchestrationSurface?.fallbackMode ?? "provider-error";
|
|
4076
|
+
const providerProfiles = {
|
|
4077
|
+
...orchestrationSurface?.providerProfiles ?? {},
|
|
4078
|
+
...options.providerProfiles ?? {}
|
|
4079
|
+
};
|
|
4080
|
+
const providerHealthOption = options.providerHealth ?? orchestrationSurface?.providerHealth;
|
|
4081
|
+
const healthOptions = typeof providerHealthOption === "object" ? providerHealthOption : providerHealthOption ? {} : undefined;
|
|
4008
4082
|
const healthState = new Map;
|
|
4009
4083
|
const now = () => healthOptions?.now?.() ?? Date.now();
|
|
4010
4084
|
const failureThreshold = Math.max(1, healthOptions?.failureThreshold ?? 1);
|
|
4011
4085
|
const cooldownMs = Math.max(0, healthOptions?.cooldownMs ?? 30000);
|
|
4012
4086
|
const rateLimitCooldownMs = Math.max(0, healthOptions?.rateLimitCooldownMs ?? 60000);
|
|
4013
4087
|
const getProviderTimeoutMs = (provider) => {
|
|
4014
|
-
const timeoutMs =
|
|
4088
|
+
const timeoutMs = providerProfiles[provider]?.timeoutMs ?? options.timeoutMs ?? orchestrationSurface?.timeoutMs;
|
|
4015
4089
|
return typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : undefined;
|
|
4016
4090
|
};
|
|
4017
4091
|
const getHealth = (provider) => {
|
|
@@ -4077,12 +4151,12 @@ var createVoiceProviderRouter = (options) => {
|
|
|
4077
4151
|
return cloneHealth(provider);
|
|
4078
4152
|
};
|
|
4079
4153
|
const resolveAllowedProviders = async (input) => {
|
|
4080
|
-
const allowProviders = policy?.allowProviders ?? options.allowProviders;
|
|
4154
|
+
const allowProviders = policy?.allowProviders ?? options.allowProviders ?? orchestrationSurface?.allowProviders;
|
|
4081
4155
|
const allowed = typeof allowProviders === "function" ? await allowProviders(input) : allowProviders;
|
|
4082
4156
|
return new Set(allowed ?? providerIds);
|
|
4083
4157
|
};
|
|
4084
4158
|
const passesBudgetFilters = (provider) => {
|
|
4085
|
-
const profile =
|
|
4159
|
+
const profile = providerProfiles[provider];
|
|
4086
4160
|
if (typeof policy?.maxCost === "number" && typeof profile?.cost === "number" && profile.cost > policy.maxCost) {
|
|
4087
4161
|
return false;
|
|
4088
4162
|
}
|
|
@@ -4095,7 +4169,7 @@ var createVoiceProviderRouter = (options) => {
|
|
|
4095
4169
|
return true;
|
|
4096
4170
|
};
|
|
4097
4171
|
const getBalancedScore = (provider) => {
|
|
4098
|
-
const profile =
|
|
4172
|
+
const profile = providerProfiles[provider];
|
|
4099
4173
|
if (policy?.scoreProvider) {
|
|
4100
4174
|
return policy.scoreProvider(provider, profile);
|
|
4101
4175
|
}
|
|
@@ -4107,8 +4181,8 @@ var createVoiceProviderRouter = (options) => {
|
|
|
4107
4181
|
return providers;
|
|
4108
4182
|
}
|
|
4109
4183
|
return [...providers].sort((left, right) => {
|
|
4110
|
-
const leftProfile =
|
|
4111
|
-
const rightProfile =
|
|
4184
|
+
const leftProfile = providerProfiles[left];
|
|
4185
|
+
const rightProfile = providerProfiles[right];
|
|
4112
4186
|
if (strategy === "quality-first") {
|
|
4113
4187
|
return (rightProfile?.quality ?? Number.MIN_SAFE_INTEGER) - (leftProfile?.quality ?? Number.MIN_SAFE_INTEGER) || (leftProfile?.priority ?? Number.MAX_SAFE_INTEGER) - (rightProfile?.priority ?? Number.MAX_SAFE_INTEGER) || (leftProfile?.latencyMs ?? Number.MAX_SAFE_INTEGER) - (rightProfile?.latencyMs ?? Number.MAX_SAFE_INTEGER) || (leftProfile?.cost ?? Number.MAX_SAFE_INTEGER) - (rightProfile?.cost ?? Number.MAX_SAFE_INTEGER);
|
|
4114
4188
|
}
|
|
@@ -4123,7 +4197,8 @@ var createVoiceProviderRouter = (options) => {
|
|
|
4123
4197
|
const resolveOrder = async (input) => {
|
|
4124
4198
|
const selectedProvider = await options.selectProvider?.(input);
|
|
4125
4199
|
const allowedProviders = await resolveAllowedProviders(input);
|
|
4126
|
-
const
|
|
4200
|
+
const fallbackSource = options.fallback ?? orchestrationSurface?.fallback;
|
|
4201
|
+
const fallbackOrder = typeof fallbackSource === "function" ? await fallbackSource(input) : fallbackSource;
|
|
4127
4202
|
const allowedRankedProviders = sortProviders([
|
|
4128
4203
|
...fallbackOrder ?? providerIds
|
|
4129
4204
|
]).filter((provider) => allowedProviders.has(provider));
|
|
@@ -56,6 +56,7 @@ export declare const useVoiceReadinessFailures: (path?: string, options?: VoiceR
|
|
|
56
56
|
readonly phoneAgentSmoke?: string | undefined;
|
|
57
57
|
readonly telephonyWebhookSecurity?: string | undefined;
|
|
58
58
|
readonly providerContracts?: string | undefined;
|
|
59
|
+
readonly providerOrchestration?: string | undefined;
|
|
59
60
|
readonly providerRoutingContracts?: string | undefined;
|
|
60
61
|
readonly providerSlo?: string | undefined;
|
|
61
62
|
readonly quality?: string | undefined;
|
|
@@ -310,6 +311,15 @@ export declare const useVoiceReadinessFailures: (path?: string, options?: VoiceR
|
|
|
310
311
|
readonly total: number;
|
|
311
312
|
readonly warned: number;
|
|
312
313
|
} | undefined;
|
|
314
|
+
readonly providerOrchestration?: {
|
|
315
|
+
readonly failed: number;
|
|
316
|
+
readonly issues: number;
|
|
317
|
+
readonly passed: number;
|
|
318
|
+
readonly providers: number;
|
|
319
|
+
readonly status: import("..").VoiceProductionReadinessStatus;
|
|
320
|
+
readonly surfaces: number;
|
|
321
|
+
readonly warned: number;
|
|
322
|
+
} | undefined;
|
|
313
323
|
readonly providerRecovery: {
|
|
314
324
|
readonly recovered: number;
|
|
315
325
|
readonly recoveredSessions: number;
|
|
@@ -429,6 +439,7 @@ export declare const useVoiceReadinessFailures: (path?: string, options?: VoiceR
|
|
|
429
439
|
readonly phoneAgentSmoke?: string | undefined;
|
|
430
440
|
readonly telephonyWebhookSecurity?: string | undefined;
|
|
431
441
|
readonly providerContracts?: string | undefined;
|
|
442
|
+
readonly providerOrchestration?: string | undefined;
|
|
432
443
|
readonly providerRoutingContracts?: string | undefined;
|
|
433
444
|
readonly providerSlo?: string | undefined;
|
|
434
445
|
readonly quality?: string | undefined;
|
|
@@ -683,6 +694,15 @@ export declare const useVoiceReadinessFailures: (path?: string, options?: VoiceR
|
|
|
683
694
|
readonly total: number;
|
|
684
695
|
readonly warned: number;
|
|
685
696
|
} | undefined;
|
|
697
|
+
readonly providerOrchestration?: {
|
|
698
|
+
readonly failed: number;
|
|
699
|
+
readonly issues: number;
|
|
700
|
+
readonly passed: number;
|
|
701
|
+
readonly providers: number;
|
|
702
|
+
readonly status: import("..").VoiceProductionReadinessStatus;
|
|
703
|
+
readonly surfaces: number;
|
|
704
|
+
readonly warned: number;
|
|
705
|
+
} | undefined;
|
|
686
706
|
readonly providerRecovery: {
|
|
687
707
|
readonly recovered: number;
|
|
688
708
|
readonly recoveredSessions: number;
|