@absolutejs/voice 0.0.22-beta.352 → 0.0.22-beta.354

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.
@@ -0,0 +1,19 @@
1
+ import type { VoiceRealCallProfileHistoryReport } from '../proofTrends';
2
+ export type VoiceProfileComparisonClientOptions = {
3
+ fetch?: typeof fetch;
4
+ intervalMs?: number;
5
+ };
6
+ export type VoiceProfileComparisonSnapshot = {
7
+ error: string | null;
8
+ isLoading: boolean;
9
+ report?: VoiceRealCallProfileHistoryReport;
10
+ updatedAt?: number;
11
+ };
12
+ export declare const fetchVoiceProfileComparison: (path?: string, options?: Pick<VoiceProfileComparisonClientOptions, "fetch">) => Promise<VoiceRealCallProfileHistoryReport>;
13
+ export declare const createVoiceProfileComparisonStore: (path?: string, options?: VoiceProfileComparisonClientOptions) => {
14
+ close: () => void;
15
+ getServerSnapshot: () => VoiceProfileComparisonSnapshot;
16
+ getSnapshot: () => VoiceProfileComparisonSnapshot;
17
+ refresh: () => Promise<VoiceRealCallProfileHistoryReport | undefined>;
18
+ subscribe: (listener: () => void) => () => void;
19
+ };
@@ -0,0 +1,41 @@
1
+ import { type VoiceProfileComparisonClientOptions, type VoiceProfileComparisonSnapshot } from './profileComparison';
2
+ export type VoiceProfileComparisonProfileView = {
3
+ evidence: Array<{
4
+ label: string;
5
+ value: string;
6
+ }>;
7
+ label: string;
8
+ nextMove: string;
9
+ profileId: string;
10
+ providerRoutes: string;
11
+ status: string;
12
+ };
13
+ export type VoiceProfileComparisonViewModel = {
14
+ description: string;
15
+ error: string | null;
16
+ isLoading: boolean;
17
+ label: string;
18
+ links: Array<{
19
+ href: string;
20
+ label: string;
21
+ }>;
22
+ profiles: VoiceProfileComparisonProfileView[];
23
+ status: 'empty' | 'error' | 'loading' | 'ready' | 'warning';
24
+ title: string;
25
+ };
26
+ export type VoiceProfileComparisonWidgetOptions = VoiceProfileComparisonClientOptions & {
27
+ description?: string;
28
+ links?: Array<{
29
+ href: string;
30
+ label: string;
31
+ }>;
32
+ title?: string;
33
+ };
34
+ export declare const createVoiceProfileComparisonViewModel: (snapshot: VoiceProfileComparisonSnapshot, options?: VoiceProfileComparisonWidgetOptions) => VoiceProfileComparisonViewModel;
35
+ export declare const renderVoiceProfileComparisonHTML: (snapshot: VoiceProfileComparisonSnapshot, options?: VoiceProfileComparisonWidgetOptions) => string;
36
+ export declare const getVoiceProfileComparisonCSS: () => string;
37
+ export declare const mountVoiceProfileComparison: (element: Element, path?: string, options?: VoiceProfileComparisonWidgetOptions) => {
38
+ close: () => void;
39
+ refresh: () => Promise<import("..").VoiceRealCallProfileHistoryReport | undefined>;
40
+ };
41
+ export declare const defineVoiceProfileComparisonElement: (tagName?: string) => void;
@@ -0,0 +1,19 @@
1
+ import type { VoiceProfileSwitchRecommendation } from '../profileSwitchRecommendation';
2
+ export type VoiceProfileSwitchRecommendationClientOptions = {
3
+ fetch?: typeof fetch;
4
+ intervalMs?: number;
5
+ };
6
+ export type VoiceProfileSwitchRecommendationSnapshot = {
7
+ error: string | null;
8
+ isLoading: boolean;
9
+ recommendation?: VoiceProfileSwitchRecommendation;
10
+ updatedAt?: number;
11
+ };
12
+ export declare const fetchVoiceProfileSwitchRecommendation: (path?: string, options?: Pick<VoiceProfileSwitchRecommendationClientOptions, "fetch">) => Promise<VoiceProfileSwitchRecommendation>;
13
+ export declare const createVoiceProfileSwitchRecommendationStore: (path?: string, options?: VoiceProfileSwitchRecommendationClientOptions) => {
14
+ close: () => void;
15
+ getServerSnapshot: () => VoiceProfileSwitchRecommendationSnapshot;
16
+ getSnapshot: () => VoiceProfileSwitchRecommendationSnapshot;
17
+ refresh: () => Promise<VoiceProfileSwitchRecommendation | undefined>;
18
+ subscribe: (listener: () => void) => () => void;
19
+ };
@@ -0,0 +1,12 @@
1
+ import { type VoiceProfileSwitchRecommendationClientOptions, type VoiceProfileSwitchRecommendationSnapshot } from './profileSwitchRecommendation';
2
+ export type VoiceProfileSwitchRecommendationWidgetOptions = VoiceProfileSwitchRecommendationClientOptions & {
3
+ description?: string;
4
+ title?: string;
5
+ };
6
+ export declare const renderVoiceProfileSwitchRecommendationHTML: (snapshot: VoiceProfileSwitchRecommendationSnapshot, options?: VoiceProfileSwitchRecommendationWidgetOptions) => string;
7
+ export declare const getVoiceProfileSwitchRecommendationCSS: () => string;
8
+ export declare const mountVoiceProfileSwitchRecommendation: (element: Element, path?: string, options?: VoiceProfileSwitchRecommendationWidgetOptions) => {
9
+ close: () => void;
10
+ refresh: () => Promise<import("..").VoiceProfileSwitchRecommendation | undefined>;
11
+ };
12
+ export declare const defineVoiceProfileSwitchRecommendationElement: (tagName?: string) => void;
package/dist/index.d.ts CHANGED
@@ -31,6 +31,8 @@ export { assertVoiceCompetitiveCoverage, buildVoiceCompetitiveCoverageReport, cr
31
31
  export type { VoiceCompetitiveCoverageAssertionInput, VoiceCompetitiveCoverageAssertionReport, VoiceCompetitiveCoverageIssue, VoiceCompetitiveCoverageLevel, VoiceCompetitiveCoverageReport, VoiceCompetitiveCoverageReportInput, VoiceCompetitiveCoverageRoutesOptions, VoiceCompetitiveCoverageStatus, VoiceCompetitiveCoverageSummary, VoiceCompetitiveDepthLevel, VoiceCompetitiveEvidence, VoiceCompetitiveSurface } from './competitiveCoverage';
32
32
  export type { VoicePlatformCoverageAssertionInput, VoicePlatformCoverageAssertionReport, VoicePlatformCoverageEvidence, VoicePlatformCoverageRoutesOptions, VoicePlatformCoverageStatus, VoicePlatformCoverageSummary, VoicePlatformCoverageSummaryInput, VoicePlatformCoverageSurface } from './platformCoverage';
33
33
  export { assertVoiceProofTrendEvidence, buildEmptyVoiceProofTrendReport, buildVoiceProofTrendProfileSummaries, buildVoiceProofTrendRecommendationReport, buildVoiceProofTrendReportFromRealCallProfiles, buildVoiceProofTrendReport, buildVoiceRealCallProfileDefaults, buildVoiceRealCallProfileHistoryReport, createVoiceProofTrendRecommendationRoutes, createVoiceProofTrendRoutes, createVoiceRealCallProfileHistoryRoutes, DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, evaluateVoiceProofTrendEvidence, formatVoiceProofTrendAge, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile, renderVoiceProofTrendRecommendationHTML, renderVoiceProofTrendRecommendationMarkdown, renderVoiceRealCallProfileHistoryHTML, renderVoiceRealCallProfileHistoryMarkdown, resolveVoiceRealCallProfileProviderRoute } from './proofTrends';
34
+ export { recommendVoiceProfileSwitch } from './profileSwitchRecommendation';
35
+ export type { VoiceProfileSwitchObservedSignals, VoiceProfileSwitchRecommendation, VoiceProfileSwitchRecommendationOptions } from './profileSwitchRecommendation';
34
36
  export { buildVoiceProviderDecisionTraceReport, createVoiceProviderDecisionTraceEvent, createVoiceProviderDecisionTraceRoutes, listVoiceProviderDecisionTraces, renderVoiceProviderDecisionTraceHTML, renderVoiceProviderDecisionTraceMarkdown } from './providerDecisionTraces';
35
37
  export type { VoiceProviderDecisionStatus, VoiceProviderDecisionSurfaceReport, VoiceProviderDecisionTrace, VoiceProviderDecisionTraceInput, VoiceProviderDecisionTraceIssue, VoiceProviderDecisionTraceReport, VoiceProviderDecisionTraceReportOptions, VoiceProviderDecisionTraceRoutesOptions } from './providerDecisionTraces';
36
38
  export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, VoiceProofTrendCycle, VoiceProofTrendProfileDefinition, VoiceProofTrendProfileRecommendation, VoiceProofTrendProfileSummaryOptions, VoiceProofTrendProfileSummary, VoiceProofTrendProviderRecommendation, VoiceProofTrendProviderSummary, VoiceProofTrendRecommendation, VoiceProofTrendRecommendationOptions, VoiceProofTrendRecommendationReport, VoiceProofTrendRecommendationRoutesOptions, VoiceProofTrendRecommendationStatus, VoiceProofTrendRecommendationSurface, VoiceProofTrendRealCallProfileEvidence, VoiceProofTrendRealCallProfileReportOptions, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendRuntimeChannelSummary, VoiceProofTrendStatus, VoiceProofTrendSummary, VoiceRealCallProfileDefault, VoiceRealCallProfileDefaultsOptions, VoiceRealCallProfileDefaultsReport, VoiceRealCallProfileHistoryOptions, VoiceRealCallProfileHistoryReport, VoiceRealCallProfileHistoryRoutesOptions, VoiceRealCallProfileProviderRouteOptions } from './proofTrends';
