@absolutejs/voice 0.0.22-beta.352 → 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.
@@ -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/readinessFailuresWidget.ts
4905
- var DEFAULT_TITLE4 = "Readiness Gate Explanations";
4906
- var DEFAULT_DESCRIPTION4 = "Structured reasons for calibrated production-readiness warnings and failures.";
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("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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 escapeHtml5 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
5081
+ var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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 ?? DEFAULT_DESCRIPTION4,
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 ?? DEFAULT_LINKS3,
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 ?? DEFAULT_TITLE4,
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--${escapeHtml5(failure.status)}">
4953
- <span>${escapeHtml5(failure.status.toUpperCase())}</span>
4954
- <strong>${escapeHtml5(failure.label)}</strong>
4955
- <p>Observed ${escapeHtml5(failure.observed)} against ${escapeHtml5(failure.thresholdLabel)} ${escapeHtml5(failure.threshold)}.</p>
4956
- <p>${escapeHtml5(failure.remediation)}</p>
4957
- <p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${escapeHtml5(failure.evidenceHref)}">Evidence</a>` : ""}${failure.sourceHref ? `<a href="${escapeHtml5(failure.sourceHref)}">Threshold source</a>` : ""}</p>
4958
- </article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ? escapeHtml5(model.error) : "No calibrated readiness gate explanations are open."}</p>`;
4959
- const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${escapeHtml5(link.href)}">${escapeHtml5(link.label)}</a>`).join("")}</p>` : "";
4960
- return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${escapeHtml5(model.status)}">
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">${escapeHtml5(model.title)}</span>
4963
- <strong class="absolute-voice-readiness-failures__label">${escapeHtml5(model.label)}</strong>
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">${escapeHtml5(model.description)}</p>
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">${escapeHtml5(model.error)}</p>` : ""}
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 DEFAULT_TITLE5 = "Voice Ops Action Center";
5009
- var DEFAULT_DESCRIPTION5 = "Run production voice proofs and operator actions from one primitive panel.";
5010
- var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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 ?? DEFAULT_DESCRIPTION5,
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 ?? DEFAULT_TITLE5
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="${escapeHtml6(action.id)}"${action.disabled ? " disabled" : ""}>
5033
- ${escapeHtml6(action.isRunning ? "Working..." : action.label)}
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--${escapeHtml6(model.status)}">
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">${escapeHtml6(model.title)}</span>
5038
- <strong class="absolute-voice-ops-action-center__label">${escapeHtml6(model.label)}</strong>
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">${escapeHtml6(model.description)}</p>
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">${escapeHtml6(model.lastResultLabel)}</p>
5043
- ${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml6(model.error)}</p>` : ""}
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 escapeHtml7 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
5814
+ var escapeHtml8 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
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>${escapeHtml7(String(offset))}</td>`,
5925
- `<td>${escapeHtml7(event.type)}</td>`,
5926
- `<td>${escapeHtml7(event.turnId ?? "")}</td>`,
5927
- `<td><code>${escapeHtml7(JSON.stringify(event.payload))}</code></td>`,
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>${escapeHtml7(options.title ?? "Voice Trace")}</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>${escapeHtml7(options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim())}</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>${escapeHtml7(markdown)}</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 escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6492
+ var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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="${escapeHtml8(action)}"${disabled ? " disabled" : ""}>${escapeHtml8(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
6334
- const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml8(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml8(snapshot.lastResult.action)}. Control: ${escapeHtml8(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
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>${escapeHtml8(options.title ?? "Live Ops")}</span>
6338
- <strong>${escapeHtml8(sessionId || "No active session")}</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">${escapeHtml8(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
6341
- <label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml8(options.defaultAssignee ?? "operator")}" /></label>
6342
- <label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml8(options.defaultTag ?? "live-ops")}" /></label>
6343
- <label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml8(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
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 escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6600
+ var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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>${escapeHtml9(entry.actionId)}</span><strong>${escapeHtml9(entry.ok ? "Success" : "Failed")}</strong><small>${escapeHtml9(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</small></li>`).join("");
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>${escapeHtml9(options.title ?? "Action History")}</strong></header>
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">${escapeHtml9(snapshot.error)}</p>` : ""}
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 DEFAULT_TITLE6 = "Voice Delivery Runtime";
6461
- var DEFAULT_DESCRIPTION6 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
6462
- var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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 ?? DEFAULT_DESCRIPTION6,
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 ?? DEFAULT_TITLE6,
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--${escapeHtml10(surface.status)}">
6512
- <span>${escapeHtml10(surface.label)}</span>
6513
- <strong>${escapeHtml10(surface.detail)}</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 &middot; ${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">${escapeHtml10(model.actionError)}</p>` : "";
6521
- return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml10(model.status)}">
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">${escapeHtml10(model.title)}</span>
6524
- <strong class="absolute-voice-delivery-runtime__label">${escapeHtml10(model.label)}</strong>
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">${escapeHtml10(model.description)}</p>
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">${escapeHtml10(model.error)}</p>` : ""}
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,11 +6833,11 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
6663
6833
  };
6664
6834
  };
6665
6835
  // src/client/routingStatusWidget.ts
6666
- var DEFAULT_TITLE7 = "Voice Routing";
6667
- var DEFAULT_DESCRIPTION7 = "Latest provider routing decision from the self-hosted trace store.";
6668
- var escapeHtml11 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
6669
6839
  var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
6670
- var formatProviderRoutes = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
6840
+ var formatProviderRoutes2 = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
6671
6841
  var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
6672
6842
  var formatFallbackPath = (decision) => {
6673
6843
  const provider = formatValue(decision.provider, "Unknown");
@@ -6724,7 +6894,7 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
6724
6894
  },
6725
6895
  {
6726
6896
  label: "Default routes",
6727
- value: formatProviderRoutes(decision.providerRoutes)
6897
+ value: formatProviderRoutes2(decision.providerRoutes)
6728
6898
  },
6729
6899
  {
6730
6900
  label: "Latency budget",
@@ -6734,35 +6904,35 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
6734
6904
  return {
6735
6905
  activeStack,
6736
6906
  decision,
6737
- description: options.description ?? DEFAULT_DESCRIPTION7,
6907
+ description: options.description ?? DEFAULT_DESCRIPTION8,
6738
6908
  error: snapshot.error,
6739
6909
  isLoading: snapshot.isLoading,
6740
6910
  label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
6741
6911
  rows,
6742
6912
  status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
6743
- title: options.title ?? DEFAULT_TITLE7,
6913
+ title: options.title ?? DEFAULT_TITLE8,
6744
6914
  updatedAt: snapshot.updatedAt
6745
6915
  };
6746
6916
  };
6747
6917
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
6748
6918
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
6749
6919
  const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
6750
- <span>${escapeHtml11(item.label)}</span>
6751
- <strong>${escapeHtml11(item.value)}</strong>
6920
+ <span>${escapeHtml12(item.label)}</span>
6921
+ <strong>${escapeHtml12(item.value)}</strong>
6752
6922
  </div>`).join("")}</div>` : "";
6753
6923
  const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
6754
- <span>${escapeHtml11(row.label)}</span>
6755
- <strong>${escapeHtml11(row.value)}</strong>
6924
+ <span>${escapeHtml12(row.label)}</span>
6925
+ <strong>${escapeHtml12(row.value)}</strong>
6756
6926
  </div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
6757
- return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml11(model.status)}">
6927
+ return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml12(model.status)}">
6758
6928
  <header class="absolute-voice-routing-status__header">
