@absolutejs/voice 0.0.22-beta.351 → 0.0.22-beta.353
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/angular/index.d.ts +1 -0
- package/dist/angular/index.js +313 -192
- package/dist/angular/voice-profile-comparison.service.d.ts +12 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +429 -211
- package/dist/client/profileComparison.d.ts +19 -0
- package/dist/client/profileComparisonWidget.d.ts +41 -0
- package/dist/client/routingStatusWidget.d.ts +4 -0
- package/dist/react/VoiceProfileComparison.d.ts +6 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +715 -396
- package/dist/react/useVoiceProfileComparison.d.ts +8 -0
- package/dist/svelte/createVoiceProfileComparison.d.ts +7 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +128 -1
- package/dist/vue/index.d.ts +1 -0
- package/dist/vue/index.js +203 -52
- package/dist/vue/useVoiceProfileComparison.d.ts +9 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -2960,6 +2960,80 @@ var createVoiceProofTrendsStore = (path = "/api/voice/proof-trends", options = {
|
|
|
2960
2960
|
}
|
|
2961
2961
|
};
|
|
2962
2962
|
};
|
|
2963
|
+
// src/client/profileComparison.ts
|
|
2964
|
+
var fetchVoiceProfileComparison = async (path = "/api/voice/real-call-profile-history", options = {}) => {
|
|
2965
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2966
|
+
const response = await fetchImpl(path);
|
|
2967
|
+
if (!response.ok) {
|
|
2968
|
+
throw new Error(`Voice profile comparison failed: HTTP ${response.status}`);
|
|
2969
|
+
}
|
|
2970
|
+
return await response.json();
|
|
2971
|
+
};
|
|
2972
|
+
var createVoiceProfileComparisonStore = (path = "/api/voice/real-call-profile-history", options = {}) => {
|
|
2973
|
+
const listeners = new Set;
|
|
2974
|
+
let closed = false;
|
|
2975
|
+
let timer;
|
|
2976
|
+
let snapshot = {
|
|
2977
|
+
error: null,
|
|
2978
|
+
isLoading: false
|
|
2979
|
+
};
|
|
2980
|
+
const emit = () => {
|
|
2981
|
+
for (const listener of listeners) {
|
|
2982
|
+
listener();
|
|
2983
|
+
}
|
|
2984
|
+
};
|
|
2985
|
+
const refresh = async () => {
|
|
2986
|
+
if (closed) {
|
|
2987
|
+
return snapshot.report;
|
|
2988
|
+
}
|
|
2989
|
+
snapshot = { ...snapshot, error: null, isLoading: true };
|
|
2990
|
+
emit();
|
|
2991
|
+
try {
|
|
2992
|
+
const report = await fetchVoiceProfileComparison(path, options);
|
|
2993
|
+
snapshot = {
|
|
2994
|
+
error: null,
|
|
2995
|
+
isLoading: false,
|
|
2996
|
+
report,
|
|
2997
|
+
updatedAt: Date.now()
|
|
2998
|
+
};
|
|
2999
|
+
emit();
|
|
3000
|
+
return report;
|
|
3001
|
+
} catch (error) {
|
|
3002
|
+
snapshot = {
|
|
3003
|
+
...snapshot,
|
|
3004
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3005
|
+
isLoading: false
|
|
3006
|
+
};
|
|
3007
|
+
emit();
|
|
3008
|
+
throw error;
|
|
3009
|
+
}
|
|
3010
|
+
};
|
|
3011
|
+
const close = () => {
|
|
3012
|
+
closed = true;
|
|
3013
|
+
if (timer) {
|
|
3014
|
+
clearInterval(timer);
|
|
3015
|
+
timer = undefined;
|
|
3016
|
+
}
|
|
3017
|
+
listeners.clear();
|
|
3018
|
+
};
|
|
3019
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
3020
|
+
timer = setInterval(() => {
|
|
3021
|
+
refresh().catch(() => {});
|
|
3022
|
+
}, options.intervalMs);
|
|
3023
|
+
}
|
|
3024
|
+
return {
|
|
3025
|
+
close,
|
|
3026
|
+
getServerSnapshot: () => snapshot,
|
|
3027
|
+
getSnapshot: () => snapshot,
|
|
3028
|
+
refresh,
|
|
3029
|
+
subscribe: (listener) => {
|
|
3030
|
+
listeners.add(listener);
|
|
3031
|
+
return () => {
|
|
3032
|
+
listeners.delete(listener);
|
|
3033
|
+
};
|
|
3034
|
+
}
|
|
3035
|
+
};
|
|
3036
|
+
};
|
|
2963
3037
|
// src/client/readinessFailures.ts
|
|
2964
3038
|
var fetchVoiceReadinessFailures = async (path = "/api/production-readiness", options = {}) => {
|
|
2965
3039
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -4901,14 +4975,110 @@ var defineVoiceProofTrendsElement = (tagName = "absolute-voice-proof-trends") =>
|
|
|
4901
4975
|
}
|
|
4902
4976
|
});
|
|
4903
4977
|
};
|
|
4904
|
-
// src/client/
|
|
4905
|
-
var DEFAULT_TITLE4 = "
|
|
4906
|
-
var DEFAULT_DESCRIPTION4 = "
|
|
4978
|
+
// src/client/profileComparisonWidget.ts
|
|
4979
|
+
var DEFAULT_TITLE4 = "Profile Stack Comparison";
|
|
4980
|
+
var DEFAULT_DESCRIPTION4 = "Measured real-call evidence behind each profile default: provider routes, latency, and the next move.";
|
|
4907
4981
|
var DEFAULT_LINKS3 = [
|
|
4982
|
+
{ href: "/voice/real-call-profile-history", label: "Profile history" },
|
|
4983
|
+
{ href: "/api/voice/real-call-profile-history", label: "JSON" }
|
|
4984
|
+
];
|
|
4985
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4986
|
+
var formatMs2 = (value) => typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}ms` : "n/a";
|
|
4987
|
+
var formatProviderRoutes = (profile) => Object.entries(profile.providerRoutes).map(([role, provider]) => `${role}: ${provider}`).join(", ") || "No complete route yet";
|
|
4988
|
+
var createProfileView = (profile) => ({
|
|
4989
|
+
evidence: [
|
|
4990
|
+
{ label: "Live p95", value: formatMs2(profile.evidence.liveP95Ms) },
|
|
4991
|
+
{ label: "Provider p95", value: formatMs2(profile.evidence.providerP95Ms) },
|
|
4992
|
+
{ label: "Turn p95", value: formatMs2(profile.evidence.turnP95Ms) }
|
|
4993
|
+
],
|
|
4994
|
+
label: profile.label ?? profile.profileId,
|
|
4995
|
+
nextMove: profile.nextMove,
|
|
4996
|
+
profileId: profile.profileId,
|
|
4997
|
+
providerRoutes: formatProviderRoutes(profile),
|
|
4998
|
+
status: profile.status
|
|
4999
|
+
});
|
|
5000
|
+
var createVoiceProfileComparisonViewModel = (snapshot, options = {}) => {
|
|
5001
|
+
const report = snapshot.report;
|
|
5002
|
+
const profiles = report?.defaults.profiles.map(createProfileView) ?? [];
|
|
5003
|
+
return {
|
|
5004
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
5005
|
+
error: snapshot.error,
|
|
5006
|
+
isLoading: snapshot.isLoading,
|
|
5007
|
+
label: snapshot.error ? "Unavailable" : report ? `${report.defaults.summary.actionableProfiles}/${report.defaults.summary.profileCount} profiles ready` : snapshot.isLoading ? "Checking" : "No profile evidence",
|
|
5008
|
+
links: options.links ?? DEFAULT_LINKS3,
|
|
5009
|
+
profiles,
|
|
5010
|
+
status: snapshot.error ? "error" : report ? report.status === "pass" ? "ready" : "warning" : snapshot.isLoading ? "loading" : "empty",
|
|
5011
|
+
title: options.title ?? DEFAULT_TITLE4
|
|
5012
|
+
};
|
|
5013
|
+
};
|
|
5014
|
+
var renderVoiceProfileComparisonHTML = (snapshot, options = {}) => {
|
|
5015
|
+
const model = createVoiceProfileComparisonViewModel(snapshot, options);
|
|
5016
|
+
const profiles = model.profiles.length ? `<div class="absolute-voice-profile-comparison__profiles">${model.profiles.map((profile) => `<article class="absolute-voice-profile-comparison__profile absolute-voice-profile-comparison__profile--${escapeHtml5(profile.status)}">
|
|
5017
|
+
<header>
|
|
5018
|
+
<span>${escapeHtml5(profile.status)}</span>
|
|
5019
|
+
<strong>${escapeHtml5(profile.label)}</strong>
|
|
5020
|
+
</header>
|
|
5021
|
+
<p>${escapeHtml5(profile.providerRoutes)}</p>
|
|
5022
|
+
<div>${profile.evidence.map((metric) => `<span><small>${escapeHtml5(metric.label)}</small><b>${escapeHtml5(metric.value)}</b></span>`).join("")}</div>
|
|
5023
|
+
<em>${escapeHtml5(profile.nextMove)}</em>
|
|
5024
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-profile-comparison__empty">${model.error ? escapeHtml5(model.error) : "Run real-call profile collection to populate profile comparisons."}</p>`;
|
|
5025
|
+
const links = model.links.length ? `<p class="absolute-voice-profile-comparison__links">${model.links.map((link) => `<a href="${escapeHtml5(link.href)}">${escapeHtml5(link.label)}</a>`).join("")}</p>` : "";
|
|
5026
|
+
return `<section class="absolute-voice-profile-comparison absolute-voice-profile-comparison--${escapeHtml5(model.status)}">
|
|
5027
|
+
<header class="absolute-voice-profile-comparison__header">
|
|
5028
|
+
<span class="absolute-voice-profile-comparison__eyebrow">${escapeHtml5(model.title)}</span>
|
|
5029
|
+
<strong class="absolute-voice-profile-comparison__label">${escapeHtml5(model.label)}</strong>
|
|
5030
|
+
</header>
|
|
5031
|
+
<p class="absolute-voice-profile-comparison__description">${escapeHtml5(model.description)}</p>
|
|
5032
|
+
${profiles}
|
|
5033
|
+
${links}
|
|
5034
|
+
${model.error ? `<p class="absolute-voice-profile-comparison__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
5035
|
+
</section>`;
|
|
5036
|
+
};
|
|
5037
|
+
var getVoiceProfileComparisonCSS = () => `.absolute-voice-profile-comparison{border:1px solid #c7d2fe;border-radius:20px;background:#eef2ff;color:#111827;padding:18px;box-shadow:0 18px 40px rgba(79,70,229,.12);font-family:inherit}.absolute-voice-profile-comparison--warning,.absolute-voice-profile-comparison--error{border-color:#fbbf24;background:#fffbeb}.absolute-voice-profile-comparison__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-profile-comparison__eyebrow{color:#4338ca;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-profile-comparison__label{font-size:24px;line-height:1}.absolute-voice-profile-comparison__description,.absolute-voice-profile-comparison__empty{color:#4b5563}.absolute-voice-profile-comparison__profiles{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));margin-top:14px}.absolute-voice-profile-comparison__profile{background:#fff;border:1px solid #c7d2fe;border-radius:16px;padding:14px}.absolute-voice-profile-comparison__profile--warn{border-color:#fbbf24}.absolute-voice-profile-comparison__profile--fail{border-color:#f87171}.absolute-voice-profile-comparison__profile header{align-items:center;display:flex;gap:8px;justify-content:space-between}.absolute-voice-profile-comparison__profile header span{border:1px solid currentColor;border-radius:999px;color:#4338ca;font-size:11px;font-weight:900;padding:3px 7px;text-transform:uppercase}.absolute-voice-profile-comparison__profile p{color:#1f2937;font-weight:800;overflow-wrap:anywhere}.absolute-voice-profile-comparison__profile div{display:grid;gap:8px;grid-template-columns:repeat(3,minmax(0,1fr))}.absolute-voice-profile-comparison__profile small{color:#6b7280;display:block;font-size:11px}.absolute-voice-profile-comparison__profile b{display:block}.absolute-voice-profile-comparison__profile em{color:#4b5563;display:block;font-size:13px;margin-top:12px}.absolute-voice-profile-comparison__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-profile-comparison__links a{border:1px solid #a5b4fc;border-radius:999px;color:#4338ca;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-profile-comparison__error{color:#9f1239;font-weight:700}`;
|
|
5038
|
+
var mountVoiceProfileComparison = (element, path = "/api/voice/real-call-profile-history", options = {}) => {
|
|
5039
|
+
const store = createVoiceProfileComparisonStore(path, options);
|
|
5040
|
+
const render = () => {
|
|
5041
|
+
element.innerHTML = renderVoiceProfileComparisonHTML(store.getSnapshot(), options);
|
|
5042
|
+
};
|
|
5043
|
+
const unsubscribe = store.subscribe(render);
|
|
5044
|
+
render();
|
|
5045
|
+
store.refresh().catch(() => {});
|
|
5046
|
+
return {
|
|
5047
|
+
close: () => {
|
|
5048
|
+
unsubscribe();
|
|
5049
|
+
store.close();
|
|
5050
|
+
},
|
|
5051
|
+
refresh: store.refresh
|
|
5052
|
+
};
|
|
5053
|
+
};
|
|
5054
|
+
var defineVoiceProfileComparisonElement = (tagName = "absolute-voice-profile-comparison") => {
|
|
5055
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
5056
|
+
return;
|
|
5057
|
+
}
|
|
5058
|
+
customElements.define(tagName, class AbsoluteVoiceProfileComparisonElement extends HTMLElement {
|
|
5059
|
+
mounted;
|
|
5060
|
+
connectedCallback() {
|
|
5061
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
5062
|
+
this.mounted = mountVoiceProfileComparison(this, this.getAttribute("path") ?? "/api/voice/real-call-profile-history", {
|
|
5063
|
+
description: this.getAttribute("description") ?? undefined,
|
|
5064
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
5065
|
+
title: this.getAttribute("title") ?? undefined
|
|
5066
|
+
});
|
|
5067
|
+
}
|
|
5068
|
+
disconnectedCallback() {
|
|
5069
|
+
this.mounted?.close();
|
|
5070
|
+
this.mounted = undefined;
|
|
5071
|
+
}
|
|
5072
|
+
});
|
|
5073
|
+
};
|
|
5074
|
+
// src/client/readinessFailuresWidget.ts
|
|
5075
|
+
var DEFAULT_TITLE5 = "Readiness Gate Explanations";
|
|
5076
|
+
var DEFAULT_DESCRIPTION5 = "Structured reasons for calibrated production-readiness warnings and failures.";
|
|
5077
|
+
var DEFAULT_LINKS4 = [
|
|
4908
5078
|
{ href: "/production-readiness", label: "Readiness page" },
|
|
4909
5079
|
{ href: "/voice/slo-readiness-thresholds", label: "Gate thresholds" }
|
|
4910
5080
|
];
|
|
4911
|
-
var
|
|
5081
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4912
5082
|
var formatExplanationValue = (value, unit) => {
|
|
4913
5083
|
if (value === undefined || value === null) {
|
|
4914
5084
|
return "n/a";
|
|
@@ -4936,36 +5106,36 @@ var createVoiceReadinessFailuresViewModel = (snapshot, options = {}) => {
|
|
|
4936
5106
|
const failures = snapshot.report?.checks.map(toFailureView).filter((value) => !!value) ?? [];
|
|
4937
5107
|
const hasOpenIssues = failures.length > 0;
|
|
4938
5108
|
return {
|
|
4939
|
-
description: options.description ??
|
|
5109
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
4940
5110
|
error: snapshot.error,
|
|
4941
5111
|
failures,
|
|
4942
5112
|
isLoading: snapshot.isLoading,
|
|
4943
5113
|
label: snapshot.error ? "Unavailable" : snapshot.report ? hasOpenIssues ? `${failures.length} calibrated gate issue(s)` : "No calibrated gate issues" : snapshot.isLoading ? "Checking" : "No readiness report",
|
|
4944
|
-
links: options.links ??
|
|
5114
|
+
links: options.links ?? DEFAULT_LINKS4,
|
|
4945
5115
|
status: snapshot.error ? "error" : snapshot.report ? hasOpenIssues ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
4946
|
-
title: options.title ??
|
|
5116
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
4947
5117
|
updatedAt: snapshot.updatedAt
|
|
4948
5118
|
};
|
|
4949
5119
|
};
|
|
4950
5120
|
var renderVoiceReadinessFailuresHTML = (snapshot, options = {}) => {
|
|
4951
5121
|
const model = createVoiceReadinessFailuresViewModel(snapshot, options);
|
|
4952
|
-
const failures = model.failures.length ? `<div class="absolute-voice-readiness-failures__items">${model.failures.map((failure) => `<article class="absolute-voice-readiness-failures__item absolute-voice-readiness-failures__item--${
|
|
4953
|
-
<span>${
|
|
4954
|
-
<strong>${
|
|
4955
|
-
<p>Observed ${
|
|
4956
|
-
<p>${
|
|
4957
|
-
<p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${
|
|
4958
|
-
</article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ?
|
|
4959
|
-
const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${
|
|
4960
|
-
return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${
|
|
5122
|
+
const failures = model.failures.length ? `<div class="absolute-voice-readiness-failures__items">${model.failures.map((failure) => `<article class="absolute-voice-readiness-failures__item absolute-voice-readiness-failures__item--${escapeHtml6(failure.status)}">
|
|
5123
|
+
<span>${escapeHtml6(failure.status.toUpperCase())}</span>
|
|
5124
|
+
<strong>${escapeHtml6(failure.label)}</strong>
|
|
5125
|
+
<p>Observed ${escapeHtml6(failure.observed)} against ${escapeHtml6(failure.thresholdLabel)} ${escapeHtml6(failure.threshold)}.</p>
|
|
5126
|
+
<p>${escapeHtml6(failure.remediation)}</p>
|
|
5127
|
+
<p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${escapeHtml6(failure.evidenceHref)}">Evidence</a>` : ""}${failure.sourceHref ? `<a href="${escapeHtml6(failure.sourceHref)}">Threshold source</a>` : ""}</p>
|
|
5128
|
+
</article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ? escapeHtml6(model.error) : "No calibrated readiness gate explanations are open."}</p>`;
|
|
5129
|
+
const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${escapeHtml6(link.href)}">${escapeHtml6(link.label)}</a>`).join("")}</p>` : "";
|
|
5130
|
+
return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${escapeHtml6(model.status)}">
|
|
4961
5131
|
<header class="absolute-voice-readiness-failures__header">
|
|
4962
|
-
<span class="absolute-voice-readiness-failures__eyebrow">${
|
|
4963
|
-
<strong class="absolute-voice-readiness-failures__label">${
|
|
5132
|
+
<span class="absolute-voice-readiness-failures__eyebrow">${escapeHtml6(model.title)}</span>
|
|
5133
|
+
<strong class="absolute-voice-readiness-failures__label">${escapeHtml6(model.label)}</strong>
|
|
4964
5134
|
</header>
|
|
4965
|
-
<p class="absolute-voice-readiness-failures__description">${
|
|
5135
|
+
<p class="absolute-voice-readiness-failures__description">${escapeHtml6(model.description)}</p>
|
|
4966
5136
|
${failures}
|
|
4967
5137
|
${links}
|
|
4968
|
-
${model.error ? `<p class="absolute-voice-readiness-failures__error">${
|
|
5138
|
+
${model.error ? `<p class="absolute-voice-readiness-failures__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
4969
5139
|
</section>`;
|
|
4970
5140
|
};
|
|
4971
5141
|
var getVoiceReadinessFailuresCSS = () => `.absolute-voice-readiness-failures{border:1px solid #fed7aa;border-radius:20px;background:#fff7ed;color:#1c1917;padding:18px;box-shadow:0 18px 40px rgba(234,88,12,.12);font-family:inherit}.absolute-voice-readiness-failures--ready{border-color:#86efac;background:#f0fdf4}.absolute-voice-readiness-failures--error{border-color:#fda4af;background:#fff1f2}.absolute-voice-readiness-failures__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-readiness-failures__eyebrow{color:#9a3412;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-readiness-failures__label{font-size:24px;line-height:1}.absolute-voice-readiness-failures__description,.absolute-voice-readiness-failures__empty{color:#57534e}.absolute-voice-readiness-failures__items{display:grid;gap:10px;margin-top:14px}.absolute-voice-readiness-failures__item{background:white;border:1px solid #fed7aa;border-radius:16px;padding:12px}.absolute-voice-readiness-failures__item--fail{border-color:#fb7185}.absolute-voice-readiness-failures__item span{color:#9a3412;display:block;font-size:12px;font-weight:900;text-transform:uppercase}.absolute-voice-readiness-failures__item strong{display:block;font-size:18px;margin-top:4px}.absolute-voice-readiness-failures__item p{margin:.45rem 0 0}.absolute-voice-readiness-failures__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-readiness-failures__links a{border:1px solid #fdba74;border-radius:999px;color:#9a3412;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-readiness-failures__error{color:#9f1239;font-weight:700}`;
|
|
@@ -5005,9 +5175,9 @@ var defineVoiceReadinessFailuresElement = (tagName = "absolute-voice-readiness-f
|
|
|
5005
5175
|
});
|
|
5006
5176
|
};
|
|
5007
5177
|
// src/client/opsActionCenterWidget.ts
|
|
5008
|
-
var
|
|
5009
|
-
var
|
|
5010
|
-
var
|
|
5178
|
+
var DEFAULT_TITLE6 = "Voice Ops Action Center";
|
|
5179
|
+
var DEFAULT_DESCRIPTION6 = "Run production voice proofs and operator actions from one primitive panel.";
|
|
5180
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
5011
5181
|
var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
5012
5182
|
const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
|
|
5013
5183
|
return {
|
|
@@ -5018,29 +5188,29 @@ var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
|
5018
5188
|
isRunning: snapshot.runningActionId === action.id,
|
|
5019
5189
|
label: action.label
|
|
5020
5190
|
})),
|
|
5021
|
-
description: options.description ??
|
|
5191
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
5022
5192
|
error: snapshot.error,
|
|
5023
5193
|
isRunning: snapshot.isRunning,
|
|
5024
5194
|
label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
|
|
5025
5195
|
lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
|
|
5026
5196
|
status,
|
|
5027
|
-
title: options.title ??
|
|
5197
|
+
title: options.title ?? DEFAULT_TITLE6
|
|
5028
5198
|
};
|
|
5029
5199
|
};
|
|
5030
5200
|
var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
|
|
5031
5201
|
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
5032
|
-
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${
|
|
5033
|
-
${
|
|
5202
|
+
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml7(action.id)}"${action.disabled ? " disabled" : ""}>
|
|
5203
|
+
${escapeHtml7(action.isRunning ? "Working..." : action.label)}
|
|
5034
5204
|
</button>`).join("");
|
|
5035
|
-
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${
|
|
5205
|
+
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml7(model.status)}">
|
|
5036
5206
|
<header class="absolute-voice-ops-action-center__header">
|
|
5037
|
-
<span class="absolute-voice-ops-action-center__eyebrow">${
|
|
5038
|
-
<strong class="absolute-voice-ops-action-center__label">${
|
|
5207
|
+
<span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml7(model.title)}</span>
|
|
5208
|
+
<strong class="absolute-voice-ops-action-center__label">${escapeHtml7(model.label)}</strong>
|
|
5039
5209
|
</header>
|
|
5040
|
-
<p class="absolute-voice-ops-action-center__description">${
|
|
5210
|
+
<p class="absolute-voice-ops-action-center__description">${escapeHtml7(model.description)}</p>
|
|
5041
5211
|
<div class="absolute-voice-ops-action-center__actions">${actions}</div>
|
|
5042
|
-
<p class="absolute-voice-ops-action-center__result">${
|
|
5043
|
-
${model.error ? `<p class="absolute-voice-ops-action-center__error">${
|
|
5212
|
+
<p class="absolute-voice-ops-action-center__result">${escapeHtml7(model.lastResultLabel)}</p>
|
|
5213
|
+
${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
5044
5214
|
</section>`;
|
|
5045
5215
|
};
|
|
5046
5216
|
var getVoiceOpsActionCenterCSS = () => `.absolute-voice-ops-action-center{border:1px solid #d5cbb8;border-radius:20px;background:#fffaf1;color:#17130b;padding:18px;box-shadow:0 18px 40px rgba(58,42,16,.12);font-family:inherit}.absolute-voice-ops-action-center--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-action-center__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-action-center__eyebrow{color:#725d37;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-action-center__label{font-size:28px;line-height:1}.absolute-voice-ops-action-center__description,.absolute-voice-ops-action-center__result{color:#5b4b2f;margin:12px 0 0}.absolute-voice-ops-action-center__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-action-center__actions button{background:#7c4a03;border:0;border-radius:999px;color:#fff8e8;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-ops-action-center__actions button:disabled{cursor:not-allowed;opacity:.5}.absolute-voice-ops-action-center__error{color:#9f1239;font-weight:700}`;
|
|
@@ -5641,7 +5811,7 @@ var exportVoiceTrace = async (input) => {
|
|
|
5641
5811
|
};
|
|
5642
5812
|
};
|
|
5643
5813
|
var toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
5644
|
-
var
|
|
5814
|
+
var escapeHtml8 = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
5645
5815
|
var formatTraceValue = (value) => {
|
|
5646
5816
|
if (value === undefined || value === null) {
|
|
5647
5817
|
return "";
|
|
@@ -5921,10 +6091,10 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
5921
6091
|
const offset = summary.startedAt === undefined ? event.at : Math.max(0, event.at - summary.startedAt);
|
|
5922
6092
|
return [
|
|
5923
6093
|
"<tr>",
|
|
5924
|
-
`<td>${
|
|
5925
|
-
`<td>${
|
|
5926
|
-
`<td>${
|
|
5927
|
-
`<td><code>${
|
|
6094
|
+
`<td>${escapeHtml8(String(offset))}</td>`,
|
|
6095
|
+
`<td>${escapeHtml8(event.type)}</td>`,
|
|
6096
|
+
`<td>${escapeHtml8(event.turnId ?? "")}</td>`,
|
|
6097
|
+
`<td><code>${escapeHtml8(JSON.stringify(event.payload))}</code></td>`,
|
|
5928
6098
|
"</tr>"
|
|
5929
6099
|
].join("");
|
|
5930
6100
|
}).join(`
|
|
@@ -5935,7 +6105,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
5935
6105
|
"<head>",
|
|
5936
6106
|
'<meta charset="utf-8" />',
|
|
5937
6107
|
'<meta name="viewport" content="width=device-width, initial-scale=1" />',
|
|
5938
|
-
`<title>${
|
|
6108
|
+
`<title>${escapeHtml8(options.title ?? "Voice Trace")}</title>`,
|
|
5939
6109
|
"<style>",
|
|
5940
6110
|
"body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;line-height:1.45;background:#f8f7f2;color:#181713}",
|
|
5941
6111
|
"main{max-width:1100px;margin:auto}",
|
|
@@ -5949,7 +6119,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
5949
6119
|
"</style>",
|
|
5950
6120
|
"</head>",
|
|
5951
6121
|
"<body><main>",
|
|
5952
|
-
`<h1>${
|
|
6122
|
+
`<h1>${escapeHtml8(options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim())}</h1>`,
|
|
5953
6123
|
`<p class="${evaluation.pass ? "pass" : "fail"}">QA: ${evaluation.pass ? "pass" : "fail"}</p>`,
|
|
5954
6124
|
'<section class="summary">',
|
|
5955
6125
|
`<div class="card"><strong>Events</strong><br>${summary.eventCount}</div>`,
|
|
@@ -5963,7 +6133,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
|
|
|
5963
6133
|
eventRows,
|
|
5964
6134
|
"</tbody></table>",
|
|
5965
6135
|
"<h2>Markdown Export</h2>",
|
|
5966
|
-
`<pre>${
|
|
6136
|
+
`<pre>${escapeHtml8(markdown)}</pre>`,
|
|
5967
6137
|
"</main></body></html>"
|
|
5968
6138
|
].join(`
|
|
5969
6139
|
`);
|
|
@@ -6319,7 +6489,7 @@ var ACTION_LABELS = {
|
|
|
6319
6489
|
"resume-assistant": "Resume assistant",
|
|
6320
6490
|
tag: "Tag"
|
|
6321
6491
|
};
|
|
6322
|
-
var
|
|
6492
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6323
6493
|
var createVoiceLiveOpsInput = (action, input) => ({
|
|
6324
6494
|
action,
|
|
6325
6495
|
assignee: input.assignee,
|
|
@@ -6330,17 +6500,17 @@ var createVoiceLiveOpsInput = (action, input) => ({
|
|
|
6330
6500
|
var renderVoiceLiveOpsHTML = (snapshot, options = {}) => {
|
|
6331
6501
|
const sessionId = options.getSessionId?.() ?? "";
|
|
6332
6502
|
const disabled = snapshot.isRunning || !sessionId;
|
|
6333
|
-
const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${
|
|
6334
|
-
const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${
|
|
6503
|
+
const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${escapeHtml9(action)}"${disabled ? " disabled" : ""}>${escapeHtml9(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
|
|
6504
|
+
const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml9(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml9(snapshot.lastResult.action)}. Control: ${escapeHtml9(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
|
|
6335
6505
|
return `<section class="absolute-voice-live-ops">
|
|
6336
6506
|
<header class="absolute-voice-live-ops__header">
|
|
6337
|
-
<span>${
|
|
6338
|
-
<strong>${
|
|
6507
|
+
<span>${escapeHtml9(options.title ?? "Live Ops")}</span>
|
|
6508
|
+
<strong>${escapeHtml9(sessionId || "No active session")}</strong>
|
|
6339
6509
|
</header>
|
|
6340
|
-
<p class="absolute-voice-live-ops__description">${
|
|
6341
|
-
<label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${
|
|
6342
|
-
<label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${
|
|
6343
|
-
<label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${
|
|
6510
|
+
<p class="absolute-voice-live-ops__description">${escapeHtml9(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
|
|
6511
|
+
<label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml9(options.defaultAssignee ?? "operator")}" /></label>
|
|
6512
|
+
<label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml9(options.defaultTag ?? "live-ops")}" /></label>
|
|
6513
|
+
<label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml9(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
|
|
6344
6514
|
<div class="absolute-voice-live-ops__actions">${actions}</div>
|
|
6345
6515
|
${result}
|
|
6346
6516
|
</section>`;
|
|
@@ -6427,16 +6597,16 @@ var defineVoiceLiveOpsElement = (tagName = "absolute-voice-live-ops", options =
|
|
|
6427
6597
|
});
|
|
6428
6598
|
};
|
|
6429
6599
|
// src/client/opsActionHistoryWidget.ts
|
|
6430
|
-
var
|
|
6600
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6431
6601
|
var renderVoiceOpsActionHistoryWidgetHTML = (snapshot, options = {}) => {
|
|
6432
6602
|
const report = snapshot.report;
|
|
6433
6603
|
const entries = (report?.entries ?? []).slice(0, options.limit ?? 5);
|
|
6434
|
-
const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${
|
|
6604
|
+
const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${escapeHtml10(entry.actionId)}</span><strong>${escapeHtml10(entry.ok ? "Success" : "Failed")}</strong><small>${escapeHtml10(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</small></li>`).join("");
|
|
6435
6605
|
return `<section class="absolute-voice-ops-action-history">
|
|
6436
|
-
<header><span>Operator proof</span><strong>${
|
|
6606
|
+
<header><span>Operator proof</span><strong>${escapeHtml10(options.title ?? "Action History")}</strong></header>
|
|
6437
6607
|
<p>${String(report?.total ?? 0)} action(s), ${String(report?.failed ?? 0)} failed.</p>
|
|
6438
6608
|
<ul>${rows || "<li>No operator actions recorded yet.</li>"}</ul>
|
|
6439
|
-
${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${
|
|
6609
|
+
${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${escapeHtml10(snapshot.error)}</p>` : ""}
|
|
6440
6610
|
</section>`;
|
|
6441
6611
|
};
|
|
6442
6612
|
var getVoiceOpsActionHistoryCSS = () => `.absolute-voice-ops-action-history{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;font-family:inherit}.absolute-voice-ops-action-history header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-action-history header span{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-action-history header strong{font-size:24px}.absolute-voice-ops-action-history p{color:#514733}.absolute-voice-ops-action-history ul{display:grid;gap:8px;list-style:none;margin:12px 0 0;padding:0}.absolute-voice-ops-action-history__entry{background:#fff;border:1px solid #eee4d2;border-radius:14px;display:grid;gap:3px;padding:10px 12px}.absolute-voice-ops-action-history__entry--error{border-color:#f2a7a7}.absolute-voice-ops-action-history__entry span{font-weight:800}.absolute-voice-ops-action-history__entry small{color:#655944}.absolute-voice-ops-action-history__error{color:#9f1239;font-weight:700}`;
|
|
@@ -6457,9 +6627,9 @@ var mountVoiceOpsActionHistory = (element, path = "/api/voice/ops-actions/histor
|
|
|
6457
6627
|
};
|
|
6458
6628
|
};
|
|
6459
6629
|
// src/client/deliveryRuntimeWidget.ts
|
|
6460
|
-
var
|
|
6461
|
-
var
|
|
6462
|
-
var
|
|
6630
|
+
var DEFAULT_TITLE7 = "Voice Delivery Runtime";
|
|
6631
|
+
var DEFAULT_DESCRIPTION7 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
6632
|
+
var escapeHtml11 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6463
6633
|
var createSurface = (id, summary) => {
|
|
6464
6634
|
if (!summary) {
|
|
6465
6635
|
return {
|
|
@@ -6493,7 +6663,7 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
6493
6663
|
];
|
|
6494
6664
|
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
6495
6665
|
return {
|
|
6496
|
-
description: options.description ??
|
|
6666
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
6497
6667
|
error: snapshot.error,
|
|
6498
6668
|
actionError: snapshot.actionError,
|
|
6499
6669
|
actionStatus: snapshot.actionStatus,
|
|
@@ -6502,32 +6672,32 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
6502
6672
|
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
6503
6673
|
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
6504
6674
|
surfaces,
|
|
6505
|
-
title: options.title ??
|
|
6675
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
6506
6676
|
updatedAt: snapshot.updatedAt
|
|
6507
6677
|
};
|
|
6508
6678
|
};
|
|
6509
6679
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
6510
6680
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
6511
|
-
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${
|
|
6512
|
-
<span>${
|
|
6513
|
-
<strong>${
|
|
6681
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml11(surface.status)}">
|
|
6682
|
+
<span>${escapeHtml11(surface.label)}</span>
|
|
6683
|
+
<strong>${escapeHtml11(surface.detail)}</strong>
|
|
6514
6684
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
6515
6685
|
</li>`).join("");
|
|
6516
6686
|
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
6517
6687
|
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
6518
6688
|
<button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
|
|
6519
6689
|
</div>`;
|
|
6520
|
-
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
6521
|
-
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${
|
|
6690
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml11(model.actionError)}</p>` : "";
|
|
6691
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml11(model.status)}">
|
|
6522
6692
|
<header class="absolute-voice-delivery-runtime__header">
|
|
6523
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
6524
|
-
<strong class="absolute-voice-delivery-runtime__label">${
|
|
6693
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml11(model.title)}</span>
|
|
6694
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml11(model.label)}</strong>
|
|
6525
6695
|
</header>
|
|
6526
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
6696
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml11(model.description)}</p>
|
|
6527
6697
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
6528
6698
|
${actions}
|
|
6529
6699
|
${actionError}
|
|
6530
|
-
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
6700
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml11(model.error)}</p>` : ""}
|
|
6531
6701
|
</section>`;
|
|
6532
6702
|
};
|
|
6533
6703
|
var getVoiceDeliveryRuntimeCSS = () => `.absolute-voice-delivery-runtime{border:1px solid #c9d8cf;border-radius:20px;background:#f6fff9;color:#0d1b12;padding:18px;box-shadow:0 18px 40px rgba(19,55,35,.12);font-family:inherit}.absolute-voice-delivery-runtime--warn,.absolute-voice-delivery-runtime--error{border-color:#f2b56b;background:#fff9ed}.absolute-voice-delivery-runtime__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-delivery-runtime__eyebrow{color:#4e6b59;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-delivery-runtime__label{font-size:28px;line-height:1}.absolute-voice-delivery-runtime__description{color:#33483b;margin:12px 0 0}.absolute-voice-delivery-runtime__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-delivery-runtime__surface{background:#fff;border:1px solid #d9eadf;border-radius:14px;display:grid;gap:4px;padding:10px 12px}.absolute-voice-delivery-runtime__surface--warn{border-color:#f2b56b}.absolute-voice-delivery-runtime__surface--disabled{opacity:.72}.absolute-voice-delivery-runtime__surface span,.absolute-voice-delivery-runtime__surface small{color:#587063}.absolute-voice-delivery-runtime__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-delivery-runtime__actions button{background:#134e2d;border:0;border-radius:999px;color:#f6fff9;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-delivery-runtime__actions button:disabled{cursor:not-allowed;opacity:.48}.absolute-voice-delivery-runtime__error{color:#9f1239;font-weight:700}`;
|
|
@@ -6663,13 +6833,48 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
6663
6833
|
};
|
|
6664
6834
|
};
|
|
6665
6835
|
// src/client/routingStatusWidget.ts
|
|
6666
|
-
var
|
|
6667
|
-
var
|
|
6668
|
-
var
|
|
6836
|
+
var DEFAULT_TITLE8 = "Voice Routing";
|
|
6837
|
+
var DEFAULT_DESCRIPTION8 = "Latest provider routing decision from the self-hosted trace store.";
|
|
6838
|
+
var escapeHtml12 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
6669
6839
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
6670
|
-
var
|
|
6840
|
+
var formatProviderRoutes2 = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
|
|
6841
|
+
var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
|
|
6842
|
+
var formatFallbackPath = (decision) => {
|
|
6843
|
+
const provider = formatValue(decision.provider, "Unknown");
|
|
6844
|
+
const selectedProvider = formatValue(decision.selectedProvider, provider);
|
|
6845
|
+
const fallbackProvider = formatValue(decision.fallbackProvider, "");
|
|
6846
|
+
if (fallbackProvider !== "None" && fallbackProvider.trim()) {
|
|
6847
|
+
return `${provider} -> ${fallbackProvider}`;
|
|
6848
|
+
}
|
|
6849
|
+
if (selectedProvider !== provider) {
|
|
6850
|
+
return `${provider} -> ${selectedProvider}`;
|
|
6851
|
+
}
|
|
6852
|
+
return `${provider} primary`;
|
|
6853
|
+
};
|
|
6671
6854
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
6672
6855
|
const decision = snapshot.decision;
|
|
6856
|
+
const activeStack = decision ? [
|
|
6857
|
+
{
|
|
6858
|
+
label: "Profile",
|
|
6859
|
+
value: formatValue(decision.profileLabel ?? decision.profileId)
|
|
6860
|
+
},
|
|
6861
|
+
{
|
|
6862
|
+
label: "LLM",
|
|
6863
|
+
value: getProviderRoute(decision.providerRoutes, "llm")
|
|
6864
|
+
},
|
|
6865
|
+
{
|
|
6866
|
+
label: "STT",
|
|
6867
|
+
value: getProviderRoute(decision.providerRoutes, "stt")
|
|
6868
|
+
},
|
|
6869
|
+
{
|
|
6870
|
+
label: "TTS",
|
|
6871
|
+
value: getProviderRoute(decision.providerRoutes, "tts")
|
|
6872
|
+
},
|
|
6873
|
+
{
|
|
6874
|
+
label: "Fallback path",
|
|
6875
|
+
value: formatFallbackPath(decision)
|
|
6876
|
+
}
|
|
6877
|
+
] : [];
|
|
6673
6878
|
const rows = decision ? [
|
|
6674
6879
|
{ label: "Kind", value: decision.kind.toUpperCase() },
|
|
6675
6880
|
{ label: "Policy", value: formatValue(decision.routing, "Unknown") },
|
|
@@ -6689,7 +6894,7 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
6689
6894
|
},
|
|
6690
6895
|
{
|
|
6691
6896
|
label: "Default routes",
|
|
6692
|
-
value:
|
|
6897
|
+
value: formatProviderRoutes2(decision.providerRoutes)
|
|
6693
6898
|
},
|
|
6694
6899
|
{
|
|
6695
6900
|
label: "Latency budget",
|
|
@@ -6697,34 +6902,40 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
6697
6902
|
}
|
|
6698
6903
|
] : [];
|
|
6699
6904
|
return {
|
|
6905
|
+
activeStack,
|
|
6700
6906
|
decision,
|
|
6701
|
-
description: options.description ??
|
|
6907
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
6702
6908
|
error: snapshot.error,
|
|
6703
6909
|
isLoading: snapshot.isLoading,
|
|
6704
6910
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
6705
6911
|
rows,
|
|
6706
6912
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
6707
|
-
title: options.title ??
|
|
6913
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
6708
6914
|
updatedAt: snapshot.updatedAt
|
|
6709
6915
|
};
|
|
6710
6916
|
};
|
|
6711
6917
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
6712
6918
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
6919
|
+
const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
|
|
6920
|
+
<span>${escapeHtml12(item.label)}</span>
|
|
6921
|
+
<strong>${escapeHtml12(item.value)}</strong>
|
|
6922
|
+
</div>`).join("")}</div>` : "";
|
|
6713
6923
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
6714
|
-
<span>${
|
|
6715
|
-
<strong>${
|
|
6924
|
+
<span>${escapeHtml12(row.label)}</span>
|
|
6925
|
+
<strong>${escapeHtml12(row.value)}</strong>
|
|
6716
6926
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
6717
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
6927
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml12(model.status)}">
|
|
6718
6928
|
<header class="absolute-voice-routing-status__header">
|
|
6719
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
6720
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
6929
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml12(model.title)}</span>
|
|
6930
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml12(model.label)}</strong>
|
|
6721
6931
|
</header>
|
|
6722
|
-
<p class="absolute-voice-routing-status__description">${
|
|
6932
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml12(model.description)}</p>
|
|
6933
|
+
${activeStack}
|
|
6723
6934
|
${rows}
|
|
6724
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
6935
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml12(model.error)}</p>` : ""}
|
|
6725
6936
|
</section>`;
|
|
6726
6937
|
};
|
|
6727
|
-
var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}`;
|
|
6938
|
+
var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__stack{background:linear-gradient(135deg,#16130d,#49391f);border-radius:18px;color:#fff;display:grid;gap:8px;grid-template-columns:repeat(5,minmax(0,1fr));margin-top:14px;padding:12px}.absolute-voice-routing-status__stack div{border-left:1px solid rgba(255,255,255,.18);padding-left:10px}.absolute-voice-routing-status__stack div:first-child{border-left:0;padding-left:0}.absolute-voice-routing-status__stack span{color:#e9d9b8;display:block;font-size:11px;font-weight:800;letter-spacing:.08em;margin-bottom:5px;text-transform:uppercase}.absolute-voice-routing-status__stack strong{display:block;font-size:13px;line-height:1.25;overflow-wrap:anywhere}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}@media (max-width:760px){.absolute-voice-routing-status__stack{grid-template-columns:repeat(2,minmax(0,1fr))}.absolute-voice-routing-status__stack div{border-left:0;border-top:1px solid rgba(255,255,255,.18);padding-left:0;padding-top:8px}.absolute-voice-routing-status__stack div:first-child{border-top:0;padding-top:0}}`;
|
|
6728
6939
|
var mountVoiceRoutingStatus = (element, path = "/api/routing/latest", options = {}) => {
|
|
6729
6940
|
const store = createVoiceRoutingStatusStore(path, options);
|
|
6730
6941
|
const render = () => {
|
|
@@ -7520,7 +7731,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
7520
7731
|
};
|
|
7521
7732
|
};
|
|
7522
7733
|
// src/client/providerSimulationControlsWidget.ts
|
|
7523
|
-
var
|
|
7734
|
+
var escapeHtml13 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
7524
7735
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
7525
7736
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
7526
7737
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -7540,18 +7751,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
7540
7751
|
};
|
|
7541
7752
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
7542
7753
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
7543
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
7544
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
7754
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml13(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml13(provider.provider)} ${escapeHtml13(formatKind(options.kind))} failure</button>`).join("");
|
|
7755
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml13(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml13(provider.provider)} recovered</button>`).join("");
|
|
7545
7756
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
7546
7757
|
<header class="absolute-voice-provider-simulation__header">
|
|
7547
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
7548
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
7758
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml13(model.title)}</span>
|
|
7759
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml13(model.label)}</strong>
|
|
7549
7760
|
</header>
|
|
7550
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
7551
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
7761
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml13(model.description)}</p>
|
|
7762
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml13(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
7552
7763
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
7553
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
7554
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
7764
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml13(snapshot.error)}</p>` : ""}
|
|
7765
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml13(model.resultText)}</pre>` : ""}
|
|
7555
7766
|
</section>`;
|
|
7556
7767
|
};
|
|
7557
7768
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -7616,9 +7827,9 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
7616
7827
|
});
|
|
7617
7828
|
};
|
|
7618
7829
|
// src/client/providerStatusWidget.ts
|
|
7619
|
-
var
|
|
7620
|
-
var
|
|
7621
|
-
var
|
|
7830
|
+
var DEFAULT_TITLE9 = "Voice Providers";
|
|
7831
|
+
var DEFAULT_DESCRIPTION9 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
7832
|
+
var escapeHtml14 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
7622
7833
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
7623
7834
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
7624
7835
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -7662,37 +7873,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
7662
7873
|
const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
|
|
7663
7874
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
7664
7875
|
return {
|
|
7665
|
-
description: options.description ??
|
|
7876
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
7666
7877
|
error: snapshot.error,
|
|
7667
7878
|
isLoading: snapshot.isLoading,
|
|
7668
7879
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
7669
7880
|
providers,
|
|
7670
7881
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
7671
|
-
title: options.title ??
|
|
7882
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
7672
7883
|
updatedAt: snapshot.updatedAt
|
|
7673
7884
|
};
|
|
7674
7885
|
};
|
|
7675
7886
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
7676
7887
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
7677
|
-
const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${
|
|
7888
|
+
const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml14(provider.status)}">
|
|
7678
7889
|
<header>
|
|
7679
|
-
<strong>${
|
|
7680
|
-
<span>${
|
|
7890
|
+
<strong>${escapeHtml14(provider.label)}</strong>
|
|
7891
|
+
<span>${escapeHtml14(formatStatus2(provider.status))}</span>
|
|
7681
7892
|
</header>
|
|
7682
|
-
<p>${
|
|
7893
|
+
<p>${escapeHtml14(provider.detail)}</p>
|
|
7683
7894
|
<dl>${provider.rows.map((row) => `<div>
|
|
7684
|
-
<dt>${
|
|
7685
|
-
<dd>${
|
|
7895
|
+
<dt>${escapeHtml14(row.label)}</dt>
|
|
7896
|
+
<dd>${escapeHtml14(row.value)}</dd>
|
|
7686
7897
|
</div>`).join("")}</dl>
|
|
7687
7898
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
7688
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
7899
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml14(model.status)}">
|
|
7689
7900
|
<header class="absolute-voice-provider-status__header">
|
|
7690
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
7691
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
7901
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml14(model.title)}</span>
|
|
7902
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml14(model.label)}</strong>
|
|
7692
7903
|
</header>
|
|
7693
|
-
<p class="absolute-voice-provider-status__description">${
|
|
7904
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml14(model.description)}</p>
|
|
7694
7905
|
${providers}
|
|
7695
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
7906
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml14(model.error)}</p>` : ""}
|
|
7696
7907
|
</section>`;
|
|
7697
7908
|
};
|
|
7698
7909
|
var getVoiceProviderStatusCSS = () => `.absolute-voice-provider-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-provider-status--error,.absolute-voice-provider-status--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-provider-status__header,.absolute-voice-provider-status__provider header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-status__label{font-size:24px;line-height:1}.absolute-voice-provider-status__description,.absolute-voice-provider-status__provider p,.absolute-voice-provider-status__provider dt,.absolute-voice-provider-status__empty{color:#514733}.absolute-voice-provider-status__providers{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-status__provider{background:#fff;border:1px solid #eee4d2;border-radius:16px;padding:14px}.absolute-voice-provider-status__provider--degraded,.absolute-voice-provider-status__provider--rate-limited,.absolute-voice-provider-status__provider--suppressed{border-color:#f2a7a7}.absolute-voice-provider-status__provider--recoverable{border-color:#fbbf24}.absolute-voice-provider-status__provider p{margin:10px 0}.absolute-voice-provider-status__provider dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-status__provider div{background:#fffaf0;border:1px solid #eee4d2;border-radius:12px;padding:8px}.absolute-voice-provider-status__provider dt{font-size:12px}.absolute-voice-provider-status__provider dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-status__empty{margin:14px 0 0}.absolute-voice-provider-status__error{color:#9f1239;font-weight:700}`;
|
|
@@ -7733,9 +7944,9 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
7733
7944
|
});
|
|
7734
7945
|
};
|
|
7735
7946
|
// src/client/providerCapabilitiesWidget.ts
|
|
7736
|
-
var
|
|
7737
|
-
var
|
|
7738
|
-
var
|
|
7947
|
+
var DEFAULT_TITLE10 = "Provider Capabilities";
|
|
7948
|
+
var DEFAULT_DESCRIPTION10 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
7949
|
+
var escapeHtml15 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
7739
7950
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
7740
7951
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
7741
7952
|
var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -7779,36 +7990,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
7779
7990
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
7780
7991
|
return {
|
|
7781
7992
|
capabilities,
|
|
7782
|
-
description: options.description ??
|
|
7993
|
+
description: options.description ?? DEFAULT_DESCRIPTION10,
|
|
7783
7994
|
error: snapshot.error,
|
|
7784
7995
|
isLoading: snapshot.isLoading,
|
|
7785
7996
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
7786
7997
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
7787
|
-
title: options.title ??
|
|
7998
|
+
title: options.title ?? DEFAULT_TITLE10,
|
|
7788
7999
|
updatedAt: snapshot.updatedAt
|
|
7789
8000
|
};
|
|
7790
8001
|
};
|
|
7791
8002
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
7792
8003
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
7793
|
-
const capabilities = model.capabilities.length ? `<div class="absolute-voice-provider-capabilities__providers">${model.capabilities.map((capability) => `<article class="absolute-voice-provider-capabilities__provider absolute-voice-provider-capabilities__provider--${
|
|
8004
|
+
const capabilities = model.capabilities.length ? `<div class="absolute-voice-provider-capabilities__providers">${model.capabilities.map((capability) => `<article class="absolute-voice-provider-capabilities__provider absolute-voice-provider-capabilities__provider--${escapeHtml15(capability.status)}">
|
|
7794
8005
|
<header>
|
|
7795
|
-
<strong>${
|
|
7796
|
-
<span>${
|
|
8006
|
+
<strong>${escapeHtml15(capability.label)}</strong>
|
|
8007
|
+
<span>${escapeHtml15(formatStatus3(capability.status))}</span>
|
|
7797
8008
|
</header>
|
|
7798
|
-
<p>${
|
|
8009
|
+
<p>${escapeHtml15(capability.detail)}</p>
|
|
7799
8010
|
<dl>${capability.rows.map((row) => `<div>
|
|
7800
|
-
<dt>${
|
|
7801
|
-
<dd>${
|
|
8011
|
+
<dt>${escapeHtml15(row.label)}</dt>
|
|
8012
|
+
<dd>${escapeHtml15(row.value)}</dd>
|
|
7802
8013
|
</div>`).join("")}</dl>
|
|
7803
8014
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
7804
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
8015
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml15(model.status)}">
|
|
7805
8016
|
<header class="absolute-voice-provider-capabilities__header">
|
|
7806
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
7807
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
8017
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml15(model.title)}</span>
|
|
8018
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml15(model.label)}</strong>
|
|
7808
8019
|
</header>
|
|
7809
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
8020
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml15(model.description)}</p>
|
|
7810
8021
|
${capabilities}
|
|
7811
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
8022
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml15(model.error)}</p>` : ""}
|
|
7812
8023
|
</section>`;
|
|
7813
8024
|
};
|
|
7814
8025
|
var getVoiceProviderCapabilitiesCSS = () => `.absolute-voice-provider-capabilities{border:1px solid #bfd7ea;border-radius:20px;background:#f6fbff;color:#08131f;padding:18px;box-shadow:0 18px 40px rgba(14,51,78,.12);font-family:inherit}.absolute-voice-provider-capabilities--error,.absolute-voice-provider-capabilities--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-provider-capabilities__header,.absolute-voice-provider-capabilities__provider header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-capabilities__eyebrow{color:#255f85;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-capabilities__label{font-size:24px;line-height:1}.absolute-voice-provider-capabilities__description,.absolute-voice-provider-capabilities__provider p,.absolute-voice-provider-capabilities__provider dt,.absolute-voice-provider-capabilities__empty{color:#405467}.absolute-voice-provider-capabilities__providers{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-capabilities__provider{background:#fff;border:1px solid #d7e7f3;border-radius:16px;padding:14px}.absolute-voice-provider-capabilities__provider--selected,.absolute-voice-provider-capabilities__provider--healthy{border-color:#86efac}.absolute-voice-provider-capabilities__provider--degraded,.absolute-voice-provider-capabilities__provider--rate-limited,.absolute-voice-provider-capabilities__provider--suppressed,.absolute-voice-provider-capabilities__provider--unconfigured{border-color:#f2a7a7}.absolute-voice-provider-capabilities__provider p{margin:10px 0}.absolute-voice-provider-capabilities__provider dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-capabilities__provider div{background:#f6fbff;border:1px solid #d7e7f3;border-radius:12px;padding:8px}.absolute-voice-provider-capabilities__provider dt{font-size:12px}.absolute-voice-provider-capabilities__provider dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-capabilities__empty{margin:14px 0 0}.absolute-voice-provider-capabilities__error{color:#9f1239;font-weight:700}`;
|
|
@@ -7849,9 +8060,9 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
7849
8060
|
});
|
|
7850
8061
|
};
|
|
7851
8062
|
// src/client/providerContractsWidget.ts
|
|
7852
|
-
var
|
|
7853
|
-
var
|
|
7854
|
-
var
|
|
8063
|
+
var DEFAULT_TITLE11 = "Provider Contracts";
|
|
8064
|
+
var DEFAULT_DESCRIPTION11 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
|
|
8065
|
+
var escapeHtml16 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
7855
8066
|
var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
7856
8067
|
var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
7857
8068
|
var contractDetail = (row) => {
|
|
@@ -7883,38 +8094,38 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
|
|
|
7883
8094
|
}));
|
|
7884
8095
|
const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
|
|
7885
8096
|
return {
|
|
7886
|
-
description: options.description ??
|
|
8097
|
+
description: options.description ?? DEFAULT_DESCRIPTION11,
|
|
7887
8098
|
error: snapshot.error,
|
|
7888
8099
|
isLoading: snapshot.isLoading,
|
|
7889
8100
|
label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
|
|
7890
8101
|
rows,
|
|
7891
8102
|
status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
7892
|
-
title: options.title ??
|
|
8103
|
+
title: options.title ?? DEFAULT_TITLE11,
|
|
7893
8104
|
updatedAt: snapshot.updatedAt
|
|
7894
8105
|
};
|
|
7895
8106
|
};
|
|
7896
8107
|
var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
|
|
7897
8108
|
const model = createVoiceProviderContractsViewModel(snapshot, options);
|
|
7898
|
-
const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${
|
|
8109
|
+
const rows = model.rows.length ? `<div class="absolute-voice-provider-contracts__rows">${model.rows.map((row) => `<article class="absolute-voice-provider-contracts__row absolute-voice-provider-contracts__row--${escapeHtml16(row.status)}">
|
|
7899
8110
|
<header>
|
|
7900
|
-
<strong>${
|
|
7901
|
-
<span>${
|
|
8111
|
+
<strong>${escapeHtml16(row.label)}</strong>
|
|
8112
|
+
<span>${escapeHtml16(formatStatus4(row.status))}</span>
|
|
7902
8113
|
</header>
|
|
7903
|
-
<p>${
|
|
7904
|
-
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${
|
|
8114
|
+
<p>${escapeHtml16(row.detail)}</p>
|
|
8115
|
+
${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml16(remediation.href)}">${escapeHtml16(remediation.label)}</a>` : `<strong>${escapeHtml16(remediation.label)}</strong>`}<span>${escapeHtml16(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
|
|
7905
8116
|
<dl>${row.rows.map((item) => `<div>
|
|
7906
|
-
<dt>${
|
|
7907
|
-
<dd>${
|
|
8117
|
+
<dt>${escapeHtml16(item.label)}</dt>
|
|
8118
|
+
<dd>${escapeHtml16(item.value)}</dd>
|
|
7908
8119
|
</div>`).join("")}</dl>
|
|
7909
8120
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
|
|
7910
|
-
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${
|
|
8121
|
+
return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml16(model.status)}">
|
|
7911
8122
|
<header class="absolute-voice-provider-contracts__header">
|
|
7912
|
-
<span class="absolute-voice-provider-contracts__eyebrow">${
|
|
7913
|
-
<strong class="absolute-voice-provider-contracts__label">${
|
|
8123
|
+
<span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml16(model.title)}</span>
|
|
8124
|
+
<strong class="absolute-voice-provider-contracts__label">${escapeHtml16(model.label)}</strong>
|
|
7914
8125
|
</header>
|
|
7915
|
-
<p class="absolute-voice-provider-contracts__description">${
|
|
8126
|
+
<p class="absolute-voice-provider-contracts__description">${escapeHtml16(model.description)}</p>
|
|
7916
8127
|
${rows}
|
|
7917
|
-
${model.error ? `<p class="absolute-voice-provider-contracts__error">${
|
|
8128
|
+
${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml16(model.error)}</p>` : ""}
|
|
7918
8129
|
</section>`;
|
|
7919
8130
|
};
|
|
7920
8131
|
var getVoiceProviderContractsCSS = () => `.absolute-voice-provider-contracts{border:1px solid #b8dcc7;border-radius:20px;background:#f7fff9;color:#09140d;padding:18px;box-shadow:0 18px 40px rgba(21,83,45,.12);font-family:inherit}.absolute-voice-provider-contracts--error,.absolute-voice-provider-contracts--warning{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-provider-contracts__header,.absolute-voice-provider-contracts__row header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-provider-contracts__eyebrow{color:#166534;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-provider-contracts__label{font-size:24px;line-height:1}.absolute-voice-provider-contracts__description,.absolute-voice-provider-contracts__row p,.absolute-voice-provider-contracts__row dt,.absolute-voice-provider-contracts__empty{color:#405448}.absolute-voice-provider-contracts__rows{display:grid;gap:12px;margin-top:14px}.absolute-voice-provider-contracts__row{background:#fff;border:1px solid #d6eadb;border-radius:16px;padding:14px}.absolute-voice-provider-contracts__row--pass{border-color:#86efac}.absolute-voice-provider-contracts__row--warn,.absolute-voice-provider-contracts__row--fail{border-color:#f2a7a7}.absolute-voice-provider-contracts__row p{margin:10px 0}.absolute-voice-provider-contracts__remediations{display:grid;gap:8px;list-style:none;margin:0 0 10px;padding:0}.absolute-voice-provider-contracts__remediations li{background:#fff7ed;border:1px solid #fed7aa;border-radius:12px;display:grid;gap:3px;padding:8px}.absolute-voice-provider-contracts__remediations a,.absolute-voice-provider-contracts__remediations strong{color:#9a3412}.absolute-voice-provider-contracts__remediations span{color:#7c2d12}.absolute-voice-provider-contracts__row dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-provider-contracts__row div{background:#f7fff9;border:1px solid #d6eadb;border-radius:12px;padding:8px}.absolute-voice-provider-contracts__row dt{font-size:12px}.absolute-voice-provider-contracts__row dd{font-weight:800;margin:4px 0 0}.absolute-voice-provider-contracts__error{color:#9f1239;font-weight:700}`;
|
|
@@ -7955,9 +8166,9 @@ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-co
|
|
|
7955
8166
|
});
|
|
7956
8167
|
};
|
|
7957
8168
|
// src/client/turnQualityWidget.ts
|
|
7958
|
-
var
|
|
7959
|
-
var
|
|
7960
|
-
var
|
|
8169
|
+
var DEFAULT_TITLE12 = "Turn Quality";
|
|
8170
|
+
var DEFAULT_DESCRIPTION12 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
8171
|
+
var escapeHtml17 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
7961
8172
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
7962
8173
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
7963
8174
|
var getTurnDetail = (turn) => {
|
|
@@ -7995,37 +8206,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
7995
8206
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
7996
8207
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
7997
8208
|
return {
|
|
7998
|
-
description: options.description ??
|
|
8209
|
+
description: options.description ?? DEFAULT_DESCRIPTION12,
|
|
7999
8210
|
error: snapshot.error,
|
|
8000
8211
|
isLoading: snapshot.isLoading,
|
|
8001
8212
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
8002
8213
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
8003
|
-
title: options.title ??
|
|
8214
|
+
title: options.title ?? DEFAULT_TITLE12,
|
|
8004
8215
|
turns,
|
|
8005
8216
|
updatedAt: snapshot.updatedAt
|
|
8006
8217
|
};
|
|
8007
8218
|
};
|
|
8008
8219
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
8009
8220
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
8010
|
-
const turns = model.turns.length ? `<div class="absolute-voice-turn-quality__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-quality__turn absolute-voice-turn-quality__turn--${
|
|
8221
|
+
const turns = model.turns.length ? `<div class="absolute-voice-turn-quality__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-quality__turn absolute-voice-turn-quality__turn--${escapeHtml17(turn.status)}">
|
|
8011
8222
|
<header>
|
|
8012
|
-
<strong>${
|
|
8013
|
-
<span>${
|
|
8223
|
+
<strong>${escapeHtml17(turn.label)}</strong>
|
|
8224
|
+
<span>${escapeHtml17(turn.status)}</span>
|
|
8014
8225
|
</header>
|
|
8015
|
-
<p>${
|
|
8226
|
+
<p>${escapeHtml17(turn.detail)}</p>
|
|
8016
8227
|
<dl>${turn.rows.map((row) => `<div>
|
|
8017
|
-
<dt>${
|
|
8018
|
-
<dd>${
|
|
8228
|
+
<dt>${escapeHtml17(row.label)}</dt>
|
|
8229
|
+
<dd>${escapeHtml17(row.value)}</dd>
|
|
8019
8230
|
</div>`).join("")}</dl>
|
|
8020
8231
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
8021
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
8232
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml17(model.status)}">
|
|
8022
8233
|
<header class="absolute-voice-turn-quality__header">
|
|
8023
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
8024
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
8234
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml17(model.title)}</span>
|
|
8235
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml17(model.label)}</strong>
|
|
8025
8236
|
</header>
|
|
8026
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
8237
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml17(model.description)}</p>
|
|
8027
8238
|
${turns}
|
|
8028
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
8239
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml17(model.error)}</p>` : ""}
|
|
8029
8240
|
</section>`;
|
|
8030
8241
|
};
|
|
8031
8242
|
var getVoiceTurnQualityCSS = () => `.absolute-voice-turn-quality{border:1px solid #e4d1a3;border-radius:20px;background:#fff9eb;color:#17120a;padding:18px;box-shadow:0 18px 40px rgba(73,48,14,.12);font-family:inherit}.absolute-voice-turn-quality--error,.absolute-voice-turn-quality--warning{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-turn-quality__header,.absolute-voice-turn-quality__turn header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-turn-quality__eyebrow{color:#8a5a0a;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-turn-quality__label{font-size:24px;line-height:1}.absolute-voice-turn-quality__description,.absolute-voice-turn-quality__turn p,.absolute-voice-turn-quality__turn dt,.absolute-voice-turn-quality__empty{color:#5a4930}.absolute-voice-turn-quality__turns{display:grid;gap:12px;margin-top:14px}.absolute-voice-turn-quality__turn{background:#fff;border:1px solid #f0dfba;border-radius:16px;padding:14px}.absolute-voice-turn-quality__turn--pass{border-color:#86efac}.absolute-voice-turn-quality__turn--warn,.absolute-voice-turn-quality__turn--unknown{border-color:#fbbf24}.absolute-voice-turn-quality__turn--fail{border-color:#f2a7a7}.absolute-voice-turn-quality__turn p{margin:10px 0}.absolute-voice-turn-quality__turn dl{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin:0}.absolute-voice-turn-quality__turn div{background:#fff9eb;border:1px solid #f0dfba;border-radius:12px;padding:8px}.absolute-voice-turn-quality__turn dt{font-size:12px}.absolute-voice-turn-quality__turn dd{font-weight:800;margin:4px 0 0}.absolute-voice-turn-quality__empty{margin:14px 0 0}.absolute-voice-turn-quality__error{color:#9f1239;font-weight:700}`;
|
|
@@ -8066,56 +8277,56 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
8066
8277
|
});
|
|
8067
8278
|
};
|
|
8068
8279
|
// src/client/turnLatencyWidget.ts
|
|
8069
|
-
var
|
|
8070
|
-
var
|
|
8280
|
+
var DEFAULT_TITLE13 = "Turn Latency";
|
|
8281
|
+
var DEFAULT_DESCRIPTION13 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
8071
8282
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
8072
|
-
var
|
|
8073
|
-
var
|
|
8283
|
+
var escapeHtml18 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8284
|
+
var formatMs3 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
8074
8285
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
8075
8286
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
8076
8287
|
...turn,
|
|
8077
8288
|
label: turn.text || "Empty turn",
|
|
8078
8289
|
rows: turn.stages.map((stage) => ({
|
|
8079
8290
|
label: stage.label,
|
|
8080
|
-
value:
|
|
8291
|
+
value: formatMs3(stage.valueMs)
|
|
8081
8292
|
}))
|
|
8082
8293
|
}));
|
|
8083
8294
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
8084
8295
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
8085
8296
|
return {
|
|
8086
|
-
description: options.description ??
|
|
8297
|
+
description: options.description ?? DEFAULT_DESCRIPTION13,
|
|
8087
8298
|
error: snapshot.error,
|
|
8088
8299
|
isLoading: snapshot.isLoading,
|
|
8089
|
-
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${
|
|
8300
|
+
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs3(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
8090
8301
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
8091
8302
|
showProofAction: Boolean(options.proofPath),
|
|
8092
8303
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
8093
|
-
title: options.title ??
|
|
8304
|
+
title: options.title ?? DEFAULT_TITLE13,
|
|
8094
8305
|
turns,
|
|
8095
8306
|
updatedAt: snapshot.updatedAt
|
|
8096
8307
|
};
|
|
8097
8308
|
};
|
|
8098
8309
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
8099
8310
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
8100
|
-
const turns = model.turns.length ? `<div class="absolute-voice-turn-latency__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-latency__turn absolute-voice-turn-latency__turn--${
|
|
8311
|
+
const turns = model.turns.length ? `<div class="absolute-voice-turn-latency__turns">${model.turns.map((turn) => `<article class="absolute-voice-turn-latency__turn absolute-voice-turn-latency__turn--${escapeHtml18(turn.status)}">
|
|
8101
8312
|
<header>
|
|
8102
|
-
<strong>${
|
|
8103
|
-
<span>${
|
|
8313
|
+
<strong>${escapeHtml18(turn.label)}</strong>
|
|
8314
|
+
<span>${escapeHtml18(turn.status)}</span>
|
|
8104
8315
|
</header>
|
|
8105
8316
|
<dl>${turn.rows.map((row) => `<div>
|
|
8106
|
-
<dt>${
|
|
8107
|
-
<dd>${
|
|
8317
|
+
<dt>${escapeHtml18(row.label)}</dt>
|
|
8318
|
+
<dd>${escapeHtml18(row.value)}</dd>
|
|
8108
8319
|
</div>`).join("")}</dl>
|
|
8109
8320
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
8110
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
8321
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml18(model.status)}">
|
|
8111
8322
|
<header class="absolute-voice-turn-latency__header">
|
|
8112
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
8113
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
8323
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml18(model.title)}</span>
|
|
8324
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml18(model.label)}</strong>
|
|
8114
8325
|
</header>
|
|
8115
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
8116
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
8326
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml18(model.description)}</p>
|
|
8327
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml18(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
8117
8328
|
${turns}
|
|
8118
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
8329
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml18(model.error)}</p>` : ""}
|
|
8119
8330
|
</section>`;
|
|
8120
8331
|
};
|
|
8121
8332
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -8165,16 +8376,16 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
8165
8376
|
});
|
|
8166
8377
|
};
|
|
8167
8378
|
// src/client/traceTimelineWidget.ts
|
|
8168
|
-
var
|
|
8169
|
-
var
|
|
8170
|
-
var
|
|
8171
|
-
var
|
|
8379
|
+
var DEFAULT_TITLE14 = "Voice Traces";
|
|
8380
|
+
var DEFAULT_DESCRIPTION14 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
8381
|
+
var escapeHtml19 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8382
|
+
var formatMs4 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
8172
8383
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
8173
8384
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
8174
8385
|
const sessions = (snapshot.report?.sessions ?? []).slice(0, options.limit ?? 3).map((session) => ({
|
|
8175
8386
|
...session,
|
|
8176
8387
|
detailHref: `${options.detailBasePath ?? "/traces"}/${encodeURIComponent(session.sessionId)}`,
|
|
8177
|
-
durationLabel:
|
|
8388
|
+
durationLabel: formatMs4(session.summary.callDurationMs),
|
|
8178
8389
|
incidentBundleHref: options.incidentBundleBasePath === false ? undefined : `${options.incidentBundleBasePath ?? "/voice-incidents"}/${encodeURIComponent(session.sessionId)}/markdown`,
|
|
8179
8390
|
label: `${session.summary.eventCount} events / ${session.summary.turnCount} turns`,
|
|
8180
8391
|
operationsRecordHref: options.operationsRecordBasePath === false ? undefined : `${options.operationsRecordBasePath ?? "/voice-operations"}/${encodeURIComponent(session.sessionId)}`,
|
|
@@ -8183,13 +8394,13 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
8183
8394
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
8184
8395
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
8185
8396
|
return {
|
|
8186
|
-
description: options.description ??
|
|
8397
|
+
description: options.description ?? DEFAULT_DESCRIPTION14,
|
|
8187
8398
|
error: snapshot.error,
|
|
8188
8399
|
isLoading: snapshot.isLoading,
|
|
8189
8400
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
8190
8401
|
sessions,
|
|
8191
8402
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
8192
|
-
title: options.title ??
|
|
8403
|
+
title: options.title ?? DEFAULT_TITLE14,
|
|
8193
8404
|
updatedAt: snapshot.updatedAt
|
|
8194
8405
|
};
|
|
8195
8406
|
};
|
|
@@ -8197,27 +8408,27 @@ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
|
8197
8408
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
8198
8409
|
const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => {
|
|
8199
8410
|
const supportLinks = [
|
|
8200
|
-
`<a href="${
|
|
8201
|
-
session.operationsRecordHref ? `<a href="${
|
|
8202
|
-
session.incidentBundleHref ? `<a href="${
|
|
8411
|
+
`<a href="${escapeHtml19(session.detailHref)}">Open timeline</a>`,
|
|
8412
|
+
session.operationsRecordHref ? `<a href="${escapeHtml19(session.operationsRecordHref)}">Open operations record</a>` : undefined,
|
|
8413
|
+
session.incidentBundleHref ? `<a href="${escapeHtml19(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
|
|
8203
8414
|
].filter(Boolean).join("");
|
|
8204
|
-
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${
|
|
8415
|
+
return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml19(session.status)}">
|
|
8205
8416
|
<header>
|
|
8206
|
-
<strong>${
|
|
8207
|
-
<span>${
|
|
8417
|
+
<strong>${escapeHtml19(session.sessionId)}</strong>
|
|
8418
|
+
<span>${escapeHtml19(session.status)}</span>
|
|
8208
8419
|
</header>
|
|
8209
|
-
<p>${
|
|
8420
|
+
<p>${escapeHtml19(session.label)} \xB7 ${escapeHtml19(session.durationLabel)} \xB7 ${escapeHtml19(session.providerLabel)}</p>
|
|
8210
8421
|
<p class="absolute-voice-trace-timeline__actions">${supportLinks}</p>
|
|
8211
8422
|
</article>`;
|
|
8212
8423
|
}).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
8213
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
8424
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml19(model.status)}">
|
|
8214
8425
|
<header class="absolute-voice-trace-timeline__header">
|
|
8215
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
8216
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
8426
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml19(model.title)}</span>
|
|
8427
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml19(model.label)}</strong>
|
|
8217
8428
|
</header>
|
|
8218
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
8429
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml19(model.description)}</p>
|
|
8219
8430
|
${sessions}
|
|
8220
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
8431
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml19(model.error)}</p>` : ""}
|
|
8221
8432
|
</section>`;
|
|
8222
8433
|
};
|
|
8223
8434
|
var getVoiceTraceTimelineCSS = () => `.absolute-voice-trace-timeline{border:1px solid #bad7d3;border-radius:20px;background:#f3fffb;color:#09201c;padding:18px;box-shadow:0 18px 40px rgba(9,32,28,.12);font-family:inherit}.absolute-voice-trace-timeline--error,.absolute-voice-trace-timeline--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-trace-timeline--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-trace-timeline__header,.absolute-voice-trace-timeline__session header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-trace-timeline__eyebrow{color:#17665b;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-trace-timeline__label{font-size:24px;line-height:1}.absolute-voice-trace-timeline__description,.absolute-voice-trace-timeline__session p,.absolute-voice-trace-timeline__empty{color:#35544f}.absolute-voice-trace-timeline__sessions{display:grid;gap:12px;margin-top:14px}.absolute-voice-trace-timeline__session{background:#fff;border:1px solid #cfe7e2;border-radius:16px;padding:14px}.absolute-voice-trace-timeline__session--failed{border-color:#f2a7a7}.absolute-voice-trace-timeline__session--warning{border-color:#fbbf24}.absolute-voice-trace-timeline__session p{margin:10px 0}.absolute-voice-trace-timeline__actions{display:flex;flex-wrap:wrap;gap:10px}.absolute-voice-trace-timeline__session a{color:#0f766e;font-weight:800}.absolute-voice-trace-timeline__empty{margin:14px 0 0}.absolute-voice-trace-timeline__error{color:#9f1239;font-weight:700}`;
|
|
@@ -8263,9 +8474,9 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
|
|
|
8263
8474
|
});
|
|
8264
8475
|
};
|
|
8265
8476
|
// src/client/agentSquadStatusWidget.ts
|
|
8266
|
-
var
|
|
8267
|
-
var
|
|
8268
|
-
var
|
|
8477
|
+
var DEFAULT_TITLE15 = "Voice Agent Squad";
|
|
8478
|
+
var DEFAULT_DESCRIPTION15 = "Current specialist and recent handoffs from your self-hosted voice traces.";
|
|
8479
|
+
var escapeHtml20 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
8269
8480
|
var labelFor = (current) => {
|
|
8270
8481
|
if (!current)
|
|
8271
8482
|
return "Waiting for specialist activity";
|
|
@@ -8279,37 +8490,37 @@ var labelFor = (current) => {
|
|
|
8279
8490
|
};
|
|
8280
8491
|
var createVoiceAgentSquadStatusViewModel = (snapshot, options = {}) => ({
|
|
8281
8492
|
current: snapshot.report.current,
|
|
8282
|
-
description: options.description ??
|
|
8493
|
+
description: options.description ?? DEFAULT_DESCRIPTION15,
|
|
8283
8494
|
error: snapshot.error,
|
|
8284
8495
|
isLoading: snapshot.isLoading,
|
|
8285
8496
|
label: snapshot.error ? "Unavailable" : labelFor(snapshot.report.current),
|
|
8286
8497
|
sessionCount: snapshot.report.sessionCount,
|
|
8287
8498
|
sessions: snapshot.report.sessions,
|
|
8288
|
-
title: options.title ??
|
|
8499
|
+
title: options.title ?? DEFAULT_TITLE15,
|
|
8289
8500
|
updatedAt: snapshot.updatedAt
|
|
8290
8501
|
});
|
|
8291
8502
|
var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
|
|
8292
8503
|
const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
|
|
8293
8504
|
const current = model.current;
|
|
8294
8505
|
const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
|
|
8295
|
-
<span>${
|
|
8296
|
-
<strong>${
|
|
8297
|
-
<em>${
|
|
8298
|
-
${session.summary || session.reason ? `<p>${
|
|
8506
|
+
<span>${escapeHtml20(session.sessionId)}</span>
|
|
8507
|
+
<strong>${escapeHtml20(session.targetAgentId ?? "none")}</strong>
|
|
8508
|
+
<em>${escapeHtml20(session.status)}</em>
|
|
8509
|
+
${session.summary || session.reason ? `<p>${escapeHtml20(session.summary ?? session.reason ?? "")}</p>` : ""}
|
|
8299
8510
|
</li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
|
|
8300
8511
|
return `<section class="absolute-voice-agent-squad-status">
|
|
8301
8512
|
<header>
|
|
8302
|
-
<span>${
|
|
8303
|
-
<strong>${
|
|
8513
|
+
<span>${escapeHtml20(model.title)}</span>
|
|
8514
|
+
<strong>${escapeHtml20(model.label)}</strong>
|
|
8304
8515
|
</header>
|
|
8305
|
-
<p>${
|
|
8516
|
+
<p>${escapeHtml20(model.description)}</p>
|
|
8306
8517
|
<div>
|
|
8307
|
-
<span>Session</span><strong>${
|
|
8308
|
-
<span>From</span><strong>${
|
|
8309
|
-
<span>Status</span><strong>${
|
|
8518
|
+
<span>Session</span><strong>${escapeHtml20(current?.sessionId ?? "n/a")}</strong>
|
|
8519
|
+
<span>From</span><strong>${escapeHtml20(current?.fromAgentId ?? "n/a")}</strong>
|
|
8520
|
+
<span>Status</span><strong>${escapeHtml20(current?.status ?? "idle")}</strong>
|
|
8310
8521
|
</div>
|
|
8311
8522
|
<ul>${rows}</ul>
|
|
8312
|
-
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${
|
|
8523
|
+
${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml20(model.error)}</p>` : ""}
|
|
8313
8524
|
</section>`;
|
|
8314
8525
|
};
|
|
8315
8526
|
var getVoiceAgentSquadStatusCSS = () => `.absolute-voice-agent-squad-status{border:1px solid #38bdf866;border-radius:20px;background:#0f172a;color:#f8fafc;padding:18px;font-family:inherit}.absolute-voice-agent-squad-status header{display:grid;gap:4px}.absolute-voice-agent-squad-status header span{color:#7dd3fc;font-size:12px;font-weight:900;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-agent-squad-status header strong{font-size:20px}.absolute-voice-agent-squad-status p{color:#cbd5e1}.absolute-voice-agent-squad-status div{display:grid;gap:6px;grid-template-columns:max-content 1fr;margin:14px 0}.absolute-voice-agent-squad-status div span{color:#94a3b8}.absolute-voice-agent-squad-status ul{display:grid;gap:8px;list-style:none;margin:0;padding:0}.absolute-voice-agent-squad-status li{background:#020617;border:1px solid #1e293b;border-radius:14px;padding:10px}.absolute-voice-agent-squad-status li span{color:#94a3b8;display:block;font-size:12px}.absolute-voice-agent-squad-status li strong{display:block}.absolute-voice-agent-squad-status li em{color:#7dd3fc;font-style:normal}.absolute-voice-agent-squad-status__error{color:#fecaca;font-weight:800}`;
|
|
@@ -8445,6 +8656,7 @@ export {
|
|
|
8445
8656
|
renderVoiceProviderContractsHTML,
|
|
8446
8657
|
renderVoiceProviderCapabilitiesHTML,
|
|
8447
8658
|
renderVoiceProofTrendsHTML,
|
|
8659
|
+
renderVoiceProfileComparisonHTML,
|
|
8448
8660
|
renderVoicePlatformCoverageHTML,
|
|
8449
8661
|
renderVoiceOpsStatusHTML,
|
|
8450
8662
|
renderVoiceOpsActionHistoryWidgetHTML,
|
|
@@ -8464,6 +8676,7 @@ export {
|
|
|
8464
8676
|
mountVoiceProviderContracts,
|
|
8465
8677
|
mountVoiceProviderCapabilities,
|
|
8466
8678
|
mountVoiceProofTrends,
|
|
8679
|
+
mountVoiceProfileComparison,
|
|
8467
8680
|
mountVoicePlatformCoverage,
|
|
8468
8681
|
mountVoiceOpsStatus,
|
|
8469
8682
|
mountVoiceOpsActionHistory,
|
|
@@ -8479,6 +8692,7 @@ export {
|
|
|
8479
8692
|
getVoiceProviderContractsCSS,
|
|
8480
8693
|
getVoiceProviderCapabilitiesCSS,
|
|
8481
8694
|
getVoiceProofTrendsCSS,
|
|
8695
|
+
getVoiceProfileComparisonCSS,
|
|
8482
8696
|
getVoicePlatformCoverageCSS,
|
|
8483
8697
|
getVoiceOpsStatusLabel,
|
|
8484
8698
|
getVoiceOpsStatusCSS,
|
|
@@ -8497,6 +8711,7 @@ export {
|
|
|
8497
8711
|
fetchVoiceProviderContracts,
|
|
8498
8712
|
fetchVoiceProviderCapabilities,
|
|
8499
8713
|
fetchVoiceProofTrends,
|
|
8714
|
+
fetchVoiceProfileComparison,
|
|
8500
8715
|
fetchVoicePlatformCoverage,
|
|
8501
8716
|
fetchVoiceOpsStatus,
|
|
8502
8717
|
fetchVoiceOpsActionHistory,
|
|
@@ -8512,6 +8727,7 @@ export {
|
|
|
8512
8727
|
defineVoiceProviderContractsElement,
|
|
8513
8728
|
defineVoiceProviderCapabilitiesElement,
|
|
8514
8729
|
defineVoiceProofTrendsElement,
|
|
8730
|
+
defineVoiceProfileComparisonElement,
|
|
8515
8731
|
defineVoicePlatformCoverageElement,
|
|
8516
8732
|
defineVoiceOpsStatusElement,
|
|
8517
8733
|
defineVoiceOpsActionCenterElement,
|
|
@@ -8541,6 +8757,8 @@ export {
|
|
|
8541
8757
|
createVoiceProviderCapabilitiesStore,
|
|
8542
8758
|
createVoiceProofTrendsViewModel,
|
|
8543
8759
|
createVoiceProofTrendsStore,
|
|
8760
|
+
createVoiceProfileComparisonViewModel,
|
|
8761
|
+
createVoiceProfileComparisonStore,
|
|
8544
8762
|
createVoicePlatformCoverageViewModel,
|
|
8545
8763
|
createVoicePlatformCoverageStore,
|
|
8546
8764
|
createVoiceOpsStatusViewModel,
|