package/dist/index.js CHANGED
@@ -15694,6 +15694,72 @@ var formatVoiceProofTrendAge = (ageMs) => {
15694
15694
  const days = Math.floor(hours / 24);
15695
15695
  return `${days}d ${hours % 24}h`;
15696
15696
  };
15697
+ // src/profileSwitchRecommendation.ts
15698
+ var readDefaults = (input) => ("defaults" in input) ? input.defaults : input;
15699
+ var isNumber = (value) => typeof value === "number" && Number.isFinite(value);
15700
+ var exceeds = (observed, budget) => isNumber(observed) && isNumber(budget) && observed > budget;
15701
+ var scoreProfile = (profile, observed) => {
15702
+ const evidence = profile.evidence;
15703
+ const live = evidence.liveP95Ms ?? observed.liveP95Ms ?? 0;
15704
+ const provider = evidence.providerP95Ms ?? observed.providerP95Ms ?? 0;
15705
+ const turn = evidence.turnP95Ms ?? observed.turnP95Ms ?? 0;
15706
+ const statusPenalty = profile.status === "pass" ? 0 : profile.status === "warn" ? 1e4 : 25000;
15707
+ const noisyBonus = (observed.fallbackUsed || (observed.turnWarnings ?? 0) > 0) && /noisy|phone/i.test(`${profile.profileId} ${profile.label ?? ""}`) ? -1000 : 0;
15708
+ return live + provider + turn + statusPenalty + noisyBonus;
15709
+ };
15710
+ var recommendVoiceProfileSwitch = (options) => {
15711
+ const defaults = readDefaults(options.defaults);
15712
+ const observed = options.observed ?? {};
15713
+ const currentProfileId = observed.currentProfileId ?? options.defaultProfileId ?? defaults.profiles[0]?.profileId;
15714
+ const currentProfile = defaults.profiles.find((profile) => profile.profileId === currentProfileId);
15715
+ const candidates = defaults.profiles.filter((profile) => profile.status !== "fail");
15716
+ const recommended = candidates.slice().sort((left, right) => scoreProfile(left, observed) - scoreProfile(right, observed))[0];
15717
+ const issues = [
15718
+ ...defaults.profiles.length === 0 ? ["No measured profile defaults are available."] : [],
15719
+ ...!currentProfile && currentProfileId ? [`Current profile ${currentProfileId} is not present in measured defaults.`] : [],
15720
+ ...!recommended ? ["No non-failing measured profile can be recommended."] : []
15721
+ ];
15722
+ const currentOverBudget = currentProfile ? [
15723
+ exceeds(observed.liveP95Ms, currentProfile.latencyBudgets.maxLiveP95Ms) ? "live p95 exceeds this profile budget" : undefined,
15724
+ exceeds(observed.providerP95Ms, currentProfile.latencyBudgets.maxProviderP95Ms) ? "provider p95 exceeds this profile budget" : undefined,
15725
+ exceeds(observed.turnP95Ms, currentProfile.latencyBudgets.maxTurnP95Ms) ? "turn p95 exceeds this profile budget" : undefined
15726
+ ].filter((reason) => Boolean(reason)) : [];
15727
+ const minImprovementMs = options.minImprovementMs ?? 250;
15728
+ const currentScore = currentProfile ? scoreProfile(currentProfile, observed) : Number.POSITIVE_INFINITY;
15729
+ const recommendedScore = recommended ? scoreProfile(recommended, observed) : Number.POSITIVE_INFINITY;
15730
+ const shouldSwitch = Boolean(recommended) && recommended?.profileId !== currentProfile?.profileId && (!currentProfile || currentProfile.status !== "pass" || currentOverBudget.length > 0 || currentScore - recommendedScore >= minImprovementMs);
15731
+ const reasons = [
15732
+ ...currentOverBudget,
15733
+ ...currentProfile?.status && currentProfile.status !== "pass" ? [`current profile is ${currentProfile.status}`] : [],
15734
+ ...observed.fallbackUsed ? ["current session used provider fallback"] : [],
15735
+ ...(observed.turnWarnings ?? 0) > 0 ? [`${observed.turnWarnings} turn quality warning(s) observed`] : [],
15736
+ ...shouldSwitch && recommended ? [
15737
+ `${recommended.label ?? recommended.profileId} has the strongest measured fit for these signals`
15738
+ ] : []
15739
+ ];
15740
+ return {
15741
+ currentProfile: currentProfile ? {
15742
+ label: currentProfile.label,
15743
+ profileId: currentProfile.profileId,
15744
+ status: currentProfile.status
15745
+ } : undefined,
15746
+ generatedAt: new Date().toISOString(),
15747
+ issues,
15748
+ nextMove: issues.length > 0 ? "Collect fresh real-call profile evidence before switching automatically." : shouldSwitch && recommended ? `Switch to ${recommended.label ?? recommended.profileId} for this session profile.` : "Keep the current measured profile unless new session evidence drifts.",
15749
+ ok: issues.length === 0,
15750
+ observed,
15751
+ reasons: reasons.length > 0 ? reasons : ["current profile matches measured defaults and observed budgets"],
15752
+ recommendedProfile: recommended ? {
15753
+ evidence: recommended.evidence,
15754
+ label: recommended.label,
15755
+ latencyBudgets: recommended.latencyBudgets,
15756
+ profileId: recommended.profileId,
15757
+ providerRoutes: recommended.providerRoutes,
15758
+ status: recommended.status
15759
+ } : undefined,
15760
+ status: issues.length > 0 ? "warn" : shouldSwitch ? "switch" : "stay"
15761
+ };
15762
+ };
15697
15763
  // src/providerDecisionTraces.ts
