@absolutejs/voice 0.0.22-beta.341 → 0.0.22-beta.343

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.
@@ -3999,6 +3999,89 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
3999
3999
  };
4000
4000
  });
4001
4001
  };
4002
+ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
4003
+ const providerCap = options.maxProviderP95Ms ?? 1000;
4004
+ const liveCap = options.maxLiveP95Ms ?? 800;
4005
+ const turnCap = options.maxTurnP95Ms ?? 700;
4006
+ const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
4007
+ const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
4008
+ const runtimeJitterCap = options.maxRuntimeJitterMs ?? 30;
4009
+ const runtimeTimestampDriftCap = options.maxRuntimeTimestampDriftMs ?? 800;
4010
+ const budgets = {
4011
+ maxLiveP95Ms: liveCap,
4012
+ maxProviderP95Ms: providerCap,
4013
+ maxRuntimeFirstAudioLatencyMs: runtimeFirstAudioCap,
4014
+ maxRuntimeInterruptionP95Ms: runtimeInterruptionCap,
4015
+ maxRuntimeJitterMs: runtimeJitterCap,
4016
+ maxRuntimeTimestampDriftMs: runtimeTimestampDriftCap,
4017
+ maxTurnP95Ms: turnCap
4018
+ };
4019
+ const definitionById = new Map((options.profiles ?? DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS).map((profile) => [profile.id, profile]));
4020
+ for (const evidence of options.evidence) {
4021
+ if (!definitionById.has(evidence.profileId)) {
4022
+ definitionById.set(evidence.profileId, {
4023
+ description: evidence.profileDescription,
4024
+ id: evidence.profileId,
4025
+ label: evidence.profileLabel
4026
+ });
4027
+ }
4028
+ }
4029
+ const profiles = [];
4030
+ for (const definition of definitionById.values()) {
4031
+ const matchingEvidence = options.evidence.filter((evidence) => evidence.profileId === definition.id);
4032
+ if (matchingEvidence.length === 0) {
4033
+ continue;
4034
+ }
4035
+ const profile = {
4036
+ description: definition.description ?? matchingEvidence.find((evidence) => evidence.profileDescription)?.profileDescription,
4037
+ id: definition.id,
4038
+ label: definition.label ?? matchingEvidence.find((evidence) => evidence.profileLabel)?.profileLabel,
4039
+ maxLiveP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.liveP95Ms)),
4040
+ maxProviderP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.providerP95Ms)),
4041
+ maxTurnP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.turnP95Ms)),
4042
+ providers: aggregateProofTrendProviders(matchingEvidence.flatMap((evidence) => evidence.providers ?? [])),
4043
+ runtimeChannel: aggregateProofTrendRuntimeChannel(matchingEvidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined))
4044
+ };
4045
+ profiles.push({
4046
+ ...profile,
4047
+ status: readProofTrendProfileStatus(profile, budgets)
4048
+ });
4049
+ }
4050
+ const cycles = options.evidence.map((evidence, index) => ({
4051
+ at: evidence.generatedAt,
4052
+ cycle: index + 1,
4053
+ liveLatency: evidence.liveP95Ms === undefined ? undefined : { p95Ms: evidence.liveP95Ms, samples: 1 },
4054
+ ok: evidence.ok !== false,
4055
+ providers: evidence.providers,
4056
+ runtimeChannel: evidence.runtimeChannel,
4057
+ turnLatency: evidence.turnP95Ms === undefined ? undefined : {
4058
+ p95Ms: evidence.turnP95Ms,
4059
+ samples: 1,
4060
+ status: evidence.turnP95Ms <= turnCap ? "pass" : "fail"
4061
+ }
4062
+ }));
4063
+ const summary = {
4064
+ cycles: options.evidence.length,
4065
+ maxLiveP95Ms: maxNumber(options.evidence.map((evidence) => evidence.liveP95Ms)),
4066
+ maxProviderP95Ms: maxNumber(options.evidence.map((evidence) => evidence.providerP95Ms)),
4067
+ maxTurnP95Ms: maxNumber(options.evidence.map((evidence) => evidence.turnP95Ms)),
4068
+ profiles,
4069
+ providers: aggregateProofTrendProviders(options.evidence.flatMap((evidence) => evidence.providers ?? [])),
4070
+ runtimeChannel: aggregateProofTrendRuntimeChannel(options.evidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined))
4071
+ };
4072
+ return buildVoiceProofTrendReport({
4073
+ baseUrl: options.baseUrl,
4074
+ cycles,
4075
+ generatedAt: options.generatedAt,
4076
+ maxAgeMs: options.maxAgeMs,
4077
+ now: options.now,
4078
+ ok: options.evidence.length > 0 && options.evidence.every((evidence) => evidence.ok !== false) && profiles.every((profile) => profile.status !== "fail"),
4079
+ outputDir: options.outputDir,
4080
+ runId: options.runId,
4081
+ source: options.source,
4082
+ summary
4083
+ });
4084
+ };
4002
4085
  var normalizeProviderStatus = (status) => status === "pass" ? "pass" : status === "fail" ? "fail" : "warn";
