@absolutejs/voice 0.0.22-beta.239 → 0.0.22-beta.240

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/vue/index.js CHANGED
@@ -1128,8 +1128,290 @@ var VoiceDeliveryRuntime = defineComponent3({
1128
1128
  };
1129
1129
  }
1130
1130
  });
1131
+ // src/vue/VoicePlatformCoverage.ts
1132
+ import { defineComponent as defineComponent4, h as h4 } from "vue";
1133
+
1134
+ // src/vue/useVoicePlatformCoverage.ts
1135
+ import { onUnmounted as onUnmounted4, ref as ref4, shallowRef as shallowRef4 } from "vue";
1136
+
1137
+ // src/client/platformCoverage.ts
1138
+ var fetchVoicePlatformCoverage = async (path = "/api/voice/platform-coverage", options = {}) => {
1139
+ const fetchImpl = options.fetch ?? globalThis.fetch;
1140
+ const response = await fetchImpl(path);
1141
+ if (!response.ok) {
1142
+ throw new Error(`Voice platform coverage failed: HTTP ${response.status}`);
1143
+ }
1144
+ return await response.json();
1145
+ };
1146
+ var createVoicePlatformCoverageStore = (path = "/api/voice/platform-coverage", options = {}) => {
1147
+ const listeners = new Set;
1148
+ let closed = false;
1149
+ let timer;
1150
+ let snapshot = {
1151
+ error: null,
1152
+ isLoading: false
1153
+ };
1154
+ const emit = () => {
1155
+ for (const listener of listeners) {
1156
+ listener();
1157
+ }
1158
+ };
1159
+ const refresh = async () => {
1160
+ if (closed) {
1161
+ return snapshot.report;
1162
+ }
1163
+ snapshot = {
1164
+ ...snapshot,
1165
+ error: null,
1166
+ isLoading: true
1167
+ };
1168
+ emit();
1169
+ try {
1170
+ const report = await fetchVoicePlatformCoverage(path, options);
1171
+ snapshot = {
1172
+ error: null,
1173
+ isLoading: false,
1174
+ report,
1175
+ updatedAt: Date.now()
1176
+ };
1177
+ emit();
1178
+ return report;
1179
+ } catch (error) {
1180
+ snapshot = {
1181
+ ...snapshot,
1182
+ error: error instanceof Error ? error.message : String(error),
1183
+ isLoading: false
1184
+ };
1185
+ emit();
1186
+ throw error;
1187
+ }
1188
+ };
1189
+ const close = () => {
1190
+ closed = true;
1191
+ if (timer) {
1192
+ clearInterval(timer);
1193
+ timer = undefined;
1194
+ }
1195
+ listeners.clear();
1196
+ };
1197
+ if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
1198
+ timer = setInterval(() => {
1199
+ refresh().catch(() => {});
1200
+ }, options.intervalMs);
1201
+ }
1202
+ return {
1203
+ close,
1204
+ getServerSnapshot: () => snapshot,
1205
+ getSnapshot: () => snapshot,
1206
+ refresh,
1207
+ subscribe: (listener) => {
1208
+ listeners.add(listener);
1209
+ return () => {
1210
+ listeners.delete(listener);
1211
+ };
1212
+ }
1213
+ };
1214
+ };
1215
+
1216
+ // src/vue/useVoicePlatformCoverage.ts
1217
+ function useVoicePlatformCoverage(path = "/api/voice/platform-coverage", options = {}) {
1218
+ const store = createVoicePlatformCoverageStore(path, options);
1219
+ const error = ref4(null);
1220
+ const isLoading = ref4(false);
1221
+ const report = shallowRef4(undefined);
1222
+ const updatedAt = ref4(undefined);
1223
+ const sync = () => {
1224
+ const snapshot = store.getSnapshot();
1225
+ error.value = snapshot.error;
1226
+ isLoading.value = snapshot.isLoading;
1227
+ report.value = snapshot.report;
1228
+ updatedAt.value = snapshot.updatedAt;
1229
+ };
1230
+ const unsubscribe = store.subscribe(sync);
1231
+ sync();
1232
+ if (typeof window !== "undefined") {
1233
+ store.refresh().catch(() => {});
1234
+ }
1235
+ onUnmounted4(() => {
1236
+ unsubscribe();
1237
+ store.close();
1238
+ });
1239
+ return {
1240
+ error,
1241
+ isLoading,
1242
+ refresh: store.refresh,
1243
+ report,
1244
+ updatedAt
1245
+ };
1246
+ }
1247
+
1248
+ // src/client/platformCoverageWidget.ts
1249
+ var DEFAULT_TITLE4 = "Platform Replacement Coverage";
1250
+ var DEFAULT_DESCRIPTION4 = "Code-owned coverage for hosted voice-platform surfaces, backed by the same proof routes used by release evidence.";
1251
+ var DEFAULT_LINKS = [
1252
+ { href: "/switching-from-vapi", label: "Switching guide" },
1253
+ { href: "/api/voice/vapi-coverage", label: "Coverage JSON" }
1254
+ ];
1255
+ var escapeHtml4 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1256
+ var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
1257
+ var surfaceDetail2 = (surface) => {
1258
+ if (surface.status === "pass") {
1259
+ return surface.replacement;
1260
+ }
1261
+ if (surface.gap) {
1262
+ return surface.gap;
1263
+ }
1264
+ if (surface.missingEvidence?.length) {
1265
+ return `Missing evidence: ${surface.missingEvidence.join(", ")}`;
1266
+ }
1267
+ return surface.replacement;
1268
+ };
1269
+ var createVoicePlatformCoverageViewModel = (snapshot, options = {}) => {
1270
+ const allSurfaces = snapshot.report?.coverage ?? [];
1271
+ const failing = allSurfaces.filter((surface) => surface.status !== "pass");
1272
+ const limit = options.limit ?? 6;
1273
+ const surfaces = allSurfaces.slice(0, limit).map((surface) => ({
1274
+ ...surface,
1275
+ detail: surfaceDetail2(surface),
1276
+ label: surface.surface
1277
+ }));
1278
+ return {
1279
+ description: options.description ?? DEFAULT_DESCRIPTION4,
1280
+ error: snapshot.error,
1281
+ isLoading: snapshot.isLoading,
1282
+ label: snapshot.error ? "Unavailable" : snapshot.report ? failing.length ? `${failing.length} gaps` : `${snapshot.report.total} surfaces passing` : snapshot.isLoading ? "Checking" : "No coverage report",
1283
+ links: options.links ?? DEFAULT_LINKS,
1284
+ status: snapshot.error ? "error" : snapshot.report ? failing.length ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
1285
+ surfaces,
1286
+ title: options.title ?? DEFAULT_TITLE4,
1287
+ updatedAt: snapshot.updatedAt
1288
+ };
1289
+ };
1290
+ var renderVoicePlatformCoverageHTML = (snapshot, options = {}) => {
1291
+ const model = createVoicePlatformCoverageViewModel(snapshot, options);
1292
+ 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)}">
1293
+ <header>
1294
+ <strong>${escapeHtml4(surface.label)}</strong>
1295
+ <span>${escapeHtml4(formatStatus(surface.status))}</span>
1296
+ </header>
1297
+ <p>${escapeHtml4(surface.detail)}</p>
1298
+ <small>${surface.evidence.filter((item) => item.ok).length}/${surface.evidence.length} evidence checks passing</small>
1299
+ </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>`;
1300
+ 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>` : "";
1301
+ return `<section class="absolute-voice-platform-coverage absolute-voice-platform-coverage--${escapeHtml4(model.status)}">
1302
+ <header class="absolute-voice-platform-coverage__header">
1303
+ <span class="absolute-voice-platform-coverage__eyebrow">${escapeHtml4(model.title)}</span>
1304
+ <strong class="absolute-voice-platform-coverage__label">${escapeHtml4(model.label)}</strong>
1305
+ </header>
1306
+ <p class="absolute-voice-platform-coverage__description">${escapeHtml4(model.description)}</p>
1307
+ ${surfaces}
1308
+ ${links}
1309
+ ${model.error ? `<p class="absolute-voice-platform-coverage__error">${escapeHtml4(model.error)}</p>` : ""}
1310
+ </section>`;
1311
+ };
1312
+ 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}`;
1313
+ var mountVoicePlatformCoverage = (element, path = "/api/voice/platform-coverage", options = {}) => {
1314
+ const store = createVoicePlatformCoverageStore(path, options);
1315
+ const render = () => {
1316
+ element.innerHTML = renderVoicePlatformCoverageHTML(store.getSnapshot(), options);
1317
+ };
1318
+ const unsubscribe = store.subscribe(render);
1319
+ render();
1320
+ store.refresh().catch(() => {});
1321
+ return {
1322
+ close: () => {
1323
+ unsubscribe();
1324
+ store.close();
1325
+ },
1326
+ refresh: store.refresh
1327
+ };
1328
+ };
1329
+ var defineVoicePlatformCoverageElement = (tagName = "absolute-voice-platform-coverage") => {
1330
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
1331
+ return;
1332
+ }
1333
+ customElements.define(tagName, class AbsoluteVoicePlatformCoverageElement extends HTMLElement {
1334
+ mounted;
1335
+ connectedCallback() {
1336
+ this.mounted = mountVoicePlatformCoverage(this, this.getAttribute("path") ?? "/api/voice/platform-coverage", {
1337
+ description: this.getAttribute("description") ?? undefined,
1338
+ intervalMs: Number(this.getAttribute("interval-ms") ?? 0) || undefined,
1339
+ limit: Number(this.getAttribute("limit") ?? 0) || undefined,
1340
+ title: this.getAttribute("title") ?? undefined
1341
+ });
1342
+ }
1343
+ disconnectedCallback() {
1344
+ this.mounted?.close();
1345
+ this.mounted = undefined;
1346
+ }
1347
+ });
1348
+ };
1349
+
1350
+ // src/vue/VoicePlatformCoverage.ts
1351
+ var VoicePlatformCoverage = defineComponent4({
1352
+ name: "VoicePlatformCoverage",
1353
+ props: {
1354
+ description: String,
1355
+ intervalMs: Number,
1356
+ limit: Number,
1357
+ path: {
1358
+ default: "/api/voice/platform-coverage",
1359
+ type: String
1360
+ },
1361
+ title: String
1362
+ },
1363
+ setup(props) {
1364
+ const state = useVoicePlatformCoverage(props.path, {
1365
+ description: props.description,
1366
+ intervalMs: props.intervalMs,
1367
+ limit: props.limit,
1368
+ title: props.title
1369
+ });
1370
+ return () => {
1371
+ const model = createVoicePlatformCoverageViewModel({
1372
+ error: state.error.value,
1373
+ isLoading: state.isLoading.value,
1374
+ report: state.report.value,
1375
+ updatedAt: state.updatedAt.value
1376
+ }, {
1377
+ description: props.description,
1378
+ intervalMs: props.intervalMs,
1379
+ limit: props.limit,
1380
+ title: props.title
1381
+ });
1382
+ return h4("section", {
1383
+ class: [
1384
+ "absolute-voice-platform-coverage",
1385
+ `absolute-voice-platform-coverage--${model.status}`
1386
+ ]
1387
+ }, [
1388
+ h4("header", { class: "absolute-voice-platform-coverage__header" }, [
1389
+ h4("span", { class: "absolute-voice-platform-coverage__eyebrow" }, model.title),
1390
+ h4("strong", { class: "absolute-voice-platform-coverage__label" }, model.label)
1391
+ ]),
1392
+ h4("p", { class: "absolute-voice-platform-coverage__description" }, model.description),
1393
+ model.surfaces.length ? h4("div", { class: "absolute-voice-platform-coverage__surfaces" }, model.surfaces.map((surface) => h4("article", {
1394
+ class: [
1395
+ "absolute-voice-platform-coverage__surface",
1396
+ `absolute-voice-platform-coverage__surface--${surface.status}`
1397
+ ],
1398
+ key: surface.surface
1399
+ }, [
1400
+ h4("header", [
1401
+ h4("strong", surface.label),
1402
+ h4("span", surface.status)
1403
+ ]),
1404
+ h4("p", surface.detail),
1405
+ h4("small", `${surface.evidence.filter((item) => item.ok).length}/${surface.evidence.length} evidence checks passing`)
1406
+ ]))) : h4("p", { class: "absolute-voice-platform-coverage__empty" }, model.error ?? "Run the proof pack to populate platform coverage evidence."),
1407
+ model.links.length ? h4("p", { class: "absolute-voice-platform-coverage__links" }, model.links.map((link) => h4("a", { href: link.href, key: link.href }, link.label))) : null,
1408
+ model.error ? h4("p", { class: "absolute-voice-platform-coverage__error" }, model.error) : null
1409
+ ]);
1410
+ };
1411
+ }
1412
+ });
1131
1413
  // src/vue/VoiceProviderSimulationControls.ts
1132
- import { computed, defineComponent as defineComponent4, h as h4 } from "vue";
1414
+ import { computed, defineComponent as defineComponent5, h as h5 } from "vue";
1133
1415
 
1134
1416
  // src/client/providerSimulationControls.ts
1135
1417
  var postSimulation = async (pathPrefix, mode, provider, fetchImpl) => {
@@ -1211,7 +1493,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
1211
1493
  };
1212
1494
 
1213
1495
  // src/client/providerSimulationControlsWidget.ts
1214
- var escapeHtml4 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1496
+ var escapeHtml5 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1215
1497
  var formatKind = (kind) => (kind ?? "stt").toUpperCase();
1216
1498
  var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
1217
1499
  const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
@@ -1231,18 +1513,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
1231
1513
  };
1232
1514
  var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
1233
1515
  const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
1234
- const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml4(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml4(provider.provider)} ${escapeHtml4(formatKind(options.kind))} failure</button>`).join("");
1235
- const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml4(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml4(provider.provider)} recovered</button>`).join("");
1516
+ const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml5(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml5(provider.provider)} ${escapeHtml5(formatKind(options.kind))} failure</button>`).join("");
1517
+ const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml5(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml5(provider.provider)} recovered</button>`).join("");
1236
1518
  return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
1237
1519
  <header class="absolute-voice-provider-simulation__header">
1238
- <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml4(model.title)}</span>
1239
- <strong class="absolute-voice-provider-simulation__label">${escapeHtml4(model.label)}</strong>
1520
+ <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml5(model.title)}</span>
1521
+ <strong class="absolute-voice-provider-simulation__label">${escapeHtml5(model.label)}</strong>
1240
1522
  </header>
1241
- <p class="absolute-voice-provider-simulation__description">${escapeHtml4(model.description)}</p>
1242
- ${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml4(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
1523
+ <p class="absolute-voice-provider-simulation__description">${escapeHtml5(model.description)}</p>
1524
+ ${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml5(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
1243
1525
  <div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
1244
- ${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml4(snapshot.error)}</p>` : ""}
1245
- ${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml4(model.resultText)}</pre>` : ""}
1526
+ ${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml5(snapshot.error)}</p>` : ""}
1527
+ ${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml5(model.resultText)}</pre>` : ""}
1246
1528
  </section>`;
