@absolutejs/voice 0.0.22-beta.403 → 0.0.22-beta.405

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.
@@ -3066,11 +3066,185 @@ var createVoiceSessionSnapshotStore = (path, options = {}) => {
3066
3066
  }
3067
3067
  };
3068
3068
  };
3069
+ // src/client/callDebugger.ts
3070
+ var fetchVoiceCallDebugger = async (path, options = {}) => {
3071
+ const fetchImpl = options.fetch ?? globalThis.fetch;
3072
+ const response = await fetchImpl(path);
3073
+ if (!response.ok) {
3074
+ throw new Error(`Voice call debugger failed: HTTP ${response.status}`);
3075
+ }
3076
+ return await response.json();
3077
+ };
3078
+ var createVoiceCallDebuggerStore = (path, options = {}) => {
3079
+ const listeners = new Set;
3080
+ let closed = false;
3081
+ let timer;
3082
+ let snapshot = {
3083
+ error: null,
3084
+ isLoading: false
3085
+ };
3086
+ const emit = () => {
3087
+ for (const listener of listeners) {
3088
+ listener();
3089
+ }
3090
+ };
3091
+ const refresh = async () => {
3092
+ if (closed) {
3093
+ return snapshot.report;
3094
+ }
3095
+ snapshot = { ...snapshot, error: null, isLoading: true };
3096
+ emit();
3097
+ try {
3098
+ const report = await fetchVoiceCallDebugger(path, options);
3099
+ snapshot = {
3100
+ error: null,
3101
+ isLoading: false,
3102
+ report,
3103
+ updatedAt: Date.now()
3104
+ };
3105
+ emit();
3106
+ return report;
3107
+ } catch (error) {
3108
+ snapshot = {
3109
+ ...snapshot,
3110
+ error: error instanceof Error ? error.message : String(error),
3111
+ isLoading: false
3112
+ };
3113
+ emit();
3114
+ throw error;
3115
+ }
3116
+ };
3117
+ const close = () => {
3118
+ closed = true;
3119
+ if (timer) {
3120
+ clearInterval(timer);
3121
+ timer = undefined;
3122
+ }
3123
+ listeners.clear();
3124
+ };
3125
+ if (options.intervalMs && options.intervalMs > 0) {
3126
+ timer = setInterval(() => {
3127
+ refresh().catch(() => {});
3128
+ }, options.intervalMs);
3129
+ }
3130
+ return {
3131
+ close,
3132
+ getServerSnapshot: () => snapshot,
3133
+ getSnapshot: () => snapshot,
3134
+ refresh,
3135
+ subscribe: (listener) => {
3136
+ listeners.add(listener);
3137
+ return () => {
3138
+ listeners.delete(listener);
3139
+ };
3140
+ }
3141
+ };
3142
+ };
3143
+ // src/client/callDebuggerWidget.ts
3144
+ var DEFAULT_TITLE = "Call Debugger";
3145
+ var DEFAULT_DESCRIPTION = "Open the latest call artifact with snapshot, operations record, failure replay, provider path, transcript, and incident markdown.";
3146
+ var DEFAULT_LINK_LABEL = "Open debugger";
3147
+ var escapeHtml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3148
+ var defaultHref = (path, report) => {
3149
+ if (path.startsWith("/api/voice-call-debugger/")) {
3150
+ return path.replace("/api/voice-call-debugger/", "/voice-call-debugger/");
3151
+ }
3152
+ return report ? `/voice-call-debugger/${encodeURIComponent(report.sessionId)}` : path;
3153
+ };
3154
+ var resolveHref = (path, state, options) => {
3155
+ if (typeof options.href === "function") {
3156
+ return options.href({ report: state.report });
3157
+ }
3158
+ return options.href ?? defaultHref(path, state.report);
3159
+ };
3160
+ var createVoiceCallDebuggerLaunchViewModel = (path, state, options = {}) => {
3161
+ const report = state.report;
3162
+ const href = resolveHref(path, state, options);
3163
+ return {
3164
+ description: options.description ?? DEFAULT_DESCRIPTION,
3165
+ error: state.error,
3166
+ href,
3167
+ isLoading: state.isLoading,
3168
+ label: state.error ? "Unavailable" : report ? `${report.status} \xB7 ${report.sessionId}` : state.isLoading ? "Loading" : "No call loaded",
3169
+ rows: report ? [
3170
+ { label: "Events", value: String(report.operationsRecord.summary.eventCount) },
3171
+ { label: "Turns", value: String(report.operationsRecord.summary.turnCount) },
3172
+ { label: "Errors", value: String(report.operationsRecord.summary.errorCount) },
3173
+ {
3174
+ label: "Provider recovery",
3175
+ value: report.operationsRecord.providerDecisionSummary.recoveryStatus
3176
+ },
3177
+ {
3178
+ label: "Fallbacks",
3179
+ value: String(report.operationsRecord.providerDecisionSummary.fallbacks)
3180
+ },
3181
+ { label: "Snapshot", value: report.snapshot.status }
3182
+ ] : [],
3183
+ status: state.error ? "error" : report ? report.status === "healthy" ? "ready" : "warning" : state.isLoading ? "loading" : "empty",
3184
+ title: options.title ?? DEFAULT_TITLE,
3185
+ updatedAt: state.updatedAt
3186
+ };
3187
+ };
3188
+ var renderVoiceCallDebuggerLaunchHTML = (path, state, options = {}) => {
3189
+ const model = createVoiceCallDebuggerLaunchViewModel(path, state, options);
3190
+ const rows = model.rows.length ? `<dl>${model.rows.map((row) => `<div>
3191
+ <dt>${escapeHtml(row.label)}</dt>
3192
+ <dd>${escapeHtml(row.value)}</dd>
3193
+ </div>`).join("")}</dl>` : '<p class="absolute-voice-call-debugger-launch__empty">Load a call debugger report to see the latest support artifact.</p>';
3194
+ return `<section class="absolute-voice-call-debugger-launch absolute-voice-call-debugger-launch--${escapeHtml(model.status)}">
3195
+ <header class="absolute-voice-call-debugger-launch__header">
3196
+ <span class="absolute-voice-call-debugger-launch__eyebrow">${escapeHtml(model.title)}</span>
3197
+ <strong class="absolute-voice-call-debugger-launch__label">${escapeHtml(model.label)}</strong>
3198
+ </header>
3199
+ <p class="absolute-voice-call-debugger-launch__description">${escapeHtml(model.description)}</p>
3200
+ <a class="absolute-voice-call-debugger-launch__link" href="${escapeHtml(model.href)}">${escapeHtml(options.linkLabel ?? DEFAULT_LINK_LABEL)}</a>
3201
+ ${rows}
3202
+ ${model.error ? `<p class="absolute-voice-call-debugger-launch__error">${escapeHtml(model.error)}</p>` : ""}
3203
+ </section>`;
3204
+ };
3205
+ var mountVoiceCallDebuggerLaunch = (element, path, options = {}) => {
3206
+ const store = createVoiceCallDebuggerStore(path, options);
3207
+ const render = () => {
3208
+ element.innerHTML = renderVoiceCallDebuggerLaunchHTML(path, store.getSnapshot(), options);
3209
+ };
3210
+ const unsubscribe = store.subscribe(render);
3211
+ render();
3212
+ store.refresh().catch(() => {});
3213
+ return {
3214
+ close: () => {
3215
+ unsubscribe();
3216
+ store.close();
3217
+ },
3218
+ refresh: store.refresh
3219
+ };
3220
+ };
3221
+ var defineVoiceCallDebuggerLaunchElement = (tagName = "absolute-voice-call-debugger-launch") => {
3222
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
3223
+ return;
3224
+ }
3225
+ customElements.define(tagName, class AbsoluteVoiceCallDebuggerLaunchElement extends HTMLElement {
3226
+ mounted;
3227
+ connectedCallback() {
3228
+ const intervalMs = Number(this.getAttribute("interval-ms") ?? 0);
3229
+ this.mounted = mountVoiceCallDebuggerLaunch(this, this.getAttribute("path") ?? "/api/voice-call-debugger/latest", {
3230
+ description: this.getAttribute("description") ?? undefined,
3231
+ href: this.getAttribute("href") ?? undefined,
3232
+ intervalMs: Number.isFinite(intervalMs) ? intervalMs : 0,
3233
+ linkLabel: this.getAttribute("link-label") ?? undefined,
3234
+ title: this.getAttribute("title") ?? undefined
3235
+ });
3236
+ }
3237
+ disconnectedCallback() {
3238
+ this.mounted?.close();
3239
+ this.mounted = undefined;
3240
+ }
3241
+ });
3242
+ };
3069
3243
  // src/client/sessionSnapshotWidget.ts
3070
- var DEFAULT_TITLE = "Session Snapshot";
3071
- var DEFAULT_DESCRIPTION = "Portable call artifact with media graph, provider routing, proof, quality, and telephony evidence.";
3244
+ var DEFAULT_TITLE2 = "Session Snapshot";
3245
+ var DEFAULT_DESCRIPTION2 = "Portable call artifact with media graph, provider routing, proof, quality, and telephony evidence.";
3072
3246
  var DEFAULT_DOWNLOAD_LABEL = "Download snapshot";
3073
- var escapeHtml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3247
+ var escapeHtml2 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3074
3248
  var formatStatus = (status) => status ?? "n/a";
3075
3249
  var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
3076
3250
  const snapshot = state.snapshot;
@@ -3086,7 +3260,7 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
3086
3260
  label: artifact.label,
3087
3261
  status: formatStatus(artifact.status)
3088
3262
  })) ?? [],
3089
- description: options.description ?? DEFAULT_DESCRIPTION,
3263
+ description: options.description ?? DEFAULT_DESCRIPTION2,
3090
3264
  error: state.error,
3091
3265
  isLoading: state.isLoading,
3092
3266
  label: state.error ? "Unavailable" : snapshot ? `${snapshot.status} \xB7 ${snapshot.sessionId}` : state.isLoading ? "Loading" : "No snapshot",
@@ -3110,30 +3284,30 @@ var createVoiceSessionSnapshotViewModel = (state, options = {}) => {
3110
3284
  ] : [],
3111
3285
  showDownload: snapshot !== undefined,
3112
3286
  status: state.error ? "error" : snapshot ? snapshot.status === "pass" ? "ready" : "warning" : state.isLoading ? "loading" : "empty",
3113
- title: options.title ?? DEFAULT_TITLE,
3287
+ title: options.title ?? DEFAULT_TITLE2,
3114
3288
  updatedAt: state.updatedAt
3115
3289
  };
3116
3290
  };
3117
3291
  var renderVoiceSessionSnapshotHTML = (state, options = {}) => {
3118
3292
  const model = createVoiceSessionSnapshotViewModel(state, options);
3119
3293
  const rows = model.rows.length ? `<dl>${model.rows.map((row) => `<div>
3120
- <dt>${escapeHtml(row.label)}</dt>
3121
- <dd>${escapeHtml(row.value)}</dd>
3294
+ <dt>${escapeHtml2(row.label)}</dt>
3295
+ <dd>${escapeHtml2(row.value)}</dd>
3122
3296
  </div>`).join("")}</dl>` : '<p class="absolute-voice-session-snapshot__empty">Load a session snapshot to see support diagnostics.</p>';
3123
3297
  const artifacts = model.artifacts.length ? `<div class="absolute-voice-session-snapshot__artifacts">${model.artifacts.map((artifact) => {
3124
- const body = `<strong>${escapeHtml(artifact.label)}</strong><span>${escapeHtml(artifact.status)}</span>`;
3125
- return artifact.href ? `<a href="${escapeHtml(artifact.href)}">${body}</a>` : `<div>${body}</div>`;
3298
+ const body = `<strong>${escapeHtml2(artifact.label)}</strong><span>${escapeHtml2(artifact.status)}</span>`;
3299
+ return artifact.href ? `<a href="${escapeHtml2(artifact.href)}">${body}</a>` : `<div>${body}</div>`;
3126
3300
  }).join("")}</div>` : "";
3127
- return `<section class="absolute-voice-session-snapshot absolute-voice-session-snapshot--${escapeHtml(model.status)}">
3301
+ return `<section class="absolute-voice-session-snapshot absolute-voice-session-snapshot--${escapeHtml2(model.status)}">
3128
3302
  <header class="absolute-voice-session-snapshot__header">
3129
- <span class="absolute-voice-session-snapshot__eyebrow">${escapeHtml(model.title)}</span>
3130
- <strong class="absolute-voice-session-snapshot__label">${escapeHtml(model.label)}</strong>
3303
+ <span class="absolute-voice-session-snapshot__eyebrow">${escapeHtml2(model.title)}</span>
3304
+ <strong class="absolute-voice-session-snapshot__label">${escapeHtml2(model.label)}</strong>
3131
3305
  </header>
3132
- <p class="absolute-voice-session-snapshot__description">${escapeHtml(model.description)}</p>
3133
- ${model.showDownload ? `<button class="absolute-voice-session-snapshot__download" data-absolute-voice-session-snapshot-download type="button">${escapeHtml(options.downloadLabel ?? DEFAULT_DOWNLOAD_LABEL)}</button>` : ""}
3306
+ <p class="absolute-voice-session-snapshot__description">${escapeHtml2(model.description)}</p>
3307
+ ${model.showDownload ? `<button class="absolute-voice-session-snapshot__download" data-absolute-voice-session-snapshot-download type="button">${escapeHtml2(options.downloadLabel ?? DEFAULT_DOWNLOAD_LABEL)}</button>` : ""}
3134
3308
  ${rows}
3135
3309
  ${artifacts}
3136
- ${model.error ? `<p class="absolute-voice-session-snapshot__error">${escapeHtml(model.error)}</p>` : ""}
3310
+ ${model.error ? `<p class="absolute-voice-session-snapshot__error">${escapeHtml2(model.error)}</p>` : ""}
3137
3311
  </section>`;
3138
3312
  };
3139
3313
  var downloadBlob = (blob, filename) => {
@@ -3903,8 +4077,8 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
3903
4077
  };
3904
4078
  };
3905
4079
  // src/client/opsStatusWidget.ts
3906
- var DEFAULT_TITLE2 = "Voice Ops Status";
3907
- var DEFAULT_DESCRIPTION2 = "Certified workflow, provider, and handoff readiness from your AbsoluteJS voice app.";
4080
+ var DEFAULT_TITLE3 = "Voice Ops Status";
4081
+ var DEFAULT_DESCRIPTION3 = "Certified workflow, provider, and handoff readiness from your AbsoluteJS voice app.";
3908
4082
  var SURFACE_LABELS = {
3909
4083
  handoffs: "Handoffs",
3910
4084
  providers: "Providers",
@@ -3912,7 +4086,7 @@ var SURFACE_LABELS = {
3912
4086
  sessions: "Sessions",
3913
4087
  workflows: "Workflows"
3914
4088
  };
3915
- var escapeHtml2 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4089
+ var escapeHtml3 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3916
4090
  var readNumber = (value, key) => value && typeof value === "object" && (key in value) ? Number(value[key] ?? 0) : 0;
3917
4091
  var surfaceDetail = (surface) => {
3918
4092
  const total = readNumber(surface, "total");
@@ -3952,7 +4126,7 @@ var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
3952
4126
  };
3953
4127
  });
3954
4128
  return {
3955
- description: options.description ?? DEFAULT_DESCRIPTION2,
4129
+ description: options.description ?? DEFAULT_DESCRIPTION3,
3956
4130
  error: snapshot.error,
3957
4131
  isLoading: snapshot.isLoading,
3958
4132
  label: getVoiceOpsStatusLabel(report, snapshot.error),
@@ -3960,31 +4134,31 @@ var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
3960
4134
  passed: report?.passed ?? 0,
3961
4135
  status: snapshot.error ? "error" : report ? report.status : snapshot.isLoading ? "loading" : "loading",
3962
4136
  surfaces,
3963
- title: options.title ?? DEFAULT_TITLE2,
4137
+ title: options.title ?? DEFAULT_TITLE3,
3964
4138
  total: report?.total ?? 0,
3965
4139
  updatedAt: snapshot.updatedAt
3966
4140
  };
3967
4141
  };
3968
4142
  var renderVoiceOpsStatusHTML = (snapshot, options = {}) => {
3969
4143
  const model = createVoiceOpsStatusViewModel(snapshot, options);
3970
- const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml2(surface.status)}">
3971
- <span>${escapeHtml2(surface.label)}</span>
3972
- <strong>${escapeHtml2(surface.detail)}</strong>
4144
+ const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml3(surface.status)}">
4145
+ <span>${escapeHtml3(surface.label)}</span>
4146
+ <strong>${escapeHtml3(surface.detail)}</strong>
3973
4147
  </li>`).join("") : '<li class="absolute-voice-ops-status__surface"><span>Status</span><strong>Waiting for first check</strong></li>';