4003
4086
  var providerSortScore = (provider) => [
4004
4087
  recommendationStatusRank[provider.status],
package/dist/index.d.ts CHANGED
@@ -28,10 +28,10 @@ export { assertVoicePlatformCoverage, buildVoicePlatformCoverageSummary, createV
28
28
  export { assertVoiceCompetitiveCoverage, buildVoiceCompetitiveCoverageReport, createVoiceCompetitiveCoverageRoutes, evaluateVoiceCompetitiveCoverage, renderVoiceCompetitiveCoverageHTML, renderVoiceCompetitiveCoverageMarkdown } from './competitiveCoverage';
29
29
  export type { VoiceCompetitiveCoverageAssertionInput, VoiceCompetitiveCoverageAssertionReport, VoiceCompetitiveCoverageIssue, VoiceCompetitiveCoverageLevel, VoiceCompetitiveCoverageReport, VoiceCompetitiveCoverageReportInput, VoiceCompetitiveCoverageRoutesOptions, VoiceCompetitiveCoverageStatus, VoiceCompetitiveCoverageSummary, VoiceCompetitiveDepthLevel, VoiceCompetitiveEvidence, VoiceCompetitiveSurface } from './competitiveCoverage';
30
30
  export type { VoicePlatformCoverageAssertionInput, VoicePlatformCoverageAssertionReport, VoicePlatformCoverageEvidence, VoicePlatformCoverageRoutesOptions, VoicePlatformCoverageStatus, VoicePlatformCoverageSummary, VoicePlatformCoverageSummaryInput, VoicePlatformCoverageSurface } from './platformCoverage';
31
- export { assertVoiceProofTrendEvidence, buildEmptyVoiceProofTrendReport, buildVoiceProofTrendProfileSummaries, buildVoiceProofTrendRecommendationReport, buildVoiceProofTrendReport, createVoiceProofTrendRecommendationRoutes, createVoiceProofTrendRoutes, DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, evaluateVoiceProofTrendEvidence, formatVoiceProofTrendAge, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile, renderVoiceProofTrendRecommendationHTML, renderVoiceProofTrendRecommendationMarkdown } from './proofTrends';
31
+ export { assertVoiceProofTrendEvidence, buildEmptyVoiceProofTrendReport, buildVoiceProofTrendProfileSummaries, buildVoiceProofTrendRecommendationReport, buildVoiceProofTrendReportFromRealCallProfiles, buildVoiceProofTrendReport, createVoiceProofTrendRecommendationRoutes, createVoiceProofTrendRoutes, DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, evaluateVoiceProofTrendEvidence, formatVoiceProofTrendAge, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile, renderVoiceProofTrendRecommendationHTML, renderVoiceProofTrendRecommendationMarkdown } from './proofTrends';
32
32
  export { buildVoiceProviderDecisionTraceReport, createVoiceProviderDecisionTraceEvent, createVoiceProviderDecisionTraceRoutes, listVoiceProviderDecisionTraces, renderVoiceProviderDecisionTraceHTML, renderVoiceProviderDecisionTraceMarkdown } from './providerDecisionTraces';
33
33
  export type { VoiceProviderDecisionStatus, VoiceProviderDecisionSurfaceReport, VoiceProviderDecisionTrace, VoiceProviderDecisionTraceInput, VoiceProviderDecisionTraceIssue, VoiceProviderDecisionTraceReport, VoiceProviderDecisionTraceReportOptions, VoiceProviderDecisionTraceRoutesOptions } from './providerDecisionTraces';
34
- export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, VoiceProofTrendCycle, VoiceProofTrendProfileDefinition, VoiceProofTrendProfileRecommendation, VoiceProofTrendProfileSummaryOptions, VoiceProofTrendProfileSummary, VoiceProofTrendProviderRecommendation, VoiceProofTrendProviderSummary, VoiceProofTrendRecommendation, VoiceProofTrendRecommendationOptions, VoiceProofTrendRecommendationReport, VoiceProofTrendRecommendationRoutesOptions, VoiceProofTrendRecommendationStatus, VoiceProofTrendRecommendationSurface, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendStatus, VoiceProofTrendSummary } from './proofTrends';
34
+ 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 } from './proofTrends';
35
35
  export { assertVoiceSloCalibration, buildVoiceSloCalibrationReport, buildVoiceSloReadinessThresholdReport, createVoiceSloReadinessThresholdOptions, createVoiceSloReadinessThresholdRoutes, createVoiceSloThresholdProfile, createVoiceSloCalibrationRoutes, renderVoiceSloCalibrationMarkdown, renderVoiceSloReadinessThresholdHTML, renderVoiceSloReadinessThresholdMarkdown } from './sloCalibration';