6759
- <span class="absolute-voice-routing-status__eyebrow">${escapeHtml11(model.title)}</span>
6760
- <strong class="absolute-voice-routing-status__label">${escapeHtml11(model.label)}</strong>
6929
+ <span class="absolute-voice-routing-status__eyebrow">${escapeHtml12(model.title)}</span>
6930
+ <strong class="absolute-voice-routing-status__label">${escapeHtml12(model.label)}</strong>
6761
6931
  </header>
6762
- <p class="absolute-voice-routing-status__description">${escapeHtml11(model.description)}</p>
6932
+ <p class="absolute-voice-routing-status__description">${escapeHtml12(model.description)}</p>
6763
6933
  ${activeStack}
6764
6934
  ${rows}
6765
- ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml11(model.error)}</p>` : ""}
6935
+ ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml12(model.error)}</p>` : ""}
6766
6936
  </section>`;
6767
6937
  };
6768
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}}`;
@@ -7561,7 +7731,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
7561
7731
  };
7562
7732
  };
7563
7733
  // src/client/providerSimulationControlsWidget.ts
7564
- var escapeHtml12 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7734
+ var escapeHtml13 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7565
7735
  var formatKind = (kind) => (kind ?? "stt").toUpperCase();
7566
7736
  var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
7567
7737
  const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
@@ -7581,18 +7751,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
7581
7751
  };
7582
7752
  var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
7583
7753
  const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
7584
- const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml12(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml12(provider.provider)} ${escapeHtml12(formatKind(options.kind))} failure</button>`).join("");
7585
- const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml12(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml12(provider.provider)} recovered</button>`).join("");
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("");
7586
7756
  return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
7587
7757
  <header class="absolute-voice-provider-simulation__header">