15698
15764
  import { Elysia as Elysia23 } from "elysia";
15699
15765
 
@@ -37316,6 +37382,7 @@ export {
37316
37382
  recordVoiceAuditEvent,
37317
37383
  recommendVoiceReadinessProfile,
37318
37384
  recommendVoiceProviderStack,
37385
+ recommendVoiceProfileSwitch,
37319
37386
  readVoiceProofTrendReportFile,
37320
37387
  pruneVoiceTraceEvents,
37321
37388
  pruneVoiceIncidentBundleArtifacts,
@@ -0,0 +1,38 @@
1
+ import type { VoiceRealCallProfileDefault, VoiceRealCallProfileDefaultsReport, VoiceRealCallProfileHistoryReport } from './proofTrends';
2
+ export type VoiceProfileSwitchObservedSignals = {
3
+ currentProfileId?: string;
4
+ fallbackUsed?: boolean;
5
+ liveP95Ms?: number;
6
+ providerP95Ms?: number;
7
+ turnP95Ms?: number;
8
+ turnWarnings?: number;
9
+ };
10
+ export type VoiceProfileSwitchRecommendation = {
11
+ currentProfile?: {
12
+ label?: string;
13
+ profileId: string;
14
+ status: string;
15
+ };
16
+ generatedAt: string;
17
+ issues: string[];
18
+ nextMove: string;
19
+ ok: boolean;
20
+ observed: VoiceProfileSwitchObservedSignals;
21
+ reasons: string[];
22
+ recommendedProfile?: {
23
+ evidence: VoiceRealCallProfileDefault['evidence'];
24
+ label?: string;
25
+ latencyBudgets: VoiceRealCallProfileDefault['latencyBudgets'];
26
+ profileId: string;
27
+ providerRoutes: Record<string, string>;
28
+ status: string;
29
+ };
30
+ status: 'stay' | 'switch' | 'warn';
31
+ };
32
+ export type VoiceProfileSwitchRecommendationOptions = {
33
+ defaultProfileId?: string;
34
+ defaults: VoiceRealCallProfileDefaultsReport | VoiceRealCallProfileHistoryReport;
35
+ minImprovementMs?: number;
36
+ observed?: VoiceProfileSwitchObservedSignals;
37
+ };
38
+ export declare const recommendVoiceProfileSwitch: (options: VoiceProfileSwitchRecommendationOptions) => VoiceProfileSwitchRecommendation;
@@ -0,0 +1,6 @@
1
+ import { type VoiceProfileComparisonWidgetOptions } from '../client/profileComparisonWidget';
2
+ export type VoiceProfileComparisonProps = VoiceProfileComparisonWidgetOptions & {
3
+ className?: string;
4
+ path?: string;
5
+ };
6
+ export declare const VoiceProfileComparison: ({ className, path, ...options }: VoiceProfileComparisonProps) => import("react/jsx-runtime").JSX.Element;
@@ -3,6 +3,7 @@ export { VoiceOpsActionCenter } from './VoiceOpsActionCenter';
3
3
  export { VoiceDeliveryRuntime } from './VoiceDeliveryRuntime';
4
4
  export { VoicePlatformCoverage } from './VoicePlatformCoverage';
5
5
  export { VoiceProofTrends } from './VoiceProofTrends';
6
+ export { VoiceProfileComparison } from './VoiceProfileComparison';
6
7
  export { VoiceReadinessFailures } from './VoiceReadinessFailures';
7
8
  export { VoiceProviderSimulationControls } from './VoiceProviderSimulationControls';
8
9
  export { VoiceProviderCapabilities } from './VoiceProviderCapabilities';
@@ -16,6 +17,7 @@ export { VoiceTurnQuality } from './VoiceTurnQuality';
16
17
  export { useVoiceOpsStatus } from './useVoiceOpsStatus';
17
18
  export { useVoicePlatformCoverage } from './useVoicePlatformCoverage';
18
19
  export { useVoiceProofTrends } from './useVoiceProofTrends';
20
+ export { useVoiceProfileComparison } from './useVoiceProfileComparison';
19
21
  export { useVoiceReadinessFailures } from './useVoiceReadinessFailures';
20
22
  export { useVoiceOpsActionCenter } from './useVoiceOpsActionCenter';
21
23
  export { useVoiceLiveOps } from './useVoiceLiveOps';