36
36
  export type { VoiceSloCalibrationMetricKey, VoiceSloCalibrationOptions, VoiceSloCalibrationReport, VoiceSloCalibrationRoutesOptions, VoiceSloCalibrationSample, VoiceSloCalibrationStatus, VoiceSloCalibrationThreshold, VoiceSloCalibrationThresholds, VoiceSloReadinessThresholdReport, VoiceSloReadinessThresholdReportOptions, VoiceSloReadinessThresholdOptions, VoiceSloReadinessThresholdRoutesOptions, VoiceSloThresholdProfile } from './sloCalibration';
37
37
  export { assertVoiceLiveOpsControlEvidence, assertVoiceLiveOpsEvidence, buildVoiceLiveOpsControlState, createVoiceLiveOpsController, createVoiceLiveOpsRoutes, createVoiceMemoryLiveOpsControlStore, evaluateVoiceLiveOpsControlEvidence, evaluateVoiceLiveOpsEvidence, getVoiceLiveOpsControlStatus, VOICE_LIVE_OPS_ACTIONS } from './liveOps';
package/dist/index.js CHANGED
@@ -14716,6 +14716,89 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
14716
14716
  };
14717
14717
  });
14718
14718
  };
14719
+ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
14720
+ const providerCap = options.maxProviderP95Ms ?? 1000;
14721
+ const liveCap = options.maxLiveP95Ms ?? 800;
14722
+ const turnCap = options.maxTurnP95Ms ?? 700;
14723
+ const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
14724
+ const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
14725
+ const runtimeJitterCap = options.maxRuntimeJitterMs ?? 30;
14726
+ const runtimeTimestampDriftCap = options.maxRuntimeTimestampDriftMs ?? 800;
14727
+ const budgets = {
14728
+ maxLiveP95Ms: liveCap,
14729
+ maxProviderP95Ms: providerCap,
14730
+ maxRuntimeFirstAudioLatencyMs: runtimeFirstAudioCap,
14731
+ maxRuntimeInterruptionP95Ms: runtimeInterruptionCap,
14732
+ maxRuntimeJitterMs: runtimeJitterCap,
14733
+ maxRuntimeTimestampDriftMs: runtimeTimestampDriftCap,
14734
+ maxTurnP95Ms: turnCap
14735
+ };
14736
+ const definitionById = new Map((options.profiles ?? DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS).map((profile) => [profile.id, profile]));
14737
+ for (const evidence of options.evidence) {
14738
+ if (!definitionById.has(evidence.profileId)) {
14739
+ definitionById.set(evidence.profileId, {
14740
+ description: evidence.profileDescription,
14741
+ id: evidence.profileId,
14742
+ label: evidence.profileLabel
14743
+ });
14744
+ }
14745
+ }
14746
+ const profiles = [];
14747
+ for (const definition of definitionById.values()) {
14748
+ const matchingEvidence = options.evidence.filter((evidence) => evidence.profileId === definition.id);
14749
+ if (matchingEvidence.length === 0) {
14750
+ continue;
14751
+ }
14752
+ const profile = {
14753
+ description: definition.description ?? matchingEvidence.find((evidence) => evidence.profileDescription)?.profileDescription,
14754
+ id: definition.id,
14755
+ label: definition.label ?? matchingEvidence.find((evidence) => evidence.profileLabel)?.profileLabel,
14756
+ maxLiveP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.liveP95Ms)),
14757
+ maxProviderP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.providerP95Ms)),
14758
+ maxTurnP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.turnP95Ms)),
14759
+ providers: aggregateProofTrendProviders(matchingEvidence.flatMap((evidence) => evidence.providers ?? [])),
14760
+ runtimeChannel: aggregateProofTrendRuntimeChannel(matchingEvidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined))
14761
+ };
14762
+ profiles.push({
14763
+ ...profile,
14764
+ status: readProofTrendProfileStatus(profile, budgets)
14765
+ });
14766
+ }
14767
+ const cycles = options.evidence.map((evidence, index) => ({
14768
+ at: evidence.generatedAt,
14769
+ cycle: index + 1,
14770
+ liveLatency: evidence.liveP95Ms === undefined ? undefined : { p95Ms: evidence.liveP95Ms, samples: 1 },
14771
+ ok: evidence.ok !== false,
14772
+ providers: evidence.providers,
14773
+ runtimeChannel: evidence.runtimeChannel,
14774
+ turnLatency: evidence.turnP95Ms === undefined ? undefined : {
14775
+ p95Ms: evidence.turnP95Ms,
14776
+ samples: 1,
14777
+ status: evidence.turnP95Ms <= turnCap ? "pass" : "fail"
14778
+ }
14779
+ }));
14780
+ const summary = {
14781
+ cycles: options.evidence.length,
14782
+ maxLiveP95Ms: maxNumber(options.evidence.map((evidence) => evidence.liveP95Ms)),
14783
+ maxProviderP95Ms: maxNumber(options.evidence.map((evidence) => evidence.providerP95Ms)),
14784
+ maxTurnP95Ms: maxNumber(options.evidence.map((evidence) => evidence.turnP95Ms)),
14785
+ profiles,
14786
+ providers: aggregateProofTrendProviders(options.evidence.flatMap((evidence) => evidence.providers ?? [])),
14787
+ runtimeChannel: aggregateProofTrendRuntimeChannel(options.evidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined))
14788
+ };
14789
+ return buildVoiceProofTrendReport({
14790
+ baseUrl: options.baseUrl,
14791
+ cycles,
14792
+ generatedAt: options.generatedAt,
14793
+ maxAgeMs: options.maxAgeMs,
14794
+ now: options.now,
14795
+ ok: options.evidence.length > 0 && options.evidence.every((evidence) => evidence.ok !== false) && profiles.every((profile) => profile.status !== "fail"),
14796
+ outputDir: options.outputDir,
14797
+ runId: options.runId,
14798
+ source: options.source,
14799
+ summary
14800
+ });
14801
+ };
14719
14802
  var normalizeProviderStatus = (status) => status === "pass" ? "pass" : status === "fail" ? "fail" : "warn";