7588
- <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml12(model.title)}</span>
7589
- <strong class="absolute-voice-provider-simulation__label">${escapeHtml12(model.label)}</strong>
7758
+ <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml13(model.title)}</span>
7759
+ <strong class="absolute-voice-provider-simulation__label">${escapeHtml13(model.label)}</strong>
7590
7760
  </header>
7591
- <p class="absolute-voice-provider-simulation__description">${escapeHtml12(model.description)}</p>
7592
- ${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml12(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
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>`}
7593
7763
  <div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
7594
- ${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml12(snapshot.error)}</p>` : ""}
7595
- ${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml12(model.resultText)}</pre>` : ""}
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>` : ""}
7596
7766
  </section>`;
7597
7767
  };
7598
7768
  var bindVoiceProviderSimulationControls = (element, store) => {
@@ -7657,9 +7827,9 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
7657
7827
  });
7658
7828
  };
7659
7829
  // src/client/providerStatusWidget.ts
7660
- var DEFAULT_TITLE8 = "Voice Providers";
7661
- var DEFAULT_DESCRIPTION8 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
7662
- var escapeHtml13 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7663
7833
  var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
7664
7834
  var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
7665
7835
  var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
@@ -7703,37 +7873,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
7703
7873
  const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
7704
7874
  const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
7705
7875
  return {
7706
- description: options.description ?? DEFAULT_DESCRIPTION8,
7876
+ description: options.description ?? DEFAULT_DESCRIPTION9,
7707
7877
  error: snapshot.error,
7708
7878
  isLoading: snapshot.isLoading,
7709
7879
  label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
7710
7880
  providers,
7711
7881
  status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
7712
- title: options.title ?? DEFAULT_TITLE8,
7882
+ title: options.title ?? DEFAULT_TITLE9,
7713
7883
  updatedAt: snapshot.updatedAt
7714
7884
  };
7715
7885
  };
7716
7886
  var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
7717
7887
  const model = createVoiceProviderStatusViewModel(snapshot, options);
7718
- 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--${escapeHtml13(provider.status)}">
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)}">
7719
7889
  <header>
7720
- <strong>${escapeHtml13(provider.label)}</strong>
7721
- <span>${escapeHtml13(formatStatus2(provider.status))}</span>
7890
+ <strong>${escapeHtml14(provider.label)}</strong>
7891
+ <span>${escapeHtml14(formatStatus2(provider.status))}</span>
7722
7892
  </header>
7723
- <p>${escapeHtml13(provider.detail)}</p>
7893
+ <p>${escapeHtml14(provider.detail)}</p>
7724
7894
  <dl>${provider.rows.map((row) => `<div>
7725
- <dt>${escapeHtml13(row.label)}</dt>
7726
- <dd>${escapeHtml13(row.value)}</dd>
7895
+ <dt>${escapeHtml14(row.label)}</dt>
7896
+ <dd>${escapeHtml14(row.value)}</dd>
7727
7897
  </div>`).join("")}</dl>
7728
7898
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
7729
- return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml13(model.status)}">
7899
+ return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml14(model.status)}">
7730
7900
  <header class="absolute-voice-provider-status__header">
7731
- <span class="absolute-voice-provider-status__eyebrow">${escapeHtml13(model.title)}</span>
7732
- <strong class="absolute-voice-provider-status__label">${escapeHtml13(model.label)}</strong>
7901
+ <span class="absolute-voice-provider-status__eyebrow">${escapeHtml14(model.title)}</span>
7902
+ <strong class="absolute-voice-provider-status__label">${escapeHtml14(model.label)}</strong>
7733
7903
  </header>
7734
- <p class="absolute-voice-provider-status__description">${escapeHtml13(model.description)}</p>
7904
+ <p class="absolute-voice-provider-status__description">${escapeHtml14(model.description)}</p>
7735
7905
  ${providers}
7736
- ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml13(model.error)}</p>` : ""}
7906
+ ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml14(model.error)}</p>` : ""}
7737
7907
  </section>`;
7738
7908
  };