3974
- const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${escapeHtml2(link.href)}">${escapeHtml2(link.label)}</a>`).join("")}</nav>` : "";
3975
- return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${escapeHtml2(model.status)}">
4148
+ const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${escapeHtml3(link.href)}">${escapeHtml3(link.label)}</a>`).join("")}</nav>` : "";
4149
+ return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${escapeHtml3(model.status)}">
3976
4150
  <header class="absolute-voice-ops-status__header">
3977
- <span class="absolute-voice-ops-status__eyebrow">${escapeHtml2(model.title)}</span>
3978
- <strong class="absolute-voice-ops-status__label">${escapeHtml2(model.label)}</strong>
4151
+ <span class="absolute-voice-ops-status__eyebrow">${escapeHtml3(model.title)}</span>
4152
+ <strong class="absolute-voice-ops-status__label">${escapeHtml3(model.label)}</strong>
3979
4153
  </header>
3980
- <p class="absolute-voice-ops-status__description">${escapeHtml2(model.description)}</p>
4154
+ <p class="absolute-voice-ops-status__description">${escapeHtml3(model.description)}</p>
3981
4155
  <div class="absolute-voice-ops-status__summary">
3982
4156
  <span>${model.passed} passing</span>
3983
4157
  <span>${Math.max(model.total - model.passed, 0)} failing</span>
3984
4158
  <span>${model.total} checks</span>
3985
4159
  </div>
3986
4160
  <ul class="absolute-voice-ops-status__surfaces">${surfaces}</ul>
3987
- ${model.error ? `<p class="absolute-voice-ops-status__error">${escapeHtml2(model.error)}</p>` : ""}
4161
+ ${model.error ? `<p class="absolute-voice-ops-status__error">${escapeHtml3(model.error)}</p>` : ""}
3988
4162
  ${links}
3989
4163
  </section>`;
3990
4164
  };
@@ -4027,13 +4201,13 @@ var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
4027
4201
  });
4028
4202
  };
4029
4203
  // src/client/platformCoverageWidget.ts
4030
- var DEFAULT_TITLE3 = "Platform Replacement Coverage";
4031
- var DEFAULT_DESCRIPTION3 = "Code-owned coverage for hosted voice-platform surfaces, backed by the same proof routes used by release evidence.";
4204
+ var DEFAULT_TITLE4 = "Platform Replacement Coverage";
4205
+ var DEFAULT_DESCRIPTION4 = "Code-owned coverage for hosted voice-platform surfaces, backed by the same proof routes used by release evidence.";
4032
4206
  var DEFAULT_LINKS = [
4033
4207
  { href: "/switching-from-vapi", label: "Switching guide" },
4034
4208
  { href: "/api/voice/vapi-coverage", label: "Coverage JSON" }
4035
4209
  ];
4036
- var escapeHtml3 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4210
+ var escapeHtml4 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4037
4211
  var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
4038
4212
  var surfaceDetail2 = (surface) => {
4039
4213
  if (surface.status === "pass") {
@@ -4057,37 +4231,37 @@ var createVoicePlatformCoverageViewModel = (snapshot, options = {}) => {
4057
4231
  label: surface.surface
4058
4232
  }));
4059
4233
  return {
4060
- description: options.description ?? DEFAULT_DESCRIPTION3,
4234
+ description: options.description ?? DEFAULT_DESCRIPTION4,
4061
4235
  error: snapshot.error,
4062
4236
  isLoading: snapshot.isLoading,
4063
4237
  label: snapshot.error ? "Unavailable" : snapshot.report ? failing.length ? `${failing.length} gaps` : `${snapshot.report.total} surfaces passing` : snapshot.isLoading ? "Checking" : "No coverage report",
4064
4238
  links: options.links ?? DEFAULT_LINKS,
4065
4239
  status: snapshot.error ? "error" : snapshot.report ? failing.length ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
4066
4240
  surfaces,
4067
- title: options.title ?? DEFAULT_TITLE3,
4241
+ title: options.title ?? DEFAULT_TITLE4,
4068
4242
  updatedAt: snapshot.updatedAt
4069
4243
  };
4070
4244
  };
4071
4245
  var renderVoicePlatformCoverageHTML = (snapshot, options = {}) => {
4072
4246
  const model = createVoicePlatformCoverageViewModel(snapshot, options);
4073
- const surfaces = model.surfaces.length ? `<div class="absolute-voice-platform-coverage__surfaces">${model.surfaces.map((surface) => `<article class="absolute-voice-platform-coverage__surface absolute-voice-platform-coverage__surface--${escapeHtml3(surface.status)}">
4247
+ const surfaces = model.surfaces.length ? `<div class="absolute-voice-platform-coverage__surfaces">${model.surfaces.map((surface) => `<article class="absolute-voice-platform-coverage__surface absolute-voice-platform-coverage__surface--${escapeHtml4(surface.status)}">
4074
4248
  <header>
4075
- <strong>${escapeHtml3(surface.label)}</strong>
4076
- <span>${escapeHtml3(formatStatus2(surface.status))}</span>
4249
+ <strong>${escapeHtml4(surface.label)}</strong>
4250
+ <span>${escapeHtml4(formatStatus2(surface.status))}</span>
4077
4251
  </header>
4078
- <p>${escapeHtml3(surface.detail)}</p>
4252
+ <p>${escapeHtml4(surface.detail)}</p>
4079
4253
  <small>${surface.evidence.filter((item) => item.ok).length}/${surface.evidence.length} evidence checks passing</small>
4080
- </article>`).join("")}</div>` : `<p class="absolute-voice-platform-coverage__empty">${model.error ? escapeHtml3(model.error) : "Run the proof pack to populate platform coverage evidence."}</p>`;
4081
- const links = model.links.length ? `<p class="absolute-voice-platform-coverage__links">${model.links.map((link) => `<a href="${escapeHtml3(link.href)}">${escapeHtml3(link.label)}</a>`).join("")}</p>` : "";
4082
- return `<section class="absolute-voice-platform-coverage absolute-voice-platform-coverage--${escapeHtml3(model.status)}">
4254
+ </article>`).join("")}</div>` : `<p class="absolute-voice-platform-coverage__empty">${model.error ? escapeHtml4(model.error) : "Run the proof pack to populate platform coverage evidence."}</p>`;
4255
+ const links = model.links.length ? `<p class="absolute-voice-platform-coverage__links">${model.links.map((link) => `<a href="${escapeHtml4(link.href)}">${escapeHtml4(link.label)}</a>`).join("")}</p>` : "";
4256
+ return `<section class="absolute-voice-platform-coverage absolute-voice-platform-coverage--${escapeHtml4(model.status)}">
4083
4257
  <header class="absolute-voice-platform-coverage__header">
4084
- <span class="absolute-voice-platform-coverage__eyebrow">${escapeHtml3(model.title)}</span>
4085
- <strong class="absolute-voice-platform-coverage__label">${escapeHtml3(model.label)}</strong>
4258
+ <span class="absolute-voice-platform-coverage__eyebrow">${escapeHtml4(model.title)}</span>
4259
+ <strong class="absolute-voice-platform-coverage__label">${escapeHtml4(model.label)}</strong>
4086
4260
  </header>
4087
- <p class="absolute-voice-platform-coverage__description">${escapeHtml3(model.description)}</p>
4261
+ <p class="absolute-voice-platform-coverage__description">${escapeHtml4(model.description)}</p>
4088
4262
  ${surfaces}
4089
4263
  ${links}
4090
- ${model.error ? `<p class="absolute-voice-platform-coverage__error">${escapeHtml3(model.error)}</p>` : ""}
4264
+ ${model.error ? `<p class="absolute-voice-platform-coverage__error">${escapeHtml4(model.error)}</p>` : ""}
4091
4265
  </section>`;
4092
4266
  };
4093
4267
  var getVoicePlatformCoverageCSS = () => `.absolute-voice-platform-coverage{border:1px solid #c7d2fe;border-radius:20px;background:#f8fbff;color:#111827;padding:18px;box-shadow:0 18px 40px rgba(30,64,175,.12);font-family:inherit}.absolute-voice-platform-coverage--warning,.absolute-voice-platform-coverage--error{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-platform-coverage__header,.absolute-voice-platform-coverage__surface header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-platform-coverage__eyebrow{color:#1d4ed8;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-platform-coverage__label{font-size:24px;line-height:1}.absolute-voice-platform-coverage__description,.absolute-voice-platform-coverage__surface p,.absolute-voice-platform-coverage__surface small,.absolute-voice-platform-coverage__empty{color:#475569}.absolute-voice-platform-coverage__surfaces{display:grid;gap:10px;margin-top:14px}.absolute-voice-platform-coverage__surface{background:#fff;border:1px solid #dbeafe;border-radius:16px;padding:12px}.absolute-voice-platform-coverage__surface--pass{border-color:#86efac}.absolute-voice-platform-coverage__surface--fail,.absolute-voice-platform-coverage__surface--missing,.absolute-voice-platform-coverage__surface--stale{border-color:#f2a7a7}.absolute-voice-platform-coverage__surface p{margin:8px 0}.absolute-voice-platform-coverage__surface span{text-transform:capitalize}.absolute-voice-platform-coverage__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-platform-coverage__links a{border:1px solid #bfdbfe;border-radius:999px;color:#1d4ed8;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-platform-coverage__error{color:#9f1239;font-weight:700}`;
@@ -4278,16 +4452,16 @@ var summarizeVoiceProviderHealth = async (input) => {
4278
4452
  }
4279
4453
  return summaries;
4280
4454
  };