14720
14803
  var providerSortScore = (provider) => [
14721
14804
  recommendationStatusRank[provider.status],
@@ -37158,6 +37241,7 @@ export {
37158
37241
  buildVoiceProviderOrchestrationReport,
37159
37242
  buildVoiceProviderDecisionTraceReport,
37160
37243
  buildVoiceProviderContractMatrix,
37244
+ buildVoiceProofTrendReportFromRealCallProfiles,
37161
37245
  buildVoiceProofTrendReport,
37162
37246
  buildVoiceProofTrendRecommendationReport,
37163
37247
  buildVoiceProofTrendProfileSummaries,
@@ -120,6 +120,30 @@ export type VoiceProofTrendProfileSummaryOptions = {
120
120
  maxTurnP95Ms?: number;
121
121
  profiles?: readonly VoiceProofTrendProfileDefinition[];
122
122
  };
123
+ export type VoiceProofTrendRealCallProfileEvidence = {
124
+ generatedAt?: string;
125
+ liveP95Ms?: number;
126
+ ok?: boolean;
127
+ operationsRecordHref?: string;
128
+ profileDescription?: string;
129
+ profileId: string;
130
+ profileLabel?: string;
131
+ providerP95Ms?: number;
132
+ providers?: VoiceProofTrendProviderSummary[];
133
+ runtimeChannel?: VoiceProofTrendRuntimeChannelSummary;
134
+ sessionId: string;
135
+ turnP95Ms?: number;
136
+ };
137
+ export type VoiceProofTrendRealCallProfileReportOptions = VoiceProofTrendProfileSummaryOptions & {
138
+ baseUrl?: string;
139
+ evidence: readonly VoiceProofTrendRealCallProfileEvidence[];
140
+ generatedAt?: string;
141
+ maxAgeMs?: number;
142
+ now?: Date | number | string;
143
+ outputDir?: string;
144
+ runId?: string;
145
+ source?: string;
146
+ };
123
147
  export type VoiceProofTrendAssertionInput = {
124
148
  maxAgeMs?: number;
125
149
  maxRuntimeBackpressureEvents?: number;
@@ -261,6 +285,7 @@ export declare const readVoiceProofTrendReportFile: (path: string, options?: {
261
285
  maxAgeMs?: number;
262
286
  }) => Promise<VoiceProofTrendReport>;
263
287
  export declare const buildVoiceProofTrendProfileSummaries: (input: VoiceProofTrendReport | readonly VoiceProofTrendReport[], options?: VoiceProofTrendProfileSummaryOptions) => VoiceProofTrendProfileSummary[];
288
+ export declare const buildVoiceProofTrendReportFromRealCallProfiles: (options: VoiceProofTrendRealCallProfileReportOptions) => VoiceProofTrendReport;
264
289
  export declare const evaluateVoiceProofTrendEvidence: (report: VoiceProofTrendReport, input?: VoiceProofTrendAssertionInput) => VoiceProofTrendAssertionReport;
265
290
  export declare const assertVoiceProofTrendEvidence: (report: VoiceProofTrendReport, input?: VoiceProofTrendAssertionInput) => VoiceProofTrendAssertionReport;
266
291
  export declare const buildVoiceProofTrendRecommendationReport: (report: VoiceProofTrendReport, options?: VoiceProofTrendRecommendationOptions) => VoiceProofTrendRecommendationReport;
@@ -1747,6 +1747,89 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
1747
1747
  };
1748
1748
  });