7739
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}`;
@@ -7774,9 +7944,9 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
7774
7944
  });
7775
7945
  };
7776
7946
  // src/client/providerCapabilitiesWidget.ts
7777
- var DEFAULT_TITLE9 = "Provider Capabilities";
7778
- var DEFAULT_DESCRIPTION9 = "Configured, selected, and healthy voice providers for this deployment.";
7779
- var escapeHtml14 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7780
7950
  var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
7781
7951
  var formatKind2 = (kind) => kind.toUpperCase();
7782
7952
  var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
@@ -7820,36 +7990,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
7820
7990
  const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
7821
7991
  return {
7822
7992
  capabilities,
7823
- description: options.description ?? DEFAULT_DESCRIPTION9,
7993
+ description: options.description ?? DEFAULT_DESCRIPTION10,
7824
7994
  error: snapshot.error,
7825
7995
  isLoading: snapshot.isLoading,
7826
7996
  label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
7827
7997
  status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
7828
- title: options.title ?? DEFAULT_TITLE9,
7998
+ title: options.title ?? DEFAULT_TITLE10,
7829
7999
  updatedAt: snapshot.updatedAt
7830
8000
  };
7831
8001
  };
7832
8002
  var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
7833
8003
  const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
7834
- 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--${escapeHtml14(capability.status)}">
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)}">
7835
8005
  <header>
7836
- <strong>${escapeHtml14(capability.label)}</strong>
7837
- <span>${escapeHtml14(formatStatus3(capability.status))}</span>
8006
+ <strong>${escapeHtml15(capability.label)}</strong>
8007
+ <span>${escapeHtml15(formatStatus3(capability.status))}</span>
7838
8008
  </header>
7839
- <p>${escapeHtml14(capability.detail)}</p>
8009
+ <p>${escapeHtml15(capability.detail)}</p>
7840
8010
  <dl>${capability.rows.map((row) => `<div>
7841
- <dt>${escapeHtml14(row.label)}</dt>
7842
- <dd>${escapeHtml14(row.value)}</dd>
8011
+ <dt>${escapeHtml15(row.label)}</dt>
8012
+ <dd>${escapeHtml15(row.value)}</dd>
7843
8013
  </div>`).join("")}</dl>
7844
8014
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
7845
- return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml14(model.status)}">
8015
+ return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml15(model.status)}">
7846
8016
  <header class="absolute-voice-provider-capabilities__header">
7847
- <span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml14(model.title)}</span>
7848
- <strong class="absolute-voice-provider-capabilities__label">${escapeHtml14(model.label)}</strong>
8017
+ <span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml15(model.title)}</span>
8018
+ <strong class="absolute-voice-provider-capabilities__label">${escapeHtml15(model.label)}</strong>
7849
8019
  </header>
7850
- <p class="absolute-voice-provider-capabilities__description">${escapeHtml14(model.description)}</p>
8020
+ <p class="absolute-voice-provider-capabilities__description">${escapeHtml15(model.description)}</p>
7851
8021
  ${capabilities}
7852
- ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml14(model.error)}</p>` : ""}
8022
+ ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml15(model.error)}</p>` : ""}
7853
8023
  </section>`;
7854
8024
  };
7855
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}`;
@@ -7890,9 +8060,9 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
7890
8060
  });
7891
8061
  };
7892
8062
  // src/client/providerContractsWidget.ts
7893
- var DEFAULT_TITLE10 = "Provider Contracts";
7894
- var DEFAULT_DESCRIPTION10 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
7895
- var escapeHtml15 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7896
8066
  var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
7897
8067
  var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
7898
8068
  var contractDetail = (row) => {
@@ -7924,38 +8094,38 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
7924
8094
  }));
7925
8095
  const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
7926
8096
  return {
7927
- description: options.description ?? DEFAULT_DESCRIPTION10,
8097
+ description: options.description ?? DEFAULT_DESCRIPTION11,
7928
8098
  error: snapshot.error,
7929
8099
  isLoading: snapshot.isLoading,
7930
8100
  label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
7931
8101
  rows,
7932
8102
  status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
7933
- title: options.title ?? DEFAULT_TITLE10,
8103
+ title: options.title ?? DEFAULT_TITLE11,
7934
8104
  updatedAt: snapshot.updatedAt
7935
8105
  };
7936
8106
  };
7937
8107
  var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
7938
8108
  const model = createVoiceProviderContractsViewModel(snapshot, options);
7939
- 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--${escapeHtml15(row.status)}">
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)}">
7940
8110
  <header>
7941
- <strong>${escapeHtml15(row.label)}</strong>
7942
- <span>${escapeHtml15(formatStatus4(row.status))}</span>
8111
+ <strong>${escapeHtml16(row.label)}</strong>
8112
+ <span>${escapeHtml16(formatStatus4(row.status))}</span>
7943
8113
  </header>
7944
- <p>${escapeHtml15(row.detail)}</p>
7945
- ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml15(remediation.href)}">${escapeHtml15(remediation.label)}</a>` : `<strong>${escapeHtml15(remediation.label)}</strong>`}<span>${escapeHtml15(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
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>` : ""}
7946
8116
  <dl>${row.rows.map((item) => `<div>
7947
- <dt>${escapeHtml15(item.label)}</dt>
7948
- <dd>${escapeHtml15(item.value)}</dd>
8117
+ <dt>${escapeHtml16(item.label)}</dt>
8118
+ <dd>${escapeHtml16(item.value)}</dd>
7949
8119
  </div>`).join("")}</dl>
7950
8120
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
7951
- return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml15(model.status)}">
8121
+ return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml16(model.status)}">
7952
8122
  <header class="absolute-voice-provider-contracts__header">
7953
- <span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml15(model.title)}</span>
7954
- <strong class="absolute-voice-provider-contracts__label">${escapeHtml15(model.label)}</strong>
8123
+ <span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml16(model.title)}</span>
8124
+ <strong class="absolute-voice-provider-contracts__label">${escapeHtml16(model.label)}</strong>
7955
8125
  </header>
7956
- <p class="absolute-voice-provider-contracts__description">${escapeHtml15(model.description)}</p>
8126
+ <p class="absolute-voice-provider-contracts__description">${escapeHtml16(model.description)}</p>
7957
8127
  ${rows}
7958
- ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml15(model.error)}</p>` : ""}
8128
+ ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml16(model.error)}</p>` : ""}
7959
8129
  </section>`;