1247
1529
  };
1248
1530
  var bindVoiceProviderSimulationControls = (element, store) => {
@@ -1308,15 +1590,15 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
1308
1590
  };
1309
1591
 
1310
1592
  // src/vue/useVoiceProviderSimulationControls.ts
1311
- import { onUnmounted as onUnmounted4, ref as ref4 } from "vue";
1593
+ import { onUnmounted as onUnmounted5, ref as ref5 } from "vue";
1312
1594
  function useVoiceProviderSimulationControls(options) {
1313
1595
  const store = createVoiceProviderSimulationControlsStore(options);
1314
- const error = ref4(null);
1315
- const isRunning = ref4(false);
1316
- const lastResult = ref4(null);
1317
- const mode = ref4(null);
1318
- const provider = ref4(null);
1319
- const updatedAt = ref4(undefined);
1596
+ const error = ref5(null);
1597
+ const isRunning = ref5(false);
1598
+ const lastResult = ref5(null);
1599
+ const mode = ref5(null);
1600
+ const provider = ref5(null);
1601
+ const updatedAt = ref5(undefined);
1320
1602
  const sync = () => {
1321
1603
  const snapshot = store.getSnapshot();
1322
1604
  error.value = snapshot.error;
@@ -1328,7 +1610,7 @@ function useVoiceProviderSimulationControls(options) {
1328
1610
  };
1329
1611
  const unsubscribe = store.subscribe(sync);
1330
1612
  sync();
1331
- onUnmounted4(() => {
1613
+ onUnmounted5(() => {
1332
1614
  unsubscribe();
1333
1615
  store.close();
1334
1616
  });
@@ -1344,7 +1626,7 @@ function useVoiceProviderSimulationControls(options) {
1344
1626
  }
1345
1627
 
1346
1628
  // src/vue/VoiceProviderSimulationControls.ts
1347
- var VoiceProviderSimulationControls = defineComponent4({
1629
+ var VoiceProviderSimulationControls = defineComponent5({
1348
1630
  name: "VoiceProviderSimulationControls",
1349
1631
  props: {
1350
1632
  class: { default: "", type: String },
@@ -1386,40 +1668,40 @@ var VoiceProviderSimulationControls = defineComponent4({
1386
1668
  const run = (provider, mode) => {
1387
1669
  controls.run(provider, mode).catch(() => {});
1388
1670
  };
1389
- return () => h4("section", {
1671
+ return () => h5("section", {
1390
1672
  class: [
1391
1673
  "absolute-voice-provider-simulation",
1392
1674
  `absolute-voice-provider-simulation--${controls.error.value ? "error" : controls.isRunning.value ? "running" : "ready"}`,
1393
1675
  props.class
1394
1676
  ]
1395
1677
  }, [
1396
- h4("header", { class: "absolute-voice-provider-simulation__header" }, [
1397
- h4("span", { class: "absolute-voice-provider-simulation__eyebrow" }, model.value.title),
1398
- h4("strong", { class: "absolute-voice-provider-simulation__label" }, model.value.label)
1678
+ h5("header", { class: "absolute-voice-provider-simulation__header" }, [
1679
+ h5("span", { class: "absolute-voice-provider-simulation__eyebrow" }, model.value.title),
1680
+ h5("strong", { class: "absolute-voice-provider-simulation__label" }, model.value.label)
1399
1681
  ]),
1400
- h4("p", { class: "absolute-voice-provider-simulation__description" }, model.value.description),
1401
- model.value.canSimulateFailure ? null : h4("p", { class: "absolute-voice-provider-simulation__empty" }, props.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure."),
1402
- h4("div", { class: "absolute-voice-provider-simulation__actions" }, [
1403
- ...model.value.failureProviders.map((provider) => h4("button", {
1682
+ h5("p", { class: "absolute-voice-provider-simulation__description" }, model.value.description),
1683
+ model.value.canSimulateFailure ? null : h5("p", { class: "absolute-voice-provider-simulation__empty" }, props.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure."),
1684
+ h5("div", { class: "absolute-voice-provider-simulation__actions" }, [
1685
+ ...model.value.failureProviders.map((provider) => h5("button", {
1404
1686
  disabled: !model.value.canSimulateFailure || controls.isRunning.value,
1405
1687
  key: `fail-${provider.provider}`,
1406
1688
  onClick: () => run(provider.provider, "failure"),
1407
1689
  type: "button"
1408
1690
  }, `Simulate ${provider.provider} ${props.kind.toUpperCase()} failure`)),
1409
- ...model.value.providers.map((provider) => h4("button", {
1691
+ ...model.value.providers.map((provider) => h5("button", {
1410
1692
  disabled: controls.isRunning.value,
1411
1693
  key: `recover-${provider.provider}`,
1412
1694
  onClick: () => run(provider.provider, "recovery"),
1413
1695
  type: "button"
1414
1696
  }, `Mark ${provider.provider} recovered`))
1415
1697
  ]),
1416
- controls.error.value ? h4("p", { class: "absolute-voice-provider-simulation__error" }, controls.error.value) : null,
1417
- model.value.resultText ? h4("pre", { class: "absolute-voice-provider-simulation__result" }, model.value.resultText) : null
1698
+ controls.error.value ? h5("p", { class: "absolute-voice-provider-simulation__error" }, controls.error.value) : null,
1699
+ model.value.resultText ? h5("pre", { class: "absolute-voice-provider-simulation__result" }, model.value.resultText) : null
1418
1700
  ]);
1419
1701
  }
1420
1702
  });
1421
1703
  // src/vue/VoiceProviderCapabilities.ts
1422
- import { computed as computed2, defineComponent as defineComponent5, h as h5 } from "vue";
1704
+ import { computed as computed2, defineComponent as defineComponent6, h as h6 } from "vue";
1423
1705
 
1424
1706
  // src/client/providerCapabilities.ts
1425
1707
  var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
@@ -1501,12 +1783,12 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
1501
1783
  };
1502
1784
 
1503
1785
  // src/client/providerCapabilitiesWidget.ts
1504
- var DEFAULT_TITLE4 = "Provider Capabilities";
1505
- var DEFAULT_DESCRIPTION4 = "Configured, selected, and healthy voice providers for this deployment.";
1506
- var escapeHtml5 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1786
+ var DEFAULT_TITLE5 = "Provider Capabilities";
1787
+ var DEFAULT_DESCRIPTION5 = "Configured, selected, and healthy voice providers for this deployment.";
1788
+ var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1507
1789
  var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
1508
1790
  var formatKind2 = (kind) => kind.toUpperCase();
1509
- var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
1791
+ var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
1510
1792
  var getCapabilityDetail = (capability) => {
1511
1793
  if (!capability.configured) {
1512
1794
  return "Not configured in this deployment.";
@@ -1532,7 +1814,7 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
1532
1814
  detail: getCapabilityDetail(capability),
1533
1815
  label: `${formatProvider(capability.provider)} ${formatKind2(capability.kind)}`,
1534
1816
  rows: [
1535
- { label: "Status", value: formatStatus(capability.status) },
1817
+ { label: "Status", value: formatStatus2(capability.status) },
1536
1818
  { label: "Selected", value: capability.selected ? "Yes" : "No" },
1537
1819
  { label: "Model", value: capability.model ?? "Default" },
1538
1820
  {
@@ -1547,36 +1829,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
1547
1829
  const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
1548
1830
  return {
1549
1831
  capabilities,
1550
- description: options.description ?? DEFAULT_DESCRIPTION4,
1832
+ description: options.description ?? DEFAULT_DESCRIPTION5,
1551
1833
  error: snapshot.error,
1552
1834
  isLoading: snapshot.isLoading,
1553
1835
  label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
1554
1836
  status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
1555
- title: options.title ?? DEFAULT_TITLE4,
1837
+ title: options.title ?? DEFAULT_TITLE5,
1556
1838
  updatedAt: snapshot.updatedAt
1557
1839
  };
1558
1840
  };
1559
1841
  var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
1560
1842
  const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
1561
- 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--${escapeHtml5(capability.status)}">
1843
+ 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--${escapeHtml6(capability.status)}">
1562
1844
  <header>
1563
- <strong>${escapeHtml5(capability.label)}</strong>
1564
- <span>${escapeHtml5(formatStatus(capability.status))}</span>
1845
+ <strong>${escapeHtml6(capability.label)}</strong>
1846
+ <span>${escapeHtml6(formatStatus2(capability.status))}</span>
1565
1847
  </header>
1566
- <p>${escapeHtml5(capability.detail)}</p>
1848
+ <p>${escapeHtml6(capability.detail)}</p>
1567
1849
  <dl>${capability.rows.map((row) => `<div>
1568
- <dt>${escapeHtml5(row.label)}</dt>
1569
- <dd>${escapeHtml5(row.value)}</dd>
1850
+ <dt>${escapeHtml6(row.label)}</dt>
1851
+ <dd>${escapeHtml6(row.value)}</dd>
1570
1852
  </div>`).join("")}</dl>
1571
1853
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
1572
- return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml5(model.status)}">
1854
+ return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml6(model.status)}">
1573
1855
  <header class="absolute-voice-provider-capabilities__header">
1574
- <span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml5(model.title)}</span>
1575
- <strong class="absolute-voice-provider-capabilities__label">${escapeHtml5(model.label)}</strong>
1856
+ <span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml6(model.title)}</span>
1857
+ <strong class="absolute-voice-provider-capabilities__label">${escapeHtml6(model.label)}</strong>
1576
1858
  </header>
1577
- <p class="absolute-voice-provider-capabilities__description">${escapeHtml5(model.description)}</p>
1859
+ <p class="absolute-voice-provider-capabilities__description">${escapeHtml6(model.description)}</p>
1578
1860
  ${capabilities}
1579
- ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml5(model.error)}</p>` : ""}
1861
+ ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml6(model.error)}</p>` : ""}
1580
1862
  </section>`;
1581
1863
  };
1582
1864
  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}`;
@@ -1618,13 +1900,13 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
1618
1900
  };
1619
1901
 
1620
1902
  // src/vue/useVoiceProviderCapabilities.ts
1621
- import { onUnmounted as onUnmounted5, shallowRef as shallowRef4 } from "vue";
1903
+ import { onUnmounted as onUnmounted6, shallowRef as shallowRef5 } from "vue";
1622
1904
  function useVoiceProviderCapabilities(path = "/api/provider-capabilities", options = {}) {
1623
1905
  const store = createVoiceProviderCapabilitiesStore(path, options);
1624
- const error = shallowRef4(null);
1625
- const isLoading = shallowRef4(false);
1626
- const report = shallowRef4();
1627
- const updatedAt = shallowRef4(undefined);
1906
+ const error = shallowRef5(null);
1907
+ const isLoading = shallowRef5(false);
1908
+ const report = shallowRef5();
1909
+ const updatedAt = shallowRef5(undefined);
1628
1910
  const sync = () => {
1629
1911
  const snapshot = store.getSnapshot();
1630
1912
  error.value = snapshot.error;
@@ -1635,7 +1917,7 @@ function useVoiceProviderCapabilities(path = "/api/provider-capabilities", optio
1635
1917
  const unsubscribe = store.subscribe(sync);
1636
1918
  sync();
1637
1919
  store.refresh().catch(() => {});
1638
- onUnmounted5(() => {
1920
+ onUnmounted6(() => {
1639
1921
  unsubscribe();
1640
1922
  store.close();
1641
1923
  });
@@ -1649,7 +1931,7 @@ function useVoiceProviderCapabilities(path = "/api/provider-capabilities", optio
1649
1931
  }
1650
1932
 
1651
1933
  // src/vue/VoiceProviderCapabilities.ts
1652
- var VoiceProviderCapabilities = defineComponent5({
1934
+ var VoiceProviderCapabilities = defineComponent6({
1653
1935
  name: "VoiceProviderCapabilities",
1654
1936
  props: {
1655
1937
  class: {
@@ -1686,44 +1968,44 @@ var VoiceProviderCapabilities = defineComponent5({
1686
1968
  report: capabilities.report.value,
1687
1969
  updatedAt: capabilities.updatedAt.value
1688
1970
  }, options));
1689
- return () => h5("section", {
1971
+ return () => h6("section", {
1690
1972
  class: [
1691
1973
  "absolute-voice-provider-capabilities",
1692
1974
  `absolute-voice-provider-capabilities--${model.value.status}`,
1693
1975
  props.class
1694
1976
  ]
1695
1977
  }, [
1696
- h5("header", { class: "absolute-voice-provider-capabilities__header" }, [
1697
- h5("span", { class: "absolute-voice-provider-capabilities__eyebrow" }, model.value.title),
1698
- h5("strong", { class: "absolute-voice-provider-capabilities__label" }, model.value.label)
1978
+ h6("header", { class: "absolute-voice-provider-capabilities__header" }, [
1979
+ h6("span", { class: "absolute-voice-provider-capabilities__eyebrow" }, model.value.title),
1980
+ h6("strong", { class: "absolute-voice-provider-capabilities__label" }, model.value.label)
1699
1981
  ]),
1700
- h5("p", { class: "absolute-voice-provider-capabilities__description" }, model.value.description),
1701
- model.value.capabilities.length ? h5("div", { class: "absolute-voice-provider-capabilities__providers" }, model.value.capabilities.map((capability) => h5("article", {
1982
+ h6("p", { class: "absolute-voice-provider-capabilities__description" }, model.value.description),
1983
+ model.value.capabilities.length ? h6("div", { class: "absolute-voice-provider-capabilities__providers" }, model.value.capabilities.map((capability) => h6("article", {
1702
1984
  class: [
1703
1985
  "absolute-voice-provider-capabilities__provider",
1704
1986
  `absolute-voice-provider-capabilities__provider--${capability.status}`
1705
1987
  ],
1706
1988
  key: `${capability.kind}:${capability.provider}`
1707
1989
  }, [
1708
- h5("header", [
1709
- h5("strong", capability.label),
1710
- h5("span", capability.status)
1990
+ h6("header", [
1991
+ h6("strong", capability.label),
1992
+ h6("span", capability.status)
1711
1993
  ]),
1712
- h5("p", capability.detail),
1713
- h5("dl", capability.rows.map((row) => h5("div", { key: row.label }, [
1714
- h5("dt", row.label),
1715
- h5("dd", row.value)
1994
+ h6("p", capability.detail),
1995
+ h6("dl", capability.rows.map((row) => h6("div", { key: row.label }, [
1996
+ h6("dt", row.label),
1997
+ h6("dd", row.value)
1716
1998
  ])))
1717
- ]))) : h5("p", { class: "absolute-voice-provider-capabilities__empty" }, "Configure provider capabilities to see deployment coverage."),
1718
- model.value.error ? h5("p", { class: "absolute-voice-provider-capabilities__error" }, model.value.error) : null
1999
+ ]))) : h6("p", { class: "absolute-voice-provider-capabilities__empty" }, "Configure provider capabilities to see deployment coverage."),
2000
+ model.value.error ? h6("p", { class: "absolute-voice-provider-capabilities__error" }, model.value.error) : null
1719
2001
  ]);
1720
2002
  }
1721
2003
  });
1722
2004
  // src/vue/VoiceProviderContracts.ts
1723
- import { defineComponent as defineComponent6, h as h6 } from "vue";
2005
+ import { defineComponent as defineComponent7, h as h7 } from "vue";
1724
2006
 
1725
2007
  // src/vue/useVoiceProviderContracts.ts
1726
- import { onUnmounted as onUnmounted6, shallowRef as shallowRef5 } from "vue";
2008
+ import { onUnmounted as onUnmounted7, shallowRef as shallowRef6 } from "vue";
1727
2009
 
1728
2010
  // src/client/providerContracts.ts
1729
2011
  var fetchVoiceProviderContracts = async (path = "/api/provider-contracts", options = {}) => {
@@ -1803,10 +2085,10 @@ var createVoiceProviderContractsStore = (path = "/api/provider-contracts", optio
1803
2085
  // src/vue/useVoiceProviderContracts.ts
1804
2086
  function useVoiceProviderContracts(path = "/api/provider-contracts", options = {}) {
1805
2087
  const store = createVoiceProviderContractsStore(path, options);
1806
- const error = shallowRef5(null);
1807
- const isLoading = shallowRef5(false);
1808
- const report = shallowRef5();
1809
- const updatedAt = shallowRef5(undefined);
2088
+ const error = shallowRef6(null);
2089
+ const isLoading = shallowRef6(false);
2090
+ const report = shallowRef6();
2091
+ const updatedAt = shallowRef6(undefined);
1810
2092
  const sync = () => {
1811
2093
  const snapshot = store.getSnapshot();
1812
2094
  error.value = snapshot.error;
@@ -1817,7 +2099,7 @@ function useVoiceProviderContracts(path = "/api/provider-contracts", options = {
1817
2099
  const unsubscribe = store.subscribe(sync);
1818
2100
  sync();
1819
2101
  store.refresh().catch(() => {});
1820
- onUnmounted6(() => {
2102
+ onUnmounted7(() => {
1821
2103
  unsubscribe();
1822
2104
  store.close();
1823
2105
  });
@@ -1831,11 +2113,11 @@ function useVoiceProviderContracts(path = "/api/provider-contracts", options = {
1831
2113
  }
1832
2114
 
1833
2115
  // src/client/providerContractsWidget.ts
1834
- var DEFAULT_TITLE5 = "Provider Contracts";
1835
- var DEFAULT_DESCRIPTION5 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
1836
- var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2116
+ var DEFAULT_TITLE6 = "Provider Contracts";
2117
+ var DEFAULT_DESCRIPTION6 = "Production contract coverage for provider env, latency, fallback, streaming, and capabilities.";
2118
+ var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
1837
2119
  var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
1838
- var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
2120
+ var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
1839
2121
  var contractDetail = (row) => {
1840
2122
  const failing = row.checks.filter((check) => check.status !== "pass");
1841
2123
  if (failing.length === 0) {
@@ -1854,49 +2136,49 @@ var createVoiceProviderContractsViewModel = (snapshot, options = {}) => {
1854
2136
  label: check.remediation?.label ?? check.label
1855
2137
  })),
1856
2138
  rows: [
1857
- { label: "Status", value: formatStatus2(row.status) },
2139
+ { label: "Status", value: formatStatus3(row.status) },
1858
2140
  { label: "Selected", value: row.selected ? "Yes" : "No" },
1859
2141
  { label: "Configured", value: row.configured ? "Yes" : "No" },
1860
2142
  {
1861
2143
  label: "Checks",
1862
- value: row.checks.map((check) => `${check.label}: ${formatStatus2(check.status)}`).join(", ")
2144
+ value: row.checks.map((check) => `${check.label}: ${formatStatus3(check.status)}`).join(", ")
1863
2145
  }
1864
2146
  ]
1865
2147
  }));
1866
2148
  const warningCount = snapshot.report ? snapshot.report.failed + snapshot.report.warned : rows.filter((row) => row.status !== "pass").length;
1867
2149
  return {
1868
- description: options.description ?? DEFAULT_DESCRIPTION5,
2150
+ description: options.description ?? DEFAULT_DESCRIPTION6,
1869
2151
  error: snapshot.error,
1870
2152
  isLoading: snapshot.isLoading,
1871
2153
  label: snapshot.error ? "Unavailable" : rows.length ? warningCount > 0 ? `${warningCount} needs attention` : `${rows.length} passing` : snapshot.isLoading ? "Checking" : "No contracts",
1872
2154
  rows,
1873
2155
  status: snapshot.error ? "error" : rows.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
1874
- title: options.title ?? DEFAULT_TITLE5,
2156
+ title: options.title ?? DEFAULT_TITLE6,
1875
2157
  updatedAt: snapshot.updatedAt
1876
2158
  };
1877
2159
  };
1878
2160
  var renderVoiceProviderContractsHTML = (snapshot, options = {}) => {
1879
2161
  const model = createVoiceProviderContractsViewModel(snapshot, options);
1880
- 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--${escapeHtml6(row.status)}">
2162
+ 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--${escapeHtml7(row.status)}">
1881
2163
  <header>
1882
- <strong>${escapeHtml6(row.label)}</strong>
1883
- <span>${escapeHtml6(formatStatus2(row.status))}</span>
2164
+ <strong>${escapeHtml7(row.label)}</strong>
2165
+ <span>${escapeHtml7(formatStatus3(row.status))}</span>
1884
2166
  </header>
1885
- <p>${escapeHtml6(row.detail)}</p>
1886
- ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml6(remediation.href)}">${escapeHtml6(remediation.label)}</a>` : `<strong>${escapeHtml6(remediation.label)}</strong>`}<span>${escapeHtml6(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
2167
+ <p>${escapeHtml7(row.detail)}</p>
2168
+ ${row.remediations.length ? `<ul class="absolute-voice-provider-contracts__remediations">${row.remediations.map((remediation) => `<li>${remediation.href ? `<a href="${escapeHtml7(remediation.href)}">${escapeHtml7(remediation.label)}</a>` : `<strong>${escapeHtml7(remediation.label)}</strong>`}<span>${escapeHtml7(remediation.detail)}</span></li>`).join("")}</ul>` : ""}
1887
2169
  <dl>${row.rows.map((item) => `<div>
1888
- <dt>${escapeHtml6(item.label)}</dt>
1889
- <dd>${escapeHtml6(item.value)}</dd>
2170
+ <dt>${escapeHtml7(item.label)}</dt>
2171
+ <dd>${escapeHtml7(item.value)}</dd>
1890
2172
  </div>`).join("")}</dl>
1891
2173
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-contracts__empty">Configure provider contracts to see production coverage.</p>';
1892
- return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml6(model.status)}">
2174
+ return `<section class="absolute-voice-provider-contracts absolute-voice-provider-contracts--${escapeHtml7(model.status)}">
1893
2175
  <header class="absolute-voice-provider-contracts__header">
1894
- <span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml6(model.title)}</span>
1895
- <strong class="absolute-voice-provider-contracts__label">${escapeHtml6(model.label)}</strong>
2176
+ <span class="absolute-voice-provider-contracts__eyebrow">${escapeHtml7(model.title)}</span>
2177
+ <strong class="absolute-voice-provider-contracts__label">${escapeHtml7(model.label)}</strong>
1896
2178
  </header>
1897
- <p class="absolute-voice-provider-contracts__description">${escapeHtml6(model.description)}</p>
2179
+ <p class="absolute-voice-provider-contracts__description">${escapeHtml7(model.description)}</p>
1898
2180
  ${rows}
1899
- ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml6(model.error)}</p>` : ""}
2181
+ ${model.error ? `<p class="absolute-voice-provider-contracts__error">${escapeHtml7(model.error)}</p>` : ""}
1900
2182
  </section>`;
1901
2183
  };
1902
2184
  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}`;
@@ -1938,7 +2220,7 @@ var defineVoiceProviderContractsElement = (tagName = "absolute-voice-provider-co
1938
2220
  };
1939
2221
 
1940
2222
  // src/vue/VoiceProviderContracts.ts
1941
- var VoiceProviderContracts = defineComponent6({
2223
+ var VoiceProviderContracts = defineComponent7({
1942
2224
  name: "VoiceProviderContracts",
1943
2225
  props: {
1944
2226
  description: String,
@@ -1966,49 +2248,49 @@ var VoiceProviderContracts = defineComponent6({
1966
2248
  intervalMs: props.intervalMs,
1967
2249
  title: props.title
1968
2250
  });
1969
- return h6("section", {
2251
+ return h7("section", {
1970
2252
  class: [
1971
2253
  "absolute-voice-provider-contracts",
1972
2254
  `absolute-voice-provider-contracts--${model.status}`
1973
2255
  ]
1974
2256
  }, [
1975
- h6("header", { class: "absolute-voice-provider-contracts__header" }, [
1976
- h6("span", { class: "absolute-voice-provider-contracts__eyebrow" }, model.title),
1977
- h6("strong", { class: "absolute-voice-provider-contracts__label" }, model.label)
2257
+ h7("header", { class: "absolute-voice-provider-contracts__header" }, [
2258
+ h7("span", { class: "absolute-voice-provider-contracts__eyebrow" }, model.title),
2259
+ h7("strong", { class: "absolute-voice-provider-contracts__label" }, model.label)
1978
2260
  ]),
1979
- h6("p", { class: "absolute-voice-provider-contracts__description" }, model.description),
1980
- model.rows.length ? h6("div", { class: "absolute-voice-provider-contracts__rows" }, model.rows.map((row) => h6("article", {
2261
+ h7("p", { class: "absolute-voice-provider-contracts__description" }, model.description),
2262
+ model.rows.length ? h7("div", { class: "absolute-voice-provider-contracts__rows" }, model.rows.map((row) => h7("article", {
1981
2263
  class: [
1982
2264
  "absolute-voice-provider-contracts__row",
1983
2265
  `absolute-voice-provider-contracts__row--${row.status}`
1984
2266
  ],
1985
2267
  key: `${row.kind}:${row.provider}`
1986
2268
  }, [
1987
- h6("header", [
1988
- h6("strong", row.label),
1989
- h6("span", row.status)
2269
+ h7("header", [
2270
+ h7("strong", row.label),
2271
+ h7("span", row.status)
1990
2272
  ]),
1991
- h6("p", row.detail),
1992
- row.remediations.length ? h6("ul", {
2273
+ h7("p", row.detail),
2274
+ row.remediations.length ? h7("ul", {
1993
2275
  class: "absolute-voice-provider-contracts__remediations"
1994
- }, row.remediations.map((remediation) => h6("li", {
2276
+ }, row.remediations.map((remediation) => h7("li", {
1995
2277
  key: `${row.kind}:${row.provider}:${remediation.label}`
1996
2278
  }, [
1997
- remediation.href ? h6("a", { href: remediation.href }, remediation.label) : h6("strong", remediation.label),
1998
- h6("span", remediation.detail)
2279
+ remediation.href ? h7("a", { href: remediation.href }, remediation.label) : h7("strong", remediation.label),
2280
+ h7("span", remediation.detail)
1999
2281
  ]))) : null,
2000
- h6("dl", row.rows.map((item) => h6("div", { key: item.label }, [
2001
- h6("dt", item.label),
2002
- h6("dd", item.value)
2282
+ h7("dl", row.rows.map((item) => h7("div", { key: item.label }, [
2283
+ h7("dt", item.label),
2284
+ h7("dd", item.value)
2003
2285
  ])))
2004
- ]))) : h6("p", { class: "absolute-voice-provider-contracts__empty" }, "Configure provider contracts to see production coverage."),
2005
- model.error ? h6("p", { class: "absolute-voice-provider-contracts__error" }, model.error) : null
2286
+ ]))) : h7("p", { class: "absolute-voice-provider-contracts__empty" }, "Configure provider contracts to see production coverage."),
2287
+ model.error ? h7("p", { class: "absolute-voice-provider-contracts__error" }, model.error) : null
2006
2288
  ]);
2007
2289
  };
2008
2290
  }
2009
2291
  });
2010
2292
  // src/vue/VoiceProviderStatus.ts
2011
- import { computed as computed3, defineComponent as defineComponent7, h as h7 } from "vue";
2293
+ import { computed as computed3, defineComponent as defineComponent8, h as h8 } from "vue";
2012
2294
 
2013
2295
  // src/client/providerStatus.ts
2014
2296
  var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
@@ -2091,11 +2373,11 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
2091
2373
  };
2092
2374
 
2093
2375
  // src/client/providerStatusWidget.ts
2094
- var DEFAULT_TITLE6 = "Voice Providers";
2095
- var DEFAULT_DESCRIPTION6 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
2096
- var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2376
+ var DEFAULT_TITLE7 = "Voice Providers";
2377
+ var DEFAULT_DESCRIPTION7 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
2378
+ var escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2097
2379
  var formatProvider3 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
2098
- var formatStatus3 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
2380
+ var formatStatus4 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
2099
2381
  var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
2100
2382
  var formatSuppression = (value) => typeof value === "number" ? `${Math.ceil(value / 1000)}s` : "None";
2101
2383
  var getProviderDetail = (provider) => {
@@ -2137,37 +2419,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
2137
2419
  const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
2138
2420
  const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
2139
2421
  return {
2140
- description: options.description ?? DEFAULT_DESCRIPTION6,
2422
+ description: options.description ?? DEFAULT_DESCRIPTION7,
2141
2423
  error: snapshot.error,
2142
2424
  isLoading: snapshot.isLoading,
2143
2425
  label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
2144
2426
  providers,
2145
2427
  status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
2146
- title: options.title ?? DEFAULT_TITLE6,
2428
+ title: options.title ?? DEFAULT_TITLE7,
2147
2429
  updatedAt: snapshot.updatedAt
2148
2430
  };
2149
2431
  };
2150
2432
  var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
2151
2433
  const model = createVoiceProviderStatusViewModel(snapshot, options);
2152
- 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--${escapeHtml7(provider.status)}">
2434
+ 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--${escapeHtml8(provider.status)}">
2153
2435
  <header>
2154
- <strong>${escapeHtml7(provider.label)}</strong>
2155
- <span>${escapeHtml7(formatStatus3(provider.status))}</span>
2436
+ <strong>${escapeHtml8(provider.label)}</strong>
2437
+ <span>${escapeHtml8(formatStatus4(provider.status))}</span>
2156
2438
  </header>
2157
- <p>${escapeHtml7(provider.detail)}</p>
2439
+ <p>${escapeHtml8(provider.detail)}</p>
2158
2440
  <dl>${provider.rows.map((row) => `<div>
2159
- <dt>${escapeHtml7(row.label)}</dt>
2160
- <dd>${escapeHtml7(row.value)}</dd>
2441
+ <dt>${escapeHtml8(row.label)}</dt>
2442
+ <dd>${escapeHtml8(row.value)}</dd>
2161
2443
  </div>`).join("")}</dl>
2162
2444
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
2163
- return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml7(model.status)}">
2445
+ return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml8(model.status)}">
2164
2446
  <header class="absolute-voice-provider-status__header">
2165
- <span class="absolute-voice-provider-status__eyebrow">${escapeHtml7(model.title)}</span>
2166
- <strong class="absolute-voice-provider-status__label">${escapeHtml7(model.label)}</strong>
2447
+ <span class="absolute-voice-provider-status__eyebrow">${escapeHtml8(model.title)}</span>
2448
+ <strong class="absolute-voice-provider-status__label">${escapeHtml8(model.label)}</strong>
2167
2449
  </header>
2168
- <p class="absolute-voice-provider-status__description">${escapeHtml7(model.description)}</p>
2450
+ <p class="absolute-voice-provider-status__description">${escapeHtml8(model.description)}</p>
2169
2451
  ${providers}
2170
- ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml7(model.error)}</p>` : ""}
2452
+ ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml8(model.error)}</p>` : ""}
2171
2453
  </section>`;
2172
2454
  };
2173
2455
  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}`;
@@ -2209,13 +2491,13 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
2209
2491
  };
2210
2492
 
2211
2493
  // src/vue/useVoiceProviderStatus.ts
2212
- import { onUnmounted as onUnmounted7, ref as ref5, shallowRef as shallowRef6 } from "vue";
2494
+ import { onUnmounted as onUnmounted8, ref as ref6, shallowRef as shallowRef7 } from "vue";
2213
2495
  function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
2214
2496
  const store = createVoiceProviderStatusStore(path, options);
2215
- const error = ref5(null);
2216
- const isLoading = ref5(false);
2217
- const providers = shallowRef6([]);
2218
- const updatedAt = ref5(undefined);
2497
+ const error = ref6(null);
2498
+ const isLoading = ref6(false);
2499
+ const providers = shallowRef7([]);
2500
+ const updatedAt = ref6(undefined);
2219
2501
  const sync = () => {
2220
2502
  const snapshot = store.getSnapshot();
2221
2503
  error.value = snapshot.error;
@@ -2226,7 +2508,7 @@ function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
2226
2508
  const unsubscribe = store.subscribe(sync);
2227
2509
  sync();
2228
2510
  store.refresh().catch(() => {});
2229
- onUnmounted7(() => {
2511
+ onUnmounted8(() => {
2230
2512
  unsubscribe();
2231
2513
  store.close();
2232
2514
  });
@@ -2240,7 +2522,7 @@ function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
2240
2522
  }
2241
2523
 
2242
2524
  // src/vue/VoiceProviderStatus.ts
2243
- var VoiceProviderStatus = defineComponent7({
2525
+ var VoiceProviderStatus = defineComponent8({
2244
2526
  name: "VoiceProviderStatus",
2245
2527
  props: {
2246
2528
  class: {
@@ -2277,41 +2559,41 @@ var VoiceProviderStatus = defineComponent7({
2277
2559
  providers: status.providers.value,
2278
2560
  updatedAt: status.updatedAt.value
2279
2561
  }, options));
2280
- return () => h7("section", {
2562
+ return () => h8("section", {
2281
2563
  class: [
2282
2564
  "absolute-voice-provider-status",
2283
2565
  `absolute-voice-provider-status--${model.value.status}`,
2284
2566
  props.class
2285
2567
  ]
2286
2568
  }, [
2287
- h7("header", { class: "absolute-voice-provider-status__header" }, [
2288
- h7("span", { class: "absolute-voice-provider-status__eyebrow" }, model.value.title),
2289
- h7("strong", { class: "absolute-voice-provider-status__label" }, model.value.label)
2569
+ h8("header", { class: "absolute-voice-provider-status__header" }, [
2570
+ h8("span", { class: "absolute-voice-provider-status__eyebrow" }, model.value.title),
2571
+ h8("strong", { class: "absolute-voice-provider-status__label" }, model.value.label)
2290
2572
  ]),
2291
- h7("p", { class: "absolute-voice-provider-status__description" }, model.value.description),
2292
- model.value.providers.length ? h7("div", { class: "absolute-voice-provider-status__providers" }, model.value.providers.map((provider) => h7("article", {
2573
+ h8("p", { class: "absolute-voice-provider-status__description" }, model.value.description),
2574
+ model.value.providers.length ? h8("div", { class: "absolute-voice-provider-status__providers" }, model.value.providers.map((provider) => h8("article", {
2293
2575
  class: [
2294
2576
  "absolute-voice-provider-status__provider",
2295
2577
  `absolute-voice-provider-status__provider--${provider.status}`
2296
2578
  ],
2297
2579
  key: provider.provider
2298
2580
  }, [
2299
- h7("header", [
2300
- h7("strong", provider.label),
2301
- h7("span", provider.status)
2581
+ h8("header", [
2582
+ h8("strong", provider.label),
2583
+ h8("span", provider.status)
2302
2584
  ]),
2303
- h7("p", provider.detail),
2304
- h7("dl", provider.rows.map((row) => h7("div", { key: row.label }, [
2305
- h7("dt", row.label),
2306
- h7("dd", row.value)
2585
+ h8("p", provider.detail),
2586
+ h8("dl", provider.rows.map((row) => h8("div", { key: row.label }, [
2587
+ h8("dt", row.label),
2588
+ h8("dd", row.value)
2307
2589
  ])))
2308
- ]))) : h7("p", { class: "absolute-voice-provider-status__empty" }, "Run voice traffic to see provider health."),
2309
- model.value.error ? h7("p", { class: "absolute-voice-provider-status__error" }, model.value.error) : null
2590
+ ]))) : h8("p", { class: "absolute-voice-provider-status__empty" }, "Run voice traffic to see provider health."),
2591
+ model.value.error ? h8("p", { class: "absolute-voice-provider-status__error" }, model.value.error) : null
2310
2592
  ]);
2311
2593
  }
2312
2594
  });
2313
2595
  // src/vue/VoiceRoutingStatus.ts
2314
- import { computed as computed4, defineComponent as defineComponent8, h as h8 } from "vue";
2596
+ import { computed as computed4, defineComponent as defineComponent9, h as h9 } from "vue";
2315
2597
 
2316
2598
  // src/client/routingStatus.ts
2317
2599
  var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
@@ -2394,9 +2676,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
2394
2676
  };
2395
2677
 
2396
2678
  // src/client/routingStatusWidget.ts
2397
- var DEFAULT_TITLE7 = "Voice Routing";
2398
- var DEFAULT_DESCRIPTION7 = "Latest provider routing decision from the self-hosted trace store.";
2399
- var escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2679
+ var DEFAULT_TITLE8 = "Voice Routing";
2680
+ var DEFAULT_DESCRIPTION8 = "Latest provider routing decision from the self-hosted trace store.";
2681
+ var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2400
2682
  var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
2401
2683
  var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
2402
2684
  const decision = snapshot.decision;
@@ -2420,30 +2702,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
2420
2702
  ] : [];
2421
2703
  return {
2422
2704
  decision,
2423
- description: options.description ?? DEFAULT_DESCRIPTION7,
2705
+ description: options.description ?? DEFAULT_DESCRIPTION8,
2424
2706
  error: snapshot.error,
2425
2707
  isLoading: snapshot.isLoading,
2426
2708
  label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
2427
2709
  rows,
2428
2710
  status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
2429
- title: options.title ?? DEFAULT_TITLE7,
2711
+ title: options.title ?? DEFAULT_TITLE8,
2430
2712
  updatedAt: snapshot.updatedAt
2431
2713
  };
2432
2714
  };
2433
2715
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
2434
2716
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
2435
2717
  const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
2436
- <span>${escapeHtml8(row.label)}</span>
2437
- <strong>${escapeHtml8(row.value)}</strong>
2718
+ <span>${escapeHtml9(row.label)}</span>
2719
+ <strong>${escapeHtml9(row.value)}</strong>
2438
2720
  </div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
2439
- return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml8(model.status)}">
2721
+ return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml9(model.status)}">
2440
2722
  <header class="absolute-voice-routing-status__header">
2441
- <span class="absolute-voice-routing-status__eyebrow">${escapeHtml8(model.title)}</span>
2442
- <strong class="absolute-voice-routing-status__label">${escapeHtml8(model.label)}</strong>
2723
+ <span class="absolute-voice-routing-status__eyebrow">${escapeHtml9(model.title)}</span>
2724
+ <strong class="absolute-voice-routing-status__label">${escapeHtml9(model.label)}</strong>
2443
2725
  </header>
2444
- <p class="absolute-voice-routing-status__description">${escapeHtml8(model.description)}</p>
2726
+ <p class="absolute-voice-routing-status__description">${escapeHtml9(model.description)}</p>
2445
2727
  ${rows}
2446
- ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml8(model.error)}</p>` : ""}
2728
+ ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml9(model.error)}</p>` : ""}
2447
2729
  </section>`;
2448
2730
  };
2449
2731
  var getVoiceRoutingStatusCSS = () => `.absolute-voice-routing-status{border:1px solid #d8d2c4;border-radius:20px;background:#fffaf0;color:#16130d;padding:18px;box-shadow:0 18px 40px rgba(47,37,18,.12);font-family:inherit}.absolute-voice-routing-status--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-routing-status__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-routing-status__eyebrow{color:#73664f;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-routing-status__label{font-size:24px;line-height:1}.absolute-voice-routing-status__description{color:#514733;margin:12px 0 0}.absolute-voice-routing-status__grid{display:grid;gap:8px;grid-template-columns:repeat(2,minmax(0,1fr));margin-top:14px}.absolute-voice-routing-status__grid div{background:#fff;border:1px solid #eee4d2;border-radius:14px;padding:10px 12px}.absolute-voice-routing-status__grid span{color:#655944;display:block;font-size:12px;margin-bottom:4px}.absolute-voice-routing-status__grid strong{overflow-wrap:anywhere}.absolute-voice-routing-status__empty{color:#655944;margin:14px 0 0}.absolute-voice-routing-status__error{color:#9f1239;font-weight:700}`;
@@ -2485,13 +2767,13 @@ var defineVoiceRoutingStatusElement = (tagName = "absolute-voice-routing-status"
2485
2767
  };
2486
2768
 
2487
2769
  // src/vue/useVoiceRoutingStatus.ts
2488
- import { onUnmounted as onUnmounted8, ref as ref6, shallowRef as shallowRef7 } from "vue";
2770
+ import { onUnmounted as onUnmounted9, ref as ref7, shallowRef as shallowRef8 } from "vue";
2489
2771
  function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
2490
2772
  const store = createVoiceRoutingStatusStore(path, options);
2491
- const decision = shallowRef7(null);
2492
- const error = ref6(null);
2493
- const isLoading = ref6(false);
2494
- const updatedAt = ref6(undefined);
2773
+ const decision = shallowRef8(null);
2774
+ const error = ref7(null);
2775
+ const isLoading = ref7(false);
2776
+ const updatedAt = ref7(undefined);
2495
2777
  const sync = () => {
2496
2778
  const snapshot = store.getSnapshot();
2497
2779
  decision.value = snapshot.decision;
@@ -2502,7 +2784,7 @@ function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
2502
2784
  const unsubscribe = store.subscribe(sync);
2503
2785
  sync();
2504
2786
  store.refresh().catch(() => {});
2505
- onUnmounted8(() => {
2787
+ onUnmounted9(() => {
2506
2788
  unsubscribe();
2507
2789
  store.close();
2508
2790
  });
@@ -2516,7 +2798,7 @@ function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
2516
2798
  }
2517
2799
 
2518
2800
  // src/vue/VoiceRoutingStatus.ts
2519
- var VoiceRoutingStatus = defineComponent8({
2801
+ var VoiceRoutingStatus = defineComponent9({
2520
2802
  name: "VoiceRoutingStatus",
2521
2803
  props: {
2522
2804
  class: {
@@ -2553,28 +2835,28 @@ var VoiceRoutingStatus = defineComponent8({
2553
2835
  isLoading: status.isLoading.value,
2554
2836
  updatedAt: status.updatedAt.value
2555
2837
  }, options));
2556
- return () => h8("section", {
2838
+ return () => h9("section", {
2557
2839
  class: [
2558
2840
  "absolute-voice-routing-status",
2559
2841
  `absolute-voice-routing-status--${model.value.status}`,
2560
2842
  props.class
2561
2843
  ]
2562
2844
  }, [
2563
- h8("header", { class: "absolute-voice-routing-status__header" }, [
2564
- h8("span", { class: "absolute-voice-routing-status__eyebrow" }, model.value.title),
2565
- h8("strong", { class: "absolute-voice-routing-status__label" }, model.value.label)
2845
+ h9("header", { class: "absolute-voice-routing-status__header" }, [
2846
+ h9("span", { class: "absolute-voice-routing-status__eyebrow" }, model.value.title),
2847
+ h9("strong", { class: "absolute-voice-routing-status__label" }, model.value.label)
2566
2848
  ]),
2567
- h8("p", { class: "absolute-voice-routing-status__description" }, model.value.description),
2568
- model.value.rows.length ? h8("div", { class: "absolute-voice-routing-status__grid" }, model.value.rows.map((row) => h8("div", { key: row.label }, [
2569
- h8("span", row.label),
2570
- h8("strong", row.value)
2571
- ]))) : h8("p", { class: "absolute-voice-routing-status__empty" }, "Start a voice session to see the selected provider."),
2572
- model.value.error ? h8("p", { class: "absolute-voice-routing-status__error" }, model.value.error) : null
2849
+ h9("p", { class: "absolute-voice-routing-status__description" }, model.value.description),
2850
+ model.value.rows.length ? h9("div", { class: "absolute-voice-routing-status__grid" }, model.value.rows.map((row) => h9("div", { key: row.label }, [
2851
+ h9("span", row.label),
2852
+ h9("strong", row.value)
2853
+ ]))) : h9("p", { class: "absolute-voice-routing-status__empty" }, "Start a voice session to see the selected provider."),
2854
+ model.value.error ? h9("p", { class: "absolute-voice-routing-status__error" }, model.value.error) : null
2573
2855
  ]);
2574
2856
  }
2575
2857
  });
2576
2858
  // src/vue/useVoiceAgentSquadStatus.ts
2577
- import { onUnmounted as onUnmounted9, ref as ref7, shallowRef as shallowRef8 } from "vue";
2859
+ import { onUnmounted as onUnmounted10, ref as ref8, shallowRef as shallowRef9 } from "vue";
2578
2860
 
2579
2861
  // src/client/traceTimeline.ts
2580
2862
  var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
@@ -2733,11 +3015,11 @@ var createVoiceAgentSquadStatusStore = (path = "/api/voice-traces", options = {}
2733
3015
  // src/vue/useVoiceAgentSquadStatus.ts
2734
3016
  function useVoiceAgentSquadStatus(path = "/api/voice-traces", options = {}) {
2735
3017
  const store = createVoiceAgentSquadStatusStore(path, options);
2736
- const current = shallowRef8(undefined);
2737
- const error = ref7(null);
2738
- const isLoading = ref7(false);
2739
- const report = shallowRef8(undefined);
2740
- const updatedAt = ref7(undefined);
3018
+ const current = shallowRef9(undefined);
3019
+ const error = ref8(null);
3020
+ const isLoading = ref8(false);
3021
+ const report = shallowRef9(undefined);
3022
+ const updatedAt = ref8(undefined);
2741
3023
  const sync = () => {
2742
3024
  const snapshot = store.getSnapshot();
2743
3025
  current.value = snapshot.report.current;
@@ -2751,7 +3033,7 @@ function useVoiceAgentSquadStatus(path = "/api/voice-traces", options = {}) {
2751
3033
  if (typeof window !== "undefined") {
2752
3034
  store.refresh().catch(() => {});
2753
3035
  }
2754
- onUnmounted9(() => {
3036
+ onUnmounted10(() => {
2755
3037
  unsubscribe();
2756
3038
  store.close();
2757
3039
  });
@@ -2765,7 +3047,7 @@ function useVoiceAgentSquadStatus(path = "/api/voice-traces", options = {}) {
2765
3047
  };
2766
3048
  }
2767
3049
  // src/vue/VoiceTurnLatency.ts
2768
- import { computed as computed5, defineComponent as defineComponent9, h as h9 } from "vue";
3050
+ import { computed as computed5, defineComponent as defineComponent10, h as h10 } from "vue";
2769
3051
 
2770
3052
  // src/client/turnLatency.ts
2771
3053
  var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
@@ -2871,10 +3153,10 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
2871
3153
  };
2872
3154
 
2873
3155
  // src/client/turnLatencyWidget.ts
2874
- var DEFAULT_TITLE8 = "Turn Latency";
2875
- var DEFAULT_DESCRIPTION8 = "Per-turn timing from first transcript to commit and assistant response start.";
3156
+ var DEFAULT_TITLE9 = "Turn Latency";
3157
+ var DEFAULT_DESCRIPTION9 = "Per-turn timing from first transcript to commit and assistant response start.";
2876
3158
  var DEFAULT_PROOF_LABEL = "Run latency proof";
2877
- var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3159
+ var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2878
3160
  var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
2879
3161
  var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
2880
3162
  const turns = (snapshot.report?.turns ?? []).map((turn) => ({
@@ -2888,39 +3170,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
2888
3170
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
2889
3171
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
2890
3172
  return {
2891
- description: options.description ?? DEFAULT_DESCRIPTION8,
3173
+ description: options.description ?? DEFAULT_DESCRIPTION9,
2892
3174
  error: snapshot.error,
2893
3175
  isLoading: snapshot.isLoading,
2894
3176
  label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
2895
3177
  proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
2896
3178
  showProofAction: Boolean(options.proofPath),
2897
3179
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
2898
- title: options.title ?? DEFAULT_TITLE8,
3180
+ title: options.title ?? DEFAULT_TITLE9,
2899
3181
  turns,
2900
3182
  updatedAt: snapshot.updatedAt
2901
3183
  };
2902
3184
  };
2903
3185
  var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
2904
3186
  const model = createVoiceTurnLatencyViewModel(snapshot, options);
2905
- 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--${escapeHtml9(turn.status)}">
3187
+ 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--${escapeHtml10(turn.status)}">
2906
3188
  <header>
2907
- <strong>${escapeHtml9(turn.label)}</strong>
2908
- <span>${escapeHtml9(turn.status)}</span>
3189
+ <strong>${escapeHtml10(turn.label)}</strong>
3190
+ <span>${escapeHtml10(turn.status)}</span>
2909
3191
  </header>
2910
3192
  <dl>${turn.rows.map((row) => `<div>
2911
- <dt>${escapeHtml9(row.label)}</dt>
2912
- <dd>${escapeHtml9(row.value)}</dd>
3193
+ <dt>${escapeHtml10(row.label)}</dt>
3194
+ <dd>${escapeHtml10(row.value)}</dd>
2913
3195
  </div>`).join("")}</dl>
2914
3196
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
2915
- return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml9(model.status)}">
3197
+ return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml10(model.status)}">
2916
3198
  <header class="absolute-voice-turn-latency__header">
2917
- <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml9(model.title)}</span>
2918
- <strong class="absolute-voice-turn-latency__label">${escapeHtml9(model.label)}</strong>
3199
+ <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml10(model.title)}</span>
3200
+ <strong class="absolute-voice-turn-latency__label">${escapeHtml10(model.label)}</strong>
2919
3201
  </header>
2920
- <p class="absolute-voice-turn-latency__description">${escapeHtml9(model.description)}</p>
2921
- ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml9(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
3202
+ <p class="absolute-voice-turn-latency__description">${escapeHtml10(model.description)}</p>
3203
+ ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml10(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
2922
3204
  ${turns}
2923
- ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml9(model.error)}</p>` : ""}
3205
+ ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml10(model.error)}</p>` : ""}
2924
3206
  </section>`;
2925
3207
  };
2926
3208
  var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
@@ -2971,13 +3253,13 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
2971
3253
  };
2972
3254
 
2973
3255
  // src/vue/useVoiceTurnLatency.ts
2974
- import { onUnmounted as onUnmounted10, shallowRef as shallowRef9 } from "vue";
3256
+ import { onUnmounted as onUnmounted11, shallowRef as shallowRef10 } from "vue";
2975
3257
  function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
2976
3258
  const store = createVoiceTurnLatencyStore(path, options);
2977
- const error = shallowRef9(null);
2978
- const isLoading = shallowRef9(false);
2979
- const report = shallowRef9();
2980
- const updatedAt = shallowRef9(undefined);
3259
+ const error = shallowRef10(null);
3260
+ const isLoading = shallowRef10(false);
3261
+ const report = shallowRef10();
3262
+ const updatedAt = shallowRef10(undefined);
2981
3263
  const sync = () => {
2982
3264
  const snapshot = store.getSnapshot();
2983
3265
  error.value = snapshot.error;
@@ -2988,7 +3270,7 @@ function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
2988
3270
  const unsubscribe = store.subscribe(sync);
2989
3271
  sync();
2990
3272
  store.refresh().catch(() => {});
2991
- onUnmounted10(() => {
3273
+ onUnmounted11(() => {
2992
3274
  unsubscribe();
2993
3275
  store.close();
2994
3276
  });
@@ -3003,7 +3285,7 @@ function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
3003
3285
  }
3004
3286
 
3005
3287
  // src/vue/VoiceTurnLatency.ts
3006
- var VoiceTurnLatency = defineComponent9({
3288
+ var VoiceTurnLatency = defineComponent10({
3007
3289
  name: "VoiceTurnLatency",
3008
3290
  props: {
3009
3291
  class: { default: "", type: String },
@@ -3029,47 +3311,47 @@ var VoiceTurnLatency = defineComponent9({
3029
3311
  report: latency.report.value,
3030
3312
  updatedAt: latency.updatedAt.value
3031
3313
  }, options));
3032
- return () => h9("section", {
3314
+ return () => h10("section", {
3033
3315
  class: [
3034
3316
  "absolute-voice-turn-latency",
3035
3317
  `absolute-voice-turn-latency--${model.value.status}`,
3036
3318
  props.class
3037
3319
  ]
3038
3320
  }, [
3039
- h9("header", { class: "absolute-voice-turn-latency__header" }, [
3040
- h9("span", { class: "absolute-voice-turn-latency__eyebrow" }, model.value.title),
3041
- h9("strong", { class: "absolute-voice-turn-latency__label" }, model.value.label)
3321
+ h10("header", { class: "absolute-voice-turn-latency__header" }, [
3322
+ h10("span", { class: "absolute-voice-turn-latency__eyebrow" }, model.value.title),
3323
+ h10("strong", { class: "absolute-voice-turn-latency__label" }, model.value.label)
3042
3324
  ]),
3043
- h9("p", { class: "absolute-voice-turn-latency__description" }, model.value.description),
3044
- model.value.showProofAction ? h9("button", {
3325
+ h10("p", { class: "absolute-voice-turn-latency__description" }, model.value.description),
3326
+ model.value.showProofAction ? h10("button", {
3045
3327
  class: "absolute-voice-turn-latency__proof",
3046
3328
  onClick: () => {
3047
3329
  latency.runProof().catch(() => {});
3048
3330
  },
3049
3331
  type: "button"
3050
3332
  }, model.value.proofLabel) : null,
3051
- model.value.turns.length ? h9("div", { class: "absolute-voice-turn-latency__turns" }, model.value.turns.map((turn) => h9("article", {
3333
+ model.value.turns.length ? h10("div", { class: "absolute-voice-turn-latency__turns" }, model.value.turns.map((turn) => h10("article", {
3052
3334
  class: [
3053
3335
  "absolute-voice-turn-latency__turn",
3054
3336
  `absolute-voice-turn-latency__turn--${turn.status}`
3055
3337
  ],
3056
3338
  key: `${turn.sessionId}:${turn.turnId}`
3057
3339
  }, [
3058
- h9("header", [
3059
- h9("strong", turn.label),
3060
- h9("span", turn.status)
3340
+ h10("header", [
3341
+ h10("strong", turn.label),
3342
+ h10("span", turn.status)
3061
3343
  ]),
3062
- h9("dl", turn.rows.map((row) => h9("div", { key: row.label }, [
3063
- h9("dt", row.label),
3064
- h9("dd", row.value)
3344
+ h10("dl", turn.rows.map((row) => h10("div", { key: row.label }, [
3345
+ h10("dt", row.label),
3346
+ h10("dd", row.value)
3065
3347
  ])))
3066
- ]))) : h9("p", { class: "absolute-voice-turn-latency__empty" }, "Complete a voice turn to see latency diagnostics."),
3067
- model.value.error ? h9("p", { class: "absolute-voice-turn-latency__error" }, model.value.error) : null
3348
+ ]))) : h10("p", { class: "absolute-voice-turn-latency__empty" }, "Complete a voice turn to see latency diagnostics."),
3349
+ model.value.error ? h10("p", { class: "absolute-voice-turn-latency__error" }, model.value.error) : null
3068
3350
  ]);
3069
3351
  }
3070
3352
  });
3071
3353
  // src/vue/VoiceTurnQuality.ts
3072
- import { computed as computed6, defineComponent as defineComponent10, h as h10 } from "vue";
3354
+ import { computed as computed6, defineComponent as defineComponent11, h as h11 } from "vue";
3073
3355
 
3074
3356
  // src/client/turnQuality.ts
3075
3357
  var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
@@ -3151,9 +3433,9 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
3151
3433
  };
3152
3434
 
3153
3435
  // src/client/turnQualityWidget.ts
3154
- var DEFAULT_TITLE9 = "Turn Quality";
3155
- var DEFAULT_DESCRIPTION9 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
3156
- var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3436
+ var DEFAULT_TITLE10 = "Turn Quality";
3437
+ var DEFAULT_DESCRIPTION10 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
3438
+ var escapeHtml11 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3157
3439
  var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
3158
3440
  var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
3159
3441
  var getTurnDetail = (turn) => {
@@ -3191,37 +3473,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
3191
3473
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
3192
3474
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
3193
3475
  return {
3194
- description: options.description ?? DEFAULT_DESCRIPTION9,
3476
+ description: options.description ?? DEFAULT_DESCRIPTION10,
3195
3477
  error: snapshot.error,
3196
3478
  isLoading: snapshot.isLoading,
3197
3479
  label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
3198
3480
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
3199
- title: options.title ?? DEFAULT_TITLE9,
3481
+ title: options.title ?? DEFAULT_TITLE10,
3200
3482
  turns,
3201
3483
  updatedAt: snapshot.updatedAt
3202
3484
  };
3203
3485
  };
3204
3486
  var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
3205
3487
  const model = createVoiceTurnQualityViewModel(snapshot, options);
3206
- 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--${escapeHtml10(turn.status)}">
3488
+ 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--${escapeHtml11(turn.status)}">
3207
3489
  <header>
3208
- <strong>${escapeHtml10(turn.label)}</strong>
3209
- <span>${escapeHtml10(turn.status)}</span>
3490
+ <strong>${escapeHtml11(turn.label)}</strong>
3491
+ <span>${escapeHtml11(turn.status)}</span>
3210
3492
  </header>
3211
- <p>${escapeHtml10(turn.detail)}</p>
3493
+ <p>${escapeHtml11(turn.detail)}</p>
3212
3494
  <dl>${turn.rows.map((row) => `<div>
3213
- <dt>${escapeHtml10(row.label)}</dt>
3214
- <dd>${escapeHtml10(row.value)}</dd>
3495
+ <dt>${escapeHtml11(row.label)}</dt>
3496
+ <dd>${escapeHtml11(row.value)}</dd>
3215
3497
  </div>`).join("")}</dl>
3216
3498
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
3217
- return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml10(model.status)}">
3499
+ return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml11(model.status)}">
3218
3500
  <header class="absolute-voice-turn-quality__header">
3219
- <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml10(model.title)}</span>
3220
- <strong class="absolute-voice-turn-quality__label">${escapeHtml10(model.label)}</strong>
3501
+ <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml11(model.title)}</span>
3502
+ <strong class="absolute-voice-turn-quality__label">${escapeHtml11(model.label)}</strong>
3221
3503
  </header>
3222
- <p class="absolute-voice-turn-quality__description">${escapeHtml10(model.description)}</p>
3504
+ <p class="absolute-voice-turn-quality__description">${escapeHtml11(model.description)}</p>
3223
3505
  ${turns}
3224
- ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml10(model.error)}</p>` : ""}
3506
+ ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml11(model.error)}</p>` : ""}
3225
3507
  </section>`;
3226
3508
  };
3227
3509
  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}`;
@@ -3263,13 +3545,13 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
3263
3545
  };
3264
3546
 
3265
3547
  // src/vue/useVoiceTurnQuality.ts
3266
- import { onUnmounted as onUnmounted11, shallowRef as shallowRef10 } from "vue";
3548
+ import { onUnmounted as onUnmounted12, shallowRef as shallowRef11 } from "vue";
3267
3549
  function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
3268
3550
  const store = createVoiceTurnQualityStore(path, options);
3269
- const error = shallowRef10(null);
3270
- const isLoading = shallowRef10(false);
3271
- const report = shallowRef10();
3272
- const updatedAt = shallowRef10(undefined);
3551
+ const error = shallowRef11(null);
3552
+ const isLoading = shallowRef11(false);
3553
+ const report = shallowRef11();
3554
+ const updatedAt = shallowRef11(undefined);
3273
3555
  const sync = () => {
3274
3556
  const snapshot = store.getSnapshot();
3275
3557
  error.value = snapshot.error;
@@ -3280,7 +3562,7 @@ function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
3280
3562
  const unsubscribe = store.subscribe(sync);
3281
3563
  sync();
3282
3564
  store.refresh().catch(() => {});
3283
- onUnmounted11(() => {
3565
+ onUnmounted12(() => {
3284
3566
  unsubscribe();
3285
3567
  store.close();
3286
3568
  });
@@ -3288,7 +3570,7 @@ function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
3288
3570
  }
3289
3571
 
3290
3572
  // src/vue/VoiceTurnQuality.ts
3291
- var VoiceTurnQuality = defineComponent10({
3573
+ var VoiceTurnQuality = defineComponent11({
3292
3574
  name: "VoiceTurnQuality",
3293
3575
  props: {
3294
3576
  class: { default: "", type: String },
@@ -3310,152 +3592,39 @@ var VoiceTurnQuality = defineComponent10({
3310
3592
  report: quality.report.value,
3311
3593
  updatedAt: quality.updatedAt.value
3312
3594
  }, options));
3313
- return () => h10("section", {
3595
+ return () => h11("section", {
3314
3596
  class: [
3315
3597
  "absolute-voice-turn-quality",
3316
3598
  `absolute-voice-turn-quality--${model.value.status}`,
3317
3599
  props.class
3318
3600
  ]
3319
3601
  }, [
3320
- h10("header", { class: "absolute-voice-turn-quality__header" }, [
3321
- h10("span", { class: "absolute-voice-turn-quality__eyebrow" }, model.value.title),
3322
- h10("strong", { class: "absolute-voice-turn-quality__label" }, model.value.label)
3602
+ h11("header", { class: "absolute-voice-turn-quality__header" }, [
3603
+ h11("span", { class: "absolute-voice-turn-quality__eyebrow" }, model.value.title),
3604
+ h11("strong", { class: "absolute-voice-turn-quality__label" }, model.value.label)
3323
3605
  ]),
3324
- h10("p", { class: "absolute-voice-turn-quality__description" }, model.value.description),
3325
- model.value.turns.length ? h10("div", { class: "absolute-voice-turn-quality__turns" }, model.value.turns.map((turn) => h10("article", {
3606
+ h11("p", { class: "absolute-voice-turn-quality__description" }, model.value.description),
3607
+ model.value.turns.length ? h11("div", { class: "absolute-voice-turn-quality__turns" }, model.value.turns.map((turn) => h11("article", {
3326
3608
  class: [
3327
3609
  "absolute-voice-turn-quality__turn",
3328
3610
  `absolute-voice-turn-quality__turn--${turn.status}`
3329
3611
  ],
3330
3612
  key: `${turn.sessionId}:${turn.turnId}`
3331
3613
  }, [
3332
- h10("header", [
3333
- h10("strong", turn.label),
3334
- h10("span", turn.status)
3614
+ h11("header", [
3615
+ h11("strong", turn.label),
3616
+ h11("span", turn.status)
3335
3617
  ]),
3336
- h10("p", turn.detail),
3337
- h10("dl", turn.rows.map((row) => h10("div", { key: row.label }, [
3338
- h10("dt", row.label),
3339
- h10("dd", row.value)
3618
+ h11("p", turn.detail),
3619
+ h11("dl", turn.rows.map((row) => h11("div", { key: row.label }, [
3620
+ h11("dt", row.label),
3621
+ h11("dd", row.value)
3340
3622
  ])))
3341
- ]))) : h10("p", { class: "absolute-voice-turn-quality__empty" }, "Complete a voice turn to see STT quality diagnostics."),
3342
- model.value.error ? h10("p", { class: "absolute-voice-turn-quality__error" }, model.value.error) : null
3623
+ ]))) : h11("p", { class: "absolute-voice-turn-quality__empty" }, "Complete a voice turn to see STT quality diagnostics."),
3624
+ model.value.error ? h11("p", { class: "absolute-voice-turn-quality__error" }, model.value.error) : null
3343
3625
  ]);
3344
3626
  }
3345
3627
  });
3346
- // src/vue/useVoicePlatformCoverage.ts
3347
- import { onUnmounted as onUnmounted12, ref as ref8, shallowRef as shallowRef11 } from "vue";
3348
-
3349
- // src/client/platformCoverage.ts
3350
- var fetchVoicePlatformCoverage = async (path = "/api/voice/platform-coverage", options = {}) => {
3351
- const fetchImpl = options.fetch ?? globalThis.fetch;
3352
- const response = await fetchImpl(path);
3353
- if (!response.ok) {
3354
- throw new Error(`Voice platform coverage failed: HTTP ${response.status}`);
3355
- }
3356
- return await response.json();
3357
- };
3358
- var createVoicePlatformCoverageStore = (path = "/api/voice/platform-coverage", options = {}) => {
3359
- const listeners = new Set;
3360
- let closed = false;
3361
- let timer;
3362
- let snapshot = {
3363
- error: null,
3364
- isLoading: false
3365
- };
3366
- const emit = () => {
3367
- for (const listener of listeners) {
3368
- listener();
3369
- }
3370
- };
3371
- const refresh = async () => {
3372
- if (closed) {
3373
- return snapshot.report;
3374
- }
3375
- snapshot = {
3376
- ...snapshot,
3377
- error: null,
3378
- isLoading: true
3379
- };
3380
- emit();
3381
- try {
3382
- const report = await fetchVoicePlatformCoverage(path, options);
3383
- snapshot = {
3384
- error: null,
3385
- isLoading: false,
3386
- report,
3387
- updatedAt: Date.now()
3388
- };
3389
- emit();
3390
- return report;
3391
- } catch (error) {
3392
- snapshot = {
3393
- ...snapshot,
3394
- error: error instanceof Error ? error.message : String(error),
3395
- isLoading: false
3396
- };
3397
- emit();
3398
- throw error;
3399
- }
3400
- };
3401
- const close = () => {
3402
- closed = true;
3403
- if (timer) {
3404
- clearInterval(timer);
3405
- timer = undefined;
3406
- }
3407
- listeners.clear();
3408
- };
3409
- if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
3410
- timer = setInterval(() => {
3411
- refresh().catch(() => {});
3412
- }, options.intervalMs);
3413
- }
3414
- return {
3415
- close,
3416
- getServerSnapshot: () => snapshot,
3417
- getSnapshot: () => snapshot,
3418
- refresh,
3419
- subscribe: (listener) => {
3420
- listeners.add(listener);
3421
- return () => {
3422
- listeners.delete(listener);
3423
- };
3424
- }
3425
- };
3426
- };
3427
-
3428
- // src/vue/useVoicePlatformCoverage.ts
3429
- function useVoicePlatformCoverage(path = "/api/voice/platform-coverage", options = {}) {
3430
- const store = createVoicePlatformCoverageStore(path, options);
3431
- const error = ref8(null);
3432
- const isLoading = ref8(false);
3433
- const report = shallowRef11(undefined);
3434
- const updatedAt = ref8(undefined);
3435
- const sync = () => {
3436
- const snapshot = store.getSnapshot();
3437
- error.value = snapshot.error;
3438
- isLoading.value = snapshot.isLoading;
3439
- report.value = snapshot.report;
3440
- updatedAt.value = snapshot.updatedAt;
3441
- };
3442
- const unsubscribe = store.subscribe(sync);
3443
- sync();
3444
- if (typeof window !== "undefined") {
3445
- store.refresh().catch(() => {});
3446
- }
3447
- onUnmounted12(() => {
3448
- unsubscribe();
3449
- store.close();
3450
- });
3451
- return {
3452
- error,
3453
- isLoading,
3454
- refresh: store.refresh,
3455
- report,
3456
- updatedAt
3457
- };
3458
- }
3459
3628
  // src/vue/useVoiceLiveOps.ts
3460
3629
  import { onUnmounted as onUnmounted13, ref as ref9, shallowRef as shallowRef12 } from "vue";
3461
3630
 
@@ -5292,6 +5461,7 @@ export {
5292
5461
  VoiceProviderSimulationControls,
5293
5462
  VoiceProviderContracts,
5294
5463
  VoiceProviderCapabilities,
5464
+ VoicePlatformCoverage,
5295
5465
  VoiceOpsStatus,
5296
5466
  VoiceOpsActionCenter,
5297
5467
  VoiceDeliveryRuntime