1749
1749
  };
1750
+ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
1751
+ const providerCap = options.maxProviderP95Ms ?? 1000;
1752
+ const liveCap = options.maxLiveP95Ms ?? 800;
1753
+ const turnCap = options.maxTurnP95Ms ?? 700;
1754
+ const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
1755
+ const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
1756
+ const runtimeJitterCap = options.maxRuntimeJitterMs ?? 30;
1757
+ const runtimeTimestampDriftCap = options.maxRuntimeTimestampDriftMs ?? 800;
1758
+ const budgets = {
1759
+ maxLiveP95Ms: liveCap,
1760
+ maxProviderP95Ms: providerCap,
1761
+ maxRuntimeFirstAudioLatencyMs: runtimeFirstAudioCap,
1762
+ maxRuntimeInterruptionP95Ms: runtimeInterruptionCap,
1763
+ maxRuntimeJitterMs: runtimeJitterCap,
1764
+ maxRuntimeTimestampDriftMs: runtimeTimestampDriftCap,
1765
+ maxTurnP95Ms: turnCap
1766
+ };
1767
+ const definitionById = new Map((options.profiles ?? DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS).map((profile) => [profile.id, profile]));
1768
+ for (const evidence of options.evidence) {
1769
+ if (!definitionById.has(evidence.profileId)) {
1770
+ definitionById.set(evidence.profileId, {
1771
+ description: evidence.profileDescription,
1772
+ id: evidence.profileId,
1773
+ label: evidence.profileLabel
1774
+ });
1775
+ }
1776
+ }
1777
+ const profiles = [];
1778
+ for (const definition of definitionById.values()) {
1779
+ const matchingEvidence = options.evidence.filter((evidence) => evidence.profileId === definition.id);
1780
+ if (matchingEvidence.length === 0) {
1781
+ continue;
1782
+ }
1783
+ const profile = {
1784
+ description: definition.description ?? matchingEvidence.find((evidence) => evidence.profileDescription)?.profileDescription,
1785
+ id: definition.id,
1786
+ label: definition.label ?? matchingEvidence.find((evidence) => evidence.profileLabel)?.profileLabel,
1787
+ maxLiveP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.liveP95Ms)),
1788
+ maxProviderP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.providerP95Ms)),
1789
+ maxTurnP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.turnP95Ms)),
1790
+ providers: aggregateProofTrendProviders(matchingEvidence.flatMap((evidence) => evidence.providers ?? [])),
1791
+ runtimeChannel: aggregateProofTrendRuntimeChannel(matchingEvidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined))
1792
+ };
1793
+ profiles.push({
1794
+ ...profile,
1795
+ status: readProofTrendProfileStatus(profile, budgets)
1796
+ });
1797
+ }
1798
+ const cycles = options.evidence.map((evidence, index) => ({
1799
+ at: evidence.generatedAt,
1800
+ cycle: index + 1,
1801
+ liveLatency: evidence.liveP95Ms === undefined ? undefined : { p95Ms: evidence.liveP95Ms, samples: 1 },
1802
+ ok: evidence.ok !== false,
1803
+ providers: evidence.providers,
1804
+ runtimeChannel: evidence.runtimeChannel,
1805
+ turnLatency: evidence.turnP95Ms === undefined ? undefined : {
1806
+ p95Ms: evidence.turnP95Ms,
1807
+ samples: 1,
1808
+ status: evidence.turnP95Ms <= turnCap ? "pass" : "fail"
1809
+ }
1810
+ }));
1811
+ const summary = {
1812
+ cycles: options.evidence.length,
1813
+ maxLiveP95Ms: maxNumber(options.evidence.map((evidence) => evidence.liveP95Ms)),
1814
+ maxProviderP95Ms: maxNumber(options.evidence.map((evidence) => evidence.providerP95Ms)),
1815
+ maxTurnP95Ms: maxNumber(options.evidence.map((evidence) => evidence.turnP95Ms)),
1816
+ profiles,
1817
+ providers: aggregateProofTrendProviders(options.evidence.flatMap((evidence) => evidence.providers ?? [])),
1818
+ runtimeChannel: aggregateProofTrendRuntimeChannel(options.evidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined))
1819
+ };
1820
+ return buildVoiceProofTrendReport({
1821
+ baseUrl: options.baseUrl,
1822
+ cycles,
1823
+ generatedAt: options.generatedAt,
1824
+ maxAgeMs: options.maxAgeMs,
1825
+ now: options.now,
1826
+ ok: options.evidence.length > 0 && options.evidence.every((evidence) => evidence.ok !== false) && profiles.every((profile) => profile.status !== "fail"),
1827
+ outputDir: options.outputDir,
1828
+ runId: options.runId,
1829
+ source: options.source,
1830
+ summary
1831
+ });
1832
+ };
1750
1833
  var normalizeProviderStatus = (status) => status === "pass" ? "pass" : status === "fail" ? "fail" : "warn";