7960
8130
  };
7961
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}`;
@@ -7996,9 +8166,9 @@ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-co
7996
8166
  });
7997
8167
  };
7998
8168
  // src/client/turnQualityWidget.ts
7999
- var DEFAULT_TITLE11 = "Turn Quality";
8000
- var DEFAULT_DESCRIPTION11 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
8001
- var escapeHtml16 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8002
8172
  var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
8003
8173
  var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
8004
8174
  var getTurnDetail = (turn) => {
@@ -8036,37 +8206,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
8036
8206
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
8037
8207
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
8038
8208
  return {
8039
- description: options.description ?? DEFAULT_DESCRIPTION11,
8209
+ description: options.description ?? DEFAULT_DESCRIPTION12,
8040
8210
  error: snapshot.error,
8041
8211
  isLoading: snapshot.isLoading,
8042
8212
  label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
8043
8213
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
8044
- title: options.title ?? DEFAULT_TITLE11,
8214
+ title: options.title ?? DEFAULT_TITLE12,
8045
8215
  turns,
8046
8216
  updatedAt: snapshot.updatedAt
8047
8217
  };
8048
8218
  };
8049
8219
  var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
8050
8220
  const model = createVoiceTurnQualityViewModel(snapshot, options);
8051
- 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--${escapeHtml16(turn.status)}">
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)}">
8052
8222
  <header>
8053
- <strong>${escapeHtml16(turn.label)}</strong>
8054
- <span>${escapeHtml16(turn.status)}</span>
8223
+ <strong>${escapeHtml17(turn.label)}</strong>
8224
+ <span>${escapeHtml17(turn.status)}</span>
8055
8225
  </header>
8056
- <p>${escapeHtml16(turn.detail)}</p>
8226
+ <p>${escapeHtml17(turn.detail)}</p>
8057
8227
  <dl>${turn.rows.map((row) => `<div>
8058
- <dt>${escapeHtml16(row.label)}</dt>
8059
- <dd>${escapeHtml16(row.value)}</dd>
8228
+ <dt>${escapeHtml17(row.label)}</dt>
8229
+ <dd>${escapeHtml17(row.value)}</dd>
8060
8230
  </div>`).join("")}</dl>
8061
8231
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
8062
- return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml16(model.status)}">
8232
+ return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml17(model.status)}">
8063
8233
  <header class="absolute-voice-turn-quality__header">
8064
- <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml16(model.title)}</span>
8065
- <strong class="absolute-voice-turn-quality__label">${escapeHtml16(model.label)}</strong>
8234
+ <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml17(model.title)}</span>
8235
+ <strong class="absolute-voice-turn-quality__label">${escapeHtml17(model.label)}</strong>
8066
8236
  </header>
8067
- <p class="absolute-voice-turn-quality__description">${escapeHtml16(model.description)}</p>
8237
+ <p class="absolute-voice-turn-quality__description">${escapeHtml17(model.description)}</p>
8068
8238
  ${turns}
8069
- ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml16(model.error)}</p>` : ""}
8239
+ ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml17(model.error)}</p>` : ""}
8070
8240
  </section>`;
8071
8241
  };
