@absolutejs/voice 0.0.22-beta.164 → 0.0.22-beta.165

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
@@ -46,7 +46,7 @@ export { assertVoiceProviderRoutingContract, runVoiceProviderRoutingContract } f
46
46
  export { createVoicePhoneAgentProductionSmokeHTMLHandler, createVoicePhoneAgentProductionSmokeJSONHandler, createVoicePhoneAgentProductionSmokeRoutes, renderVoicePhoneAgentProductionSmokeHTML, runVoicePhoneAgentProductionSmokeContract } from './phoneAgentProductionSmoke';
47
47
  export { buildVoiceProductionReadinessGate, buildVoiceProductionReadinessReport, createVoiceProductionReadinessRoutes, renderVoiceProductionReadinessHTML, summarizeVoiceProductionReadinessGate } from './productionReadiness';
48
48
  export { createVoiceReadinessProfile, recommendVoiceReadinessProfile } from './readinessProfiles';
49
- export { recommendVoiceProviderStack } from './providerStackRecommendations';
49
+ export { evaluateVoiceProviderStackGaps, recommendVoiceProviderStack } from './providerStackRecommendations';
50
50
  export { buildVoiceOpsConsoleReport, createVoiceOpsConsoleRoutes, renderVoiceOpsConsoleHTML } from './opsConsoleRoutes';
51
51
  export { summarizeVoiceOpsStatus } from './opsStatus';
52
52
  export { createVoiceOpsStatusRoutes, renderVoiceOpsStatusHTML } from './opsStatusRoutes';