4281
- var escapeHtml4 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4455
+ var escapeHtml5 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4282
4456
  var renderVoiceProviderHealthHTML = (providers) => providers.length === 0 ? '<p class="voice-provider-empty">No provider status yet.</p>' : [
4283
4457
  '<div class="voice-provider-health">',
4284
4458
  ...providers.map((provider) => {
4285
4459
  const suppressionSeconds = typeof provider.suppressionRemainingMs === "number" ? Math.ceil(provider.suppressionRemainingMs / 1000) : undefined;
4286
4460
  return [
4287
- `<article class="voice-provider-card ${escapeHtml4(provider.status)}">`,
4461
+ `<article class="voice-provider-card ${escapeHtml5(provider.status)}">`,
4288
4462
  '<div class="voice-provider-card-header">',
4289
- `<strong>${escapeHtml4(provider.provider)}</strong>`,
4290
- `<span>${escapeHtml4(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>`,
4463
+ `<strong>${escapeHtml5(provider.provider)}</strong>`,
4464
+ `<span>${escapeHtml5(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>`,
4291
4465
  "</div>",
4292
4466
  "<dl>",
4293
4467
  `<div><dt>Runs</dt><dd>${String(provider.runCount)}</dd></div>`,
@@ -4297,7 +4471,7 @@ var renderVoiceProviderHealthHTML = (providers) => providers.length === 0 ? '<p
4297
4471
  `<div><dt>Fallbacks</dt><dd>${String(provider.fallbackCount)}</dd></div>`,
4298
4472
  "</dl>",
4299
4473
  suppressionSeconds ? `<p>Temporarily suppressed for ${String(suppressionSeconds)}s.</p>` : "",
4300
- provider.lastError ? `<p>${escapeHtml4(provider.lastError)}</p>` : "",
4474
+ provider.lastError ? `<p>${escapeHtml5(provider.lastError)}</p>` : "",
4301
4475
  "</article>"
4302
4476
  ].join("");
4303
4477
  }),
@@ -4328,7 +4502,7 @@ var createVoiceProviderHealthRoutes = (options) => {
4328
4502
  };
4329
4503
 
4330
4504
  // src/resilienceRoutes.ts
4331
- var escapeHtml5 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4505
+ var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4332
4506
  var getString2 = (value) => typeof value === "string" ? value : undefined;
4333
4507
  var getNumber2 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
4334
4508
  var getBoolean = (value) => value === true;
@@ -4476,13 +4650,13 @@ var summarizeRoutingEvents = (events) => {
4476
4650
  };
4477
4651
  var renderProviderCards = (title, providers) => {
4478
4652
  if (providers.length === 0) {
4479
- return `<p class="muted">No ${escapeHtml5(title)} provider health yet.</p>`;
4653
+ return `<p class="muted">No ${escapeHtml6(title)} provider health yet.</p>`;
4480
4654
  }
4481
4655
  return `<div class="provider-grid">${providers.map((provider) => `
4482
- <article class="card provider ${escapeHtml5(provider.status)}">
4656
+ <article class="card provider ${escapeHtml6(provider.status)}">
4483
4657
  <div class="card-header">
4484
- <strong>${escapeHtml5(provider.provider)}</strong>
4485
- <span>${escapeHtml5(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
4658
+ <strong>${escapeHtml6(provider.provider)}</strong>
4659
+ <span>${escapeHtml6(provider.status)}${provider.recommended ? " \xB7 recommended" : ""}</span>
4486
4660
  </div>
4487
4661
  <dl>
4488
4662
  <div><dt>Runs</dt><dd>${provider.runCount}</dd></div>
@@ -4491,7 +4665,7 @@ var renderProviderCards = (title, providers) => {
4491
4665
  <div><dt>Timeouts</dt><dd>${provider.timeoutCount}</dd></div>
4492
4666
  <div><dt>Fallbacks</dt><dd>${provider.fallbackCount}</dd></div>
4493
4667
  </dl>
4494
- ${provider.lastError ? `<p class="muted">${escapeHtml5(provider.lastError)}</p>` : ""}
4668
+ ${provider.lastError ? `<p class="muted">${escapeHtml6(provider.lastError)}</p>` : ""}
4495
4669
  </article>
4496
4670
  `).join("")}</div>`;
4497
4671
  };
@@ -4500,24 +4674,24 @@ var renderTimeline = (events) => {
4500
4674
  return '<p class="muted">No provider routing events yet. Run the app or simulate provider failover.</p>';
4501
4675
  }
4502
4676
  return `<div class="timeline">${events.slice(0, 40).map((event) => `
4503
- <article class="card event ${escapeHtml5(event.status ?? "unknown")}">
4677
+ <article class="card event ${escapeHtml6(event.status ?? "unknown")}">
4504
4678
  <div class="card-header">
4505
- <strong>${escapeHtml5(event.kind.toUpperCase())} ${escapeHtml5(event.operation ?? "generate")}</strong>
4679
+ <strong>${escapeHtml6(event.kind.toUpperCase())} ${escapeHtml6(event.operation ?? "generate")}</strong>
4506
4680
  <span>${new Date(event.at).toLocaleString()}</span>
4507
4681
  </div>
4508
4682
  <p>
4509
- <span class="pill">${escapeHtml5(event.status ?? "unknown")}</span>
4510
- <span class="pill">provider: ${escapeHtml5(event.provider ?? "unknown")}</span>
4511
- ${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml5(event.fallbackProvider)}</span>` : ""}
4683
+ <span class="pill">${escapeHtml6(event.status ?? "unknown")}</span>
4684
+ <span class="pill">provider: ${escapeHtml6(event.provider ?? "unknown")}</span>
4685
+ ${event.fallbackProvider ? `<span class="pill">fallback: ${escapeHtml6(event.fallbackProvider)}</span>` : ""}
4512
4686
  ${event.timedOut ? '<span class="pill danger">timed out</span>' : ""}
4513
4687
  </p>
4514
4688
  <dl>
4515
4689
  <div><dt>Attempt</dt><dd>${event.attempt ?? 0}</dd></div>
4516
4690
  <div><dt>Elapsed</dt><dd>${event.elapsedMs ?? 0}ms</dd></div>
4517
4691
  <div><dt>Budget</dt><dd>${event.latencyBudgetMs ?? 0}ms</dd></div>
4518
- <div><dt>Session</dt><dd>${escapeHtml5(event.sessionId)}</dd></div>
4692
+ <div><dt>Session</dt><dd>${escapeHtml6(event.sessionId)}</dd></div>
4519
4693
  </dl>
4520
- ${event.error ? `<p class="muted">${escapeHtml5(event.error)}</p>` : ""}
4694
+ ${event.error ? `<p class="muted">${escapeHtml6(event.error)}</p>` : ""}
4521
4695
  </article>
4522
4696
  `).join("")}</div>`;
4523
4697
  };
@@ -4527,9 +4701,9 @@ var renderSessionKind = (kind, summary) => {
4527
4701
  const status = latest?.status ?? "idle";
4528
4702
  const fallback = latest?.fallbackProvider && latest.fallbackProvider !== provider ? ` -> ${latest.fallbackProvider}` : "";
4529
4703
  return `<div>
4530
- <dt>${escapeHtml5(kind.toUpperCase())}</dt>
4531
- <dd>${escapeHtml5(provider)}${escapeHtml5(fallback)}</dd>
4532
- <small>${escapeHtml5(status)} \xB7 ${summary.runCount} event${summary.runCount === 1 ? "" : "s"} \xB7 ${summary.errorCount} error${summary.errorCount === 1 ? "" : "s"} \xB7 ${summary.fallbackCount} fallback${summary.fallbackCount === 1 ? "" : "s"}</small>
4704
+ <dt>${escapeHtml6(kind.toUpperCase())}</dt>
4705
+ <dd>${escapeHtml6(provider)}${escapeHtml6(fallback)}</dd>
4706
+ <small>${escapeHtml6(status)} \xB7 ${summary.runCount} event${summary.runCount === 1 ? "" : "s"} \xB7 ${summary.errorCount} error${summary.errorCount === 1 ? "" : "s"} \xB7 ${summary.fallbackCount} fallback${summary.fallbackCount === 1 ? "" : "s"}</small>
4533
4707
  </div>`;
4534
4708
  };
4535
4709
  var renderSessionSummaries = (sessions) => {
@@ -4537,10 +4711,10 @@ var renderSessionSummaries = (sessions) => {
4537
4711
  return '<p class="muted">No call-level routing summaries yet. Run a voice session or provider simulation.</p>';
4538
4712
  }
4539
4713
  return `<div class="session-grid">${sessions.slice(0, 12).map((session) => `
4540
- <article class="card session ${escapeHtml5(session.status)}">
4714
+ <article class="card session ${escapeHtml6(session.status)}">
4541
4715
  <div class="card-header">
4542
- <strong>${escapeHtml5(session.sessionId)}</strong>
4543
- <span>${escapeHtml5(session.status)}</span>
4716
+ <strong>${escapeHtml6(session.sessionId)}</strong>
4717
+ <span>${escapeHtml6(session.status)}</span>
4544
4718
  </div>
4545
4719
  <p>
4546
4720
  <span class="pill">${session.eventCount} routing events</span>
@@ -4567,21 +4741,21 @@ var renderSimulationControls = (kind, simulation) => {
4567
4741
  const pathPrefix = simulation.pathPrefix ?? `/api/${kind}-simulate`;
4568
4742
  const failureProviders = simulation.failureProviders ?? configuredProviders.map(({ provider }) => provider);
4569
4743
  const canFail = (provider) => configuredProviders.some((entry) => entry.provider === provider) && (!simulation.fallbackRequiredProvider || configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider));
4570
- return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml5(pathPrefix)}">
4571
- <p class="muted">${escapeHtml5(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
4744
+ return `<div class="simulate-panel" data-sim-kind="${kind}" data-sim-prefix="${escapeHtml6(pathPrefix)}">
4745
+ <p class="muted">${escapeHtml6(simulation.failureMessage ?? `Simulate ${kind.toUpperCase()} provider failure without changing provider credentials.`)}</p>
4572
4746
  <div class="simulate-actions">
4573
- ${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml5(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml5(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
4574
- ${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml5(provider.provider)}">Mark ${escapeHtml5(provider.provider)} recovered</button>`).join("")}
4747
+ ${failureProviders.map((provider) => `<button type="button" data-provider-fail="${escapeHtml6(provider)}"${canFail(provider) ? "" : " disabled"}>Simulate ${escapeHtml6(provider)} ${kind.toUpperCase()} failure</button>`).join("")}
4748
+ ${configuredProviders.map((provider) => `<button type="button" data-provider-recover="${escapeHtml6(provider.provider)}">Mark ${escapeHtml6(provider.provider)} recovered</button>`).join("")}
4575
4749
  </div>
4576
- ${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml5(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
4750
+ ${simulation.fallbackRequiredProvider && !configuredProviders.some((entry) => entry.provider === simulation.fallbackRequiredProvider) ? `<p class="muted">${escapeHtml6(simulation.fallbackRequiredMessage ?? `Configure ${simulation.fallbackRequiredProvider} to enable fallback simulation.`)}</p>` : ""}
4577
4751
  <pre class="simulate-output" hidden></pre>
4578
4752
  </div>`;
4579
4753
  };
4580
4754
  var renderVoiceResilienceHTML = (input) => {
4581
4755
  const summary = summarizeRoutingEvents(input.routingEvents);
4582
- const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml5(kind)}: ${String(count)}</span>`).join("");
4583
- const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml5(link.href)}">${escapeHtml5(link.label)}</a>`).join(" \xB7 ") : "";
4584
- const snippet = escapeHtml5(`const sttSimulator = createVoiceIOProviderFailureSimulator({
4756
+ const kindCounts = [...summary.byKind.entries()].map(([kind, count]) => `<span class="pill">${escapeHtml6(kind)}: ${String(count)}</span>`).join("");
4757
+ const links = input.links?.length ? input.links.map((link) => `<a href="${escapeHtml6(link.href)}">${escapeHtml6(link.label)}</a>`).join(" \xB7 ") : "";
4758
+ const snippet = escapeHtml6(`const sttSimulator = createVoiceIOProviderFailureSimulator({
4585
4759
  kind: 'stt',
4586
4760
  providers: ['deepgram', 'assemblyai'],
4587
4761
  fallback: ['deepgram', 'assemblyai'],
@@ -4619,7 +4793,7 @@ app.use(
4619
4793
  <head>
4620
4794
  <meta charset="utf-8" />
4621
4795
  <meta name="viewport" content="width=device-width, initial-scale=1" />
4622
- <title>${escapeHtml5(input.title ?? "AbsoluteJS Voice Resilience")}</title>
4796
+ <title>${escapeHtml6(input.title ?? "AbsoluteJS Voice Resilience")}</title>
4623
4797
  <style>
4624
4798
  :root { color-scheme: dark; }
4625
4799
  body { background: radial-gradient(circle at top left, #172554, #09090b 36%, #050505); color: #f4f4f5; font-family: ui-sans-serif, system-ui, sans-serif; margin: 0; padding: 24px; }
@@ -4812,7 +4986,7 @@ var createVoiceResilienceRoutes = (options) => {
4812
4986
  };
4813
4987
 
4814
4988
  // src/providerDecisionTraces.ts
4815
- var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4989
+ var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4816
4990
  var getString3 = (value) => typeof value === "string" ? value : undefined;
4817
4991
  var getNumber3 = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
4818
4992
  var isDecisionTrace = (event) => Boolean(event && typeof event === "object" && "provider" in event && "reason" in event && "sessionId" in event && "status" in event && "surface" in event);
@@ -5053,7 +5227,7 @@ var renderVoiceProviderDecisionTraceHTML = (report, title = "Provider Decision T
5053
5227
  <head>
5054
5228
  <meta charset="utf-8" />
5055
5229
  <meta name="viewport" content="width=device-width, initial-scale=1" />
5056
- <title>${escapeHtml6(title)}</title>
5230
+ <title>${escapeHtml7(title)}</title>
5057
5231
  <style>
5058
5232
  body{font-family:ui-sans-serif,system-ui,sans-serif;margin:0;background:#f8fafc;color:#0f172a}
5059
5233
  main{max-width:1100px;margin:0 auto;padding:32px}
@@ -5067,8 +5241,8 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
5067
5241
  </head>
5068
5242
  <body>
5069
5243
  <main>
5070
- <p class="status ${report.status}">${escapeHtml6(report.status)}</p>
5071
- <h1>${escapeHtml6(title)}</h1>
5244
+ <p class="status ${report.status}">${escapeHtml7(report.status)}</p>
5245
+ <h1>${escapeHtml7(title)}</h1>
5072
5246
  <p class="muted">Runtime proof for why providers were selected, skipped, failed, or recovered by fallback.</p>
5073
5247
  <section class="grid">
5074
5248
  <article class="card"><strong>${String(report.summary.decisions)}</strong><p>decisions</p></article>
@@ -5079,10 +5253,10 @@ code{background:#e2e8f0;border-radius:8px;padding:2px 6px}
5079
5253
  </section>
5080
5254
  <section class="surfaces">
5081
5255
  ${report.surfaces.map((surface) => `<article class="surface">
5082
- <header><strong>${escapeHtml6(surface.surface)}</strong> <span class="status ${surface.status}">${escapeHtml6(surface.status)}</span></header>
5256
+ <header><strong>${escapeHtml7(surface.surface)}</strong> <span class="status ${surface.status}">${escapeHtml7(surface.status)}</span></header>
5083
5257
  <p>${String(surface.decisions)} decision(s), ${String(surface.fallbacks)} fallback(s), ${String(surface.degraded)} degraded decision(s), ${String(surface.errors)} error(s).</p>
5084
- <p class="muted">Providers: ${escapeHtml6(surface.providers.join(", ") || "none")}</p>
5085
- <p>${surface.reasons.map((reason) => `<code>${escapeHtml6(reason)}</code>`).join(" ")}</p>
5258
+ <p class="muted">Providers: ${escapeHtml7(surface.providers.join(", ") || "none")}</p>
5259
+ <p>${surface.reasons.map((reason) => `<code>${escapeHtml7(reason)}</code>`).join(" ")}</p>
5086
5260
  </article>`).join(`
5087
5261
  `)}
5088
5262
  </section>
@@ -5547,7 +5721,7 @@ var exportVoiceTrace = async (input) => {
5547
5721
  };
5548
5722
  };
5549
5723
  var toNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : 0;
5550
- var escapeHtml7 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
5724
+ var escapeHtml8 = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
5551
5725
  var formatTraceValue = (value) => {
5552
5726
  if (value === undefined || value === null) {
5553
5727
  return "";
@@ -5827,10 +6001,10 @@ var renderVoiceTraceHTML = (events, options = {}) => {
5827
6001
  const offset = summary.startedAt === undefined ? event.at : Math.max(0, event.at - summary.startedAt);
5828
6002
  return [
5829
6003
  "<tr>",
5830
- `<td>${escapeHtml7(String(offset))}</td>`,
5831
- `<td>${escapeHtml7(event.type)}</td>`,
5832
- `<td>${escapeHtml7(event.turnId ?? "")}</td>`,
5833
- `<td><code>${escapeHtml7(JSON.stringify(event.payload))}</code></td>`,
6004
+ `<td>${escapeHtml8(String(offset))}</td>`,
6005
+ `<td>${escapeHtml8(event.type)}</td>`,
6006
+ `<td>${escapeHtml8(event.turnId ?? "")}</td>`,
6007
+ `<td><code>${escapeHtml8(JSON.stringify(event.payload))}</code></td>`,
5834
6008
  "</tr>"
5835
6009
  ].join("");
5836
6010
  }).join(`
@@ -5841,7 +6015,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
5841
6015
  "<head>",
5842
6016
  '<meta charset="utf-8" />',
5843
6017
  '<meta name="viewport" content="width=device-width, initial-scale=1" />',
5844
- `<title>${escapeHtml7(options.title ?? "Voice Trace")}</title>`,
6018
+ `<title>${escapeHtml8(options.title ?? "Voice Trace")}</title>`,
5845
6019
  "<style>",
5846
6020
  "body{font-family:ui-sans-serif,system-ui,sans-serif;margin:2rem;line-height:1.45;background:#f8f7f2;color:#181713}",
5847
6021
  "main{max-width:1100px;margin:auto}",
@@ -5855,7 +6029,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
5855
6029
  "</style>",
5856
6030
  "</head>",
5857
6031
  "<body><main>",
5858
- `<h1>${escapeHtml7(options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim())}</h1>`,
6032
+ `<h1>${escapeHtml8(options.title ?? `Voice Trace ${summary.sessionId ?? ""}`.trim())}</h1>`,
5859
6033
  `<p class="${evaluation.pass ? "pass" : "fail"}">QA: ${evaluation.pass ? "pass" : "fail"}</p>`,
5860
6034
  '<section class="summary">',
5861
6035
  `<div class="card"><strong>Events</strong><br>${summary.eventCount}</div>`,
@@ -5869,7 +6043,7 @@ var renderVoiceTraceHTML = (events, options = {}) => {
5869
6043
  eventRows,
5870
6044
  "</tbody></table>",
5871
6045
  "<h2>Markdown Export</h2>",
5872
- `<pre>${escapeHtml7(markdown)}</pre>`,
6046
+ `<pre>${escapeHtml8(markdown)}</pre>`,
5873
6047
  "</main></body></html>"
5874
6048
  ].join(`
5875
6049
  `);
@@ -7623,7 +7797,7 @@ var buildVoiceProofTrendRecommendationReport = (report, options = {}) => {
7623
7797
  }
7624
7798
  };
7625
7799
  };
7626
- var escapeHtml8 = (value) => String(value).replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7800
+ var escapeHtml9 = (value) => String(value).replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
7627
7801
  var escapeMarkdown = (value) => value.replaceAll("|", "\\|");
7628
7802
  var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provider Runtime Recommendations") => [
7629
7803
  `# ${title}`,
@@ -7656,11 +7830,11 @@ var renderVoiceProofTrendRecommendationMarkdown = (report, title = "Voice Provid
7656
7830
  ].join(`
7657
7831
  `);
7658
7832
  var renderVoiceProofTrendRecommendationHTML = (report, title = "Voice Provider Runtime Recommendations") => {
7659
- const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml8(recommendation.status)}"><p class="eyebrow">${escapeHtml8(recommendation.surface)} \xB7 ${escapeHtml8(recommendation.status)}</p><h2>${escapeHtml8(recommendation.recommendation)}</h2><p>${escapeHtml8(recommendation.nextMove)}</p><pre>${escapeHtml8(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
7660
- const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml8(issue)}</li>`).join("");
7661
- const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml8(provider.label ?? provider.id)}</strong><span>${escapeHtml8(provider.role ?? "provider")} \xB7 ${escapeHtml8(provider.status)} \xB7 p95 ${escapeHtml8(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml8(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml8(provider.nextMove)}</small></li>`).join("");
7662
- const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml8(profile.label ?? profile.id)}</strong><span>${escapeHtml8(profile.status)} \xB7 ${escapeHtml8(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml8(profile.nextMove)}</small></li>`).join("");
7663
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml8(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml8(title)}</h1><p>Generated ${escapeHtml8(report.generatedAt)} from ${escapeHtml8(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml8(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml8(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
7833
+ const cards = report.recommendations.map((recommendation) => `<article class="${escapeHtml9(recommendation.status)}"><p class="eyebrow">${escapeHtml9(recommendation.surface)} \xB7 ${escapeHtml9(recommendation.status)}</p><h2>${escapeHtml9(recommendation.recommendation)}</h2><p>${escapeHtml9(recommendation.nextMove)}</p><pre>${escapeHtml9(JSON.stringify(recommendation.evidence, null, 2))}</pre></article>`).join("");
7834
+ const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml9(issue)}</li>`).join("");
7835
+ const providerRows = report.providers.length === 0 ? "<li>No provider-specific samples were present.</li>" : report.providers.map((provider) => `<li><strong>#${String(provider.rank)} ${escapeHtml9(provider.label ?? provider.id)}</strong><span>${escapeHtml9(provider.role ?? "provider")} \xB7 ${escapeHtml9(provider.status)} \xB7 p95 ${escapeHtml9(provider.p95Ms ?? "n/a")}ms \xB7 ${escapeHtml9(provider.samples ?? "n/a")} sample(s)</span><small>${escapeHtml9(provider.nextMove)}</small></li>`).join("");
7836
+ const profileRows = report.profiles.length === 0 ? "<li>No benchmark profiles were present.</li>" : report.profiles.map((profile) => `<li><strong>${escapeHtml9(profile.label ?? profile.id)}</strong><span>${escapeHtml9(profile.status)} \xB7 ${escapeHtml9(formatProviderMix(profile.bestProviders))}</span><small>${escapeHtml9(profile.nextMove)}</small></li>`).join("");
7837
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml9(title)}</title><style>body{background:#101418;color:#f7f3e8;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article{background:#17201d;border:1px solid #2e3d36;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(20,184,166,.18),rgba(245,158,11,.12))}.eyebrow{color:#5eead4;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #42534a;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}pre{background:#0b1110;border-radius:14px;overflow:auto;padding:12px}a{color:#5eead4}li{margin:.45rem 0}li span,li small{display:block;color:#c9d3ca}</style></head><body><main><section class="hero"><p class="eyebrow">Sustained proof recommendations</p><h1>${escapeHtml9(title)}</h1><p>Generated ${escapeHtml9(report.generatedAt)} from ${escapeHtml9(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml9(report.status)}</span><span class="pill">Provider ${report.summary.keepCurrentProviderPath ? "keep" : "change"}</span><span class="pill">Best mix ${escapeHtml9(formatProviderMix(report.bestProviders))}</span><span class="pill">Profiles ${String(report.profiles.length)}</span><span class="pill">Runtime ${report.summary.keepCurrentRuntimeChannel ? "keep" : "tune"}</span><span class="pill">${String(report.summary.recommendedActions)} action(s)</span></div></section>${cards}<section class="hero"><h2>Benchmark Profiles</h2><ul>${profileRows}</ul></section><section class="hero"><h2>Provider Comparison</h2><ul>${providerRows}</ul></section><section class="hero"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
7664
7838
  };
7665
7839
  var renderVoiceRealCallProfileHistoryMarkdown = (report, title = "Voice Real-Call Profile History") => [
7666
7840
  `# ${title}`,
@@ -7694,11 +7868,11 @@ var renderVoiceRealCallProfileHistoryMarkdown = (report, title = "Voice Real-Cal
7694
7868
  ].join(`
7695
7869
  `);
7696
7870
  var renderVoiceRealCallProfileHistoryHTML = (report, title = "Voice Real-Call Profile History") => {
7697
- const profileRows = report.summary.profiles?.length ? report.summary.profiles.map((profile) => `<tr><td>${escapeHtml8(profile.label ?? profile.id)}</td><td>${escapeHtml8(profile.status ?? "unknown")}</td><td>${escapeHtml8(profile.maxLiveP95Ms ?? "n/a")}</td><td>${escapeHtml8(profile.maxProviderP95Ms ?? "n/a")}</td><td>${escapeHtml8(profile.maxTurnP95Ms ?? "n/a")}</td><td>${escapeHtml8(formatProviderMix(profile.providers ?? []))}</td></tr>`).join("") : '<tr><td colspan="6">No profiles present.</td></tr>';
7698
- const defaultRows = report.defaults.profiles.length > 0 ? report.defaults.profiles.map((profile) => `<tr><td>${escapeHtml8(profile.label ?? profile.profileId)}</td><td>${escapeHtml8(profile.status)}</td><td>${escapeHtml8(Object.entries(profile.providerRoutes).map(([role, provider]) => `${role}: ${provider}`).join(", ") || "n/a")}</td><td>${escapeHtml8(profile.latencyBudgets.maxLiveP95Ms ?? "n/a")}</td><td>${escapeHtml8(profile.latencyBudgets.maxProviderP95Ms ?? "n/a")}</td><td>${escapeHtml8(profile.latencyBudgets.maxTurnP95Ms ?? "n/a")}</td></tr>`).join("") : '<tr><td colspan="6">No actionable defaults present.</td></tr>';
7699
- const recommendations = report.recommendations.recommendations.map((recommendation) => `<article class="${escapeHtml8(recommendation.status)}"><p class="eyebrow">${escapeHtml8(recommendation.surface)} \xB7 ${escapeHtml8(recommendation.status)}</p><h2>${escapeHtml8(recommendation.recommendation)}</h2><p>${escapeHtml8(recommendation.nextMove)}</p></article>`).join("");
7700
- const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml8(issue)}</li>`).join("");
7701
- return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml8(title)}</title><style>body{background:#111510;color:#f6f0dd;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article,.card{background:#182117;border:1px solid #32412d;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(132,204,22,.16),rgba(20,184,166,.12))}.eyebrow{color:#bef264;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #52624b;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #32412d;padding:10px;text-align:left}</style></head><body><main><section class="hero"><p class="eyebrow">Real-call benchmark history</p><h1>${escapeHtml8(title)}</h1><p>Generated ${escapeHtml8(report.generatedAt)} from ${escapeHtml8(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml8(report.status)}</span><span class="pill">Reports ${String(report.reports)}</span><span class="pill">Profiles ${String(report.summary.profileCount)}</span><span class="pill">Defaults ${String(report.defaults.summary.actionableProfiles)}/${String(report.defaults.summary.profileCount)}</span><span class="pill">Cycles ${String(report.summary.cycles ?? 0)}</span><span class="pill">Best mix ${escapeHtml8(formatProviderMix(report.recommendations.bestProviders))}</span></div></section><section class="card"><h2>Profiles</h2><table><thead><tr><th>Profile</th><th>Status</th><th>Live p95</th><th>Provider p95</th><th>Turn p95</th><th>Provider mix</th></tr></thead><tbody>${profileRows}</tbody></table></section><section class="card"><h2>Actionable Defaults</h2><table><thead><tr><th>Profile</th><th>Status</th><th>Provider routes</th><th>Live budget</th><th>Provider budget</th><th>Turn budget</th></tr></thead><tbody>${defaultRows}</tbody></table></section>${recommendations}<section class="card"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
7871
+ const profileRows = report.summary.profiles?.length ? report.summary.profiles.map((profile) => `<tr><td>${escapeHtml9(profile.label ?? profile.id)}</td><td>${escapeHtml9(profile.status ?? "unknown")}</td><td>${escapeHtml9(profile.maxLiveP95Ms ?? "n/a")}</td><td>${escapeHtml9(profile.maxProviderP95Ms ?? "n/a")}</td><td>${escapeHtml9(profile.maxTurnP95Ms ?? "n/a")}</td><td>${escapeHtml9(formatProviderMix(profile.providers ?? []))}</td></tr>`).join("") : '<tr><td colspan="6">No profiles present.</td></tr>';
7872
+ const defaultRows = report.defaults.profiles.length > 0 ? report.defaults.profiles.map((profile) => `<tr><td>${escapeHtml9(profile.label ?? profile.profileId)}</td><td>${escapeHtml9(profile.status)}</td><td>${escapeHtml9(Object.entries(profile.providerRoutes).map(([role, provider]) => `${role}: ${provider}`).join(", ") || "n/a")}</td><td>${escapeHtml9(profile.latencyBudgets.maxLiveP95Ms ?? "n/a")}</td><td>${escapeHtml9(profile.latencyBudgets.maxProviderP95Ms ?? "n/a")}</td><td>${escapeHtml9(profile.latencyBudgets.maxTurnP95Ms ?? "n/a")}</td></tr>`).join("") : '<tr><td colspan="6">No actionable defaults present.</td></tr>';
7873
+ const recommendations = report.recommendations.recommendations.map((recommendation) => `<article class="${escapeHtml9(recommendation.status)}"><p class="eyebrow">${escapeHtml9(recommendation.surface)} \xB7 ${escapeHtml9(recommendation.status)}</p><h2>${escapeHtml9(recommendation.recommendation)}</h2><p>${escapeHtml9(recommendation.nextMove)}</p></article>`).join("");
7874
+ const issues = report.issues.length === 0 ? "<li>None</li>" : report.issues.map((issue) => `<li>${escapeHtml9(issue)}</li>`).join("");
7875
+ return `<!doctype html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1" /><title>${escapeHtml9(title)}</title><style>body{background:#111510;color:#f6f0dd;font-family:ui-sans-serif,system-ui,sans-serif;margin:0}main{margin:auto;max-width:1120px;padding:32px}.hero,article,.card{background:#182117;border:1px solid #32412d;border-radius:24px;margin-bottom:16px;padding:22px}.hero{background:linear-gradient(135deg,rgba(132,204,22,.16),rgba(20,184,166,.12))}.eyebrow{color:#bef264;font-weight:900;letter-spacing:.1em;text-transform:uppercase}h1{font-size:clamp(2.2rem,6vw,4.7rem);letter-spacing:-.06em;line-height:.92;margin:.2rem 0 1rem}.summary{display:flex;flex-wrap:wrap;gap:10px}.pill{border:1px solid #52624b;border-radius:999px;padding:8px 12px}.pass{border-color:rgba(34,197,94,.55)}.warn{border-color:rgba(245,158,11,.7)}.fail{border-color:rgba(239,68,68,.75)}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #32412d;padding:10px;text-align:left}</style></head><body><main><section class="hero"><p class="eyebrow">Real-call benchmark history</p><h1>${escapeHtml9(title)}</h1><p>Generated ${escapeHtml9(report.generatedAt)} from ${escapeHtml9(report.source)}.</p><div class="summary"><span class="pill">Status ${escapeHtml9(report.status)}</span><span class="pill">Reports ${String(report.reports)}</span><span class="pill">Profiles ${String(report.summary.profileCount)}</span><span class="pill">Defaults ${String(report.defaults.summary.actionableProfiles)}/${String(report.defaults.summary.profileCount)}</span><span class="pill">Cycles ${String(report.summary.cycles ?? 0)}</span><span class="pill">Best mix ${escapeHtml9(formatProviderMix(report.recommendations.bestProviders))}</span></div></section><section class="card"><h2>Profiles</h2><table><thead><tr><th>Profile</th><th>Status</th><th>Live p95</th><th>Provider p95</th><th>Turn p95</th><th>Provider mix</th></tr></thead><tbody>${profileRows}</tbody></table></section><section class="card"><h2>Actionable Defaults</h2><table><thead><tr><th>Profile</th><th>Status</th><th>Provider routes</th><th>Live budget</th><th>Provider budget</th><th>Turn budget</th></tr></thead><tbody>${defaultRows}</tbody></table></section>${recommendations}<section class="card"><h2>Issues</h2><ul>${issues}</ul></section></main></body></html>`;
7702
7876
  };
7703
7877
  var createVoiceProofTrendRecommendationRoutes = (options) => {
7704
7878
  const path = options.path ?? "/api/voice/proof-trend-recommendations";
@@ -8008,13 +8182,13 @@ var formatVoiceProofTrendAge = (ageMs) => {
8008
8182
  };
8009
8183
 
8010
8184
  // src/client/proofTrendsWidget.ts
8011
- var DEFAULT_TITLE4 = "Sustained Proof Trends";
8012
- var DEFAULT_DESCRIPTION4 = "Repeated-cycle provider, latency, recovery, and readiness evidence with freshness gating.";
8185
+ var DEFAULT_TITLE5 = "Sustained Proof Trends";
8186
+ var DEFAULT_DESCRIPTION5 = "Repeated-cycle provider, latency, recovery, and readiness evidence with freshness gating.";
8013
8187
  var DEFAULT_LINKS2 = [
8014
8188
  { href: "/voice/proof-trends", label: "Trend page" },
8015
8189
  { href: "/api/voice/proof-trends", label: "Trend JSON" }
8016
8190
  ];
8017
- var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8191
+ var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8018
8192
  var formatMs = (value) => typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}ms` : "n/a";
8019
8193
  var statusLabel = (report) => {
8020
8194
  if (!report) {
@@ -8049,7 +8223,7 @@ var createVoiceProofTrendsViewModel = (snapshot, options = {}) => {
8049
8223
  }
8050
8224
  ] : [];
8051
8225
  return {
8052
- description: options.description ?? DEFAULT_DESCRIPTION4,
8226
+ description: options.description ?? DEFAULT_DESCRIPTION5,
8053
8227
  error: snapshot.error,
8054
8228
  isLoading: snapshot.isLoading,
8055
8229
  label: snapshot.error ? "Unavailable" : report ? statusLabel(report) : snapshot.isLoading ? "Checking" : "No trend report",
@@ -8057,26 +8231,26 @@ var createVoiceProofTrendsViewModel = (snapshot, options = {}) => {
8057
8231
  metrics,
8058
8232
  report,
8059
8233
  status: snapshot.error ? "error" : report ? report.status === "pass" ? "ready" : "warning" : snapshot.isLoading ? "loading" : "empty",
8060
- title: options.title ?? DEFAULT_TITLE4,
8234
+ title: options.title ?? DEFAULT_TITLE5,
8061
8235
  updatedAt: snapshot.updatedAt
8062
8236
  };
8063
8237
  };
8064
8238
  var renderVoiceProofTrendsHTML = (snapshot, options = {}) => {
8065
8239
  const model = createVoiceProofTrendsViewModel(snapshot, options);
8066
8240
  const metrics = model.metrics.length ? `<div class="absolute-voice-proof-trends__metrics">${model.metrics.map((metric) => `<article>
8067
- <span>${escapeHtml9(metric.label)}</span>
8068
- <strong>${escapeHtml9(metric.value)}</strong>
8069
- </article>`).join("")}</div>` : `<p class="absolute-voice-proof-trends__empty">${model.error ? escapeHtml9(model.error) : "Run the sustained proof trends script to populate evidence."}</p>`;
8070
- const links = model.links.length ? `<p class="absolute-voice-proof-trends__links">${model.links.map((link) => `<a href="${escapeHtml9(link.href)}">${escapeHtml9(link.label)}</a>`).join("")}</p>` : "";
8071
- return `<section class="absolute-voice-proof-trends absolute-voice-proof-trends--${escapeHtml9(model.status)}">
8241
+ <span>${escapeHtml10(metric.label)}</span>
8242
+ <strong>${escapeHtml10(metric.value)}</strong>
8243
+ </article>`).join("")}</div>` : `<p class="absolute-voice-proof-trends__empty">${model.error ? escapeHtml10(model.error) : "Run the sustained proof trends script to populate evidence."}</p>`;
8244
+ const links = model.links.length ? `<p class="absolute-voice-proof-trends__links">${model.links.map((link) => `<a href="${escapeHtml10(link.href)}">${escapeHtml10(link.label)}</a>`).join("")}</p>` : "";
8245
+ return `<section class="absolute-voice-proof-trends absolute-voice-proof-trends--${escapeHtml10(model.status)}">
8072
8246
  <header class="absolute-voice-proof-trends__header">
8073
- <span class="absolute-voice-proof-trends__eyebrow">${escapeHtml9(model.title)}</span>
8074
- <strong class="absolute-voice-proof-trends__label">${escapeHtml9(model.label)}</strong>
8247
+ <span class="absolute-voice-proof-trends__eyebrow">${escapeHtml10(model.title)}</span>
8248
+ <strong class="absolute-voice-proof-trends__label">${escapeHtml10(model.label)}</strong>
8075
8249
  </header>
8076
- <p class="absolute-voice-proof-trends__description">${escapeHtml9(model.description)}</p>
8250
+ <p class="absolute-voice-proof-trends__description">${escapeHtml10(model.description)}</p>
8077
8251
  ${metrics}
8078
8252
  ${links}
8079
- ${model.error ? `<p class="absolute-voice-proof-trends__error">${escapeHtml9(model.error)}</p>` : ""}
8253
+ ${model.error ? `<p class="absolute-voice-proof-trends__error">${escapeHtml10(model.error)}</p>` : ""}
8080
8254
  </section>`;
8081
8255
  };
8082
8256
  var getVoiceProofTrendsCSS = () => `.absolute-voice-proof-trends{border:1px solid #99f6e4;border-radius:20px;background:#f0fdfa;color:#0f172a;padding:18px;box-shadow:0 18px 40px rgba(13,148,136,.12);font-family:inherit}.absolute-voice-proof-trends--warning,.absolute-voice-proof-trends--error{border-color:#f2a7a7;background:#fff7f4}.absolute-voice-proof-trends__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-proof-trends__eyebrow{color:#0f766e;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-proof-trends__label{font-size:24px;line-height:1}.absolute-voice-proof-trends__description,.absolute-voice-proof-trends__empty{color:#475569}.absolute-voice-proof-trends__metrics{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));margin-top:14px}.absolute-voice-proof-trends__metrics article{background:#fff;border:1px solid #ccfbf1;border-radius:16px;padding:12px}.absolute-voice-proof-trends__metrics span{color:#64748b;display:block;font-size:12px;font-weight:800;text-transform:uppercase}.absolute-voice-proof-trends__metrics strong{display:block;font-size:20px;margin-top:4px}.absolute-voice-proof-trends__links{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 0}.absolute-voice-proof-trends__links a{border:1px solid #99f6e4;border-radius:999px;color:#0f766e;font-weight:800;padding:6px 10px;text-decoration:none}.absolute-voice-proof-trends__error{color:#9f1239;font-weight:700}`;
@@ -8116,13 +8290,13 @@ var defineVoiceProofTrendsElement = (tagName = "absolute-voice-proof-trends") =>
8116
8290
  });
8117
8291
  };
8118
8292
  // src/client/profileComparisonWidget.ts
8119
- var DEFAULT_TITLE5 = "Profile Stack Comparison";
8120
- var DEFAULT_DESCRIPTION5 = "Measured real-call evidence behind each profile default: provider routes, latency, and the next move.";
8293
+ var DEFAULT_TITLE6 = "Profile Stack Comparison";
8294
+ var DEFAULT_DESCRIPTION6 = "Measured real-call evidence behind each profile default: provider routes, latency, and the next move.";
8121
8295
  var DEFAULT_LINKS3 = [
8122
8296
  { href: "/voice/real-call-profile-history", label: "Profile history" },
8123
8297
  { href: "/api/voice/real-call-profile-history", label: "JSON" }
8124
8298
  ];
8125
- var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8299
+ var escapeHtml11 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8126
8300
  var formatMs2 = (value) => typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}ms` : "n/a";
8127
8301
  var formatProviderRoutes = (profile) => Object.entries(profile.providerRoutes).map(([role, provider]) => `${role}: ${provider}`).join(", ") || "No complete route yet";
8128
8302
  var createProfileView = (profile) => ({
@@ -8141,37 +8315,37 @@ var createVoiceProfileComparisonViewModel = (snapshot, options = {}) => {
8141
8315
  const report = snapshot.report;
8142
8316
  const profiles = report?.defaults.profiles.map(createProfileView) ?? [];
8143
8317
  return {
8144
- description: options.description ?? DEFAULT_DESCRIPTION5,
8318
+ description: options.description ?? DEFAULT_DESCRIPTION6,
8145
8319
  error: snapshot.error,
8146
8320
  isLoading: snapshot.isLoading,
8147
8321
  label: snapshot.error ? "Unavailable" : report ? `${report.defaults.summary.actionableProfiles}/${report.defaults.summary.profileCount} profiles ready` : snapshot.isLoading ? "Checking" : "No profile evidence",
8148
8322
  links: options.links ?? DEFAULT_LINKS3,
8149
8323
  profiles,
8150
8324
  status: snapshot.error ? "error" : report ? report.status === "pass" ? "ready" : "warning" : snapshot.isLoading ? "loading" : "empty",
8151
- title: options.title ?? DEFAULT_TITLE5
8325
+ title: options.title ?? DEFAULT_TITLE6
8152
8326
  };
8153
8327
  };
8154
8328
  var renderVoiceProfileComparisonHTML = (snapshot, options = {}) => {
8155
8329
  const model = createVoiceProfileComparisonViewModel(snapshot, options);
8156
- 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--${escapeHtml10(profile.status)}">
8330
+ 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--${escapeHtml11(profile.status)}">
8157
8331
  <header>
8158
- <span>${escapeHtml10(profile.status)}</span>
8159
- <strong>${escapeHtml10(profile.label)}</strong>
8332
+ <span>${escapeHtml11(profile.status)}</span>
8333
+ <strong>${escapeHtml11(profile.label)}</strong>
8160
8334
  </header>
8161
- <p>${escapeHtml10(profile.providerRoutes)}</p>
8162
- <div>${profile.evidence.map((metric) => `<span><small>${escapeHtml10(metric.label)}</small><b>${escapeHtml10(metric.value)}</b></span>`).join("")}</div>
8163
- <em>${escapeHtml10(profile.nextMove)}</em>
8164
- </article>`).join("")}</div>` : `<p class="absolute-voice-profile-comparison__empty">${model.error ? escapeHtml10(model.error) : "Run real-call profile collection to populate profile comparisons."}</p>`;
8165
- const links = model.links.length ? `<p class="absolute-voice-profile-comparison__links">${model.links.map((link) => `<a href="${escapeHtml10(link.href)}">${escapeHtml10(link.label)}</a>`).join("")}</p>` : "";
8166
- return `<section class="absolute-voice-profile-comparison absolute-voice-profile-comparison--${escapeHtml10(model.status)}">
8335
+ <p>${escapeHtml11(profile.providerRoutes)}</p>
8336
+ <div>${profile.evidence.map((metric) => `<span><small>${escapeHtml11(metric.label)}</small><b>${escapeHtml11(metric.value)}</b></span>`).join("")}</div>
8337
+ <em>${escapeHtml11(profile.nextMove)}</em>
8338
+ </article>`).join("")}</div>` : `<p class="absolute-voice-profile-comparison__empty">${model.error ? escapeHtml11(model.error) : "Run real-call profile collection to populate profile comparisons."}</p>`;
8339
+ const links = model.links.length ? `<p class="absolute-voice-profile-comparison__links">${model.links.map((link) => `<a href="${escapeHtml11(link.href)}">${escapeHtml11(link.label)}</a>`).join("")}</p>` : "";
8340
+ return `<section class="absolute-voice-profile-comparison absolute-voice-profile-comparison--${escapeHtml11(model.status)}">
8167
8341
  <header class="absolute-voice-profile-comparison__header">
8168
- <span class="absolute-voice-profile-comparison__eyebrow">${escapeHtml10(model.title)}</span>
8169
- <strong class="absolute-voice-profile-comparison__label">${escapeHtml10(model.label)}</strong>
8342
+ <span class="absolute-voice-profile-comparison__eyebrow">${escapeHtml11(model.title)}</span>
8343
+ <strong class="absolute-voice-profile-comparison__label">${escapeHtml11(model.label)}</strong>
8170
8344
  </header>
8171
- <p class="absolute-voice-profile-comparison__description">${escapeHtml10(model.description)}</p>
8345
+ <p class="absolute-voice-profile-comparison__description">${escapeHtml11(model.description)}</p>
8172
8346
  ${profiles}
8173
8347
  ${links}
8174
- ${model.error ? `<p class="absolute-voice-profile-comparison__error">${escapeHtml10(model.error)}</p>` : ""}
8348
+ ${model.error ? `<p class="absolute-voice-profile-comparison__error">${escapeHtml11(model.error)}</p>` : ""}
8175
8349
  </section>`;
8176
8350
  };
8177
8351
  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}`;
@@ -8212,29 +8386,29 @@ var defineVoiceProfileComparisonElement = (tagName = "absolute-voice-profile-com
8212
8386
  });
8213
8387
  };
8214
8388
  // src/client/profileSwitchRecommendationWidget.ts
8215
- var DEFAULT_TITLE6 = "Profile Switch Recommendation";
8216
- var DEFAULT_DESCRIPTION6 = "Compares the current session against measured profile evidence and recommends whether to switch stacks.";
8217
- var escapeHtml11 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8389
+ var DEFAULT_TITLE7 = "Profile Switch Recommendation";
8390
+ var DEFAULT_DESCRIPTION7 = "Compares the current session against measured profile evidence and recommends whether to switch stacks.";
8391
+ var escapeHtml12 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8218
8392
  var formatRoute = (routes) => routes ? Object.entries(routes).map(([role, provider]) => `${role}: ${provider}`).join(", ") : "No route";
8219
8393
  var renderVoiceProfileSwitchRecommendationHTML = (snapshot, options = {}) => {
8220
8394
  const recommendation = snapshot.recommendation;
8221
8395
  const status = snapshot.error ? "error" : recommendation ? recommendation.status : snapshot.isLoading ? "loading" : "empty";
8222
8396
  const label = snapshot.error ? "Unavailable" : recommendation ? recommendation.status === "switch" ? `Switch to ${recommendation.recommendedProfile?.label ?? recommendation.recommendedProfile?.profileId ?? "recommended profile"}` : recommendation.status === "stay" ? "Keep current profile" : "Needs evidence" : snapshot.isLoading ? "Checking" : "No recommendation";
8223
8397
  const body = recommendation ? `<div class="absolute-voice-profile-switch__body">
8224
- <p><strong>Current:</strong> ${escapeHtml11(recommendation.currentProfile?.label ?? recommendation.currentProfile?.profileId ?? "Unknown")}</p>
8225
- <p><strong>Recommended:</strong> ${escapeHtml11(recommendation.recommendedProfile?.label ?? recommendation.recommendedProfile?.profileId ?? "None")}</p>
8226
- <p><strong>Routes:</strong> ${escapeHtml11(formatRoute(recommendation.recommendedProfile?.providerRoutes))}</p>
8227
- <ul>${recommendation.reasons.map((reason) => `<li>${escapeHtml11(reason)}</li>`).join("")}</ul>
8228
- <em>${escapeHtml11(recommendation.nextMove)}</em>
8229
- </div>` : `<p class="absolute-voice-profile-switch__empty">${escapeHtml11(snapshot.error ?? "Run session traffic to populate a recommendation.")}</p>`;
8230
- return `<section class="absolute-voice-profile-switch absolute-voice-profile-switch--${escapeHtml11(status)}">
8398
+ <p><strong>Current:</strong> ${escapeHtml12(recommendation.currentProfile?.label ?? recommendation.currentProfile?.profileId ?? "Unknown")}</p>
8399
+ <p><strong>Recommended:</strong> ${escapeHtml12(recommendation.recommendedProfile?.label ?? recommendation.recommendedProfile?.profileId ?? "None")}</p>
8400
+ <p><strong>Routes:</strong> ${escapeHtml12(formatRoute(recommendation.recommendedProfile?.providerRoutes))}</p>
8401
+ <ul>${recommendation.reasons.map((reason) => `<li>${escapeHtml12(reason)}</li>`).join("")}</ul>
8402
+ <em>${escapeHtml12(recommendation.nextMove)}</em>
8403
+ </div>` : `<p class="absolute-voice-profile-switch__empty">${escapeHtml12(snapshot.error ?? "Run session traffic to populate a recommendation.")}</p>`;
8404
+ return `<section class="absolute-voice-profile-switch absolute-voice-profile-switch--${escapeHtml12(status)}">
8231
8405
  <header class="absolute-voice-profile-switch__header">
8232
- <span class="absolute-voice-profile-switch__eyebrow">${escapeHtml11(options.title ?? DEFAULT_TITLE6)}</span>
8233
- <strong class="absolute-voice-profile-switch__label">${escapeHtml11(label)}</strong>
8406
+ <span class="absolute-voice-profile-switch__eyebrow">${escapeHtml12(options.title ?? DEFAULT_TITLE7)}</span>
8407
+ <strong class="absolute-voice-profile-switch__label">${escapeHtml12(label)}</strong>
8234
8408
  </header>
8235
- <p class="absolute-voice-profile-switch__description">${escapeHtml11(options.description ?? DEFAULT_DESCRIPTION6)}</p>
8409
+ <p class="absolute-voice-profile-switch__description">${escapeHtml12(options.description ?? DEFAULT_DESCRIPTION7)}</p>
8236
8410
  ${body}
8237
- ${snapshot.error ? `<p class="absolute-voice-profile-switch__error">${escapeHtml11(snapshot.error)}</p>` : ""}
8411
+ ${snapshot.error ? `<p class="absolute-voice-profile-switch__error">${escapeHtml12(snapshot.error)}</p>` : ""}
8238
8412
  </section>`;
8239
8413
  };
8240
8414
  var getVoiceProfileSwitchRecommendationCSS = () => `.absolute-voice-profile-switch{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-profile-switch--switch{border-color:#fdba74}.absolute-voice-profile-switch--stay{border-color:#86efac;background:#f0fdf4}.absolute-voice-profile-switch--warn,.absolute-voice-profile-switch--error{border-color:#fca5a5;background:#fff1f2}.absolute-voice-profile-switch__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-profile-switch__eyebrow{color:#c2410c;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-profile-switch__label{font-size:24px;line-height:1}.absolute-voice-profile-switch__description,.absolute-voice-profile-switch__body em,.absolute-voice-profile-switch__empty{color:#57534e}.absolute-voice-profile-switch__body{background:#fff;border:1px solid #fed7aa;border-radius:16px;margin-top:14px;padding:14px}.absolute-voice-profile-switch__body p{margin:.35rem 0}.absolute-voice-profile-switch__body ul{margin:.75rem 0;padding-left:1.2rem}.absolute-voice-profile-switch__body em{display:block}.absolute-voice-profile-switch__error{color:#9f1239;font-weight:700}`;
@@ -8275,13 +8449,13 @@ var defineVoiceProfileSwitchRecommendationElement = (tagName = "absolute-voice-p
8275
8449
  });
8276
8450
  };
8277
8451
  // src/client/readinessFailuresWidget.ts
8278
- var DEFAULT_TITLE7 = "Readiness Gate Explanations";
8279
- var DEFAULT_DESCRIPTION7 = "Structured reasons for calibrated production-readiness warnings and failures.";
8452
+ var DEFAULT_TITLE8 = "Readiness Gate Explanations";
8453
+ var DEFAULT_DESCRIPTION8 = "Structured reasons for calibrated production-readiness warnings and failures.";
8280
8454
  var DEFAULT_LINKS4 = [
8281
8455
  { href: "/production-readiness", label: "Readiness page" },
8282
8456
  { href: "/voice/slo-readiness-thresholds", label: "Gate thresholds" }
8283
8457
  ];
8284
- var escapeHtml12 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8458
+ var escapeHtml13 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8285
8459
  var formatExplanationValue = (value, unit) => {
8286
8460
  if (value === undefined || value === null) {
8287
8461
  return "n/a";
@@ -8309,36 +8483,36 @@ var createVoiceReadinessFailuresViewModel = (snapshot, options = {}) => {
8309
8483
  const failures = snapshot.report?.checks.map(toFailureView).filter((value) => !!value) ?? [];
8310
8484
  const hasOpenIssues = failures.length > 0;
8311
8485
  return {
8312
- description: options.description ?? DEFAULT_DESCRIPTION7,
8486
+ description: options.description ?? DEFAULT_DESCRIPTION8,
8313
8487
  error: snapshot.error,
8314
8488
  failures,
8315
8489
  isLoading: snapshot.isLoading,
8316
8490
  label: snapshot.error ? "Unavailable" : snapshot.report ? hasOpenIssues ? `${failures.length} calibrated gate issue(s)` : "No calibrated gate issues" : snapshot.isLoading ? "Checking" : "No readiness report",
8317
8491
  links: options.links ?? DEFAULT_LINKS4,
8318
8492
  status: snapshot.error ? "error" : snapshot.report ? hasOpenIssues ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
8319
- title: options.title ?? DEFAULT_TITLE7,
8493
+ title: options.title ?? DEFAULT_TITLE8,
8320
8494
  updatedAt: snapshot.updatedAt
8321
8495
  };
8322
8496
  };
8323
8497
  var renderVoiceReadinessFailuresHTML = (snapshot, options = {}) => {
8324
8498
  const model = createVoiceReadinessFailuresViewModel(snapshot, options);
8325
- 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--${escapeHtml12(failure.status)}">
8326
- <span>${escapeHtml12(failure.status.toUpperCase())}</span>
8327
- <strong>${escapeHtml12(failure.label)}</strong>
8328
- <p>Observed ${escapeHtml12(failure.observed)} against ${escapeHtml12(failure.thresholdLabel)} ${escapeHtml12(failure.threshold)}.</p>
8329
- <p>${escapeHtml12(failure.remediation)}</p>
8330
- <p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${escapeHtml12(failure.evidenceHref)}">Evidence</a>` : ""}${failure.sourceHref ? `<a href="${escapeHtml12(failure.sourceHref)}">Threshold source</a>` : ""}</p>
8331
- </article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ? escapeHtml12(model.error) : "No calibrated readiness gate explanations are open."}</p>`;
8332
- const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${escapeHtml12(link.href)}">${escapeHtml12(link.label)}</a>`).join("")}</p>` : "";
8333
- return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${escapeHtml12(model.status)}">
8499
+ 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--${escapeHtml13(failure.status)}">
8500
+ <span>${escapeHtml13(failure.status.toUpperCase())}</span>
8501
+ <strong>${escapeHtml13(failure.label)}</strong>
8502
+ <p>Observed ${escapeHtml13(failure.observed)} against ${escapeHtml13(failure.thresholdLabel)} ${escapeHtml13(failure.threshold)}.</p>
8503
+ <p>${escapeHtml13(failure.remediation)}</p>
8504
+ <p class="absolute-voice-readiness-failures__links">${failure.evidenceHref ? `<a href="${escapeHtml13(failure.evidenceHref)}">Evidence</a>` : ""}${failure.sourceHref ? `<a href="${escapeHtml13(failure.sourceHref)}">Threshold source</a>` : ""}</p>
8505
+ </article>`).join("")}</div>` : `<p class="absolute-voice-readiness-failures__empty">${model.error ? escapeHtml13(model.error) : "No calibrated readiness gate explanations are open."}</p>`;
8506
+ const links = model.links.length ? `<p class="absolute-voice-readiness-failures__links">${model.links.map((link) => `<a href="${escapeHtml13(link.href)}">${escapeHtml13(link.label)}</a>`).join("")}</p>` : "";
8507
+ return `<section class="absolute-voice-readiness-failures absolute-voice-readiness-failures--${escapeHtml13(model.status)}">
8334
8508
  <header class="absolute-voice-readiness-failures__header">
8335
- <span class="absolute-voice-readiness-failures__eyebrow">${escapeHtml12(model.title)}</span>
8336
- <strong class="absolute-voice-readiness-failures__label">${escapeHtml12(model.label)}</strong>
8509
+ <span class="absolute-voice-readiness-failures__eyebrow">${escapeHtml13(model.title)}</span>
8510
+ <strong class="absolute-voice-readiness-failures__label">${escapeHtml13(model.label)}</strong>
8337
8511
  </header>
8338
- <p class="absolute-voice-readiness-failures__description">${escapeHtml12(model.description)}</p>
8512
+ <p class="absolute-voice-readiness-failures__description">${escapeHtml13(model.description)}</p>
8339
8513
  ${failures}
8340
8514
  ${links}
8341
- ${model.error ? `<p class="absolute-voice-readiness-failures__error">${escapeHtml12(model.error)}</p>` : ""}
8515
+ ${model.error ? `<p class="absolute-voice-readiness-failures__error">${escapeHtml13(model.error)}</p>` : ""}
8342
8516
  </section>`;
8343
8517
  };
8344
8518
  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}`;
@@ -8378,9 +8552,9 @@ var defineVoiceReadinessFailuresElement = (tagName = "absolute-voice-readiness-f
8378
8552
  });
8379
8553
  };