8072
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}`;
@@ -8107,56 +8277,56 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
8107
8277
  });
8108
8278
  };
8109
8279
  // src/client/turnLatencyWidget.ts
8110
- var DEFAULT_TITLE12 = "Turn Latency";
8111
- var DEFAULT_DESCRIPTION12 = "Per-turn timing from first transcript to commit and assistant response start.";
8280
+ var DEFAULT_TITLE13 = "Turn Latency";
8281
+ var DEFAULT_DESCRIPTION13 = "Per-turn timing from first transcript to commit and assistant response start.";
8112
8282
  var DEFAULT_PROOF_LABEL = "Run latency proof";
8113
- var escapeHtml17 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8114
- var formatMs2 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
8283
+ var escapeHtml18 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8284
+ var formatMs3 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
8115
8285
  var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
8116
8286
  const turns = (snapshot.report?.turns ?? []).map((turn) => ({
8117
8287
  ...turn,
8118
8288
  label: turn.text || "Empty turn",
8119
8289
  rows: turn.stages.map((stage) => ({
8120
8290
  label: stage.label,
8121
- value: formatMs2(stage.valueMs)
8291
+ value: formatMs3(stage.valueMs)
8122
8292
  }))
8123
8293
  }));
8124
8294
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
8125
8295
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
8126
8296
  return {
8127
- description: options.description ?? DEFAULT_DESCRIPTION12,
8297
+ description: options.description ?? DEFAULT_DESCRIPTION13,
8128
8298
  error: snapshot.error,
8129
8299
  isLoading: snapshot.isLoading,
8130
- label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs2(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
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",
8131
8301
  proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
8132
8302
  showProofAction: Boolean(options.proofPath),
8133
8303
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
8134
- title: options.title ?? DEFAULT_TITLE12,
8304
+ title: options.title ?? DEFAULT_TITLE13,
8135
8305
  turns,
8136
8306
  updatedAt: snapshot.updatedAt
8137
8307
  };
8138
8308
  };
8139
8309
  var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
8140
8310
  const model = createVoiceTurnLatencyViewModel(snapshot, options);
8141
- 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--${escapeHtml17(turn.status)}">
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)}">
8142
8312
  <header>
8143
- <strong>${escapeHtml17(turn.label)}</strong>
8144
- <span>${escapeHtml17(turn.status)}</span>
8313
+ <strong>${escapeHtml18(turn.label)}</strong>
8314
+ <span>${escapeHtml18(turn.status)}</span>
8145
8315
  </header>
8146
8316
  <dl>${turn.rows.map((row) => `<div>
8147
- <dt>${escapeHtml17(row.label)}</dt>
8148
- <dd>${escapeHtml17(row.value)}</dd>
8317
+ <dt>${escapeHtml18(row.label)}</dt>
8318
+ <dd>${escapeHtml18(row.value)}</dd>
8149
8319
  </div>`).join("")}</dl>
8150
8320
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
8151
- return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml17(model.status)}">
8321
+ return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml18(model.status)}">
8152
8322
  <header class="absolute-voice-turn-latency__header">
8153
- <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml17(model.title)}</span>
8154
- <strong class="absolute-voice-turn-latency__label">${escapeHtml17(model.label)}</strong>
8323
+ <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml18(model.title)}</span>
8324
+ <strong class="absolute-voice-turn-latency__label">${escapeHtml18(model.label)}</strong>
8155
8325
  </header>
8156
- <p class="absolute-voice-turn-latency__description">${escapeHtml17(model.description)}</p>
8157
- ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml17(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</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>` : ""}
8158
8328
  ${turns}