@@ -106,7 +106,7 @@ export type { VoiceOpsConsoleLink, VoiceOpsConsoleReport, VoiceOpsConsoleRoutesO
106
106
  export type { VoiceOpsStatus, VoiceOpsStatusLink, VoiceOpsStatusOptions, VoiceOpsStatusReport, VoiceOpsStatusRoutesOptions } from './opsStatus';
107
107
  export type { VoiceProductionReadinessAction, VoiceProductionReadinessAuditOptions, VoiceProductionReadinessAuditRequirement, VoiceProductionReadinessAuditSummary, VoiceProductionReadinessCheck, VoiceProductionReadinessGateIssue, VoiceProductionReadinessGateOptions, VoiceProductionReadinessGateProfile, VoiceProductionReadinessGateProfileSurface, VoiceProductionReadinessGateReport, VoiceProductionReadinessOpsActionHistoryOptions, VoiceProductionReadinessOpsActionHistorySummary, VoiceProductionReadinessProfileExplanation, VoiceProductionReadinessProfileSurface, VoiceProductionReadinessProofSource, VoiceProductionReadinessReport, VoiceProductionReadinessRoutesOptions, VoiceProductionReadinessTraceDeliverySummary, VoiceProductionReadinessAuditDeliveryOptions, VoiceProductionReadinessAuditDeliverySummary, VoiceProductionReadinessTraceDeliveryOptions, VoiceProductionReadinessStatus } from './productionReadiness';
108
108
  export type { VoiceReadinessProfileName, VoiceReadinessProfileOptions, VoiceReadinessProfileRecommendation, VoiceReadinessProfileRecommendationScore, VoiceReadinessProfileRoutesOptions } from './readinessProfiles';
109
- export type { VoiceProviderStackChoice, VoiceProviderStackInput, VoiceProviderStackKind, VoiceProviderStackRecommendation } from './providerStackRecommendations';
109
+ export type { VoiceProviderStackChoice, VoiceProviderStackCapabilities, VoiceProviderStackCapabilityGap, VoiceProviderStackCapabilityGapInput, VoiceProviderStackCapabilityGapReport, VoiceProviderStackInput, VoiceProviderStackKind, VoiceProviderStackRecommendation } from './providerStackRecommendations';
110
110
  export type { VoiceQualityLink, VoiceQualityMetric, VoiceQualityReport, VoiceQualityRoutesOptions, VoiceQualityStatus, VoiceQualityThresholds } from './qualityRoutes';
111
111
  export type { VoiceResilienceIOSimulator, VoiceResilienceLink, VoiceResiliencePageData, VoiceResilienceRoutesOptions, VoiceResilienceSimulationProvider, VoiceRoutingKindSummary, VoiceRoutingDecisionSummary, VoiceRoutingDecisionSummaryOptions, VoiceRoutingEvent, VoiceRoutingEventKind, VoiceRoutingSessionSummary, VoiceRoutingSessionSummaryOptions } from './resilienceRoutes';
112
112
  export type { VoiceIOProviderRouterEvent, VoiceIOProviderRouterOptions, VoiceIOProviderRouterPolicy, VoiceIOProviderRouterPolicyConfig, VoiceSTTProviderRouterOptions, VoiceTTSProviderRouterOptions } from './providerAdapters';
package/dist/index.js CHANGED
@@ -20142,6 +20142,7 @@ var readinessGateCodes = {
20142
20142
  "Provider fallback recovery": "voice.readiness.provider_fallback_recovery",
20143
20143
  "Provider health": "voice.readiness.provider_health",
20144
20144
  "Provider routing contracts": "voice.readiness.provider_routing_contracts",
20145
+ "Provider stack capabilities": "voice.readiness.provider_stack_capabilities",
20145
20146
  "Quality gates": "voice.readiness.quality_gates",
20146
20147
  "Reconnect recovery contracts": "voice.readiness.reconnect_contracts",
20147
20148
  "Routing evidence": "voice.readiness.routing_evidence",
@@ -20213,6 +20214,12 @@ var resolveProviderRoutingContracts = async (options, input) => {
20213
20214
  }
20214
20215
  return typeof options.providerRoutingContracts === "function" ? await options.providerRoutingContracts(input) : options.providerRoutingContracts;
20215
20216
  };
20217
+ var resolveProviderStack = async (options, input) => {
20218
+ if (options.providerStack === false || options.providerStack === undefined) {
20219
+ return;
20220
+ }
20221
+ return typeof options.providerStack === "function" ? await options.providerStack(input) : options.providerStack;
20222
+ };
20216
20223
  var resolvePhoneAgentSmokes = async (options, input) => {
20217
20224
  if (options.phoneAgentSmokes === false || options.phoneAgentSmokes === undefined) {
20218
20225
  return;
@@ -20472,6 +20479,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
20472
20479
  carriers,
20473
20480
  agentSquadContracts,
20474
20481
  providerRoutingContracts,
20482
+ providerStack,
20475
20483
  phoneAgentSmokes,
20476
20484
  reconnectContracts,
20477
20485
  bargeInReports,
@@ -20502,6 +20510,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
20502
20510
  resolveCarriers(options, { query, request }),
20503
20511
  resolveAgentSquadContracts(options, { query, request }),
20504
20512
  resolveProviderRoutingContracts(options, { query, request }),
20513
+ resolveProviderStack(options, { query, request }),
20505
20514
  resolvePhoneAgentSmokes(options, { query, request }),
20506
20515
  resolveReconnectContracts(options, { query, request }),
20507
20516
  resolveBargeInReports(options, { query, request }),
@@ -20695,6 +20704,23 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
20695
20704
  ]
20696
20705
  });
20697
20706
  }