8380
8554
  // src/client/opsActionCenterWidget.ts
8381
- var DEFAULT_TITLE8 = "Voice Ops Action Center";
8382
- var DEFAULT_DESCRIPTION8 = "Run production voice proofs and operator actions from one primitive panel.";
8383
- var escapeHtml13 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8555
+ var DEFAULT_TITLE9 = "Voice Ops Action Center";
8556
+ var DEFAULT_DESCRIPTION9 = "Run production voice proofs and operator actions from one primitive panel.";
8557
+ var escapeHtml14 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8384
8558
  var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
8385
8559
  const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
8386
8560
  return {
@@ -8391,29 +8565,29 @@ var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
8391
8565
  isRunning: snapshot.runningActionId === action.id,
8392
8566
  label: action.label
8393
8567
  })),
8394
- description: options.description ?? DEFAULT_DESCRIPTION8,
8568
+ description: options.description ?? DEFAULT_DESCRIPTION9,
8395
8569
  error: snapshot.error,
8396
8570
  isRunning: snapshot.isRunning,
8397
8571
  label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
8398
8572
  lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
8399
8573
  status,
8400
- title: options.title ?? DEFAULT_TITLE8
8574
+ title: options.title ?? DEFAULT_TITLE9
8401
8575
  };
8402
8576
  };