8159
- ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml17(model.error)}</p>` : ""}
8329
+ ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml18(model.error)}</p>` : ""}
8160
8330
  </section>`;
8161
8331
  };
8162
8332
  var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
@@ -8206,16 +8376,16 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
8206
8376
  });
8207
8377
  };
8208
8378
  // src/client/traceTimelineWidget.ts
8209
- var DEFAULT_TITLE13 = "Voice Traces";
8210
- var DEFAULT_DESCRIPTION13 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
8211
- var escapeHtml18 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8212
- var formatMs3 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
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("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8382
+ var formatMs4 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
8213
8383
  var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
8214
8384
  var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
8215
8385
  const sessions = (snapshot.report?.sessions ?? []).slice(0, options.limit ?? 3).map((session) => ({
8216
8386
  ...session,
8217
8387
  detailHref: `${options.detailBasePath ?? "/traces"}/${encodeURIComponent(session.sessionId)}`,
8218
- durationLabel: formatMs3(session.summary.callDurationMs),
8388
+ durationLabel: formatMs4(session.summary.callDurationMs),
8219
8389
  incidentBundleHref: options.incidentBundleBasePath === false ? undefined : `${options.incidentBundleBasePath ?? "/voice-incidents"}/${encodeURIComponent(session.sessionId)}/markdown`,
8220
8390
  label: `${session.summary.eventCount} events / ${session.summary.turnCount} turns`,
8221
8391
  operationsRecordHref: options.operationsRecordBasePath === false ? undefined : `${options.operationsRecordBasePath ?? "/voice-operations"}/${encodeURIComponent(session.sessionId)}`,
@@ -8224,13 +8394,13 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
8224
8394
  const failed = sessions.filter((session) => session.status === "failed").length;
8225
8395
  const warnings = sessions.filter((session) => session.status === "warning").length;
8226
8396
  return {
8227
- description: options.description ?? DEFAULT_DESCRIPTION13,
8397
+ description: options.description ?? DEFAULT_DESCRIPTION14,
8228
8398
  error: snapshot.error,
8229
8399
  isLoading: snapshot.isLoading,
8230
8400
  label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
8231
8401
  sessions,
8232
8402
  status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
8233
- title: options.title ?? DEFAULT_TITLE13,
8403
+ title: options.title ?? DEFAULT_TITLE14,
8234
8404
  updatedAt: snapshot.updatedAt
8235
8405
  };
8236
8406
  };
@@ -8238,27 +8408,27 @@ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
8238
8408
  const model = createVoiceTraceTimelineViewModel(snapshot, options);
8239
8409
  const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => {
8240
8410
  const supportLinks = [
8241
- `<a href="${escapeHtml18(session.detailHref)}">Open timeline</a>`,
8242
- session.operationsRecordHref ? `<a href="${escapeHtml18(session.operationsRecordHref)}">Open operations record</a>` : undefined,
8243
- session.incidentBundleHref ? `<a href="${escapeHtml18(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
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
8244
8414
  ].filter(Boolean).join("");
8245
- return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml18(session.status)}">
8415
+ return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml19(session.status)}">
8246
8416
  <header>
8247
- <strong>${escapeHtml18(session.sessionId)}</strong>
8248
- <span>${escapeHtml18(session.status)}</span>
8417
+ <strong>${escapeHtml19(session.sessionId)}</strong>
8418
+ <span>${escapeHtml19(session.status)}</span>
8249
8419
  </header>
8250
- <p>${escapeHtml18(session.label)} \xB7 ${escapeHtml18(session.durationLabel)} \xB7 ${escapeHtml18(session.providerLabel)}</p>
8420
+ <p>${escapeHtml19(session.label)} \xB7 ${escapeHtml19(session.durationLabel)} \xB7 ${escapeHtml19(session.providerLabel)}</p>
8251
8421
  <p class="absolute-voice-trace-timeline__actions">${supportLinks}</p>
8252
8422
  </article>`;
8253
8423
  }).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
8254
- return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml18(model.status)}">
8424
+ return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml19(model.status)}">
8255
8425
  <header class="absolute-voice-trace-timeline__header">
8256
- <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml18(model.title)}</span>
8257
- <strong class="absolute-voice-trace-timeline__label">${escapeHtml18(model.label)}</strong>
8426
+ <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml19(model.title)}</span>
8427
+ <strong class="absolute-voice-trace-timeline__label">${escapeHtml19(model.label)}</strong>
8258
8428
  </header>
8259
- <p class="absolute-voice-trace-timeline__description">${escapeHtml18(model.description)}</p>
8429
+ <p class="absolute-voice-trace-timeline__description">${escapeHtml19(model.description)}</p>
8260
8430
  ${sessions}
8261
- ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml18(model.error)}</p>` : ""}
8431
+ ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml19(model.error)}</p>` : ""}
8262
8432
  </section>`;
8263
8433
  };