20707
+ if (providerStack) {
20708
+ const missingLanes = providerStack.gaps.filter((gap) => gap.status !== "pass");
20709
+ checks.push({
20710
+ detail: providerStack.status === "pass" ? `${providerStack.profile} provider stack has declared capability coverage.` : missingLanes.length > 0 ? missingLanes.map((gap) => gap.provider ? `${gap.kind.toUpperCase()} ${gap.provider} missing ${gap.missing.join(", ")}` : `${gap.kind.toUpperCase()} provider is not configured`).join("; ") + "." : "Provider stack capability coverage needs review.",
20711
+ href: options.links?.providerRoutingContracts ?? options.links?.resilience ?? "/resilience",
20712
+ label: "Provider stack capabilities",
20713
+ status: providerStack.status,
20714
+ value: providerStack.status === "pass" ? "covered" : `${providerStack.missing} missing`,
20715
+ actions: providerStack.status === "pass" ? [] : [
20716
+ {
20717
+ description: "Open provider capabilities and confirm the selected stack covers this readiness profile.",
20718
+ href: options.links?.providerRoutingContracts ?? options.links?.resilience ?? "/resilience",
20719
+ label: "Open provider capabilities"
20720
+ }
20721
+ ]
20722
+ });
20723
+ }
20698
20724
  if (phoneAgentSmokeSummary) {
20699
20725
  checks.push({
20700
20726
  detail: phoneAgentSmokeSummary.status === "pass" ? `${phoneAgentSmokeSummary.passed} phone-agent smoke contract(s) are passing.` : phoneAgentSmokeSummary.total === 0 ? "No phone-agent production smoke contracts are configured." : `${phoneAgentSmokeSummary.failed} phone-agent production smoke contract(s) failed.`,
@@ -20889,6 +20915,7 @@ var buildVoiceProductionReadinessReport = async (options, input = {}) => {
20889
20915
  degraded: degradedProviders,
20890
20916
  total: providers.length
20891
20917
  },
20918
+ providerStack,
20892
20919
  providerRecovery,
20893
20920
  phoneAgentSmokes: phoneAgentSmokeSummary,
20894
20921
  providerRoutingContracts: providerRoutingContractSummary,
@@ -21319,6 +21346,23 @@ var profileProviderReasons = {
21319
21346
  tts: "phone-agent favors low-latency spoken response"
21320
21347
  }
21321
21348
  };
21349
+ var profileRequiredCapabilities = {
21350
+ "meeting-recorder": {
21351
+ llm: ["JSON result shaping", "summarization"],
21352
+ stt: ["realtime STT", "smart formatting"],
21353
+ tts: ["spoken playback"]
21354
+ },
21355
+ "ops-heavy": {
21356
+ llm: ["tool calling", "JSON result shaping", "fallback routing"],
21357
+ stt: ["realtime STT"],
21358
+ tts: ["spoken playback"]
21359
+ },
21360
+ "phone-agent": {
21361
+ llm: ["tool calling", "JSON result shaping", "fallback routing"],
21362
+ stt: ["realtime STT", "VAD events"],
21363
+ tts: ["streaming speech", "barge-in friendly"]
21364
+ }
21365
+ };
21322
21366
  var chooseProvider = (available, priorities) => priorities.find((provider) => available.includes(provider)) ?? available[0];
21323
21367
  var recommendVoiceProviderStack = (input) => {
21324
21368
  const priorities = profileProviderPriorities[input.profile];
@@ -21350,6 +21394,38 @@ var recommendVoiceProviderStack = (input) => {
21350
21394
  stacks
21351
21395
  };
21352
21396
  };
21397
+ var normalizeCapability = (value) => value.toLowerCase().replace(/[^a-z0-9]+/g, "");
21398
+ var includesCapability = (capabilities, required) => {
21399
+ const normalizedRequired = normalizeCapability(required);
21400
+ return capabilities.some((capability) => {
21401
+ const normalizedCapability = normalizeCapability(capability);
21402
+ return normalizedCapability === normalizedRequired || normalizedCapability.includes(normalizedRequired) || normalizedRequired.includes(normalizedCapability);
21403
+ });
21404
+ };
21405
+ var evaluateVoiceProviderStackGaps = (input) => {
21406
+ const recommendation = input.recommendation ?? recommendVoiceProviderStack(input);
21407
+ const gaps = ["llm", "stt", "tts"].map((kind) => {
21408
+ const required = input.required?.[kind] ?? profileRequiredCapabilities[input.profile][kind];
21409
+ const provider = recommendation.recommended[kind];
21410
+ const present = provider ? [...input.capabilities?.[kind]?.[provider] ?? []] : [];
21411
+ const missing2 = provider ? required.filter((capability) => !includesCapability(present, capability)) : [...required];
21412
+ return {
21413
+ kind,
21414
+ missing: missing2,
21415
+ present,
21416
+ provider,
21417
+ required: [...required],
21418
+ status: !provider ? "fail" : missing2.length > 0 ? "warn" : "pass"
21419
+ };
21420
+ });
21421
+ const missing = gaps.reduce((total, gap) => total + gap.missing.length, 0);
21422
+ return {
21423
+ gaps,
21424
+ missing,
21425
+ profile: input.profile,
21426
+ status: gaps.some((gap) => gap.status === "fail") ? "fail" : gaps.some((gap) => gap.status === "warn") ? "warn" : "pass"
21427
+ };
21428
+ };
21353
21429
  // src/opsConsoleRoutes.ts
21354
21430
  import { Elysia as Elysia34 } from "elysia";
21355
21431
  var DEFAULT_LINKS = [
@@ -24185,6 +24261,7 @@ export {
24185
24261
  evaluateVoiceTrace,
24186
24262
  evaluateVoiceTelephonyContract,
24187
24263
  evaluateVoiceQuality,
24264
+ evaluateVoiceProviderStackGaps,
24188
24265
  encodeTwilioMulawBase64,
24189
24266
  deliverVoiceTraceEventsToSinks,
24190
24267
  deliverVoiceIntegrationEventToSinks,
@@ -11,6 +11,7 @@ import type { VoicePhoneAgentProductionSmokeReport } from './phoneAgentProductio
11
11
  import type { VoiceReconnectContractReport } from './reconnectContract';
12
12
  import type { VoiceAuditEventStore, VoiceAuditEventType, VoiceAuditOutcome } from './audit';
13
13
  import { type VoiceAuditSinkDeliveryStore } from './auditSinks';
14
+ import type { VoiceProviderStackCapabilityGapReport } from './providerStackRecommendations';
14
15
  export type VoiceProductionReadinessStatus = 'fail' | 'pass' | 'warn';
15
16
  export type VoiceProductionReadinessAction = {
16
17
  description?: string;
@@ -137,6 +138,7 @@ export type VoiceProductionReadinessReport = {
137
138
  degraded: number;
138
139
  total: number;
139
140
  };
141
+ providerStack?: VoiceProviderStackCapabilityGapReport;
140
142
  providerRecovery: VoiceProviderFallbackRecoverySummary;
141
143
  phoneAgentSmokes?: {
142
144
  failed: number;
@@ -297,6 +299,10 @@ export type VoiceProductionReadinessRoutesOptions = {
297
299
  query: Record<string, unknown>;
298
300
  request: Request;
299
301
  }) => Promise<readonly VoiceProviderRoutingContractReport[]> | readonly VoiceProviderRoutingContractReport[]);
302
+ providerStack?: false | VoiceProviderStackCapabilityGapReport | ((input: {
303
+ query: Record<string, unknown>;
304
+ request: Request;
305
+ }) => Promise<VoiceProviderStackCapabilityGapReport> | VoiceProviderStackCapabilityGapReport);
300
306
  reconnectContracts?: false | readonly VoiceReconnectContractReport[] | ((input: {
301
307
  query: Record<string, unknown>;
302
308
  request: Request;
@@ -15,4 +15,25 @@ export type VoiceProviderStackRecommendation<TProvider extends string = string>
15
15
  recommended: Partial<Record<VoiceProviderStackKind, TProvider>>;
16
16
  stacks: Partial<Record<VoiceProviderStackKind, VoiceProviderStackChoice<TProvider>>>;
17
17
  };
18
+ export type VoiceProviderStackCapabilities<TProvider extends string = string> = Partial<Record<VoiceProviderStackKind, Partial<Record<TProvider, readonly string[]>>>>;
19
+ export type VoiceProviderStackCapabilityGap<TProvider extends string = string> = {
20
+ kind: VoiceProviderStackKind;
21
+ missing: string[];
22
+ present: string[];
23
+ provider?: TProvider;
24
+ required: string[];
25
+ status: 'fail' | 'pass' | 'warn';
26
+ };
27
+ export type VoiceProviderStackCapabilityGapReport<TProvider extends string = string> = {
28
+ gaps: VoiceProviderStackCapabilityGap<TProvider>[];
29
+ missing: number;
30
+ profile: VoiceReadinessProfileName;
31
+ status: 'fail' | 'pass' | 'warn';
32
+ };
33
+ export type VoiceProviderStackCapabilityGapInput<TProvider extends string = string> = VoiceProviderStackInput<TProvider> & {
34
+ capabilities?: VoiceProviderStackCapabilities<TProvider>;
35
+ recommendation?: VoiceProviderStackRecommendation<TProvider>;
36
+ required?: Partial<Record<VoiceProviderStackKind, readonly string[]>>;
37
+ };
18
38
  export declare const recommendVoiceProviderStack: <TProvider extends string = string>(input: VoiceProviderStackInput<TProvider>) => VoiceProviderStackRecommendation<TProvider>;
39
+ export declare const evaluateVoiceProviderStackGaps: <TProvider extends string = string>(input: VoiceProviderStackCapabilityGapInput<TProvider>) => VoiceProviderStackCapabilityGapReport<TProvider>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.164",
3
+ "version": "0.0.22-beta.165",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",