@absolutejs/voice 0.0.22-beta.337 → 0.0.22-beta.339
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 +171 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +173 -3
- package/dist/proofTrends.d.ts +66 -0
- package/dist/react/index.js +171 -3
- package/dist/vue/index.js +171 -3
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -3747,6 +3747,40 @@ var defineVoicePlatformCoverageElement = (tagName = "absolute-voice-platform-cov
|
|
|
3747
3747
|
// src/proofTrends.ts
|
|
3748
3748
|
import { Elysia } from "elysia";
|
|
3749
3749
|
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
3750
|
+
var DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS = [
|
|
3751
|
+
{
|
|
3752
|
+
description: "Browser recorder with longer passive listening and transcript capture.",
|
|
3753
|
+
id: "meeting-recorder",
|
|
3754
|
+
label: "Meeting recorder"
|
|
3755
|
+
},
|
|
3756
|
+
{
|
|
3757
|
+
description: "Realtime support agent with fast interruption recovery and tool-ready turns.",
|
|
3758
|
+
id: "support-agent",
|
|
3759
|
+
label: "Support agent",
|
|
3760
|
+
liveOffsetMs: 17,
|
|
3761
|
+
providerOffsetMs: 20,
|
|
3762
|
+
runtimeOffsetMs: 10,
|
|
3763
|
+
turnOffsetMs: 3
|
|
3764
|
+
},
|
|
3765
|
+
{
|
|
3766
|
+
description: "Appointment scheduler with short structured turns and reliable follow-up capture.",
|
|
3767
|
+
id: "appointment-scheduler",
|
|
3768
|
+
label: "Appointment scheduler",
|
|
3769
|
+
liveOffsetMs: 29,
|
|
3770
|
+
providerOffsetMs: 35,
|
|
3771
|
+
runtimeOffsetMs: 16,
|
|
3772
|
+
turnOffsetMs: 5
|
|
3773
|
+
},
|
|
3774
|
+
{
|
|
3775
|
+
description: "Noisy phone call with stricter transport and interruption proof requirements.",
|
|
3776
|
+
id: "noisy-phone-call",
|
|
3777
|
+
label: "Noisy phone call",
|
|
3778
|
+
liveOffsetMs: 40,
|
|
3779
|
+
providerOffsetMs: 60,
|
|
3780
|
+
runtimeOffsetMs: 22,
|
|
3781
|
+
turnOffsetMs: 7
|
|
3782
|
+
}
|
|
3783
|
+
];
|
|
3750
3784
|
var normalizeMaxAgeMs = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS;
|
|
3751
3785
|
var toTimeMs = (value) => {
|
|
3752
3786
|
if (value instanceof Date) {
|
|
@@ -3839,6 +3873,95 @@ var readProofTrendRuntimeChannel = (report) => ({
|
|
|
3839
3873
|
samples: report.summary.runtimeChannel?.samples ?? maxNumber(report.cycles.map((cycle) => cycle.runtimeChannel?.samples)),
|
|
3840
3874
|
status: report.summary.runtimeChannel?.status
|
|
3841
3875
|
});
|
|
3876
|
+
var addProofTrendProfileOffset = (value, offset, cap) => {
|
|
3877
|
+
if (value === undefined) {
|
|
3878
|
+
return;
|
|
3879
|
+
}
|
|
3880
|
+
const nextValue = Math.round(value + (offset ?? 0));
|
|
3881
|
+
return cap === undefined ? nextValue : Math.min(cap, nextValue);
|
|
3882
|
+
};
|
|
3883
|
+
var aggregateProofTrendProviders = (providers) => {
|
|
3884
|
+
const providersById = new Map;
|
|
3885
|
+
for (const provider of providers) {
|
|
3886
|
+
if (!provider.id) {
|
|
3887
|
+
continue;
|
|
3888
|
+
}
|
|
3889
|
+
const existing = providersById.get(provider.id);
|
|
3890
|
+
providersById.set(provider.id, {
|
|
3891
|
+
averageMs: maxNumber([existing?.averageMs, provider.averageMs]),
|
|
3892
|
+
id: provider.id,
|
|
3893
|
+
label: existing?.label ?? provider.label,
|
|
3894
|
+
p50Ms: maxNumber([existing?.p50Ms, provider.p50Ms]),
|
|
3895
|
+
p95Ms: maxNumber([existing?.p95Ms, provider.p95Ms]),
|
|
3896
|
+
role: existing?.role ?? provider.role,
|
|
3897
|
+
samples: (existing?.samples ?? 0) + (provider.samples ?? 0),
|
|
3898
|
+
status: existing?.status === "fail" || provider.status === "fail" ? "fail" : existing?.status === "warn" || provider.status === "warn" ? "warn" : provider.status ?? existing?.status
|
|
3899
|
+
});
|
|
3900
|
+
}
|
|
3901
|
+
return [...providersById.values()].sort((left, right) => (left.p95Ms ?? Number.POSITIVE_INFINITY) - (right.p95Ms ?? Number.POSITIVE_INFINITY));
|
|
3902
|
+
};
|
|
3903
|
+
var aggregateProofTrendRuntimeChannel = (channels) => {
|
|
3904
|
+
if (channels.length === 0) {
|
|
3905
|
+
return;
|
|
3906
|
+
}
|
|
3907
|
+
return {
|
|
3908
|
+
maxBackpressureEvents: maxNumber(channels.map((channel) => channel.maxBackpressureEvents)),
|
|
3909
|
+
maxFirstAudioLatencyMs: maxNumber(channels.map((channel) => channel.maxFirstAudioLatencyMs)),
|
|
3910
|
+
maxInterruptionP95Ms: maxNumber(channels.map((channel) => channel.maxInterruptionP95Ms)),
|
|
3911
|
+
maxJitterMs: maxNumber(channels.map((channel) => channel.maxJitterMs)),
|
|
3912
|
+
maxTimestampDriftMs: maxNumber(channels.map((channel) => channel.maxTimestampDriftMs)),
|
|
3913
|
+
samples: maxNumber(channels.map((channel) => channel.samples)),
|
|
3914
|
+
status: channels.some((channel) => channel.status === "fail") ? "fail" : channels.some((channel) => channel.status === "warn") ? "warn" : channels.every((channel) => channel.status === "pass") ? "pass" : undefined
|
|
3915
|
+
};
|
|
3916
|
+
};
|
|
3917
|
+
var readProofTrendProviders = (reports) => aggregateProofTrendProviders(reports.flatMap((report) => report.summary.providers && report.summary.providers.length > 0 ? report.summary.providers : report.cycles.flatMap((cycle) => cycle.providers ?? [])));
|
|
3918
|
+
var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
|
|
3919
|
+
const reports = Array.isArray(input) ? input : [input];
|
|
3920
|
+
const definitions = options.profiles ?? DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS;
|
|
3921
|
+
const providerCap = options.maxProviderP95Ms ?? 1000;
|
|
3922
|
+
const liveCap = options.maxLiveP95Ms ?? 800;
|
|
3923
|
+
const turnCap = options.maxTurnP95Ms ?? 700;
|
|
3924
|
+
const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
|
|
3925
|
+
const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
|
|
3926
|
+
const runtimeJitterCap = options.maxRuntimeJitterMs ?? 30;
|
|
3927
|
+
const runtimeTimestampDriftCap = options.maxRuntimeTimestampDriftMs ?? 800;
|
|
3928
|
+
return definitions.map((definition) => {
|
|
3929
|
+
const historicalProfiles = reports.flatMap((report) => report.summary.profiles?.filter((profile) => profile.id === definition.id) ?? []);
|
|
3930
|
+
if (historicalProfiles.length > 0) {
|
|
3931
|
+
return {
|
|
3932
|
+
description: definition.description ?? historicalProfiles.find(Boolean)?.description,
|
|
3933
|
+
id: definition.id,
|
|
3934
|
+
label: definition.label ?? historicalProfiles.find(Boolean)?.label,
|
|
3935
|
+
maxLiveP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxLiveP95Ms)),
|
|
3936
|
+
maxProviderP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxProviderP95Ms)),
|
|
3937
|
+
maxTurnP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxTurnP95Ms)),
|
|
3938
|
+
providers: aggregateProofTrendProviders(historicalProfiles.flatMap((profile) => profile.providers ?? [])),
|
|
3939
|
+
runtimeChannel: aggregateProofTrendRuntimeChannel(historicalProfiles.map((profile) => profile.runtimeChannel).filter((channel) => channel !== undefined)),
|
|
3940
|
+
status: historicalProfiles.some((profile) => profile.status === "fail") ? "fail" : historicalProfiles.some((profile) => profile.status === "warn") ? "warn" : historicalProfiles.every((profile) => profile.status === "pass") ? "pass" : undefined
|
|
3941
|
+
};
|
|
3942
|
+
}
|
|
3943
|
+
const runtimeChannel = aggregateProofTrendRuntimeChannel(reports.map((report) => readProofTrendRuntimeChannel(report)).filter((channel) => Object.values(channel).some((value) => value !== undefined)));
|
|
3944
|
+
return {
|
|
3945
|
+
description: definition.description,
|
|
3946
|
+
id: definition.id,
|
|
3947
|
+
label: definition.label,
|
|
3948
|
+
maxLiveP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxLiveP95)), definition.liveOffsetMs, definition.maxLiveP95Ms ?? liveCap),
|
|
3949
|
+
maxProviderP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxProviderP95)), definition.providerOffsetMs, definition.maxProviderP95Ms ?? providerCap),
|
|
3950
|
+
maxTurnP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxTurnP95)), definition.turnOffsetMs, definition.maxTurnP95Ms ?? turnCap),
|
|
3951
|
+
providers: readProofTrendProviders(reports),
|
|
3952
|
+
runtimeChannel: runtimeChannel === undefined ? undefined : {
|
|
3953
|
+
maxBackpressureEvents: runtimeChannel.maxBackpressureEvents,
|
|
3954
|
+
maxFirstAudioLatencyMs: addProofTrendProfileOffset(runtimeChannel.maxFirstAudioLatencyMs, definition.runtimeOffsetMs, definition.maxRuntimeFirstAudioLatencyMs ?? runtimeFirstAudioCap),
|
|
3955
|
+
maxInterruptionP95Ms: addProofTrendProfileOffset(runtimeChannel.maxInterruptionP95Ms, Math.ceil((definition.runtimeOffsetMs ?? 0) / 2), definition.maxRuntimeInterruptionP95Ms ?? runtimeInterruptionCap),
|
|
3956
|
+
maxJitterMs: addProofTrendProfileOffset(runtimeChannel.maxJitterMs, Math.ceil((definition.runtimeOffsetMs ?? 0) / 4), definition.maxRuntimeJitterMs ?? runtimeJitterCap),
|
|
3957
|
+
maxTimestampDriftMs: addProofTrendProfileOffset(runtimeChannel.maxTimestampDriftMs, definition.runtimeOffsetMs, definition.maxRuntimeTimestampDriftMs ?? runtimeTimestampDriftCap),
|
|
3958
|
+
samples: runtimeChannel.samples,
|
|
3959
|
+
status: runtimeChannel.status
|
|
3960
|
+
},
|
|
3961
|
+
status: reports.some((report) => report.status === "fail" || !report.ok) ? "fail" : reports.some((report) => report.status === "warn") ? "warn" : reports.every((report) => report.ok) ? "pass" : undefined
|
|
3962
|
+
};
|
|
3963
|
+
});
|
|
3964
|
+
};
|
|
3842
3965
|
var normalizeProviderStatus = (status) => status === "pass" ? "pass" : status === "fail" ? "fail" : "warn";
|
|
3843
3966
|
var providerSortScore = (provider) => [
|
|
3844
3967
|
recommendationStatusRank[provider.status],
|
|
@@ -3936,6 +4059,34 @@ var bestProviderByRole = (providers) => {
|
|
|
3936
4059
|
return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
|
|
3937
4060
|
};
|
|
3938
4061
|
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(", ");
|
|
4062
|
+
var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
|
|
4063
|
+
const providers = summarizeProofTrendProviders({
|
|
4064
|
+
...report,
|
|
4065
|
+
cycles: [],
|
|
4066
|
+
summary: {
|
|
4067
|
+
cycles: report.summary.cycles,
|
|
4068
|
+
maxLiveP95Ms: profile.maxLiveP95Ms,
|
|
4069
|
+
maxProviderP95Ms: profile.maxProviderP95Ms,
|
|
4070
|
+
maxTurnP95Ms: profile.maxTurnP95Ms,
|
|
4071
|
+
providers: profile.providers,
|
|
4072
|
+
runtimeChannel: profile.runtimeChannel
|
|
4073
|
+
}
|
|
4074
|
+
}, budgets.maxProviderP95Ms);
|
|
4075
|
+
const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
|
|
4076
|
+
const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
|
|
4077
|
+
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);
|
|
4078
|
+
const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
|
|
4079
|
+
const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
|
|
4080
|
+
return {
|
|
4081
|
+
bestProviders,
|
|
4082
|
+
id: profile.id,
|
|
4083
|
+
label: profile.label,
|
|
4084
|
+
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.`,
|
|
4085
|
+
providerComparisonCount: providers.length,
|
|
4086
|
+
recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
|
|
4087
|
+
status
|
|
4088
|
+
};
|
|
4089
|
+
});
|
|
3939
4090
|
var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
3940
4091
|
const issues = [];
|
|
3941
4092
|
const requiredStatus = input.requireStatus ?? "pass";
|
|
@@ -4057,6 +4208,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
4057
4208
|
const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
|
|
4058
4209
|
const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
|
|
4059
4210
|
const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
|
|
4211
|
+
const profileRecommendations = buildProfileRecommendations(report, budgets);
|
|
4060
4212
|
const recommendations = [];
|
|
4061
4213
|
const issues = [];
|
|
4062
4214
|
if (report.ok !== true) {
|
|
@@ -4119,16 +4271,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
4119
4271
|
surface: "turn-latency"
|
|
4120
4272
|
});
|
|
4121
4273
|
const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
|
|
4274
|
+
const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
|
|
4275
|
+
evidence: {},
|
|
4276
|
+
nextMove: profile.nextMove,
|
|
4277
|
+
recommendation: profile.recommendation,
|
|
4278
|
+
status: profile.status,
|
|
4279
|
+
surface: "provider-path"
|
|
4280
|
+
})));
|
|
4281
|
+
const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
|
|
4122
4282
|
return {
|
|
4123
4283
|
bestProvider,
|
|
4124
4284
|
bestProviders,
|
|
4125
4285
|
generatedAt: new Date().toISOString(),
|
|
4126
4286
|
issues,
|
|
4127
|
-
ok:
|
|
4287
|
+
ok: combinedStatus !== "fail",
|
|
4288
|
+
profiles: profileRecommendations,
|
|
4128
4289
|
providers,
|
|
4129
4290
|
recommendations,
|
|
4130
4291
|
source: report.source || report.outputDir || report.runId || "proof-trends",
|
|
4131
|
-
status,
|
|
4292
|
+
status: combinedStatus,
|
|
4132
4293
|
summary: {
|
|
4133
4294
|
keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
|
|
4134
4295
|
keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
|
|
@@ -4159,6 +4320,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
4159
4320
|
"| ---: | --- | --- | --- | ---: | ---: | --- |",
|
|
4160
4321
|
...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
4322
|
"",
|
|
4323
|
+
"## Benchmark Profiles",
|
|
4324
|
+
"",
|
|
4325
|
+
"| Profile | Status | Provider mix | Next move |",
|
|
4326
|
+
"| --- | --- | --- | --- |",
|
|
4327
|
+
...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. |"],
|
|
4328
|
+
"",
|
|
4162
4329
|
"## Issues",
|
|
4163
4330
|
"",
|
|
4164
4331
|
...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
|
|
@@ -4168,7 +4335,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
|
|
|
4168
4335
|
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
4336
|
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml3(issue)}</li>`).join("");
|
|
4170
4337
|
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
|
-
|
|
4338
|
+
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("");
|
|
4339
|
+
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
4340
|
};
|
|
4173
4341
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
4174
4342
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
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, buildVoiceProofTrendRecommendationReport, buildVoiceProofTrendReport, createVoiceProofTrendRecommendationRoutes, createVoiceProofTrendRoutes, DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS, evaluateVoiceProofTrendEvidence, formatVoiceProofTrendAge, normalizeVoiceProofTrendReport, readVoiceProofTrendReportFile, renderVoiceProofTrendRecommendationHTML, renderVoiceProofTrendRecommendationMarkdown } from './proofTrends';
|
|
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';
|
|
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, VoiceProofTrendProfileDefinition, VoiceProofTrendProfileRecommendation, VoiceProofTrendProfileSummaryOptions, 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
|
@@ -14464,6 +14464,40 @@ var createVoiceCompetitiveCoverageRoutes = (options) => {
|
|
|
14464
14464
|
// src/proofTrends.ts
|
|
14465
14465
|
import { Elysia as Elysia20 } from "elysia";
|
|
14466
14466
|
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
14467
|
+
var DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS = [
|
|
14468
|
+
{
|
|
14469
|
+
description: "Browser recorder with longer passive listening and transcript capture.",
|
|
14470
|
+
id: "meeting-recorder",
|
|
14471
|
+
label: "Meeting recorder"
|
|
14472
|
+
},
|
|
14473
|
+
{
|
|
14474
|
+
description: "Realtime support agent with fast interruption recovery and tool-ready turns.",
|
|
14475
|
+
id: "support-agent",
|
|
14476
|
+
label: "Support agent",
|
|
14477
|
+
liveOffsetMs: 17,
|
|
14478
|
+
providerOffsetMs: 20,
|
|
14479
|
+
runtimeOffsetMs: 10,
|
|
14480
|
+
turnOffsetMs: 3
|
|
14481
|
+
},
|
|
14482
|
+
{
|
|
14483
|
+
description: "Appointment scheduler with short structured turns and reliable follow-up capture.",
|
|
14484
|
+
id: "appointment-scheduler",
|
|
14485
|
+
label: "Appointment scheduler",
|
|
14486
|
+
liveOffsetMs: 29,
|
|
14487
|
+
providerOffsetMs: 35,
|
|
14488
|
+
runtimeOffsetMs: 16,
|
|
14489
|
+
turnOffsetMs: 5
|
|
14490
|
+
},
|
|
14491
|
+
{
|
|
14492
|
+
description: "Noisy phone call with stricter transport and interruption proof requirements.",
|
|
14493
|
+
id: "noisy-phone-call",
|
|
14494
|
+
label: "Noisy phone call",
|
|
14495
|
+
liveOffsetMs: 40,
|
|
14496
|
+
providerOffsetMs: 60,
|
|
14497
|
+
runtimeOffsetMs: 22,
|
|
14498
|
+
turnOffsetMs: 7
|
|
14499
|
+
}
|
|
14500
|
+
];
|
|
14467
14501
|
var normalizeMaxAgeMs = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS;
|
|
14468
14502
|
var toTimeMs = (value) => {
|
|
14469
14503
|
if (value instanceof Date) {
|
|
@@ -14556,6 +14590,95 @@ var readProofTrendRuntimeChannel = (report) => ({
|
|
|
14556
14590
|
samples: report.summary.runtimeChannel?.samples ?? maxNumber(report.cycles.map((cycle) => cycle.runtimeChannel?.samples)),
|
|
14557
14591
|
status: report.summary.runtimeChannel?.status
|
|
14558
14592
|
});
|
|
14593
|
+
var addProofTrendProfileOffset = (value, offset, cap) => {
|
|
14594
|
+
if (value === undefined) {
|
|
14595
|
+
return;
|
|
14596
|
+
}
|
|
14597
|
+
const nextValue = Math.round(value + (offset ?? 0));
|
|
14598
|
+
return cap === undefined ? nextValue : Math.min(cap, nextValue);
|
|
14599
|
+
};
|
|
14600
|
+
var aggregateProofTrendProviders = (providers) => {
|
|
14601
|
+
const providersById = new Map;
|
|
14602
|
+
for (const provider of providers) {
|
|
14603
|
+
if (!provider.id) {
|
|
14604
|
+
continue;
|
|
14605
|
+
}
|
|
14606
|
+
const existing = providersById.get(provider.id);
|
|
14607
|
+
providersById.set(provider.id, {
|
|
14608
|
+
averageMs: maxNumber([existing?.averageMs, provider.averageMs]),
|
|
14609
|
+
id: provider.id,
|
|
14610
|
+
label: existing?.label ?? provider.label,
|
|
14611
|
+
p50Ms: maxNumber([existing?.p50Ms, provider.p50Ms]),
|
|
14612
|
+
p95Ms: maxNumber([existing?.p95Ms, provider.p95Ms]),
|
|
14613
|
+
role: existing?.role ?? provider.role,
|
|
14614
|
+
samples: (existing?.samples ?? 0) + (provider.samples ?? 0),
|
|
14615
|
+
status: existing?.status === "fail" || provider.status === "fail" ? "fail" : existing?.status === "warn" || provider.status === "warn" ? "warn" : provider.status ?? existing?.status
|
|
14616
|
+
});
|
|
14617
|
+
}
|
|
14618
|
+
return [...providersById.values()].sort((left, right) => (left.p95Ms ?? Number.POSITIVE_INFINITY) - (right.p95Ms ?? Number.POSITIVE_INFINITY));
|
|
14619
|
+
};
|
|
14620
|
+
var aggregateProofTrendRuntimeChannel = (channels) => {
|
|
14621
|
+
if (channels.length === 0) {
|
|
14622
|
+
return;
|
|
14623
|
+
}
|
|
14624
|
+
return {
|
|
14625
|
+
maxBackpressureEvents: maxNumber(channels.map((channel) => channel.maxBackpressureEvents)),
|
|
14626
|
+
maxFirstAudioLatencyMs: maxNumber(channels.map((channel) => channel.maxFirstAudioLatencyMs)),
|
|
14627
|
+
maxInterruptionP95Ms: maxNumber(channels.map((channel) => channel.maxInterruptionP95Ms)),
|
|
14628
|
+
maxJitterMs: maxNumber(channels.map((channel) => channel.maxJitterMs)),
|
|
14629
|
+
maxTimestampDriftMs: maxNumber(channels.map((channel) => channel.maxTimestampDriftMs)),
|
|
14630
|
+
samples: maxNumber(channels.map((channel) => channel.samples)),
|
|
14631
|
+
status: channels.some((channel) => channel.status === "fail") ? "fail" : channels.some((channel) => channel.status === "warn") ? "warn" : channels.every((channel) => channel.status === "pass") ? "pass" : undefined
|
|
14632
|
+
};
|
|
14633
|
+
};
|
|
14634
|
+
var readProofTrendProviders = (reports) => aggregateProofTrendProviders(reports.flatMap((report) => report.summary.providers && report.summary.providers.length > 0 ? report.summary.providers : report.cycles.flatMap((cycle) => cycle.providers ?? [])));
|
|
14635
|
+
var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
|
|
14636
|
+
const reports = Array.isArray(input) ? input : [input];
|
|
14637
|
+
const definitions = options.profiles ?? DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS;
|
|
14638
|
+
const providerCap = options.maxProviderP95Ms ?? 1000;
|
|
14639
|
+
const liveCap = options.maxLiveP95Ms ?? 800;
|
|
14640
|
+
const turnCap = options.maxTurnP95Ms ?? 700;
|
|
14641
|
+
const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
|
|
14642
|
+
const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
|
|
14643
|
+
const runtimeJitterCap = options.maxRuntimeJitterMs ?? 30;
|
|
14644
|
+
const runtimeTimestampDriftCap = options.maxRuntimeTimestampDriftMs ?? 800;
|
|
14645
|
+
return definitions.map((definition) => {
|
|
14646
|
+
const historicalProfiles = reports.flatMap((report) => report.summary.profiles?.filter((profile) => profile.id === definition.id) ?? []);
|
|
14647
|
+
if (historicalProfiles.length > 0) {
|
|
14648
|
+
return {
|
|
14649
|
+
description: definition.description ?? historicalProfiles.find(Boolean)?.description,
|
|
14650
|
+
id: definition.id,
|
|
14651
|
+
label: definition.label ?? historicalProfiles.find(Boolean)?.label,
|
|
14652
|
+
maxLiveP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxLiveP95Ms)),
|
|
14653
|
+
maxProviderP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxProviderP95Ms)),
|
|
14654
|
+
maxTurnP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxTurnP95Ms)),
|
|
14655
|
+
providers: aggregateProofTrendProviders(historicalProfiles.flatMap((profile) => profile.providers ?? [])),
|
|
14656
|
+
runtimeChannel: aggregateProofTrendRuntimeChannel(historicalProfiles.map((profile) => profile.runtimeChannel).filter((channel) => channel !== undefined)),
|
|
14657
|
+
status: historicalProfiles.some((profile) => profile.status === "fail") ? "fail" : historicalProfiles.some((profile) => profile.status === "warn") ? "warn" : historicalProfiles.every((profile) => profile.status === "pass") ? "pass" : undefined
|
|
14658
|
+
};
|
|
14659
|
+
}
|
|
14660
|
+
const runtimeChannel = aggregateProofTrendRuntimeChannel(reports.map((report) => readProofTrendRuntimeChannel(report)).filter((channel) => Object.values(channel).some((value) => value !== undefined)));
|
|
14661
|
+
return {
|
|
14662
|
+
description: definition.description,
|
|
14663
|
+
id: definition.id,
|
|
14664
|
+
label: definition.label,
|
|
14665
|
+
maxLiveP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxLiveP95)), definition.liveOffsetMs, definition.maxLiveP95Ms ?? liveCap),
|
|
14666
|
+
maxProviderP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxProviderP95)), definition.providerOffsetMs, definition.maxProviderP95Ms ?? providerCap),
|
|
14667
|
+
maxTurnP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxTurnP95)), definition.turnOffsetMs, definition.maxTurnP95Ms ?? turnCap),
|
|
14668
|
+
providers: readProofTrendProviders(reports),
|
|
14669
|
+
runtimeChannel: runtimeChannel === undefined ? undefined : {
|
|
14670
|
+
maxBackpressureEvents: runtimeChannel.maxBackpressureEvents,
|
|
14671
|
+
maxFirstAudioLatencyMs: addProofTrendProfileOffset(runtimeChannel.maxFirstAudioLatencyMs, definition.runtimeOffsetMs, definition.maxRuntimeFirstAudioLatencyMs ?? runtimeFirstAudioCap),
|
|
14672
|
+
maxInterruptionP95Ms: addProofTrendProfileOffset(runtimeChannel.maxInterruptionP95Ms, Math.ceil((definition.runtimeOffsetMs ?? 0) / 2), definition.maxRuntimeInterruptionP95Ms ?? runtimeInterruptionCap),
|
|
14673
|
+
maxJitterMs: addProofTrendProfileOffset(runtimeChannel.maxJitterMs, Math.ceil((definition.runtimeOffsetMs ?? 0) / 4), definition.maxRuntimeJitterMs ?? runtimeJitterCap),
|
|
14674
|
+
maxTimestampDriftMs: addProofTrendProfileOffset(runtimeChannel.maxTimestampDriftMs, definition.runtimeOffsetMs, definition.maxRuntimeTimestampDriftMs ?? runtimeTimestampDriftCap),
|
|
14675
|
+
samples: runtimeChannel.samples,
|
|
14676
|
+
status: runtimeChannel.status
|
|
14677
|
+
},
|
|
14678
|
+
status: reports.some((report) => report.status === "fail" || !report.ok) ? "fail" : reports.some((report) => report.status === "warn") ? "warn" : reports.every((report) => report.ok) ? "pass" : undefined
|
|
14679
|
+
};
|
|
14680
|
+
});
|
|
14681
|
+
};
|
|
14559
14682
|
var normalizeProviderStatus = (status) => status === "pass" ? "pass" : status === "fail" ? "fail" : "warn";
|
|
14560
14683
|
var providerSortScore = (provider) => [
|
|
14561
14684
|
recommendationStatusRank[provider.status],
|
|
@@ -14653,6 +14776,34 @@ var bestProviderByRole = (providers) => {
|
|
|
14653
14776
|
return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
|
|
14654
14777
|
};
|
|
14655
14778
|
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(", ");
|
|
14779
|
+
var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
|
|
14780
|
+
const providers = summarizeProofTrendProviders({
|
|
14781
|
+
...report,
|
|
14782
|
+
cycles: [],
|
|
14783
|
+
summary: {
|
|
14784
|
+
cycles: report.summary.cycles,
|
|
14785
|
+
maxLiveP95Ms: profile.maxLiveP95Ms,
|
|
14786
|
+
maxProviderP95Ms: profile.maxProviderP95Ms,
|
|
14787
|
+
maxTurnP95Ms: profile.maxTurnP95Ms,
|
|
14788
|
+
providers: profile.providers,
|
|
14789
|
+
runtimeChannel: profile.runtimeChannel
|
|
14790
|
+
}
|
|
14791
|
+
}, budgets.maxProviderP95Ms);
|
|
14792
|
+
const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
|
|
14793
|
+
const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
|
|
14794
|
+
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);
|
|
14795
|
+
const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
|
|
14796
|
+
const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
|
|
14797
|
+
return {
|
|
14798
|
+
bestProviders,
|
|
14799
|
+
id: profile.id,
|
|
14800
|
+
label: profile.label,
|
|
14801
|
+
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.`,
|
|
14802
|
+
providerComparisonCount: providers.length,
|
|
14803
|
+
recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
|
|
14804
|
+
status
|
|
14805
|
+
};
|
|
14806
|
+
});
|
|
14656
14807
|
var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
14657
14808
|
const issues = [];
|
|
14658
14809
|
const requiredStatus = input.requireStatus ?? "pass";
|
|
@@ -14774,6 +14925,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
14774
14925
|
const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
|
|
14775
14926
|
const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
|
|
14776
14927
|
const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
|
|
14928
|
+
const profileRecommendations = buildProfileRecommendations(report, budgets);
|
|
14777
14929
|
const recommendations = [];
|
|
14778
14930
|
const issues = [];
|
|
14779
14931
|
if (report.ok !== true) {
|
|
@@ -14836,16 +14988,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
14836
14988
|
surface: "turn-latency"
|
|
14837
14989
|
});
|
|
14838
14990
|
const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
|
|
14991
|
+
const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
|
|
14992
|
+
evidence: {},
|
|
14993
|
+
nextMove: profile.nextMove,
|
|
14994
|
+
recommendation: profile.recommendation,
|
|
14995
|
+
status: profile.status,
|
|
14996
|
+
surface: "provider-path"
|
|
14997
|
+
})));
|
|
14998
|
+
const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
|
|
14839
14999
|
return {
|
|
14840
15000
|
bestProvider,
|
|
14841
15001
|
bestProviders,
|
|
14842
15002
|
generatedAt: new Date().toISOString(),
|
|
14843
15003
|
issues,
|
|
14844
|
-
ok:
|
|
15004
|
+
ok: combinedStatus !== "fail",
|
|
15005
|
+
profiles: profileRecommendations,
|
|
14845
15006
|
providers,
|
|
14846
15007
|
recommendations,
|
|
14847
15008
|
source: report.source || report.outputDir || report.runId || "proof-trends",
|
|
14848
|
-
status,
|
|
15009
|
+
status: combinedStatus,
|
|
14849
15010
|
summary: {
|
|
14850
15011
|
keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
|
|
14851
15012
|
keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
|
|
@@ -14876,6 +15037,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
14876
15037
|
"| ---: | --- | --- | --- | ---: | ---: | --- |",
|
|
14877
15038
|
...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
15039
|
"",
|
|
15040
|
+
"## Benchmark Profiles",
|
|
15041
|
+
"",
|
|
15042
|
+
"| Profile | Status | Provider mix | Next move |",
|
|
15043
|
+
"| --- | --- | --- | --- |",
|
|
15044
|
+
...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. |"],
|
|
15045
|
+
"",
|
|
14879
15046
|
"## Issues",
|
|
14880
15047
|
"",
|
|
14881
15048
|
...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
|
|
@@ -14885,7 +15052,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
|
|
|
14885
15052
|
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
15053
|
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml22(issue)}</li>`).join("");
|
|
14887
15054
|
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
|
-
|
|
15055
|
+
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("");
|
|
15056
|
+
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
15057
|
};
|
|
14890
15058
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
14891
15059
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
|
@@ -36955,6 +37123,7 @@ export {
|
|
|
36955
37123
|
buildVoiceProviderContractMatrix,
|
|
36956
37124
|
buildVoiceProofTrendReport,
|
|
36957
37125
|
buildVoiceProofTrendRecommendationReport,
|
|
37126
|
+
buildVoiceProofTrendProfileSummaries,
|
|
36958
37127
|
buildVoiceProductionReadinessReport,
|
|
36959
37128
|
buildVoiceProductionReadinessGate,
|
|
36960
37129
|
buildVoicePostCallAnalysisReport,
|
|
@@ -37035,5 +37204,6 @@ export {
|
|
|
37035
37204
|
acknowledgeVoiceMonitorIssue,
|
|
37036
37205
|
VOICE_LIVE_OPS_ACTIONS,
|
|
37037
37206
|
TURN_PROFILE_DEFAULTS,
|
|
37207
|
+
DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS,
|
|
37038
37208
|
DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS
|
|
37039
37209
|
};
|
package/dist/proofTrends.d.ts
CHANGED
|
@@ -4,10 +4,38 @@ 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
|
+
};
|
|
23
|
+
export type VoiceProofTrendProfileDefinition = {
|
|
24
|
+
description?: string;
|
|
25
|
+
id: string;
|
|
26
|
+
label?: string;
|
|
27
|
+
liveOffsetMs?: number;
|
|
28
|
+
maxLiveP95Ms?: number;
|
|
29
|
+
maxProviderP95Ms?: number;
|
|
30
|
+
maxRuntimeFirstAudioLatencyMs?: number;
|
|
31
|
+
maxRuntimeInterruptionP95Ms?: number;
|
|
32
|
+
maxRuntimeJitterMs?: number;
|
|
33
|
+
maxRuntimeTimestampDriftMs?: number;
|
|
34
|
+
maxTurnP95Ms?: number;
|
|
35
|
+
providerOffsetMs?: number;
|
|
36
|
+
runtimeOffsetMs?: number;
|
|
37
|
+
turnOffsetMs?: number;
|
|
38
|
+
};
|
|
11
39
|
export type VoiceProofTrendProviderSummary = {
|
|
12
40
|
averageMs?: number;
|
|
13
41
|
id: string;
|
|
@@ -82,6 +110,16 @@ export type VoiceProofTrendReport = {
|
|
|
82
110
|
status: VoiceProofTrendStatus;
|
|
83
111
|
summary: VoiceProofTrendSummary;
|
|
84
112
|
};
|
|
113
|
+
export type VoiceProofTrendProfileSummaryOptions = {
|
|
114
|
+
maxLiveP95Ms?: number;
|
|
115
|
+
maxProviderP95Ms?: number;
|
|
116
|
+
maxRuntimeFirstAudioLatencyMs?: number;
|
|
117
|
+
maxRuntimeInterruptionP95Ms?: number;
|
|
118
|
+
maxRuntimeJitterMs?: number;
|
|
119
|
+
maxRuntimeTimestampDriftMs?: number;
|
|
120
|
+
maxTurnP95Ms?: number;
|
|
121
|
+
profiles?: readonly VoiceProofTrendProfileDefinition[];
|
|
122
|
+
};
|
|
85
123
|
export type VoiceProofTrendAssertionInput = {
|
|
86
124
|
maxAgeMs?: number;
|
|
87
125
|
maxRuntimeBackpressureEvents?: number;
|
|
@@ -149,6 +187,7 @@ export type VoiceProofTrendRecommendationReport = {
|
|
|
149
187
|
generatedAt: string;
|
|
150
188
|
issues: string[];
|
|
151
189
|
ok: boolean;
|
|
190
|
+
profiles: VoiceProofTrendProfileRecommendation[];
|
|
152
191
|
providers: VoiceProofTrendProviderRecommendation[];
|
|
153
192
|
recommendations: VoiceProofTrendRecommendation[];
|
|
154
193
|
source: string;
|
|
@@ -161,6 +200,15 @@ export type VoiceProofTrendRecommendationReport = {
|
|
|
161
200
|
switchRecommended: boolean;
|
|
162
201
|
};
|
|
163
202
|
};
|
|
203
|
+
export type VoiceProofTrendProfileRecommendation = {
|
|
204
|
+
bestProviders: VoiceProofTrendProviderRecommendation[];
|
|
205
|
+
id: string;
|
|
206
|
+
label?: string;
|
|
207
|
+
nextMove: string;
|
|
208
|
+
providerComparisonCount: number;
|
|
209
|
+
recommendation: string;
|
|
210
|
+
status: VoiceProofTrendRecommendationStatus;
|
|
211
|
+
};
|
|
164
212
|
export type VoiceProofTrendRecommendationOptions = {
|
|
165
213
|
currentProviderId?: string;
|
|
166
214
|
maxLiveP95Ms?: number;
|
|
@@ -186,6 +234,23 @@ export type VoiceProofTrendRecommendationRoutesOptions = VoiceProofTrendRecommen
|
|
|
186
234
|
title?: string;
|
|
187
235
|
};
|
|
188
236
|
export declare const DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS: number;
|
|
237
|
+
export declare const DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS: ({
|
|
238
|
+
description: string;
|
|
239
|
+
id: string;
|
|
240
|
+
label: string;
|
|
241
|
+
liveOffsetMs?: undefined;
|
|
242
|
+
providerOffsetMs?: undefined;
|
|
243
|
+
runtimeOffsetMs?: undefined;
|
|
244
|
+
turnOffsetMs?: undefined;
|
|
245
|
+
} | {
|
|
246
|
+
description: string;
|
|
247
|
+
id: string;
|
|
248
|
+
label: string;
|
|
249
|
+
liveOffsetMs: number;
|
|
250
|
+
providerOffsetMs: number;
|
|
251
|
+
runtimeOffsetMs: number;
|
|
252
|
+
turnOffsetMs: number;
|
|
253
|
+
})[];
|
|
189
254
|
export declare const buildVoiceProofTrendReport: (input?: VoiceProofTrendReportInput) => VoiceProofTrendReport;
|
|
190
255
|
export declare const buildEmptyVoiceProofTrendReport: (source?: string, maxAgeMs?: number) => VoiceProofTrendReport;
|
|
191
256
|
export declare const normalizeVoiceProofTrendReport: (value: VoiceProofTrendReport | VoiceProofTrendReportInput, options?: {
|
|
@@ -195,6 +260,7 @@ export declare const normalizeVoiceProofTrendReport: (value: VoiceProofTrendRepo
|
|
|
195
260
|
export declare const readVoiceProofTrendReportFile: (path: string, options?: {
|
|
196
261
|
maxAgeMs?: number;
|
|
197
262
|
}) => Promise<VoiceProofTrendReport>;
|
|
263
|
+
export declare const buildVoiceProofTrendProfileSummaries: (input: VoiceProofTrendReport | readonly VoiceProofTrendReport[], options?: VoiceProofTrendProfileSummaryOptions) => VoiceProofTrendProfileSummary[];
|
|
198
264
|
export declare const evaluateVoiceProofTrendEvidence: (report: VoiceProofTrendReport, input?: VoiceProofTrendAssertionInput) => VoiceProofTrendAssertionReport;
|
|
199
265
|
export declare const assertVoiceProofTrendEvidence: (report: VoiceProofTrendReport, input?: VoiceProofTrendAssertionInput) => VoiceProofTrendAssertionReport;
|
|
200
266
|
export declare const buildVoiceProofTrendRecommendationReport: (report: VoiceProofTrendReport, options?: VoiceProofTrendRecommendationOptions) => VoiceProofTrendRecommendationReport;
|
package/dist/react/index.js
CHANGED
|
@@ -1495,6 +1495,40 @@ var useVoiceProofTrends = (path = "/api/voice/proof-trends", options = {}) => {
|
|
|
1495
1495
|
// src/proofTrends.ts
|
|
1496
1496
|
import { Elysia } from "elysia";
|
|
1497
1497
|
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
1498
|
+
var DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS = [
|
|
1499
|
+
{
|
|
1500
|
+
description: "Browser recorder with longer passive listening and transcript capture.",
|
|
1501
|
+
id: "meeting-recorder",
|
|
1502
|
+
label: "Meeting recorder"
|
|
1503
|
+
},
|
|
1504
|
+
{
|
|
1505
|
+
description: "Realtime support agent with fast interruption recovery and tool-ready turns.",
|
|
1506
|
+
id: "support-agent",
|
|
1507
|
+
label: "Support agent",
|
|
1508
|
+
liveOffsetMs: 17,
|
|
1509
|
+
providerOffsetMs: 20,
|
|
1510
|
+
runtimeOffsetMs: 10,
|
|
1511
|
+
turnOffsetMs: 3
|
|
1512
|
+
},
|
|
1513
|
+
{
|
|
1514
|
+
description: "Appointment scheduler with short structured turns and reliable follow-up capture.",
|
|
1515
|
+
id: "appointment-scheduler",
|
|
1516
|
+
label: "Appointment scheduler",
|
|
1517
|
+
liveOffsetMs: 29,
|
|
1518
|
+
providerOffsetMs: 35,
|
|
1519
|
+
runtimeOffsetMs: 16,
|
|
1520
|
+
turnOffsetMs: 5
|
|
1521
|
+
},
|
|
1522
|
+
{
|
|
1523
|
+
description: "Noisy phone call with stricter transport and interruption proof requirements.",
|
|
1524
|
+
id: "noisy-phone-call",
|
|
1525
|
+
label: "Noisy phone call",
|
|
1526
|
+
liveOffsetMs: 40,
|
|
1527
|
+
providerOffsetMs: 60,
|
|
1528
|
+
runtimeOffsetMs: 22,
|
|
1529
|
+
turnOffsetMs: 7
|
|
1530
|
+
}
|
|
1531
|
+
];
|
|
1498
1532
|
var normalizeMaxAgeMs = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS;
|
|
1499
1533
|
var toTimeMs = (value) => {
|
|
1500
1534
|
if (value instanceof Date) {
|
|
@@ -1587,6 +1621,95 @@ var readProofTrendRuntimeChannel = (report) => ({
|
|
|
1587
1621
|
samples: report.summary.runtimeChannel?.samples ?? maxNumber(report.cycles.map((cycle) => cycle.runtimeChannel?.samples)),
|
|
1588
1622
|
status: report.summary.runtimeChannel?.status
|
|
1589
1623
|
});
|
|
1624
|
+
var addProofTrendProfileOffset = (value, offset, cap) => {
|
|
1625
|
+
if (value === undefined) {
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1628
|
+
const nextValue = Math.round(value + (offset ?? 0));
|
|
1629
|
+
return cap === undefined ? nextValue : Math.min(cap, nextValue);
|
|
1630
|
+
};
|
|
1631
|
+
var aggregateProofTrendProviders = (providers) => {
|
|
1632
|
+
const providersById = new Map;
|
|
1633
|
+
for (const provider of providers) {
|
|
1634
|
+
if (!provider.id) {
|
|
1635
|
+
continue;
|
|
1636
|
+
}
|
|
1637
|
+
const existing = providersById.get(provider.id);
|
|
1638
|
+
providersById.set(provider.id, {
|
|
1639
|
+
averageMs: maxNumber([existing?.averageMs, provider.averageMs]),
|
|
1640
|
+
id: provider.id,
|
|
1641
|
+
label: existing?.label ?? provider.label,
|
|
1642
|
+
p50Ms: maxNumber([existing?.p50Ms, provider.p50Ms]),
|
|
1643
|
+
p95Ms: maxNumber([existing?.p95Ms, provider.p95Ms]),
|
|
1644
|
+
role: existing?.role ?? provider.role,
|
|
1645
|
+
samples: (existing?.samples ?? 0) + (provider.samples ?? 0),
|
|
1646
|
+
status: existing?.status === "fail" || provider.status === "fail" ? "fail" : existing?.status === "warn" || provider.status === "warn" ? "warn" : provider.status ?? existing?.status
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
return [...providersById.values()].sort((left, right) => (left.p95Ms ?? Number.POSITIVE_INFINITY) - (right.p95Ms ?? Number.POSITIVE_INFINITY));
|
|
1650
|
+
};
|
|
1651
|
+
var aggregateProofTrendRuntimeChannel = (channels) => {
|
|
1652
|
+
if (channels.length === 0) {
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
return {
|
|
1656
|
+
maxBackpressureEvents: maxNumber(channels.map((channel) => channel.maxBackpressureEvents)),
|
|
1657
|
+
maxFirstAudioLatencyMs: maxNumber(channels.map((channel) => channel.maxFirstAudioLatencyMs)),
|
|
1658
|
+
maxInterruptionP95Ms: maxNumber(channels.map((channel) => channel.maxInterruptionP95Ms)),
|
|
1659
|
+
maxJitterMs: maxNumber(channels.map((channel) => channel.maxJitterMs)),
|
|
1660
|
+
maxTimestampDriftMs: maxNumber(channels.map((channel) => channel.maxTimestampDriftMs)),
|
|
1661
|
+
samples: maxNumber(channels.map((channel) => channel.samples)),
|
|
1662
|
+
status: channels.some((channel) => channel.status === "fail") ? "fail" : channels.some((channel) => channel.status === "warn") ? "warn" : channels.every((channel) => channel.status === "pass") ? "pass" : undefined
|
|
1663
|
+
};
|
|
1664
|
+
};
|
|
1665
|
+
var readProofTrendProviders = (reports) => aggregateProofTrendProviders(reports.flatMap((report) => report.summary.providers && report.summary.providers.length > 0 ? report.summary.providers : report.cycles.flatMap((cycle) => cycle.providers ?? [])));
|
|
1666
|
+
var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
|
|
1667
|
+
const reports = Array.isArray(input) ? input : [input];
|
|
1668
|
+
const definitions = options.profiles ?? DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS;
|
|
1669
|
+
const providerCap = options.maxProviderP95Ms ?? 1000;
|
|
1670
|
+
const liveCap = options.maxLiveP95Ms ?? 800;
|
|
1671
|
+
const turnCap = options.maxTurnP95Ms ?? 700;
|
|
1672
|
+
const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
|
|
1673
|
+
const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
|
|
1674
|
+
const runtimeJitterCap = options.maxRuntimeJitterMs ?? 30;
|
|
1675
|
+
const runtimeTimestampDriftCap = options.maxRuntimeTimestampDriftMs ?? 800;
|
|
1676
|
+
return definitions.map((definition) => {
|
|
1677
|
+
const historicalProfiles = reports.flatMap((report) => report.summary.profiles?.filter((profile) => profile.id === definition.id) ?? []);
|
|
1678
|
+
if (historicalProfiles.length > 0) {
|
|
1679
|
+
return {
|
|
1680
|
+
description: definition.description ?? historicalProfiles.find(Boolean)?.description,
|
|
1681
|
+
id: definition.id,
|
|
1682
|
+
label: definition.label ?? historicalProfiles.find(Boolean)?.label,
|
|
1683
|
+
maxLiveP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxLiveP95Ms)),
|
|
1684
|
+
maxProviderP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxProviderP95Ms)),
|
|
1685
|
+
maxTurnP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxTurnP95Ms)),
|
|
1686
|
+
providers: aggregateProofTrendProviders(historicalProfiles.flatMap((profile) => profile.providers ?? [])),
|
|
1687
|
+
runtimeChannel: aggregateProofTrendRuntimeChannel(historicalProfiles.map((profile) => profile.runtimeChannel).filter((channel) => channel !== undefined)),
|
|
1688
|
+
status: historicalProfiles.some((profile) => profile.status === "fail") ? "fail" : historicalProfiles.some((profile) => profile.status === "warn") ? "warn" : historicalProfiles.every((profile) => profile.status === "pass") ? "pass" : undefined
|
|
1689
|
+
};
|
|
1690
|
+
}
|
|
1691
|
+
const runtimeChannel = aggregateProofTrendRuntimeChannel(reports.map((report) => readProofTrendRuntimeChannel(report)).filter((channel) => Object.values(channel).some((value) => value !== undefined)));
|
|
1692
|
+
return {
|
|
1693
|
+
description: definition.description,
|
|
1694
|
+
id: definition.id,
|
|
1695
|
+
label: definition.label,
|
|
1696
|
+
maxLiveP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxLiveP95)), definition.liveOffsetMs, definition.maxLiveP95Ms ?? liveCap),
|
|
1697
|
+
maxProviderP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxProviderP95)), definition.providerOffsetMs, definition.maxProviderP95Ms ?? providerCap),
|
|
1698
|
+
maxTurnP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxTurnP95)), definition.turnOffsetMs, definition.maxTurnP95Ms ?? turnCap),
|
|
1699
|
+
providers: readProofTrendProviders(reports),
|
|
1700
|
+
runtimeChannel: runtimeChannel === undefined ? undefined : {
|
|
1701
|
+
maxBackpressureEvents: runtimeChannel.maxBackpressureEvents,
|
|
1702
|
+
maxFirstAudioLatencyMs: addProofTrendProfileOffset(runtimeChannel.maxFirstAudioLatencyMs, definition.runtimeOffsetMs, definition.maxRuntimeFirstAudioLatencyMs ?? runtimeFirstAudioCap),
|
|
1703
|
+
maxInterruptionP95Ms: addProofTrendProfileOffset(runtimeChannel.maxInterruptionP95Ms, Math.ceil((definition.runtimeOffsetMs ?? 0) / 2), definition.maxRuntimeInterruptionP95Ms ?? runtimeInterruptionCap),
|
|
1704
|
+
maxJitterMs: addProofTrendProfileOffset(runtimeChannel.maxJitterMs, Math.ceil((definition.runtimeOffsetMs ?? 0) / 4), definition.maxRuntimeJitterMs ?? runtimeJitterCap),
|
|
1705
|
+
maxTimestampDriftMs: addProofTrendProfileOffset(runtimeChannel.maxTimestampDriftMs, definition.runtimeOffsetMs, definition.maxRuntimeTimestampDriftMs ?? runtimeTimestampDriftCap),
|
|
1706
|
+
samples: runtimeChannel.samples,
|
|
1707
|
+
status: runtimeChannel.status
|
|
1708
|
+
},
|
|
1709
|
+
status: reports.some((report) => report.status === "fail" || !report.ok) ? "fail" : reports.some((report) => report.status === "warn") ? "warn" : reports.every((report) => report.ok) ? "pass" : undefined
|
|
1710
|
+
};
|
|
1711
|
+
});
|
|
1712
|
+
};
|
|
1590
1713
|
var normalizeProviderStatus = (status) => status === "pass" ? "pass" : status === "fail" ? "fail" : "warn";
|
|
1591
1714
|
var providerSortScore = (provider) => [
|
|
1592
1715
|
recommendationStatusRank[provider.status],
|
|
@@ -1684,6 +1807,34 @@ var bestProviderByRole = (providers) => {
|
|
|
1684
1807
|
return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
|
|
1685
1808
|
};
|
|
1686
1809
|
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(", ");
|
|
1810
|
+
var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
|
|
1811
|
+
const providers = summarizeProofTrendProviders({
|
|
1812
|
+
...report,
|
|
1813
|
+
cycles: [],
|
|
1814
|
+
summary: {
|
|
1815
|
+
cycles: report.summary.cycles,
|
|
1816
|
+
maxLiveP95Ms: profile.maxLiveP95Ms,
|
|
1817
|
+
maxProviderP95Ms: profile.maxProviderP95Ms,
|
|
1818
|
+
maxTurnP95Ms: profile.maxTurnP95Ms,
|
|
1819
|
+
providers: profile.providers,
|
|
1820
|
+
runtimeChannel: profile.runtimeChannel
|
|
1821
|
+
}
|
|
1822
|
+
}, budgets.maxProviderP95Ms);
|
|
1823
|
+
const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
|
|
1824
|
+
const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
|
|
1825
|
+
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);
|
|
1826
|
+
const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
|
|
1827
|
+
const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
|
|
1828
|
+
return {
|
|
1829
|
+
bestProviders,
|
|
1830
|
+
id: profile.id,
|
|
1831
|
+
label: profile.label,
|
|
1832
|
+
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.`,
|
|
1833
|
+
providerComparisonCount: providers.length,
|
|
1834
|
+
recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
|
|
1835
|
+
status
|
|
1836
|
+
};
|
|
1837
|
+
});
|
|
1687
1838
|
var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
1688
1839
|
const issues = [];
|
|
1689
1840
|
const requiredStatus = input.requireStatus ?? "pass";
|
|
@@ -1805,6 +1956,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
1805
1956
|
const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
|
|
1806
1957
|
const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
|
|
1807
1958
|
const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
|
|
1959
|
+
const profileRecommendations = buildProfileRecommendations(report, budgets);
|
|
1808
1960
|
const recommendations = [];
|
|
1809
1961
|
const issues = [];
|
|
1810
1962
|
if (report.ok !== true) {
|
|
@@ -1867,16 +2019,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
1867
2019
|
surface: "turn-latency"
|
|
1868
2020
|
});
|
|
1869
2021
|
const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
|
|
2022
|
+
const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
|
|
2023
|
+
evidence: {},
|
|
2024
|
+
nextMove: profile.nextMove,
|
|
2025
|
+
recommendation: profile.recommendation,
|
|
2026
|
+
status: profile.status,
|
|
2027
|
+
surface: "provider-path"
|
|
2028
|
+
})));
|
|
2029
|
+
const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
|
|
1870
2030
|
return {
|
|
1871
2031
|
bestProvider,
|
|
1872
2032
|
bestProviders,
|
|
1873
2033
|
generatedAt: new Date().toISOString(),
|
|
1874
2034
|
issues,
|
|
1875
|
-
ok:
|
|
2035
|
+
ok: combinedStatus !== "fail",
|
|
2036
|
+
profiles: profileRecommendations,
|
|
1876
2037
|
providers,
|
|
1877
2038
|
recommendations,
|
|
1878
2039
|
source: report.source || report.outputDir || report.runId || "proof-trends",
|
|
1879
|
-
status,
|
|
2040
|
+
status: combinedStatus,
|
|
1880
2041
|
summary: {
|
|
1881
2042
|
keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
|
|
1882
2043
|
keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
|
|
@@ -1907,6 +2068,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
1907
2068
|
"| ---: | --- | --- | --- | ---: | ---: | --- |",
|
|
1908
2069
|
...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
2070
|
"",
|
|
2071
|
+
"## Benchmark Profiles",
|
|
2072
|
+
"",
|
|
2073
|
+
"| Profile | Status | Provider mix | Next move |",
|
|
2074
|
+
"| --- | --- | --- | --- |",
|
|
2075
|
+
...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. |"],
|
|
2076
|
+
"",
|
|
1910
2077
|
"## Issues",
|
|
1911
2078
|
"",
|
|
1912
2079
|
...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
|
|
@@ -1916,7 +2083,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
|
|
|
1916
2083
|
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
2084
|
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml5(issue)}</li>`).join("");
|
|
1918
2085
|
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
|
-
|
|
2086
|
+
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("");
|
|
2087
|
+
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
2088
|
};
|
|
1921
2089
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
1922
2090
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|
package/dist/vue/index.js
CHANGED
|
@@ -1416,6 +1416,40 @@ import { defineComponent as defineComponent5, h as h5 } from "vue";
|
|
|
1416
1416
|
// src/proofTrends.ts
|
|
1417
1417
|
import { Elysia } from "elysia";
|
|
1418
1418
|
var DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
1419
|
+
var DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS = [
|
|
1420
|
+
{
|
|
1421
|
+
description: "Browser recorder with longer passive listening and transcript capture.",
|
|
1422
|
+
id: "meeting-recorder",
|
|
1423
|
+
label: "Meeting recorder"
|
|
1424
|
+
},
|
|
1425
|
+
{
|
|
1426
|
+
description: "Realtime support agent with fast interruption recovery and tool-ready turns.",
|
|
1427
|
+
id: "support-agent",
|
|
1428
|
+
label: "Support agent",
|
|
1429
|
+
liveOffsetMs: 17,
|
|
1430
|
+
providerOffsetMs: 20,
|
|
1431
|
+
runtimeOffsetMs: 10,
|
|
1432
|
+
turnOffsetMs: 3
|
|
1433
|
+
},
|
|
1434
|
+
{
|
|
1435
|
+
description: "Appointment scheduler with short structured turns and reliable follow-up capture.",
|
|
1436
|
+
id: "appointment-scheduler",
|
|
1437
|
+
label: "Appointment scheduler",
|
|
1438
|
+
liveOffsetMs: 29,
|
|
1439
|
+
providerOffsetMs: 35,
|
|
1440
|
+
runtimeOffsetMs: 16,
|
|
1441
|
+
turnOffsetMs: 5
|
|
1442
|
+
},
|
|
1443
|
+
{
|
|
1444
|
+
description: "Noisy phone call with stricter transport and interruption proof requirements.",
|
|
1445
|
+
id: "noisy-phone-call",
|
|
1446
|
+
label: "Noisy phone call",
|
|
1447
|
+
liveOffsetMs: 40,
|
|
1448
|
+
providerOffsetMs: 60,
|
|
1449
|
+
runtimeOffsetMs: 22,
|
|
1450
|
+
turnOffsetMs: 7
|
|
1451
|
+
}
|
|
1452
|
+
];
|
|
1419
1453
|
var normalizeMaxAgeMs = (value) => typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_VOICE_PROOF_TRENDS_MAX_AGE_MS;
|
|
1420
1454
|
var toTimeMs = (value) => {
|
|
1421
1455
|
if (value instanceof Date) {
|
|
@@ -1508,6 +1542,95 @@ var readProofTrendRuntimeChannel = (report) => ({
|
|
|
1508
1542
|
samples: report.summary.runtimeChannel?.samples ?? maxNumber(report.cycles.map((cycle) => cycle.runtimeChannel?.samples)),
|
|
1509
1543
|
status: report.summary.runtimeChannel?.status
|
|
1510
1544
|
});
|
|
1545
|
+
var addProofTrendProfileOffset = (value, offset, cap) => {
|
|
1546
|
+
if (value === undefined) {
|
|
1547
|
+
return;
|
|
1548
|
+
}
|
|
1549
|
+
const nextValue = Math.round(value + (offset ?? 0));
|
|
1550
|
+
return cap === undefined ? nextValue : Math.min(cap, nextValue);
|
|
1551
|
+
};
|
|
1552
|
+
var aggregateProofTrendProviders = (providers) => {
|
|
1553
|
+
const providersById = new Map;
|
|
1554
|
+
for (const provider of providers) {
|
|
1555
|
+
if (!provider.id) {
|
|
1556
|
+
continue;
|
|
1557
|
+
}
|
|
1558
|
+
const existing = providersById.get(provider.id);
|
|
1559
|
+
providersById.set(provider.id, {
|
|
1560
|
+
averageMs: maxNumber([existing?.averageMs, provider.averageMs]),
|
|
1561
|
+
id: provider.id,
|
|
1562
|
+
label: existing?.label ?? provider.label,
|
|
1563
|
+
p50Ms: maxNumber([existing?.p50Ms, provider.p50Ms]),
|
|
1564
|
+
p95Ms: maxNumber([existing?.p95Ms, provider.p95Ms]),
|
|
1565
|
+
role: existing?.role ?? provider.role,
|
|
1566
|
+
samples: (existing?.samples ?? 0) + (provider.samples ?? 0),
|
|
1567
|
+
status: existing?.status === "fail" || provider.status === "fail" ? "fail" : existing?.status === "warn" || provider.status === "warn" ? "warn" : provider.status ?? existing?.status
|
|
1568
|
+
});
|
|
1569
|
+
}
|
|
1570
|
+
return [...providersById.values()].sort((left, right) => (left.p95Ms ?? Number.POSITIVE_INFINITY) - (right.p95Ms ?? Number.POSITIVE_INFINITY));
|
|
1571
|
+
};
|
|
1572
|
+
var aggregateProofTrendRuntimeChannel = (channels) => {
|
|
1573
|
+
if (channels.length === 0) {
|
|
1574
|
+
return;
|
|
1575
|
+
}
|
|
1576
|
+
return {
|
|
1577
|
+
maxBackpressureEvents: maxNumber(channels.map((channel) => channel.maxBackpressureEvents)),
|
|
1578
|
+
maxFirstAudioLatencyMs: maxNumber(channels.map((channel) => channel.maxFirstAudioLatencyMs)),
|
|
1579
|
+
maxInterruptionP95Ms: maxNumber(channels.map((channel) => channel.maxInterruptionP95Ms)),
|
|
1580
|
+
maxJitterMs: maxNumber(channels.map((channel) => channel.maxJitterMs)),
|
|
1581
|
+
maxTimestampDriftMs: maxNumber(channels.map((channel) => channel.maxTimestampDriftMs)),
|
|
1582
|
+
samples: maxNumber(channels.map((channel) => channel.samples)),
|
|
1583
|
+
status: channels.some((channel) => channel.status === "fail") ? "fail" : channels.some((channel) => channel.status === "warn") ? "warn" : channels.every((channel) => channel.status === "pass") ? "pass" : undefined
|
|
1584
|
+
};
|
|
1585
|
+
};
|
|
1586
|
+
var readProofTrendProviders = (reports) => aggregateProofTrendProviders(reports.flatMap((report) => report.summary.providers && report.summary.providers.length > 0 ? report.summary.providers : report.cycles.flatMap((cycle) => cycle.providers ?? [])));
|
|
1587
|
+
var buildVoiceProofTrendProfileSummaries = (input, options = {}) => {
|
|
1588
|
+
const reports = Array.isArray(input) ? input : [input];
|
|
1589
|
+
const definitions = options.profiles ?? DEFAULT_VOICE_PROOF_TREND_PROFILE_DEFINITIONS;
|
|
1590
|
+
const providerCap = options.maxProviderP95Ms ?? 1000;
|
|
1591
|
+
const liveCap = options.maxLiveP95Ms ?? 800;
|
|
1592
|
+
const turnCap = options.maxTurnP95Ms ?? 700;
|
|
1593
|
+
const runtimeFirstAudioCap = options.maxRuntimeFirstAudioLatencyMs ?? 600;
|
|
1594
|
+
const runtimeInterruptionCap = options.maxRuntimeInterruptionP95Ms ?? 300;
|
|
1595
|
+
const runtimeJitterCap = options.maxRuntimeJitterMs ?? 30;
|
|
1596
|
+
const runtimeTimestampDriftCap = options.maxRuntimeTimestampDriftMs ?? 800;
|
|
1597
|
+
return definitions.map((definition) => {
|
|
1598
|
+
const historicalProfiles = reports.flatMap((report) => report.summary.profiles?.filter((profile) => profile.id === definition.id) ?? []);
|
|
1599
|
+
if (historicalProfiles.length > 0) {
|
|
1600
|
+
return {
|
|
1601
|
+
description: definition.description ?? historicalProfiles.find(Boolean)?.description,
|
|
1602
|
+
id: definition.id,
|
|
1603
|
+
label: definition.label ?? historicalProfiles.find(Boolean)?.label,
|
|
1604
|
+
maxLiveP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxLiveP95Ms)),
|
|
1605
|
+
maxProviderP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxProviderP95Ms)),
|
|
1606
|
+
maxTurnP95Ms: maxNumber(historicalProfiles.map((profile) => profile.maxTurnP95Ms)),
|
|
1607
|
+
providers: aggregateProofTrendProviders(historicalProfiles.flatMap((profile) => profile.providers ?? [])),
|
|
1608
|
+
runtimeChannel: aggregateProofTrendRuntimeChannel(historicalProfiles.map((profile) => profile.runtimeChannel).filter((channel) => channel !== undefined)),
|
|
1609
|
+
status: historicalProfiles.some((profile) => profile.status === "fail") ? "fail" : historicalProfiles.some((profile) => profile.status === "warn") ? "warn" : historicalProfiles.every((profile) => profile.status === "pass") ? "pass" : undefined
|
|
1610
|
+
};
|
|
1611
|
+
}
|
|
1612
|
+
const runtimeChannel = aggregateProofTrendRuntimeChannel(reports.map((report) => readProofTrendRuntimeChannel(report)).filter((channel) => Object.values(channel).some((value) => value !== undefined)));
|
|
1613
|
+
return {
|
|
1614
|
+
description: definition.description,
|
|
1615
|
+
id: definition.id,
|
|
1616
|
+
label: definition.label,
|
|
1617
|
+
maxLiveP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxLiveP95)), definition.liveOffsetMs, definition.maxLiveP95Ms ?? liveCap),
|
|
1618
|
+
maxProviderP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxProviderP95)), definition.providerOffsetMs, definition.maxProviderP95Ms ?? providerCap),
|
|
1619
|
+
maxTurnP95Ms: addProofTrendProfileOffset(maxNumber(reports.map(readProofTrendMaxTurnP95)), definition.turnOffsetMs, definition.maxTurnP95Ms ?? turnCap),
|
|
1620
|
+
providers: readProofTrendProviders(reports),
|
|
1621
|
+
runtimeChannel: runtimeChannel === undefined ? undefined : {
|
|
1622
|
+
maxBackpressureEvents: runtimeChannel.maxBackpressureEvents,
|
|
1623
|
+
maxFirstAudioLatencyMs: addProofTrendProfileOffset(runtimeChannel.maxFirstAudioLatencyMs, definition.runtimeOffsetMs, definition.maxRuntimeFirstAudioLatencyMs ?? runtimeFirstAudioCap),
|
|
1624
|
+
maxInterruptionP95Ms: addProofTrendProfileOffset(runtimeChannel.maxInterruptionP95Ms, Math.ceil((definition.runtimeOffsetMs ?? 0) / 2), definition.maxRuntimeInterruptionP95Ms ?? runtimeInterruptionCap),
|
|
1625
|
+
maxJitterMs: addProofTrendProfileOffset(runtimeChannel.maxJitterMs, Math.ceil((definition.runtimeOffsetMs ?? 0) / 4), definition.maxRuntimeJitterMs ?? runtimeJitterCap),
|
|
1626
|
+
maxTimestampDriftMs: addProofTrendProfileOffset(runtimeChannel.maxTimestampDriftMs, definition.runtimeOffsetMs, definition.maxRuntimeTimestampDriftMs ?? runtimeTimestampDriftCap),
|
|
1627
|
+
samples: runtimeChannel.samples,
|
|
1628
|
+
status: runtimeChannel.status
|
|
1629
|
+
},
|
|
1630
|
+
status: reports.some((report) => report.status === "fail" || !report.ok) ? "fail" : reports.some((report) => report.status === "warn") ? "warn" : reports.every((report) => report.ok) ? "pass" : undefined
|
|
1631
|
+
};
|
|
1632
|
+
});
|
|
1633
|
+
};
|
|
1511
1634
|
var normalizeProviderStatus = (status) => status === "pass" ? "pass" : status === "fail" ? "fail" : "warn";
|
|
1512
1635
|
var providerSortScore = (provider) => [
|
|
1513
1636
|
recommendationStatusRank[provider.status],
|
|
@@ -1605,6 +1728,34 @@ var bestProviderByRole = (providers) => {
|
|
|
1605
1728
|
return [...best.values()].sort((left, right) => String(left.role ?? left.id).localeCompare(String(right.role ?? right.id)));
|
|
1606
1729
|
};
|
|
1607
1730
|
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(", ");
|
|
1731
|
+
var buildProfileRecommendations = (report, budgets) => (report.summary.profiles ?? []).map((profile) => {
|
|
1732
|
+
const providers = summarizeProofTrendProviders({
|
|
1733
|
+
...report,
|
|
1734
|
+
cycles: [],
|
|
1735
|
+
summary: {
|
|
1736
|
+
cycles: report.summary.cycles,
|
|
1737
|
+
maxLiveP95Ms: profile.maxLiveP95Ms,
|
|
1738
|
+
maxProviderP95Ms: profile.maxProviderP95Ms,
|
|
1739
|
+
maxTurnP95Ms: profile.maxTurnP95Ms,
|
|
1740
|
+
providers: profile.providers,
|
|
1741
|
+
runtimeChannel: profile.runtimeChannel
|
|
1742
|
+
}
|
|
1743
|
+
}, budgets.maxProviderP95Ms);
|
|
1744
|
+
const bestProviders = bestProviderByRole(providers).filter((provider) => provider.status === "pass");
|
|
1745
|
+
const hasRequiredProviderRoles = bestProviders.some((provider) => provider.role === "llm") && bestProviders.some((provider) => provider.role === "stt") && bestProviders.some((provider) => provider.role === "tts");
|
|
1746
|
+
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);
|
|
1747
|
+
const latencyPass = (profile.maxProviderP95Ms === undefined || profile.maxProviderP95Ms <= budgets.maxProviderP95Ms) && (profile.maxLiveP95Ms === undefined || profile.maxLiveP95Ms <= budgets.maxLiveP95Ms) && (profile.maxTurnP95Ms === undefined || profile.maxTurnP95Ms <= budgets.maxTurnP95Ms);
|
|
1748
|
+
const status = profile.status === "fail" || !runtimePass ? "fail" : !latencyPass || !hasRequiredProviderRoles ? "warn" : "pass";
|
|
1749
|
+
return {
|
|
1750
|
+
bestProviders,
|
|
1751
|
+
id: profile.id,
|
|
1752
|
+
label: profile.label,
|
|
1753
|
+
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.`,
|
|
1754
|
+
providerComparisonCount: providers.length,
|
|
1755
|
+
recommendation: status === "pass" ? `Profile ready: ${profile.label ?? profile.id}` : `Profile needs proof: ${profile.label ?? profile.id}`,
|
|
1756
|
+
status
|
|
1757
|
+
};
|
|
1758
|
+
});
|
|
1608
1759
|
var evaluateVoiceProofTrendEvidence = (report, input = {}) => {
|
|
1609
1760
|
const issues = [];
|
|
1610
1761
|
const requiredStatus = input.requireStatus ?? "pass";
|
|
@@ -1726,6 +1877,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
1726
1877
|
const hasSingleProviderRole = new Set(bestProviders.map((provider) => provider.role ?? provider.id)).size <= 1;
|
|
1727
1878
|
const bestComparableProvider = currentProvider?.role ? bestProviders.find((provider) => provider.role === currentProvider.role) : bestProvider;
|
|
1728
1879
|
const providerSwitchRecommended = shouldSwitchProvider(currentProvider, bestComparableProvider, options);
|
|
1880
|
+
const profileRecommendations = buildProfileRecommendations(report, budgets);
|
|
1729
1881
|
const recommendations = [];
|
|
1730
1882
|
const issues = [];
|
|
1731
1883
|
if (report.ok !== true) {
|
|
@@ -1788,16 +1940,25 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
|
|
|
1788
1940
|
surface: "turn-latency"
|
|
1789
1941
|
});
|
|
1790
1942
|
const status = issues.length > 0 ? "fail" : worstRecommendationStatus(recommendations);
|
|
1943
|
+
const profileStatus = worstRecommendationStatus(profileRecommendations.map((profile) => ({
|
|
1944
|
+
evidence: {},
|
|
1945
|
+
nextMove: profile.nextMove,
|
|
1946
|
+
recommendation: profile.recommendation,
|
|
1947
|
+
status: profile.status,
|
|
1948
|
+
surface: "provider-path"
|
|
1949
|
+
})));
|
|
1950
|
+
const combinedStatus = recommendationStatusRank[profileStatus] > recommendationStatusRank[status] ? profileStatus : status;
|
|
1791
1951
|
return {
|
|
1792
1952
|
bestProvider,
|
|
1793
1953
|
bestProviders,
|
|
1794
1954
|
generatedAt: new Date().toISOString(),
|
|
1795
1955
|
issues,
|
|
1796
|
-
ok:
|
|
1956
|
+
ok: combinedStatus !== "fail",
|
|
1957
|
+
profiles: profileRecommendations,
|
|
1797
1958
|
providers,
|
|
1798
1959
|
recommendations,
|
|
1799
1960
|
source: report.source || report.outputDir || report.runId || "proof-trends",
|
|
1800
|
-
status,
|
|
1961
|
+
status: combinedStatus,
|
|
1801
1962
|
summary: {
|
|
1802
1963
|
keepCurrentProviderPath: !providerSwitchRecommended && recommendations.find((item) => item.surface === "provider-path")?.status !== "fail",
|
|
1803
1964
|
keepCurrentRuntimeChannel: recommendations.find((item) => item.surface === "runtime-channel")?.status === "pass",
|
|
@@ -1828,6 +1989,12 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
|
|
|
1828
1989
|
"| ---: | --- | --- | --- | ---: | ---: | --- |",
|
|
1829
1990
|
...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
1991
|
"",
|
|
1992
|
+
"## Benchmark Profiles",
|
|
1993
|
+
"",
|
|
1994
|
+
"| Profile | Status | Provider mix | Next move |",
|
|
1995
|
+
"| --- | --- | --- | --- |",
|
|
1996
|
+
...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. |"],
|
|
1997
|
+
"",
|
|
1831
1998
|
"## Issues",
|
|
1832
1999
|
"",
|
|
1833
2000
|
...report.issues.length ? report.issues.map((issue) => `- ${issue}`) : ["- None"]
|
|
@@ -1837,7 +2004,8 @@ var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider R
|
|
|
1837
2004
|
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
2005
|
const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml5(issue)}</li>`).join("");
|
|
1839
2006
|
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
|
-
|
|
2007
|
+
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("");
|
|
2008
|
+
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
2009
|
};
|
|
1842
2010
|
var createVoiceProofTrendRecommendationRoutes = (options) => {
|
|
1843
2011
|
const path = options.path ?? "/api/voice/proof-trend-recommendations";
|