8403
8577
  var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
8404
8578
  const model = createVoiceOpsActionCenterViewModel(snapshot, options);
8405
- const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml13(action.id)}"${action.disabled ? " disabled" : ""}>
8406
- ${escapeHtml13(action.isRunning ? "Working..." : action.label)}
8579
+ const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml14(action.id)}"${action.disabled ? " disabled" : ""}>
8580
+ ${escapeHtml14(action.isRunning ? "Working..." : action.label)}
8407
8581
  </button>`).join("");
8408
- return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml13(model.status)}">
8582
+ return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml14(model.status)}">
8409
8583
  <header class="absolute-voice-ops-action-center__header">
8410
- <span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml13(model.title)}</span>
8411
- <strong class="absolute-voice-ops-action-center__label">${escapeHtml13(model.label)}</strong>
8584
+ <span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml14(model.title)}</span>
8585
+ <strong class="absolute-voice-ops-action-center__label">${escapeHtml14(model.label)}</strong>
8412
8586
  </header>
8413
- <p class="absolute-voice-ops-action-center__description">${escapeHtml13(model.description)}</p>
8587
+ <p class="absolute-voice-ops-action-center__description">${escapeHtml14(model.description)}</p>
8414
8588
  <div class="absolute-voice-ops-action-center__actions">${actions}</div>
8415
- <p class="absolute-voice-ops-action-center__result">${escapeHtml13(model.lastResultLabel)}</p>
8416
- ${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml13(model.error)}</p>` : ""}
8589
+ <p class="absolute-voice-ops-action-center__result">${escapeHtml14(model.lastResultLabel)}</p>
8590
+ ${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml14(model.error)}</p>` : ""}
8417
8591
  </section>`;