1751
1834
  var providerSortScore = (provider) => [
1752
1835
  recommendationStatusRank[provider.status],
package/dist/vue/index.js CHANGED
@@ -1668,6 +1668,89 @@ var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
1668
1668
  };
1669
1669
  });
1670
1670
  };
1671
+ var buildVoiceProofTrendReportFromRealCallProfiles = (options) => {
1672
+ const providerCap = options.maxProviderP95Ms ?? 1000;
1673
+ const liveCap = options.maxLiveP95Ms ?? 800;
1674
+ const turnCap = options.maxTurnP95Ms ?? 700;
1675
+ const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
1676
+ const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
1677
+ const runtimeJitterCap = options.maxRuntimeJitterMs ?? 30;
1678
+ const runtimeTimestampDriftCap = options.maxRuntimeTimestampDriftMs ?? 800;
1679
+ const budgets = {
1680
+ maxLiveP95Ms: liveCap,
1681
+ maxProviderP95Ms: providerCap,
1682
+ maxRuntimeFirstAudioLatencyMs: runtimeFirstAudioCap,
1683
+ maxRuntimeInterruptionP95Ms: runtimeInterruptionCap,
1684
+ maxRuntimeJitterMs: runtimeJitterCap,
1685
+ maxRuntimeTimestampDriftMs: runtimeTimestampDriftCap,
1686
+ maxTurnP95Ms: turnCap
1687
+ };
1688
+ const definitionById = new Map((options.profiles ?? DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS).map((profile) => [profile.id, profile]));
1689
+ for (const evidence of options.evidence) {
1690
+ if (!definitionById.has(evidence.profileId)) {
1691
+ definitionById.set(evidence.profileId, {
1692
+ description: evidence.profileDescription,
1693
+ id: evidence.profileId,
1694
+ label: evidence.profileLabel
1695
+ });
1696
+ }
1697
+ }
1698
+ const profiles = [];
1699
+ for (const definition of definitionById.values()) {
1700
+ const matchingEvidence = options.evidence.filter((evidence) => evidence.profileId === definition.id);
1701
+ if (matchingEvidence.length === 0) {
1702
+ continue;
1703
+ }
1704
+ const profile = {
1705
+ description: definition.description ?? matchingEvidence.find((evidence) => evidence.profileDescription)?.profileDescription,
1706
+ id: definition.id,
1707
+ label: definition.label ?? matchingEvidence.find((evidence) => evidence.profileLabel)?.profileLabel,
1708
+ maxLiveP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.liveP95Ms)),
1709
+ maxProviderP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.providerP95Ms)),
1710
+ maxTurnP95Ms: maxNumber(matchingEvidence.map((evidence) => evidence.turnP95Ms)),
1711
+ providers: aggregateProofTrendProviders(matchingEvidence.flatMap((evidence) => evidence.providers ?? [])),
1712
+ runtimeChannel: aggregateProofTrendRuntimeChannel(matchingEvidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined))
1713
+ };
1714
+ profiles.push({
1715
+ ...profile,
1716
+ status: readProofTrendProfileStatus(profile, budgets)
1717
+ });
1718
+ }
1719
+ const cycles = options.evidence.map((evidence, index) => ({
1720
+ at: evidence.generatedAt,
1721
+ cycle: index + 1,
1722
+ liveLatency: evidence.liveP95Ms === undefined ? undefined : { p95Ms: evidence.liveP95Ms, samples: 1 },
1723
+ ok: evidence.ok !== false,
1724
+ providers: evidence.providers,
1725
+ runtimeChannel: evidence.runtimeChannel,
1726
+ turnLatency: evidence.turnP95Ms === undefined ? undefined : {
1727
+ p95Ms: evidence.turnP95Ms,
1728
+ samples: 1,
1729
+ status: evidence.turnP95Ms <= turnCap ? "pass" : "fail"
1730
+ }
1731
+ }));
1732
+ const summary = {
1733
+ cycles: options.evidence.length,
1734
+ maxLiveP95Ms: maxNumber(options.evidence.map((evidence) => evidence.liveP95Ms)),
1735
+ maxProviderP95Ms: maxNumber(options.evidence.map((evidence) => evidence.providerP95Ms)),
1736
+ maxTurnP95Ms: maxNumber(options.evidence.map((evidence) => evidence.turnP95Ms)),
1737
+ profiles,
1738
+ providers: aggregateProofTrendProviders(options.evidence.flatMap((evidence) => evidence.providers ?? [])),
1739
+ runtimeChannel: aggregateProofTrendRuntimeChannel(options.evidence.map((evidence) => evidence.runtimeChannel).filter((channel) => channel !== undefined))
1740
+ };
1741
+ return buildVoiceProofTrendReport({
1742
+ baseUrl: options.baseUrl,
1743
+ cycles,
1744
+ generatedAt: options.generatedAt,
1745
+ maxAgeMs: options.maxAgeMs,
1746
+ now: options.now,
1747
+ ok: options.evidence.length > 0 && options.evidence.every((evidence) => evidence.ok !== false) && profiles.every((profile) => profile.status !== "fail"),
1748
+ outputDir: options.outputDir,
1749
+ runId: options.runId,
1750
+ source: options.source,
1751
+ summary
1752
+ });
1753
+ };
1671
1754
  var normalizeProviderStatus = (status) => status === "pass" ? "pass" : status === "fail" ? "fail" : "warn";
1672
1755
  var providerSortScore = (provider) => [
1673
1756
  recommendationStatusRank[provider.status],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@absolutejs/voice",
3
- "version": "0.0.22-beta.341",
3
+ "version": "0.0.22-beta.343",
4
4
  "description": "Voice primitives and Elysia plugin for AbsoluteJS",
5
5
  "repository": {
6
6
  "type": "git",