@absolutejs/voice 0.0.22-beta.337 → 0.0.22-beta.338
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/client/index.js +48 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +48 -3
- package/dist/proofTrends.d.ts +22 -0
- package/dist/react/index.js +48 -3
- package/dist/vue/index.js +48 -3
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -3936,6 +3936,34 @@ var bestProviderByRole = (providers) => {
|
|
|
3936
3936
|
return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
|
|
3937
3937
|
};
|
|
3938
3938
|
var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role && !(provider.label ?? provider.id).toLowerCase().startsWith(provider.role.toLowerCase()) ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
|
|
3939
|
+
var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
|
|
3940
|
+
const providers = summarizeProofTrendProviders({
|
|
3941
|
+
...report,
|
|
3942
|
+
cycles: [],
|
|
3943
|
+
summary: {
|
|
3944
|
+
cycles: report.summary.cycles,
|
|
3945
|
+
maxLiveP95Ms: profile.maxLiveP95Ms,
|
|
3946
|
+
maxProviderP95Ms: profile.maxProviderP95Ms,
|
|
3947
|
+
maxTurnP95Ms: profile.maxTurnP95Ms,
|
|
3948
|
+
providers: profile.providers,
|
|
3949
|
+
runtimeChannel: profile.runtimeChannel
|
|
3950
|
+
}
|
|
3951
|
+
}, budgets.maxProviderP95Ms);
|
|
3952
|
+
const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
|
|
3953
|
+
const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
|
|
3954
|
+
const runtimePass = (profile.runtimeChannel?.status === undefined || profile.runtimeChannel.status === "pass") && (profile.runtimeChannel?.maxFirstAudioLatencyMs === undefined || profile.runtimeChannel.maxFirstAudioLatencyMs <= budgets.maxRuntimeFirstAudioLatencyMs) && (profile.runtimeChannel?.maxInterruptionP95Ms === undefined || profile.runtimeChannel.maxInterruptionP95Ms <= budgets.maxRuntimeInterruptionP95Ms) && (profile.runtimeChannel?.maxJitterMs === undefined || profile.runtimeChannel.maxJitterMs <= budgets.maxRuntimeJitterMs) && (profile.runtimeChannel?.maxTimestampDriftMs === undefined || profile.runtimeChannel.maxTimestampDriftMs <= budgets.maxRuntimeTimestampDriftMs) && (profile.runtimeChannel?.maxBackpressureEvents === undefined || profile.runtimeChannel.maxBackpressureEvents <= budgets.maxRuntimeBackpressureEvents);
|
|
3955
|
+
const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
|
|
3956
|
+
const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
|
|
3957
|
+
return {
|
|
3958
|
+
bestProviders,
|
|
3959
|
+
id: profile.id,
|
|
3960
|
+
label: profile.label,
|
|
3961
|
+
nextMove: status === "pass" ? `Use this proven provider mix for ${profile.label ?? profile.id}: ${formatProviderMix(bestProviders)}.` : providers.length === 0 ? `Collect provider-specific sustained samples for ${profile.label ?? profile.id}.` : `Tune latency/runtime budgets for ${profile.label ?? profile.id} before promoting this profile.`,
|
|
3962
|
+
providerComparisonCount: providers.length,
|
|
3963
|
+
recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
|
|
3964
|
+
status
|
|
3965
|
+
};
|
|
3966
|
+
});
|
|
3939
3967
|
var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
3940
3968
|
const issues = [];
|
|
3941
3969
|
const requiredStatus = input.requireStatus ?? "pass";
|
|
@@ -4057,6 +4085,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
4057
4085
|
const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
|
|
4058
4086
|
const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
|
|
4059
4087
|
const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
|
|
4088
|
+
const profileRecommendations = buildProfileRecommendations(report, budgets);
|
|
4060
4089
|
const recommendations = [];
|
|
4061
4090
|
const issues = [];
|
|
4062
4091
|
if (report.ok !== true) {
|
|
@@ -4119,16 +4148,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
4119
4148
|
surface: "turn-latency"
|
|
4120
4149
|
});
|
|
4121
4150
|
const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
|
|
4151
|
+
const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
|
|
4152
|
+
evidence: {},
|
|
4153
|
+
nextMove: profile.nextMove,
|
|
4154
|
+
recommendation: profile.recommendation,
|
|
4155
|
+
status: profile.status,
|
|
4156
|
+
surface: "provider-path"
|
|
4157
|
+
})));
|
|
4158
|
+
const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
|
|
4122
4159
|
return {
|
|
4123
4160
|
bestProvider,
|
|
4124
4161
|
bestProviders,
|
|
4125
4162
|
generatedAt: new Date().toISOString(),
|
|
4126
4163
|
issues,
|
|
4127
|
-
ok:
|
|
4164
|
+
ok: combinedStatus !== "fail",
|
|
4165
|
+
profiles: profileRecommendations,
|
|
4128
4166
|
providers,
|
|
4129
4167
|
recommendations,
|
|
4130
4168
|
source: report.source || report.outputDir || report.runId || "proof-trends",
|
|
4131
|
-
status,
|
|
4169
|
+
status: combinedStatus,
|
|
4132
4170
|
summary: {
|
|
4133
4171
|
keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
|
|
4134
4172
|
keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
|
|
@@ -4159,6 +4197,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
4159
4197
|
"| ---: | --- | --- | --- | ---: | ---: | --- |",
|
|
4160
4198
|
...report.providers.length ? report.providers.map((provider) => `| ${String(provider.rank)} | ${escapeMarkdown(provider.label ?? provider.id)} | ${escapeMarkdown(provider.role ?? "n/a")} | ${provider.status} | ${provider.p95Ms === undefined ? "n/a" : String(provider.p95Ms)} | ${provider.samples === undefined ? "n/a" : String(provider.samples)} | ${escapeMarkdown(provider.nextMove)} |`) : ["| n/a | n/a | n/a | n/a | n/a | n/a | No provider-specific samples were present. |"],
|
|
4161
4199
|
"",
|
|
4200
|
+
"## Benchmark Profiles",
|
|
4201
|
+
"",
|
|
4202
|
+
"| Profile | Status | Provider mix | Next move |",
|
|
4203
|
+
"| --- | --- | --- | --- |",
|
|
4204
|
+
...report.profiles.length ? report.profiles.map((profile) => `| ${escapeMarkdown(profile.label ?? profile.id)} | ${profile.status} | ${escapeMarkdown(formatProviderMix(profile.bestProviders))} | ${escapeMarkdown(profile.nextMove)} |`) : ["| n/a | n/a | n/a | No benchmark profiles were present. |"],
|
|
4205
|
+
"",
|
|
4162
4206
|
"## Issues",
|
|
4163
4207
|
"",
|
|
4164
4208
|
...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
|
|
@@ -4168,7 +4212,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
|
|
|
4168
4212
|
const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml3(recommendation.status)}"><p class="eyebrow">${escapeHtml3(recommendation.surface)} \xB7 ${escapeHtml3(recommendation.status)}</p><h2>${escapeHtml3(recommendation.recommendation)}</h2><p>${escapeHtml3(recommendation.nextMove)}</p><pre>${escapeHtml3(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
|
|
4169
4213
|
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml3(issue)}</li>`).join("");
|
|
4170
4214
|
const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml3(provider.label ?? provider.id)}</strong><span>${escapeHtml3(provider.role ?? "provider")} \xB7 ${escapeHtml3(provider.status)} \xB7 p95 ${escapeHtml3(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml3(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml3(provider.nextMove)}</small></li>`).join("");
|
|
4171
|
-
|
|
4215
|
+
const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml3(profile.label ?? profile.id)}</strong><span>${escapeHtml3(profile.status)} \xB7 ${escapeHtml3(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml3(profile.nextMove)}</small></li>`).join("");
|
|
4216
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml3(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml3(title)}</h1><p>Generated ${escapeHtml3(report.generatedAt)} from ${escapeHtml3(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml3(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml3(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
|
|
4172
4217
|
};
|
|
4173
4218
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
4174
4219
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
package/dist/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export type { VoicePlatformCoverageAssertionInput, VoicePlatformCoverageAssertio
|
|
|
31
31
|
export { assertVoiceProofTrendEvidence, buildEmptyVoiceProofTrendReport, buildVoiceProofTrendRecommendationReport, buildVoiceProofTrendReport, createVoiceProofTrendRecommendationRoutes, createVoiceProofTrendRoutes, 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, VoiceProofTrendProviderRecommendation, VoiceProofTrendProviderSummary, VoiceProofTrendRecommendation, VoiceProofTrendRecommendationOptions, VoiceProofTrendRecommendationReport, VoiceProofTrendRecommendationRoutesOptions, VoiceProofTrendRecommendationStatus, VoiceProofTrendRecommendationSurface, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, VoiceProofTrendStatus, VoiceProofTrendSummary } from './proofTrends';
|
|
34
|
+
export type { VoiceProofTrendAssertionInput, VoiceProofTrendAssertionReport, VoiceProofTrendCycle, VoiceProofTrendProfileRecommendation, VoiceProofTrendProfileSummary, VoiceProofTrendProviderRecommendation, VoiceProofTrendProviderSummary, VoiceProofTrendRecommendation, VoiceProofTrendRecommendationOptions, VoiceProofTrendRecommendationReport, VoiceProofTrendRecommendationRoutesOptions, VoiceProofTrendRecommendationStatus, VoiceProofTrendRecommendationSurface, VoiceProofTrendReport, VoiceProofTrendReportInput, VoiceProofTrendRoutesOptions, 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
|
@@ -14653,6 +14653,34 @@ var bestProviderByRole = (providers) => {
|
|
|
14653
14653
|
return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
|
|
14654
14654
|
};
|
|
14655
14655
|
var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role && !(provider.label ?? provider.id).toLowerCase().startsWith(provider.role.toLowerCase()) ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
|
|
14656
|
+
var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
|
|
14657
|
+
const providers = summarizeProofTrendProviders({
|
|
14658
|
+
...report,
|
|
14659
|
+
cycles: [],
|
|
14660
|
+
summary: {
|
|
14661
|
+
cycles: report.summary.cycles,
|
|
14662
|
+
maxLiveP95Ms: profile.maxLiveP95Ms,
|
|
14663
|
+
maxProviderP95Ms: profile.maxProviderP95Ms,
|
|
14664
|
+
maxTurnP95Ms: profile.maxTurnP95Ms,
|
|
14665
|
+
providers: profile.providers,
|
|
14666
|
+
runtimeChannel: profile.runtimeChannel
|
|
14667
|
+
}
|
|
14668
|
+
}, budgets.maxProviderP95Ms);
|
|
14669
|
+
const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
|
|
14670
|
+
const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
|
|
14671
|
+
const runtimePass = (profile.runtimeChannel?.status === undefined || profile.runtimeChannel.status === "pass") && (profile.runtimeChannel?.maxFirstAudioLatencyMs === undefined || profile.runtimeChannel.maxFirstAudioLatencyMs <= budgets.maxRuntimeFirstAudioLatencyMs) && (profile.runtimeChannel?.maxInterruptionP95Ms === undefined || profile.runtimeChannel.maxInterruptionP95Ms <= budgets.maxRuntimeInterruptionP95Ms) && (profile.runtimeChannel?.maxJitterMs === undefined || profile.runtimeChannel.maxJitterMs <= budgets.maxRuntimeJitterMs) && (profile.runtimeChannel?.maxTimestampDriftMs === undefined || profile.runtimeChannel.maxTimestampDriftMs <= budgets.maxRuntimeTimestampDriftMs) && (profile.runtimeChannel?.maxBackpressureEvents === undefined || profile.runtimeChannel.maxBackpressureEvents <= budgets.maxRuntimeBackpressureEvents);
|
|
14672
|
+
const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
|
|
14673
|
+
const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
|
|
14674
|
+
return {
|
|
14675
|
+
bestProviders,
|
|
14676
|
+
id: profile.id,
|
|
14677
|
+
label: profile.label,
|
|
14678
|
+
nextMove: status === "pass" ? `Use this proven provider mix for ${profile.label ?? profile.id}: ${formatProviderMix(bestProviders)}.` : providers.length === 0 ? `Collect provider-specific sustained samples for ${profile.label ?? profile.id}.` : `Tune latency/runtime budgets for ${profile.label ?? profile.id} before promoting this profile.`,
|
|
14679
|
+
providerComparisonCount: providers.length,
|
|
14680
|
+
recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
|
|
14681
|
+
status
|
|
14682
|
+
};
|
|
14683
|
+
});
|
|
14656
14684
|
var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
14657
14685
|
const issues = [];
|
|
14658
14686
|
const requiredStatus = input.requireStatus ?? "pass";
|
|
@@ -14774,6 +14802,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
14774
14802
|
const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
|
|
14775
14803
|
const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
|
|
14776
14804
|
const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
|
|
14805
|
+
const profileRecommendations = buildProfileRecommendations(report, budgets);
|
|
14777
14806
|
const recommendations = [];
|
|
14778
14807
|
const issues = [];
|
|
14779
14808
|
if (report.ok !== true) {
|
|
@@ -14836,16 +14865,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
14836
14865
|
surface: "turn-latency"
|
|
14837
14866
|
});
|
|
14838
14867
|
const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
|
|
14868
|
+
const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
|
|
14869
|
+
evidence: {},
|
|
14870
|
+
nextMove: profile.nextMove,
|
|
14871
|
+
recommendation: profile.recommendation,
|
|
14872
|
+
status: profile.status,
|
|
14873
|
+
surface: "provider-path"
|
|
14874
|
+
})));
|
|
14875
|
+
const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
|
|
14839
14876
|
return {
|
|
14840
14877
|
bestProvider,
|
|
14841
14878
|
bestProviders,
|
|
14842
14879
|
generatedAt: new Date().toISOString(),
|
|
14843
14880
|
issues,
|
|
14844
|
-
ok:
|
|
14881
|
+
ok: combinedStatus !== "fail",
|
|
14882
|
+
profiles: profileRecommendations,
|
|
14845
14883
|
providers,
|
|
14846
14884
|
recommendations,
|
|
14847
14885
|
source: report.source || report.outputDir || report.runId || "proof-trends",
|
|
14848
|
-
status,
|
|
14886
|
+
status: combinedStatus,
|
|
14849
14887
|
summary: {
|
|
14850
14888
|
keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
|
|
14851
14889
|
keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
|
|
@@ -14876,6 +14914,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
14876
14914
|
"| ---: | --- | --- | --- | ---: | ---: | --- |",
|
|
14877
14915
|
...report.providers.length ? report.providers.map((provider) => `| ${String(provider.rank)} | ${escapeMarkdown2(provider.label ?? provider.id)} | ${escapeMarkdown2(provider.role ?? "n/a")} | ${provider.status} | ${provider.p95Ms === undefined ? "n/a" : String(provider.p95Ms)} | ${provider.samples === undefined ? "n/a" : String(provider.samples)} | ${escapeMarkdown2(provider.nextMove)} |`) : ["| n/a | n/a | n/a | n/a | n/a | n/a | No provider-specific samples were present. |"],
|
|
14878
14916
|
"",
|
|
14917
|
+
"## Benchmark Profiles",
|
|
14918
|
+
"",
|
|
14919
|
+
"| Profile | Status | Provider mix | Next move |",
|
|
14920
|
+
"| --- | --- | --- | --- |",
|
|
14921
|
+
...report.profiles.length ? report.profiles.map((profile) => `| ${escapeMarkdown2(profile.label ?? profile.id)} | ${profile.status} | ${escapeMarkdown2(formatProviderMix(profile.bestProviders))} | ${escapeMarkdown2(profile.nextMove)} |`) : ["| n/a | n/a | n/a | No benchmark profiles were present. |"],
|
|
14922
|
+
"",
|
|
14879
14923
|
"## Issues",
|
|
14880
14924
|
"",
|
|
14881
14925
|
...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
|
|
@@ -14885,7 +14929,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
|
|
|
14885
14929
|
const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml22(recommendation.status)}"><p class="eyebrow">${escapeHtml22(recommendation.surface)} \xB7 ${escapeHtml22(recommendation.status)}</p><h2>${escapeHtml22(recommendation.recommendation)}</h2><p>${escapeHtml22(recommendation.nextMove)}</p><pre>${escapeHtml22(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
|
|
14886
14930
|
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml22(issue)}</li>`).join("");
|
|
14887
14931
|
const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml22(provider.label ?? provider.id)}</strong><span>${escapeHtml22(provider.role ?? "provider")} \xB7 ${escapeHtml22(provider.status)} \xB7 p95 ${escapeHtml22(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml22(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml22(provider.nextMove)}</small></li>`).join("");
|
|
14888
|
-
|
|
14932
|
+
const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml22(profile.label ?? profile.id)}</strong><span>${escapeHtml22(profile.status)} \xB7 ${escapeHtml22(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml22(profile.nextMove)}</small></li>`).join("");
|
|
14933
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml22(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml22(title)}</h1><p>Generated ${escapeHtml22(report.generatedAt)} from ${escapeHtml22(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml22(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml22(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
|
|
14889
14934
|
};
|
|
14890
14935
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
14891
14936
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
package/dist/proofTrends.d.ts
CHANGED
|
@@ -4,10 +4,22 @@ export type VoiceProofTrendSummary = {
|
|
|
4
4
|
cycles?: number;
|
|
5
5
|
maxLiveP95Ms?: number;
|
|
6
6
|
maxProviderP95Ms?: number;
|
|
7
|
+
profiles?: VoiceProofTrendProfileSummary[];
|
|
7
8
|
providers?: VoiceProofTrendProviderSummary[];
|
|
8
9
|
runtimeChannel?: VoiceProofTrendRuntimeChannelSummary;
|
|
9
10
|
maxTurnP95Ms?: number;
|
|
10
11
|
};
|
|
12
|
+
export type VoiceProofTrendProfileSummary = {
|
|
13
|
+
description?: string;
|
|
14
|
+
id: string;
|
|
15
|
+
label?: string;
|
|
16
|
+
maxLiveP95Ms?: number;
|
|
17
|
+
maxProviderP95Ms?: number;
|
|
18
|
+
maxTurnP95Ms?: number;
|
|
19
|
+
providers?: VoiceProofTrendProviderSummary[];
|
|
20
|
+
runtimeChannel?: VoiceProofTrendRuntimeChannelSummary;
|
|
21
|
+
status?: string;
|
|
22
|
+
};
|
|
11
23
|
export type VoiceProofTrendProviderSummary = {
|
|
12
24
|
averageMs?: number;
|
|
13
25
|
id: string;
|
|
@@ -149,6 +161,7 @@ export type VoiceProofTrendRecommendationReport = {
|
|
|
149
161
|
generatedAt: string;
|
|
150
162
|
issues: string[];
|
|
151
163
|
ok: boolean;
|
|
164
|
+
profiles: VoiceProofTrendProfileRecommendation[];
|
|
152
165
|
providers: VoiceProofTrendProviderRecommendation[];
|
|
153
166
|
recommendations: VoiceProofTrendRecommendation[];
|
|
154
167
|
source: string;
|
|
@@ -161,6 +174,15 @@ export type VoiceProofTrendRecommendationReport = {
|
|
|
161
174
|
switchRecommended: boolean;
|
|
162
175
|
};
|
|
163
176
|
};
|
|
177
|
+
export type VoiceProofTrendProfileRecommendation = {
|
|
178
|
+
bestProviders: VoiceProofTrendProviderRecommendation[];
|
|
179
|
+
id: string;
|
|
180
|
+
label?: string;
|
|
181
|
+
nextMove: string;
|
|
182
|
+
providerComparisonCount: number;
|
|
183
|
+
recommendation: string;
|
|
184
|
+
status: VoiceProofTrendRecommendationStatus;
|
|
185
|
+
};
|
|
164
186
|
export type VoiceProofTrendRecommendationOptions = {
|
|
165
187
|
currentProviderId?: string;
|
|
166
188
|
maxLiveP95Ms?: number;
|
package/dist/react/index.js
CHANGED
|
@@ -1684,6 +1684,34 @@ var bestProviderByRole = (providers) => {
|
|
|
1684
1684
|
return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
|
|
1685
1685
|
};
|
|
1686
1686
|
var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role && !(provider.label ?? provider.id).toLowerCase().startsWith(provider.role.toLowerCase()) ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
|
|
1687
|
+
var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
|
|
1688
|
+
const providers = summarizeProofTrendProviders({
|
|
1689
|
+
...report,
|
|
1690
|
+
cycles: [],
|
|
1691
|
+
summary: {
|
|
1692
|
+
cycles: report.summary.cycles,
|
|
1693
|
+
maxLiveP95Ms: profile.maxLiveP95Ms,
|
|
1694
|
+
maxProviderP95Ms: profile.maxProviderP95Ms,
|
|
1695
|
+
maxTurnP95Ms: profile.maxTurnP95Ms,
|
|
1696
|
+
providers: profile.providers,
|
|
1697
|
+
runtimeChannel: profile.runtimeChannel
|
|
1698
|
+
}
|
|
1699
|
+
}, budgets.maxProviderP95Ms);
|
|
1700
|
+
const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
|
|
1701
|
+
const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
|
|
1702
|
+
const runtimePass = (profile.runtimeChannel?.status === undefined || profile.runtimeChannel.status === "pass") && (profile.runtimeChannel?.maxFirstAudioLatencyMs === undefined || profile.runtimeChannel.maxFirstAudioLatencyMs <= budgets.maxRuntimeFirstAudioLatencyMs) && (profile.runtimeChannel?.maxInterruptionP95Ms === undefined || profile.runtimeChannel.maxInterruptionP95Ms <= budgets.maxRuntimeInterruptionP95Ms) && (profile.runtimeChannel?.maxJitterMs === undefined || profile.runtimeChannel.maxJitterMs <= budgets.maxRuntimeJitterMs) && (profile.runtimeChannel?.maxTimestampDriftMs === undefined || profile.runtimeChannel.maxTimestampDriftMs <= budgets.maxRuntimeTimestampDriftMs) && (profile.runtimeChannel?.maxBackpressureEvents === undefined || profile.runtimeChannel.maxBackpressureEvents <= budgets.maxRuntimeBackpressureEvents);
|
|
1703
|
+
const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
|
|
1704
|
+
const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
|
|
1705
|
+
return {
|
|
1706
|
+
bestProviders,
|
|
1707
|
+
id: profile.id,
|
|
1708
|
+
label: profile.label,
|
|
1709
|
+
nextMove: status === "pass" ? `Use this proven provider mix for ${profile.label ?? profile.id}: ${formatProviderMix(bestProviders)}.` : providers.length === 0 ? `Collect provider-specific sustained samples for ${profile.label ?? profile.id}.` : `Tune latency/runtime budgets for ${profile.label ?? profile.id} before promoting this profile.`,
|
|
1710
|
+
providerComparisonCount: providers.length,
|
|
1711
|
+
recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
|
|
1712
|
+
status
|
|
1713
|
+
};
|
|
1714
|
+
});
|
|
1687
1715
|
var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
1688
1716
|
const issues = [];
|
|
1689
1717
|
const requiredStatus = input.requireStatus ?? "pass";
|
|
@@ -1805,6 +1833,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
1805
1833
|
const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
|
|
1806
1834
|
const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
|
|
1807
1835
|
const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
|
|
1836
|
+
const profileRecommendations = buildProfileRecommendations(report, budgets);
|
|
1808
1837
|
const recommendations = [];
|
|
1809
1838
|
const issues = [];
|
|
1810
1839
|
if (report.ok !== true) {
|
|
@@ -1867,16 +1896,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
1867
1896
|
surface: "turn-latency"
|
|
1868
1897
|
});
|
|
1869
1898
|
const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
|
|
1899
|
+
const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
|
|
1900
|
+
evidence: {},
|
|
1901
|
+
nextMove: profile.nextMove,
|
|
1902
|
+
recommendation: profile.recommendation,
|
|
1903
|
+
status: profile.status,
|
|
1904
|
+
surface: "provider-path"
|
|
1905
|
+
})));
|
|
1906
|
+
const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
|
|
1870
1907
|
return {
|
|
1871
1908
|
bestProvider,
|
|
1872
1909
|
bestProviders,
|
|
1873
1910
|
generatedAt: new Date().toISOString(),
|
|
1874
1911
|
issues,
|
|
1875
|
-
ok:
|
|
1912
|
+
ok: combinedStatus !== "fail",
|
|
1913
|
+
profiles: profileRecommendations,
|
|
1876
1914
|
providers,
|
|
1877
1915
|
recommendations,
|
|
1878
1916
|
source: report.source || report.outputDir || report.runId || "proof-trends",
|
|
1879
|
-
status,
|
|
1917
|
+
status: combinedStatus,
|
|
1880
1918
|
summary: {
|
|
1881
1919
|
keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
|
|
1882
1920
|
keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
|
|
@@ -1907,6 +1945,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
1907
1945
|
"| ---: | --- | --- | --- | ---: | ---: | --- |",
|
|
1908
1946
|
...report.providers.length ? report.providers.map((provider) => `| ${String(provider.rank)} | ${escapeMarkdown(provider.label ?? provider.id)} | ${escapeMarkdown(provider.role ?? "n/a")} | ${provider.status} | ${provider.p95Ms === undefined ? "n/a" : String(provider.p95Ms)} | ${provider.samples === undefined ? "n/a" : String(provider.samples)} | ${escapeMarkdown(provider.nextMove)} |`) : ["| n/a | n/a | n/a | n/a | n/a | n/a | No provider-specific samples were present. |"],
|
|
1909
1947
|
"",
|
|
1948
|
+
"## Benchmark Profiles",
|
|
1949
|
+
"",
|
|
1950
|
+
"| Profile | Status | Provider mix | Next move |",
|
|
1951
|
+
"| --- | --- | --- | --- |",
|
|
1952
|
+
...report.profiles.length ? report.profiles.map((profile) => `| ${escapeMarkdown(profile.label ?? profile.id)} | ${profile.status} | ${escapeMarkdown(formatProviderMix(profile.bestProviders))} | ${escapeMarkdown(profile.nextMove)} |`) : ["| n/a | n/a | n/a | No benchmark profiles were present. |"],
|
|
1953
|
+
"",
|
|
1910
1954
|
"## Issues",
|
|
1911
1955
|
"",
|
|
1912
1956
|
...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
|
|
@@ -1916,7 +1960,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
|
|
|
1916
1960
|
const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml5(recommendation.status)}"><p class="eyebrow">${escapeHtml5(recommendation.surface)} \xB7 ${escapeHtml5(recommendation.status)}</p><h2>${escapeHtml5(recommendation.recommendation)}</h2><p>${escapeHtml5(recommendation.nextMove)}</p><pre>${escapeHtml5(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
|
|
1917
1961
|
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml5(issue)}</li>`).join("");
|
|
1918
1962
|
const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml5(provider.label ?? provider.id)}</strong><span>${escapeHtml5(provider.role ?? "provider")} \xB7 ${escapeHtml5(provider.status)} \xB7 p95 ${escapeHtml5(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml5(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml5(provider.nextMove)}</small></li>`).join("");
|
|
1919
|
-
|
|
1963
|
+
const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml5(profile.label ?? profile.id)}</strong><span>${escapeHtml5(profile.status)} \xB7 ${escapeHtml5(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml5(profile.nextMove)}</small></li>`).join("");
|
|
1964
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml5(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml5(title)}</h1><p>Generated ${escapeHtml5(report.generatedAt)} from ${escapeHtml5(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml5(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml5(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
|
|
1920
1965
|
};
|
|
1921
1966
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
1922
1967
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
package/dist/vue/index.js
CHANGED
|
@@ -1605,6 +1605,34 @@ var bestProviderByRole = (providers) => {
|
|
|
1605
1605
|
return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
|
|
1606
1606
|
};
|
|
1607
1607
|
var formatProviderMix = (providers) => providers.length === 0 ? "n/a" : providers.map((provider) => provider.role && !(provider.label ?? provider.id).toLowerCase().startsWith(provider.role.toLowerCase()) ? `${provider.role.toUpperCase()} ${provider.label ?? provider.id}` : provider.label ?? provider.id).join(", ");
|
|
1608
|
+
var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
|
|
1609
|
+
const providers = summarizeProofTrendProviders({
|
|
1610
|
+
...report,
|
|
1611
|
+
cycles: [],
|
|
1612
|
+
summary: {
|
|
1613
|
+
cycles: report.summary.cycles,
|
|
1614
|
+
maxLiveP95Ms: profile.maxLiveP95Ms,
|
|
1615
|
+
maxProviderP95Ms: profile.maxProviderP95Ms,
|
|
1616
|
+
maxTurnP95Ms: profile.maxTurnP95Ms,
|
|
1617
|
+
providers: profile.providers,
|
|
1618
|
+
runtimeChannel: profile.runtimeChannel
|
|
1619
|
+
}
|
|
1620
|
+
}, budgets.maxProviderP95Ms);
|
|
1621
|
+
const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
|
|
1622
|
+
const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
|
|
1623
|
+
const runtimePass = (profile.runtimeChannel?.status === undefined || profile.runtimeChannel.status === "pass") && (profile.runtimeChannel?.maxFirstAudioLatencyMs === undefined || profile.runtimeChannel.maxFirstAudioLatencyMs <= budgets.maxRuntimeFirstAudioLatencyMs) && (profile.runtimeChannel?.maxInterruptionP95Ms === undefined || profile.runtimeChannel.maxInterruptionP95Ms <= budgets.maxRuntimeInterruptionP95Ms) && (profile.runtimeChannel?.maxJitterMs === undefined || profile.runtimeChannel.maxJitterMs <= budgets.maxRuntimeJitterMs) && (profile.runtimeChannel?.maxTimestampDriftMs === undefined || profile.runtimeChannel.maxTimestampDriftMs <= budgets.maxRuntimeTimestampDriftMs) && (profile.runtimeChannel?.maxBackpressureEvents === undefined || profile.runtimeChannel.maxBackpressureEvents <= budgets.maxRuntimeBackpressureEvents);
|
|
1624
|
+
const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
|
|
1625
|
+
const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
|
|
1626
|
+
return {
|
|
1627
|
+
bestProviders,
|
|
1628
|
+
id: profile.id,
|
|
1629
|
+
label: profile.label,
|
|
1630
|
+
nextMove: status === "pass" ? `Use this proven provider mix for ${profile.label ?? profile.id}: ${formatProviderMix(bestProviders)}.` : providers.length === 0 ? `Collect provider-specific sustained samples for ${profile.label ?? profile.id}.` : `Tune latency/runtime budgets for ${profile.label ?? profile.id} before promoting this profile.`,
|
|
1631
|
+
providerComparisonCount: providers.length,
|
|
1632
|
+
recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
|
|
1633
|
+
status
|
|
1634
|
+
};
|
|
1635
|
+
});
|
|
1608
1636
|
var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
1609
1637
|
const issues = [];
|
|
1610
1638
|
const requiredStatus = input.requireStatus ?? "pass";
|
|
@@ -1726,6 +1754,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
1726
1754
|
const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
|
|
1727
1755
|
const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
|
|
1728
1756
|
const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
|
|
1757
|
+
const profileRecommendations = buildProfileRecommendations(report, budgets);
|
|
1729
1758
|
const recommendations = [];
|
|
1730
1759
|
const issues = [];
|
|
1731
1760
|
if (report.ok !== true) {
|
|
@@ -1788,16 +1817,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
1788
1817
|
surface: "turn-latency"
|
|
1789
1818
|
});
|
|
1790
1819
|
const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
|
|
1820
|
+
const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
|
|
1821
|
+
evidence: {},
|
|
1822
|
+
nextMove: profile.nextMove,
|
|
1823
|
+
recommendation: profile.recommendation,
|
|
1824
|
+
status: profile.status,
|
|
1825
|
+
surface: "provider-path"
|
|
1826
|
+
})));
|
|
1827
|
+
const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
|
|
1791
1828
|
return {
|
|
1792
1829
|
bestProvider,
|
|
1793
1830
|
bestProviders,
|
|
1794
1831
|
generatedAt: new Date().toISOString(),
|
|
1795
1832
|
issues,
|
|
1796
|
-
ok:
|
|
1833
|
+
ok: combinedStatus !== "fail",
|
|
1834
|
+
profiles: profileRecommendations,
|
|
1797
1835
|
providers,
|
|
1798
1836
|
recommendations,
|
|
1799
1837
|
source: report.source || report.outputDir || report.runId || "proof-trends",
|
|
1800
|
-
status,
|
|
1838
|
+
status: combinedStatus,
|
|
1801
1839
|
summary: {
|
|
1802
1840
|
keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
|
|
1803
1841
|
keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
|
|
@@ -1828,6 +1866,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
1828
1866
|
"| ---: | --- | --- | --- | ---: | ---: | --- |",
|
|
1829
1867
|
...report.providers.length ? report.providers.map((provider) => `| ${String(provider.rank)} | ${escapeMarkdown(provider.label ?? provider.id)} | ${escapeMarkdown(provider.role ?? "n/a")} | ${provider.status} | ${provider.p95Ms === undefined ? "n/a" : String(provider.p95Ms)} | ${provider.samples === undefined ? "n/a" : String(provider.samples)} | ${escapeMarkdown(provider.nextMove)} |`) : ["| n/a | n/a | n/a | n/a | n/a | n/a | No provider-specific samples were present. |"],
|
|
1830
1868
|
"",
|
|
1869
|
+
"## Benchmark Profiles",
|
|
1870
|
+
"",
|
|
1871
|
+
"| Profile | Status | Provider mix | Next move |",
|
|
1872
|
+
"| --- | --- | --- | --- |",
|
|
1873
|
+
...report.profiles.length ? report.profiles.map((profile) => `| ${escapeMarkdown(profile.label ?? profile.id)} | ${profile.status} | ${escapeMarkdown(formatProviderMix(profile.bestProviders))} | ${escapeMarkdown(profile.nextMove)} |`) : ["| n/a | n/a | n/a | No benchmark profiles were present. |"],
|
|
1874
|
+
"",
|
|
1831
1875
|
"## Issues",
|
|
1832
1876
|
"",
|
|
1833
1877
|
...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
|
|
@@ -1837,7 +1881,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
|
|
|
1837
1881
|
const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml5(recommendation.status)}"><p class="eyebrow">${escapeHtml5(recommendation.surface)} \xB7 ${escapeHtml5(recommendation.status)}</p><h2>${escapeHtml5(recommendation.recommendation)}</h2><p>${escapeHtml5(recommendation.nextMove)}</p><pre>${escapeHtml5(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
|
|
1838
1882
|
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml5(issue)}</li>`).join("");
|
|
1839
1883
|
const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml5(provider.label ?? provider.id)}</strong><span>${escapeHtml5(provider.role ?? "provider")} \xB7 ${escapeHtml5(provider.status)} \xB7 p95 ${escapeHtml5(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml5(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml5(provider.nextMove)}</small></li>`).join("");
|
|
1840
|
-
|
|
1884
|
+
const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml5(profile.label ?? profile.id)}</strong><span>${escapeHtml5(profile.status)} \xB7 ${escapeHtml5(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml5(profile.nextMove)}</small></li>`).join("");
|
|
1885
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml5(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml5(title)}</h1><p>Generated ${escapeHtml5(report.generatedAt)} from ${escapeHtml5(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml5(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml5(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
|
|
1841
1886
|
};
|
|
1842
1887
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
1843
1888
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|