8264
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}`;
@@ -8304,9 +8474,9 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
8304
8474
  });
8305
8475
  };
8306
8476
  // src/client/agentSquadStatusWidget.ts
8307
- var DEFAULT_TITLE14 = "Voice Agent Squad";
8308
- var DEFAULT_DESCRIPTION14 = "Current specialist and recent handoffs from your self-hosted voice traces.";
8309
- var escapeHtml19 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
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("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8310
8480
  var labelFor = (current) => {
8311
8481
  if (!current)
8312
8482
  return "Waiting for specialist activity";
@@ -8320,37 +8490,37 @@ var labelFor = (current) => {
8320
8490
  };
8321
8491
  var createVoiceAgentSquadStatusViewModel = (snapshot, options = {}) => ({
8322
8492
  current: snapshot.report.current,
8323
- description: options.description ?? DEFAULT_DESCRIPTION14,
8493
+ description: options.description ?? DEFAULT_DESCRIPTION15,
8324
8494
  error: snapshot.error,
8325
8495
  isLoading: snapshot.isLoading,
8326
8496
  label: snapshot.error ? "Unavailable" : labelFor(snapshot.report.current),
8327
8497
  sessionCount: snapshot.report.sessionCount,
8328
8498
  sessions: snapshot.report.sessions,
8329
- title: options.title ?? DEFAULT_TITLE14,
8499
+ title: options.title ?? DEFAULT_TITLE15,
8330
8500
  updatedAt: snapshot.updatedAt
8331
8501
  });
8332
8502
  var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
8333
8503
  const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
8334
8504
  const current = model.current;
8335
8505
  const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
8336
- <span>${escapeHtml19(session.sessionId)}</span>
8337
- <strong>${escapeHtml19(session.targetAgentId ?? "none")}</strong>
8338
- <em>${escapeHtml19(session.status)}</em>
8339
- ${session.summary || session.reason ? `<p>${escapeHtml19(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>` : ""}
8340
8510
  </li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
8341
8511
  return `<section class="absolute-voice-agent-squad-status">
8342
8512
  <header>
8343
- <span>${escapeHtml19(model.title)}</span>
8344
- <strong>${escapeHtml19(model.label)}</strong>
8513
+ <span>${escapeHtml20(model.title)}</span>
8514
+ <strong>${escapeHtml20(model.label)}</strong>
8345
8515
  </header>
8346
- <p>${escapeHtml19(model.description)}</p>
8516
+ <p>${escapeHtml20(model.description)}</p>
8347
8517
  <div>
8348
- <span>Session</span><strong>${escapeHtml19(current?.sessionId ?? "n/a")}</strong>
8349
- <span>From</span><strong>${escapeHtml19(current?.fromAgentId ?? "n/a")}</strong>
8350
- <span>Status</span><strong>${escapeHtml19(current?.status ?? "idle")}</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>
8351
8521
  </div>
8352
8522
  <ul>${rows}</ul>
8353
- ${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml19(model.error)}</p>` : ""}
8523
+ ${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml20(model.error)}</p>` : ""}
8354
8524
  </section>`;
8355
8525
  };
8356
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}`;
@@ -8486,6 +8656,7 @@ export {
8486
8656
  renderVoiceProviderContractsHTML,
8487
8657
  renderVoiceProviderCapabilitiesHTML,
8488
8658
  renderVoiceProofTrendsHTML,
8659
+ renderVoiceProfileComparisonHTML,
8489
8660
  renderVoicePlatformCoverageHTML,
8490
8661
  renderVoiceOpsStatusHTML,
8491
8662
  renderVoiceOpsActionHistoryWidgetHTML,
@@ -8505,6 +8676,7 @@ export {
8505
8676
  mountVoiceProviderContracts,
8506
8677
  mountVoiceProviderCapabilities,
8507
8678
  mountVoiceProofTrends,
8679
+ mountVoiceProfileComparison,
8508
8680
  mountVoicePlatformCoverage,
8509
8681
  mountVoiceOpsStatus,
8510
8682
  mountVoiceOpsActionHistory,
@@ -8520,6 +8692,7 @@ export {
8520
8692
  getVoiceProviderContractsCSS,
8521
8693
  getVoiceProviderCapabilitiesCSS,
8522
8694
  getVoiceProofTrendsCSS,
8695
+ getVoiceProfileComparisonCSS,
8523
8696
  getVoicePlatformCoverageCSS,
8524
8697
  getVoiceOpsStatusLabel,
8525
8698
  getVoiceOpsStatusCSS,
@@ -8538,6 +8711,7 @@ export {
8538
8711
  fetchVoiceProviderContracts,
8539
8712
  fetchVoiceProviderCapabilities,
8540
8713
  fetchVoiceProofTrends,
8714
+ fetchVoiceProfileComparison,
8541
8715
  fetchVoicePlatformCoverage,
8542
8716
  fetchVoiceOpsStatus,
8543
8717
  fetchVoiceOpsActionHistory,
@@ -8553,6 +8727,7 @@ export {
8553
8727
  defineVoiceProviderContractsElement,
8554
8728
  defineVoiceProviderCapabilitiesElement,
8555
8729
  defineVoiceProofTrendsElement,
8730
+ defineVoiceProfileComparisonElement,
8556
8731
  defineVoicePlatformCoverageElement,
8557
8732
  defineVoiceOpsStatusElement,
8558
8733
  defineVoiceOpsActionCenterElement,
@@ -8582,6 +8757,8 @@ export {
8582
8757
  createVoiceProviderCapabilitiesStore,
8583
8758
  createVoiceProofTrendsViewModel,
8584
8759
  createVoiceProofTrendsStore,
8760
+ createVoiceProfileComparisonViewModel,
8761
+ createVoiceProfileComparisonStore,
8585
8762
  createVoicePlatformCoverageViewModel,
8586
8763
  createVoicePlatformCoverageStore,
8587
8764
  createVoiceOpsStatusViewModel,