8418
8592
  };
8419
8593
  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}`;
@@ -8975,7 +9149,7 @@ var ACTION_LABELS = {
8975
9149
  "resume-assistant": "Resume assistant",
8976
9150
  tag: "Tag"
8977
9151
  };
8978
- var escapeHtml14 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
9152
+ var escapeHtml15 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
8979
9153
  var createVoiceLiveOpsInput = (action, input) => ({
8980
9154
  action,
8981
9155
  assignee: input.assignee,
@@ -8986,17 +9160,17 @@ var createVoiceLiveOpsInput = (action, input) => ({
8986
9160
  var renderVoiceLiveOpsHTML = (snapshot, options = {}) => {
8987
9161
  const sessionId = options.getSessionId?.() ?? "";
8988
9162
  const disabled = snapshot.isRunning || !sessionId;
8989
- const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${escapeHtml14(action)}"${disabled ? " disabled" : ""}>${escapeHtml14(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
8990
- const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml14(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml14(snapshot.lastResult.action)}. Control: ${escapeHtml14(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
9163
+ const actions = VOICE_LIVE_OPS_ACTIONS.map((action) => `<button type="button" data-absolute-voice-live-ops-action="${escapeHtml15(action)}"${disabled ? " disabled" : ""}>${escapeHtml15(snapshot.runningAction === action ? "Running..." : ACTION_LABELS[action])}</button>`).join("");
9164
+ const result = snapshot.error ? `<p class="absolute-voice-live-ops__error">${escapeHtml15(snapshot.error)}</p>` : snapshot.lastResult ? `<p class="absolute-voice-live-ops__result">Recorded ${escapeHtml15(snapshot.lastResult.action)}. Control: ${escapeHtml15(snapshot.lastResult.control.status)}.</p>` : '<p class="absolute-voice-live-ops__result">No live ops action has run yet.</p>';
8991
9165
  return `<section class="absolute-voice-live-ops">
8992
9166
  <header class="absolute-voice-live-ops__header">
8993
- <span>${escapeHtml14(options.title ?? "Live Ops")}</span>
8994
- <strong>${escapeHtml14(sessionId || "No active session")}</strong>
9167
+ <span>${escapeHtml15(options.title ?? "Live Ops")}</span>
9168
+ <strong>${escapeHtml15(sessionId || "No active session")}</strong>
8995
9169
  </header>
8996
- <p class="absolute-voice-live-ops__description">${escapeHtml14(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
8997
- <label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml14(options.defaultAssignee ?? "operator")}" /></label>
8998
- <label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml14(options.defaultTag ?? "live-ops")}" /></label>
8999
- <label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml14(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
9170
+ <p class="absolute-voice-live-ops__description">${escapeHtml15(options.description ?? "Pause, resume, take over, force handoff, or inject operator instructions during a live voice session.")}</p>
9171
+ <label><span>Operator</span><input data-absolute-voice-live-ops-assignee value="${escapeHtml15(options.defaultAssignee ?? "operator")}" /></label>
9172
+ <label><span>Tag / handoff target</span><input data-absolute-voice-live-ops-tag value="${escapeHtml15(options.defaultTag ?? "live-ops")}" /></label>
9173
+ <label><span>Detail / instruction</span><input data-absolute-voice-live-ops-detail value="${escapeHtml15(options.defaultDetail ?? "Operator marked this live session.")}" /></label>
9000
9174
  <div class="absolute-voice-live-ops__actions">${actions}</div>
9001
9175
  ${result}
9002
9176
  </section>`;
@@ -9083,16 +9257,16 @@ var defineVoiceLiveOpsElement = (tagName = "absolute-voice-live-ops", options =
9083
9257
  });
9084
9258
  };
9085
9259
  // src/client/opsActionHistoryWidget.ts
9086
- var escapeHtml15 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
9260
+ var escapeHtml16 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
9087
9261
  var renderVoiceOpsActionHistoryWidgetHTML = (snapshot, options = {}) => {
9088
9262
  const report = snapshot.report;
9089
9263
  const entries = (report?.entries ?? []).slice(0, options.limit ?? 5);
9090
- const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${escapeHtml15(entry.actionId)}</span><strong>${escapeHtml15(entry.ok ? "Success" : "Failed")}</strong><small>${escapeHtml15(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</small></li>`).join("");
9264
+ const rows = entries.map((entry) => `<li class="absolute-voice-ops-action-history__entry absolute-voice-ops-action-history__entry--${entry.ok ? "success" : "error"}"><span>${escapeHtml16(entry.actionId)}</span><strong>${escapeHtml16(entry.ok ? "Success" : "Failed")}</strong><small>${escapeHtml16(new Date(entry.at).toLocaleString())}${entry.status ? ` \xB7 HTTP ${String(entry.status)}` : ""}</small></li>`).join("");
9091
9265
  return `<section class="absolute-voice-ops-action-history">
9092
- <header><span>Operator proof</span><strong>${escapeHtml15(options.title ?? "Action History")}</strong></header>
9266
+ <header><span>Operator proof</span><strong>${escapeHtml16(options.title ?? "Action History")}</strong></header>
9093
9267
  <p>${String(report?.total ?? 0)} action(s), ${String(report?.failed ?? 0)} failed.</p>
9094
9268
  <ul>${rows || "<li>No operator actions recorded yet.</li>"}</ul>
9095
- ${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${escapeHtml15(snapshot.error)}</p>` : ""}
9269
+ ${snapshot.error ? `<p class="absolute-voice-ops-action-history__error">${escapeHtml16(snapshot.error)}</p>` : ""}
9096
9270
  </section>`;
9097
9271
  };
9098
9272
  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}`;
@@ -9113,9 +9287,9 @@ var mountVoiceOpsActionHistory = (element, path = "/api/voice/ops-actions/histor
9113
9287
  };
9114
9288
  };
9115
9289
  // src/client/deliveryRuntimeWidget.ts
9116
- var DEFAULT_TITLE9 = "Voice Delivery Runtime";
9117
- var DEFAULT_DESCRIPTION9 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
9118
- var escapeHtml16 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
9290
+ var DEFAULT_TITLE10 = "Voice Delivery Runtime";
9291
+ var DEFAULT_DESCRIPTION10 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
9292
+ var escapeHtml17 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
9119
9293
  var createSurface = (id, summary) => {
9120
9294
  if (!summary) {
9121
9295
  return {
@@ -9149,7 +9323,7 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
9149
9323
  ];
9150
9324
  const hasWarnings = surfaces.some((surface) => surface.status === "warn");
9151
9325
  return {
9152
- description: options.description ?? DEFAULT_DESCRIPTION9,
9326
+ description: options.description ?? DEFAULT_DESCRIPTION10,
9153
9327
  error: snapshot.error,
9154
9328
  actionError: snapshot.actionError,
9155
9329
  actionStatus: snapshot.actionStatus,
@@ -9158,32 +9332,32 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
9158
9332
  label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
9159
9333
  status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
9160
9334
  surfaces,
9161
- title: options.title ?? DEFAULT_TITLE9,
9335
+ title: options.title ?? DEFAULT_TITLE10,
9162
9336
  updatedAt: snapshot.updatedAt
9163
9337
  };
9164
9338
  };
9165
9339
  var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
9166
9340
  const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
9167
- const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml16(surface.status)}">
9168
- <span>${escapeHtml16(surface.label)}</span>
9169
- <strong>${escapeHtml16(surface.detail)}</strong>
9341
+ const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml17(surface.status)}">
9342
+ <span>${escapeHtml17(surface.label)}</span>
9343
+ <strong>${escapeHtml17(surface.detail)}</strong>
9170
9344
  <small>${String(surface.failed)} failed &middot; ${String(surface.deadLettered)} dead-lettered</small>
9171
9345
  </li>`).join("");
9172
9346
  const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
9173
9347
  <button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
9174
9348
  <button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
9175
9349
  </div>`;
9176
- const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml16(model.actionError)}</p>` : "";
9177
- return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml16(model.status)}">
9350
+ const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml17(model.actionError)}</p>` : "";
9351
+ return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml17(model.status)}">
9178
9352
  <header class="absolute-voice-delivery-runtime__header">
9179
- <span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml16(model.title)}</span>
9180
- <strong class="absolute-voice-delivery-runtime__label">${escapeHtml16(model.label)}</strong>
9353
+ <span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml17(model.title)}</span>
9354
+ <strong class="absolute-voice-delivery-runtime__label">${escapeHtml17(model.label)}</strong>
9181
9355
  </header>
9182
- <p class="absolute-voice-delivery-runtime__description">${escapeHtml16(model.description)}</p>
9356
+ <p class="absolute-voice-delivery-runtime__description">${escapeHtml17(model.description)}</p>
9183
9357
  <ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
9184
9358
  ${actions}
9185
9359
  ${actionError}
9186
- ${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml16(model.error)}</p>` : ""}
9360
+ ${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml17(model.error)}</p>` : ""}
9187
9361
  </section>`;
9188
9362
  };
9189
9363
  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}`;
@@ -9319,9 +9493,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
9319
9493
  };
9320
9494
  };
9321
9495
  // src/client/routingStatusWidget.ts
9322
- var DEFAULT_TITLE10 = "Voice Routing";
9323
- var DEFAULT_DESCRIPTION10 = "Latest provider routing decision from the self-hosted trace store.";
9324
- var escapeHtml17 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
9496
+ var DEFAULT_TITLE11 = "Voice Routing";
9497
+ var DEFAULT_DESCRIPTION11 = "Latest provider routing decision from the self-hosted trace store.";
9498
+ var escapeHtml18 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
9325
9499
  var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
9326
9500
  var formatProviderRoutes2 = (routes) => routes && typeof routes === "object" ? Object.entries(routes).map(([role, provider]) => `${role}: ${formatValue(provider)}`).join(", ") || "None" : "None";
9327
9501
  var getProviderRoute = (routes, role) => routes && typeof routes === "object" ? formatValue(routes[role], "Not configured") : "Not configured";
@@ -9390,35 +9564,35 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
9390
9564
  return {
9391
9565
  activeStack,
9392
9566
  decision,
9393
- description: options.description ?? DEFAULT_DESCRIPTION10,
9567
+ description: options.description ?? DEFAULT_DESCRIPTION11,
9394
9568
  error: snapshot.error,
9395
9569
  isLoading: snapshot.isLoading,
9396
9570
  label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
9397
9571
  rows,
9398
9572
  status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
9399
- title: options.title ?? DEFAULT_TITLE10,
9573
+ title: options.title ?? DEFAULT_TITLE11,
9400
9574
  updatedAt: snapshot.updatedAt
9401
9575
  };
9402
9576
  };
9403
9577
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
9404
9578
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
9405
9579
  const activeStack = model.activeStack.length ? `<div class="absolute-voice-routing-status__stack" aria-label="Active voice stack">${model.activeStack.map((item) => `<div>
9406
- <span>${escapeHtml17(item.label)}</span>
9407
- <strong>${escapeHtml17(item.value)}</strong>
9580
+ <span>${escapeHtml18(item.label)}</span>
9581
+ <strong>${escapeHtml18(item.value)}</strong>
9408
9582
  </div>`).join("")}</div>` : "";
9409
9583
  const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
9410
- <span>${escapeHtml17(row.label)}</span>
9411
- <strong>${escapeHtml17(row.value)}</strong>
9584
+ <span>${escapeHtml18(row.label)}</span>
9585
+ <strong>${escapeHtml18(row.value)}</strong>
9412
9586
  </div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
9413
- return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml17(model.status)}">
9587
+ return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml18(model.status)}">
9414
9588
  <header class="absolute-voice-routing-status__header">
9415
- <span class="absolute-voice-routing-status__eyebrow">${escapeHtml17(model.title)}</span>
9416
- <strong class="absolute-voice-routing-status__label">${escapeHtml17(model.label)}</strong>
9589
+ <span class="absolute-voice-routing-status__eyebrow">${escapeHtml18(model.title)}</span>
9590
+ <strong class="absolute-voice-routing-status__label">${escapeHtml18(model.label)}</strong>
9417
9591
  </header>
9418
- <p class="absolute-voice-routing-status__description">${escapeHtml17(model.description)}</p>
9592
+ <p class="absolute-voice-routing-status__description">${escapeHtml18(model.description)}</p>
9419
9593
  ${activeStack}
9420
9594
  ${rows}
9421
- ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml17(model.error)}</p>` : ""}
9595
+ ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml18(model.error)}</p>` : ""}
9422
9596
  </section>`;
9423
9597
  };
9424
9598
  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}}`;
@@ -10217,7 +10391,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
10217
10391
  };
10218
10392
  };
10219
10393
  // src/client/providerSimulationControlsWidget.ts
10220
- var escapeHtml18 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10394
+ var escapeHtml19 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10221
10395
  var formatKind = (kind) => (kind ?? "stt").toUpperCase();
10222
10396
  var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
10223
10397
  const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
@@ -10237,18 +10411,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
10237
10411
  };
10238
10412
  var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
10239
10413
  const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
10240
- const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml18(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml18(provider.provider)} ${escapeHtml18(formatKind(options.kind))} failure</button>`).join("");
10241
- const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml18(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml18(provider.provider)} recovered</button>`).join("");
10414
+ const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml19(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml19(provider.provider)} ${escapeHtml19(formatKind(options.kind))} failure</button>`).join("");
10415
+ const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml19(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml19(provider.provider)} recovered</button>`).join("");
10242
10416
  return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
10243
10417
  <header class="absolute-voice-provider-simulation__header">
10244
- <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml18(model.title)}</span>
10245
- <strong class="absolute-voice-provider-simulation__label">${escapeHtml18(model.label)}</strong>
10418
+ <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml19(model.title)}</span>
10419
+ <strong class="absolute-voice-provider-simulation__label">${escapeHtml19(model.label)}</strong>
10246
10420
  </header>
10247
- <p class="absolute-voice-provider-simulation__description">${escapeHtml18(model.description)}</p>
10248
- ${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml18(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
10421
+ <p class="absolute-voice-provider-simulation__description">${escapeHtml19(model.description)}</p>
10422
+ ${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml19(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
10249
10423
  <div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
10250
- ${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml18(snapshot.error)}</p>` : ""}
10251
- ${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml18(model.resultText)}</pre>` : ""}
10424
+ ${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml19(snapshot.error)}</p>` : ""}
10425
+ ${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml19(model.resultText)}</pre>` : ""}
10252
10426
  </section>`;
10253
10427
  };
10254
10428
  var bindVoiceProviderSimulationControls = (element, store) => {
@@ -10313,9 +10487,9 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
10313
10487
  });
10314
10488
  };
10315
10489
  // src/client/providerStatusWidget.ts
10316
- var DEFAULT_TITLE11 = "Voice Providers";
10317
- var DEFAULT_DESCRIPTION11 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
10318
- var escapeHtml19 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10490
+ var DEFAULT_TITLE12 = "Voice Providers";
10491
+ var DEFAULT_DESCRIPTION12 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
10492
+ var escapeHtml20 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10319
10493
  var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
10320
10494
  var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
10321
10495
  var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
@@ -10359,37 +10533,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
10359
10533
  const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
10360
10534
  const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
10361
10535
  return {
10362
- description: options.description ?? DEFAULT_DESCRIPTION11,
10536
+ description: options.description ?? DEFAULT_DESCRIPTION12,
10363
10537
  error: snapshot.error,
10364
10538
  isLoading: snapshot.isLoading,
10365
10539
  label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
10366
10540
  providers,
10367
10541
  status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
10368
- title: options.title ?? DEFAULT_TITLE11,
10542
+ title: options.title ?? DEFAULT_TITLE12,
10369
10543
  updatedAt: snapshot.updatedAt
10370
10544
  };
10371
10545
  };
10372
10546
  var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
10373
10547
  const model = createVoiceProviderStatusViewModel(snapshot, options);
10374
- 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--${escapeHtml19(provider.status)}">
10548
+ 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--${escapeHtml20(provider.status)}">
10375
10549
  <header>
10376
- <strong>${escapeHtml19(provider.label)}</strong>
10377
- <span>${escapeHtml19(formatStatus3(provider.status))}</span>
10550
+ <strong>${escapeHtml20(provider.label)}</strong>
10551
+ <span>${escapeHtml20(formatStatus3(provider.status))}</span>
10378
10552
  </header>
10379
- <p>${escapeHtml19(provider.detail)}</p>
10553
+ <p>${escapeHtml20(provider.detail)}</p>
10380
10554
  <dl>${provider.rows.map((row) => `<div>
10381
- <dt>${escapeHtml19(row.label)}</dt>
10382
- <dd>${escapeHtml19(row.value)}</dd>
10555
+ <dt>${escapeHtml20(row.label)}</dt>
10556
+ <dd>${escapeHtml20(row.value)}</dd>
10383
10557
  </div>`).join("")}</dl>
10384
10558
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
10385
- return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml19(model.status)}">
10559
+ return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml20(model.status)}">
10386
10560
  <header class="absolute-voice-provider-status__header">
10387
- <span class="absolute-voice-provider-status__eyebrow">${escapeHtml19(model.title)}</span>
10388
- <strong class="absolute-voice-provider-status__label">${escapeHtml19(model.label)}</strong>
10561
+ <span class="absolute-voice-provider-status__eyebrow">${escapeHtml20(model.title)}</span>
10562
+ <strong class="absolute-voice-provider-status__label">${escapeHtml20(model.label)}</strong>
10389
10563
  </header>
10390
- <p class="absolute-voice-provider-status__description">${escapeHtml19(model.description)}</p>
10564
+ <p class="absolute-voice-provider-status__description">${escapeHtml20(model.description)}</p>
10391
10565
  ${providers}
10392
- ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml19(model.error)}</p>` : ""}
10566
+ ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml20(model.error)}</p>` : ""}
10393
10567
  </section>`;
10394
10568
  };
10395
10569
  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}`;
@@ -10430,9 +10604,9 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
10430
10604
  });
10431
10605
  };
10432
10606
  // src/client/providerCapabilitiesWidget.ts
10433
- var DEFAULT_TITLE12 = "Provider Capabilities";
10434
- var DEFAULT_DESCRIPTION12 = "Configured, selected, and healthy voice providers for this deployment.";
10435
- var escapeHtml20 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10607
+ var DEFAULT_TITLE13 = "Provider Capabilities";
10608
+ var DEFAULT_DESCRIPTION13 = "Configured, selected, and healthy voice providers for this deployment.";
10609
+ var escapeHtml21 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10436
10610
  var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
10437
10611
  var formatKind2 = (kind) => kind.toUpperCase();
10438
10612
  var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
@@ -10476,36 +10650,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
10476
10650
  const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
10477
10651
  return {
10478
10652
  capabilities,
10479
- description: options.description ?? DEFAULT_DESCRIPTION12,
10653
+ description: options.description ?? DEFAULT_DESCRIPTION13,
10480
10654
  error: snapshot.error,
10481
10655
  isLoading: snapshot.isLoading,
10482
10656
  label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
10483
10657
  status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
10484
- title: options.title ?? DEFAULT_TITLE12,
10658
+ title: options.title ?? DEFAULT_TITLE13,
10485
10659
  updatedAt: snapshot.updatedAt
10486
10660
  };
10487
10661
  };
10488
10662
  var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
10489
10663
  const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
10490
- 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--${escapeHtml20(capability.status)}">
10664
+ 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--${escapeHtml21(capability.status)}">
10491
10665
  <header>
10492
- <strong>${escapeHtml20(capability.label)}</strong>
10493
- <span>${escapeHtml20(formatStatus4(capability.status))}</span>
10666
+ <strong>${escapeHtml21(capability.label)}</strong>
10667
+ <span>${escapeHtml21(formatStatus4(capability.status))}</span>
10494
10668
  </header>
10495
- <p>${escapeHtml20(capability.detail)}</p>
10669
+ <p>${escapeHtml21(capability.detail)}</p>
10496
10670
  <dl>${capability.rows.map((row) => `<div>
10497
- <dt>${escapeHtml20(row.label)}</dt>
10498
- <dd>${escapeHtml20(row.value)}</dd>
10671
+ <dt>${escapeHtml21(row.label)}</dt>
10672
+ <dd>${escapeHtml21(row.value)}</dd>
10499
10673
  </div>`).join("")}</dl>
10500
10674
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
10501
- return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml20(model.status)}">
10675
+ return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml21(model.status)}">
10502
10676
  <header class="absolute-voice-provider-capabilities__header">
10503
- <span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml20(model.title)}</span>
10504
- <strong class="absolute-voice-provider-capabilities__label">${escapeHtml20(model.label)}</strong>
10677
+ <span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml21(model.title)}</span>
10678
+ <strong class="absolute-voice-provider-capabilities__label">${escapeHtml21(model.label)}</strong>
10505
10679
  </header>
10506
- <p class="absolute-voice-provider-capabilities__description">${escapeHtml20(model.description)}</p>
10680
+ <p class="absolute-voice-provider-capabilities__description">${escapeHtml21(model.description)}</p>
10507
10681
  ${capabilities}
10508
- ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml20(model.error)}</p>` : ""}
10682
+ ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml21(model.error)}</p>` : ""}
10509
10683
  </section>`;
10510
10684
  };
10511
10685
  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}`;
@@ -10546,9 +10720,9 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
10546
10720
  });
10547
10721
  };
10548
10722
  // src/client/providerContractsWidget.ts
10549
- var DEFAULT_TITLE13 = "Provider Contracts";
10550
- var DEFAULT_DESCRIPTION13 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
10551
- var escapeHtml21 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10723
+ var DEFAULT_TITLE14 = "Provider Contracts";
10724
+ var DEFAULT_DESCRIPTION14 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
10725
+ var escapeHtml22 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10552
10726
  var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
10553
10727
  var formatStatus5 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
10554
10728
  var contractDetail = (row) => {
@@ -10580,38 +10754,38 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
10580
10754
  }));
10581
10755
  const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
10582
10756
  return {
10583
- description: options.description ?? DEFAULT_DESCRIPTION13,
10757
+ description: options.description ?? DEFAULT_DESCRIPTION14,
10584
10758
  error: snapshot.error,
10585
10759
  isLoading: snapshot.isLoading,
10586
10760
  label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
10587
10761
  rows,
10588
10762
  status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
10589
- title: options.title ?? DEFAULT_TITLE13,
10763
+ title: options.title ?? DEFAULT_TITLE14,
10590
10764
  updatedAt: snapshot.updatedAt
10591
10765
  };
10592
10766
  };
10593
10767
  var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
10594
10768
  const model = createVoiceProviderContractsViewModel(snapshot, options);
10595
- 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--${escapeHtml21(row.status)}">
10769
+ 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--${escapeHtml22(row.status)}">
10596
10770
  <header>
10597
- <strong>${escapeHtml21(row.label)}</strong>
10598
- <span>${escapeHtml21(formatStatus5(row.status))}</span>
10771
+ <strong>${escapeHtml22(row.label)}</strong>
10772
+ <span>${escapeHtml22(formatStatus5(row.status))}</span>
10599
10773
  </header>
10600
- <p>${escapeHtml21(row.detail)}</p>
10601
- ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml21(remediation.href)}">${escapeHtml21(remediation.label)}</a>` : `<strong>${escapeHtml21(remediation.label)}</strong>`}<span>${escapeHtml21(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
10774
+ <p>${escapeHtml22(row.detail)}</p>
10775
+ ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml22(remediation.href)}">${escapeHtml22(remediation.label)}</a>` : `<strong>${escapeHtml22(remediation.label)}</strong>`}<span>${escapeHtml22(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
10602
10776
  <dl>${row.rows.map((item) => `<div>
10603
- <dt>${escapeHtml21(item.label)}</dt>
10604
- <dd>${escapeHtml21(item.value)}</dd>
10777
+ <dt>${escapeHtml22(item.label)}</dt>
10778
+ <dd>${escapeHtml22(item.value)}</dd>
10605
10779
  </div>`).join("")}</dl>
10606
10780
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
10607
- return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml21(model.status)}">
10781
+ return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml22(model.status)}">
10608
10782
  <header class="absolute-voice-provider-contracts__header">
10609
- <span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml21(model.title)}</span>
10610
- <strong class="absolute-voice-provider-contracts__label">${escapeHtml21(model.label)}</strong>
10783
+ <span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml22(model.title)}</span>
10784
+ <strong class="absolute-voice-provider-contracts__label">${escapeHtml22(model.label)}</strong>
10611
10785
  </header>
10612
- <p class="absolute-voice-provider-contracts__description">${escapeHtml21(model.description)}</p>
10786
+ <p class="absolute-voice-provider-contracts__description">${escapeHtml22(model.description)}</p>
10613
10787
  ${rows}
10614
- ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml21(model.error)}</p>` : ""}
10788
+ ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml22(model.error)}</p>` : ""}
10615
10789
  </section>`;
10616
10790
  };
10617
10791
  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}`;
@@ -10652,9 +10826,9 @@ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-co
10652
10826
  });
10653
10827
  };
10654
10828
  // src/client/turnQualityWidget.ts
10655
- var DEFAULT_TITLE14 = "Turn Quality";
10656
- var DEFAULT_DESCRIPTION14 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
10657
- var escapeHtml22 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10829
+ var DEFAULT_TITLE15 = "Turn Quality";
10830
+ var DEFAULT_DESCRIPTION15 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
10831
+ var escapeHtml23 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10658
10832
  var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
10659
10833
  var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
10660
10834
  var getTurnDetail = (turn) => {
@@ -10692,37 +10866,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
10692
10866
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
10693
10867
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
10694
10868
  return {
10695
- description: options.description ?? DEFAULT_DESCRIPTION14,
10869
+ description: options.description ?? DEFAULT_DESCRIPTION15,
10696
10870
  error: snapshot.error,
10697
10871
  isLoading: snapshot.isLoading,
10698
10872
  label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
10699
10873
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
10700
- title: options.title ?? DEFAULT_TITLE14,
10874
+ title: options.title ?? DEFAULT_TITLE15,
10701
10875
  turns,
10702
10876
  updatedAt: snapshot.updatedAt
10703
10877
  };
10704
10878
  };
10705
10879
  var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
10706
10880
  const model = createVoiceTurnQualityViewModel(snapshot, options);
10707
- 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--${escapeHtml22(turn.status)}">
10881
+ 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--${escapeHtml23(turn.status)}">
10708
10882
  <header>
10709
- <strong>${escapeHtml22(turn.label)}</strong>
10710
- <span>${escapeHtml22(turn.status)}</span>
10883
+ <strong>${escapeHtml23(turn.label)}</strong>
10884
+ <span>${escapeHtml23(turn.status)}</span>
10711
10885
  </header>
10712
- <p>${escapeHtml22(turn.detail)}</p>
10886
+ <p>${escapeHtml23(turn.detail)}</p>
10713
10887
  <dl>${turn.rows.map((row) => `<div>
10714
- <dt>${escapeHtml22(row.label)}</dt>
10715
- <dd>${escapeHtml22(row.value)}</dd>
10888
+ <dt>${escapeHtml23(row.label)}</dt>
10889
+ <dd>${escapeHtml23(row.value)}</dd>
10716
10890
  </div>`).join("")}</dl>
10717
10891
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
10718
- return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml22(model.status)}">
10892
+ return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml23(model.status)}">
10719
10893
  <header class="absolute-voice-turn-quality__header">
10720
- <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml22(model.title)}</span>
10721
- <strong class="absolute-voice-turn-quality__label">${escapeHtml22(model.label)}</strong>
10894
+ <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml23(model.title)}</span>
10895
+ <strong class="absolute-voice-turn-quality__label">${escapeHtml23(model.label)}</strong>
10722
10896
  </header>
10723
- <p class="absolute-voice-turn-quality__description">${escapeHtml22(model.description)}</p>
10897
+ <p class="absolute-voice-turn-quality__description">${escapeHtml23(model.description)}</p>
10724
10898
  ${turns}
10725
- ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml22(model.error)}</p>` : ""}
10899
+ ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml23(model.error)}</p>` : ""}
10726
10900
  </section>`;
10727
10901
  };
10728
10902
  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}`;
@@ -10763,10 +10937,10 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
10763
10937
  });
10764
10938
  };
10765
10939
  // src/client/turnLatencyWidget.ts
10766
- var DEFAULT_TITLE15 = "Turn Latency";
10767
- var DEFAULT_DESCRIPTION15 = "Per-turn timing from first transcript to commit and assistant response start.";
10940
+ var DEFAULT_TITLE16 = "Turn Latency";
10941
+ var DEFAULT_DESCRIPTION16 = "Per-turn timing from first transcript to commit and assistant response start.";
10768
10942
  var DEFAULT_PROOF_LABEL = "Run latency proof";
10769
- var escapeHtml23 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10943
+ var escapeHtml24 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10770
10944
  var formatMs3 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
10771
10945
  var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
10772
10946
  const turns = (snapshot.report?.turns ?? []).map((turn) => ({
@@ -10780,39 +10954,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
10780
10954
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
10781
10955
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
10782
10956
  return {
10783
- description: options.description ?? DEFAULT_DESCRIPTION15,
10957
+ description: options.description ?? DEFAULT_DESCRIPTION16,
10784
10958
  error: snapshot.error,
10785
10959
  isLoading: snapshot.isLoading,
10786
10960
  label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs3(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
10787
10961
  proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
10788
10962
  showProofAction: Boolean(options.proofPath),
10789
10963
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
10790
- title: options.title ?? DEFAULT_TITLE15,
10964
+ title: options.title ?? DEFAULT_TITLE16,
10791
10965
  turns,
10792
10966
  updatedAt: snapshot.updatedAt
10793
10967
  };
10794
10968
  };
10795
10969
  var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
10796
10970
  const model = createVoiceTurnLatencyViewModel(snapshot, options);
10797
- 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--${escapeHtml23(turn.status)}">
10971
+ 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--${escapeHtml24(turn.status)}">
10798
10972
  <header>
10799
- <strong>${escapeHtml23(turn.label)}</strong>
10800
- <span>${escapeHtml23(turn.status)}</span>
10973
+ <strong>${escapeHtml24(turn.label)}</strong>
10974
+ <span>${escapeHtml24(turn.status)}</span>
10801
10975
  </header>
10802
10976
  <dl>${turn.rows.map((row) => `<div>
10803
- <dt>${escapeHtml23(row.label)}</dt>
10804
- <dd>${escapeHtml23(row.value)}</dd>
10977
+ <dt>${escapeHtml24(row.label)}</dt>
10978
+ <dd>${escapeHtml24(row.value)}</dd>
10805
10979
  </div>`).join("")}</dl>
10806
10980
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
10807
- return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml23(model.status)}">
10981
+ return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml24(model.status)}">
10808
10982
  <header class="absolute-voice-turn-latency__header">
10809
- <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml23(model.title)}</span>
10810
- <strong class="absolute-voice-turn-latency__label">${escapeHtml23(model.label)}</strong>
10983
+ <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml24(model.title)}</span>
10984
+ <strong class="absolute-voice-turn-latency__label">${escapeHtml24(model.label)}</strong>
10811
10985
  </header>
10812
- <p class="absolute-voice-turn-latency__description">${escapeHtml23(model.description)}</p>
10813
- ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml23(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
10986
+ <p class="absolute-voice-turn-latency__description">${escapeHtml24(model.description)}</p>
10987
+ ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml24(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
10814
10988
  ${turns}
10815
- ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml23(model.error)}</p>` : ""}
10989
+ ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml24(model.error)}</p>` : ""}
10816
10990
  </section>`;
10817
10991
  };
10818
10992
  var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
@@ -10862,9 +11036,9 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
10862
11036
  });
10863
11037
  };
10864
11038
  // src/client/traceTimelineWidget.ts
10865
- var DEFAULT_TITLE16 = "Voice Traces";
10866
- var DEFAULT_DESCRIPTION16 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
10867
- var escapeHtml24 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
11039
+ var DEFAULT_TITLE17 = "Voice Traces";
11040
+ var DEFAULT_DESCRIPTION17 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
11041
+ var escapeHtml25 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10868
11042
  var formatMs4 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
10869
11043
  var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
10870
11044
  var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
@@ -10880,13 +11054,13 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
10880
11054
  const failed = sessions.filter((session) => session.status === "failed").length;
10881
11055
  const warnings = sessions.filter((session) => session.status === "warning").length;
10882
11056
  return {
10883
- description: options.description ?? DEFAULT_DESCRIPTION16,
11057
+ description: options.description ?? DEFAULT_DESCRIPTION17,
10884
11058
  error: snapshot.error,
10885
11059
  isLoading: snapshot.isLoading,
10886
11060
  label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
10887
11061
  sessions,
10888
11062
  status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
10889
- title: options.title ?? DEFAULT_TITLE16,
11063
+ title: options.title ?? DEFAULT_TITLE17,
10890
11064
  updatedAt: snapshot.updatedAt
10891
11065
  };
10892
11066
  };
@@ -10894,27 +11068,27 @@ var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
10894
11068
  const model = createVoiceTraceTimelineViewModel(snapshot, options);
10895
11069
  const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => {
10896
11070
  const supportLinks = [
10897
- `<a href="${escapeHtml24(session.detailHref)}">Open timeline</a>`,
10898
- session.operationsRecordHref ? `<a href="${escapeHtml24(session.operationsRecordHref)}">Open operations record</a>` : undefined,
10899
- session.incidentBundleHref ? `<a href="${escapeHtml24(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
11071
+ `<a href="${escapeHtml25(session.detailHref)}">Open timeline</a>`,
11072
+ session.operationsRecordHref ? `<a href="${escapeHtml25(session.operationsRecordHref)}">Open operations record</a>` : undefined,
11073
+ session.incidentBundleHref ? `<a href="${escapeHtml25(session.incidentBundleHref)}">Export incident bundle</a>` : undefined
10900
11074
  ].filter(Boolean).join("");
10901
- return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml24(session.status)}">
11075
+ return `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml25(session.status)}">
10902
11076
  <header>
10903
- <strong>${escapeHtml24(session.sessionId)}</strong>
10904
- <span>${escapeHtml24(session.status)}</span>
11077
+ <strong>${escapeHtml25(session.sessionId)}</strong>
11078
+ <span>${escapeHtml25(session.status)}</span>
10905
11079
  </header>
10906
- <p>${escapeHtml24(session.label)} \xB7 ${escapeHtml24(session.durationLabel)} \xB7 ${escapeHtml24(session.providerLabel)}</p>
11080
+ <p>${escapeHtml25(session.label)} \xB7 ${escapeHtml25(session.durationLabel)} \xB7 ${escapeHtml25(session.providerLabel)}</p>
10907
11081
  <p class="absolute-voice-trace-timeline__actions">${supportLinks}</p>
10908
11082
  </article>`;
10909
11083
  }).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
10910
- return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml24(model.status)}">
11084
+ return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml25(model.status)}">
10911
11085
  <header class="absolute-voice-trace-timeline__header">
10912
- <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml24(model.title)}</span>
10913
- <strong class="absolute-voice-trace-timeline__label">${escapeHtml24(model.label)}</strong>
11086
+ <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml25(model.title)}</span>
11087
+ <strong class="absolute-voice-trace-timeline__label">${escapeHtml25(model.label)}</strong>
10914
11088
  </header>
10915
- <p class="absolute-voice-trace-timeline__description">${escapeHtml24(model.description)}</p>
11089
+ <p class="absolute-voice-trace-timeline__description">${escapeHtml25(model.description)}</p>
10916
11090
  ${sessions}
10917
- ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml24(model.error)}</p>` : ""}
11091
+ ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml25(model.error)}</p>` : ""}
10918
11092
  </section>`;
10919
11093
  };
10920
11094
  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}`;
@@ -10960,9 +11134,9 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
10960
11134
  });
10961
11135
  };
10962
11136
  // src/client/agentSquadStatusWidget.ts
10963
- var DEFAULT_TITLE17 = "Voice Agent Squad";
10964
- var DEFAULT_DESCRIPTION17 = "Current specialist and recent handoffs from your self-hosted voice traces.";
10965
- var escapeHtml25 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
11137
+ var DEFAULT_TITLE18 = "Voice Agent Squad";
11138
+ var DEFAULT_DESCRIPTION18 = "Current specialist and recent handoffs from your self-hosted voice traces.";
11139
+ var escapeHtml26 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
10966
11140
  var labelFor = (current) => {
10967
11141
  if (!current)
10968
11142
  return "Waiting for specialist activity";
@@ -10976,37 +11150,37 @@ var labelFor = (current) => {
10976
11150
  };
10977
11151
  var createVoiceAgentSquadStatusViewModel = (snapshot, options = {}) => ({
10978
11152
  current: snapshot.report.current,
10979
- description: options.description ?? DEFAULT_DESCRIPTION17,
11153
+ description: options.description ?? DEFAULT_DESCRIPTION18,
10980
11154
  error: snapshot.error,
10981
11155
  isLoading: snapshot.isLoading,
10982
11156
  label: snapshot.error ? "Unavailable" : labelFor(snapshot.report.current),
10983
11157
  sessionCount: snapshot.report.sessionCount,
10984
11158
  sessions: snapshot.report.sessions,
10985
- title: options.title ?? DEFAULT_TITLE17,
11159
+ title: options.title ?? DEFAULT_TITLE18,
10986
11160
  updatedAt: snapshot.updatedAt
10987
11161
  });
10988
11162
  var renderVoiceAgentSquadStatusHTML = (snapshot, options = {}) => {
10989
11163
  const model = createVoiceAgentSquadStatusViewModel(snapshot, options);
10990
11164
  const current = model.current;
10991
11165
  const rows = model.sessions.length ? model.sessions.slice(0, 5).map((session) => `<li>
10992
- <span>${escapeHtml25(session.sessionId)}</span>
10993
- <strong>${escapeHtml25(session.targetAgentId ?? "none")}</strong>
10994
- <em>${escapeHtml25(session.status)}</em>
10995
- ${session.summary || session.reason ? `<p>${escapeHtml25(session.summary ?? session.reason ?? "")}</p>` : ""}
11166
+ <span>${escapeHtml26(session.sessionId)}</span>
11167
+ <strong>${escapeHtml26(session.targetAgentId ?? "none")}</strong>
11168
+ <em>${escapeHtml26(session.status)}</em>
11169
+ ${session.summary || session.reason ? `<p>${escapeHtml26(session.summary ?? session.reason ?? "")}</p>` : ""}
10996
11170
  </li>`).join("") : "<li><span>No squad traces yet.</span><strong>Waiting</strong></li>";
10997
11171
  return `<section class="absolute-voice-agent-squad-status">
10998
11172
  <header>
10999
- <span>${escapeHtml25(model.title)}</span>
11000
- <strong>${escapeHtml25(model.label)}</strong>
11173
+ <span>${escapeHtml26(model.title)}</span>
11174
+ <strong>${escapeHtml26(model.label)}</strong>
11001
11175
  </header>
11002
- <p>${escapeHtml25(model.description)}</p>
11176
+ <p>${escapeHtml26(model.description)}</p>
11003
11177
  <div>
11004
- <span>Session</span><strong>${escapeHtml25(current?.sessionId ?? "n/a")}</strong>
11005
- <span>From</span><strong>${escapeHtml25(current?.fromAgentId ?? "n/a")}</strong>
11006
- <span>Status</span><strong>${escapeHtml25(current?.status ?? "idle")}</strong>
11178
+ <span>Session</span><strong>${escapeHtml26(current?.sessionId ?? "n/a")}</strong>
11179
+ <span>From</span><strong>${escapeHtml26(current?.fromAgentId ?? "n/a")}</strong>
11180
+ <span>Status</span><strong>${escapeHtml26(current?.status ?? "idle")}</strong>
11007
11181
  </div>
11008
11182
  <ul>${rows}</ul>
11009
- ${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml25(model.error)}</p>` : ""}
11183
+ ${model.error ? `<p class="absolute-voice-agent-squad-status__error">${escapeHtml26(model.error)}</p>` : ""}
11010
11184
  </section>`;
11011
11185
  };
11012
11186
  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}`;
@@ -11151,6 +11325,7 @@ export {
11151
11325
  renderVoiceOpsActionCenterHTML,
11152
11326
  renderVoiceLiveOpsHTML,
11153
11327
  renderVoiceDeliveryRuntimeHTML,
11328
+ renderVoiceCallDebuggerLaunchHTML,
11154
11329
  renderVoiceAgentSquadStatusHTML,
11155
11330
  recordVoiceOpsActionResult,
11156
11331
  postVoiceLiveOpsAction,
@@ -11173,6 +11348,7 @@ export {
11173
11348
  mountVoiceOpsActionCenter,
11174
11349
  mountVoiceLiveOps,
11175
11350
  mountVoiceDeliveryRuntime,
11351
+ mountVoiceCallDebuggerLaunch,
11176
11352
  mountVoiceAgentSquadStatus,
11177
11353
  getVoiceTurnQualityCSS,
11178
11354
  getVoiceTraceTimelineCSS,
@@ -11210,6 +11386,7 @@ export {
11210
11386
  fetchVoiceOpsActionHistory,
11211
11387
  fetchVoiceDeliveryRuntime,
11212
11388
  fetchVoiceCampaignDialerProofStatus,
11389
+ fetchVoiceCallDebugger,
11213
11390
  defineVoiceTurnQualityElement,
11214
11391
  defineVoiceTurnLatencyElement,
11215
11392
  defineVoiceTraceTimelineElement,
@@ -11228,6 +11405,7 @@ export {
11228
11405
  defineVoiceOpsActionCenterElement,
11229
11406
  defineVoiceLiveOpsElement,
11230
11407
  defineVoiceDeliveryRuntimeElement,
11408
+ defineVoiceCallDebuggerLaunchElement,
11231
11409
  defineVoiceAgentSquadStatusElement,
11232
11410
  decodeVoiceAudioChunk,
11233
11411
  createVoiceWorkflowStatusStore,
@@ -11274,6 +11452,8 @@ export {
11274
11452
  createVoiceController,
11275
11453
  createVoiceConnection,
11276
11454
  createVoiceCampaignDialerProofStore,
11455
+ createVoiceCallDebuggerStore,
11456
+ createVoiceCallDebuggerLaunchViewModel,
11277
11457
  createVoiceBrowserMediaReporter,
11278
11458
  createVoiceBargeInMonitor,
11279
11459
  createVoiceAudioPlayer,