@absolutejs/voice 0.0.22-beta.152 → 0.0.22-beta.154

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.
@@ -2062,7 +2062,174 @@ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) =
2062
2062
  }
2063
2063
  };
2064
2064
  };
2065
+ // src/client/opsActionCenter.ts
2066
+ var createVoiceOpsActionCenterActions = (options = {}) => {
2067
+ const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
2068
+ const actions = [];
2069
+ if (options.includeProductionReadiness !== false) {
2070
+ actions.push({
2071
+ description: "Refresh the production readiness report.",
2072
+ id: "production-readiness",
2073
+ label: "Refresh readiness",
2074
+ method: "GET",
2075
+ path: options.productionReadinessPath ?? "/api/production-readiness"
2076
+ });
2077
+ }
2078
+ if (options.includeDeliveryRuntime !== false) {
2079
+ actions.push({
2080
+ description: "Drain pending and failed audit/trace deliveries.",
2081
+ id: "delivery-runtime.tick",
2082
+ label: "Tick delivery workers",
2083
+ method: "POST",
2084
+ path: `${deliveryRuntimePath.replace(/\/$/, "")}/tick`
2085
+ }, {
2086
+ description: "Move reviewed dead letters back to live delivery queues.",
2087
+ id: "delivery-runtime.requeue-dead-letters",
2088
+ label: "Requeue dead letters",
2089
+ method: "POST",
2090
+ path: `${deliveryRuntimePath.replace(/\/$/, "")}/requeue-dead-letters`
2091
+ });
2092
+ }
2093
+ if (options.includeTurnLatencyProof !== false) {
2094
+ actions.push({
2095
+ description: "Run the synthetic turn latency proof.",
2096
+ id: "turn-latency.proof",
2097
+ label: "Run latency proof",
2098
+ method: "POST",
2099
+ path: options.turnLatencyProofPath ?? "/api/turn-latency/proof"
2100
+ });
2101
+ }
2102
+ if (options.includeProviderSimulation !== false) {
2103
+ const pathPrefix = options.providerSimulationPathPrefix ?? "/api/stt-simulate";
2104
+ for (const provider of options.providers ?? []) {
2105
+ actions.push({
2106
+ description: `Simulate ${provider} provider failure.`,
2107
+ id: `provider.${provider}.failure`,
2108
+ label: `Simulate ${provider} failure`,
2109
+ method: "POST",
2110
+ path: `${pathPrefix}/failure?provider=${encodeURIComponent(provider)}`
2111
+ }, {
2112
+ description: `Mark ${provider} provider recovered.`,
2113
+ id: `provider.${provider}.recovery`,
2114
+ label: `Recover ${provider}`,
2115
+ method: "POST",
2116
+ path: `${pathPrefix}/recovery?provider=${encodeURIComponent(provider)}`
2117
+ });
2118
+ }
2119
+ }
2120
+ return actions;
2121
+ };
2122
+ var runVoiceOpsAction = async (action, options = {}) => {
2123
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2124
+ const response = await fetchImpl(action.path, {
2125
+ method: action.method ?? "POST"
2126
+ });
2127
+ const body = await response.json().catch(() => null);
2128
+ if (!response.ok) {
2129
+ const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
2130
+ throw new Error(message);
2131
+ }
2132
+ return {
2133
+ actionId: action.id,
2134
+ body,
2135
+ ok: response.ok,
2136
+ ranAt: Date.now(),
2137
+ status: response.status
2138
+ };
2139
+ };
2140
+ var createVoiceOpsActionCenterStore = (options = {}) => {
2141
+ const listeners = new Set;
2142
+ let closed = false;
2143
+ let timer;
2144
+ let snapshot = {
2145
+ actions: options.actions ?? createVoiceOpsActionCenterActions(),
2146
+ error: null,
2147
+ isRunning: false
2148
+ };
2149
+ const emit = () => {
2150
+ for (const listener of listeners) {
2151
+ listener();
2152
+ }
2153
+ };
2154
+ const setActions = (actions) => {
2155
+ snapshot = { ...snapshot, actions, updatedAt: Date.now() };
2156
+ emit();
2157
+ };
2158
+ const run = async (actionId) => {
2159
+ if (closed) {
2160
+ return snapshot.lastResult;
2161
+ }
2162
+ const action = snapshot.actions.find((item) => item.id === actionId);
2163
+ if (!action) {
2164
+ throw new Error(`Voice ops action "${actionId}" is not configured.`);
2165
+ }
2166
+ if (action.disabled) {
2167
+ throw new Error(`Voice ops action "${actionId}" is disabled.`);
2168
+ }
2169
+ snapshot = {
2170
+ ...snapshot,
2171
+ error: null,
2172
+ isRunning: true,
2173
+ runningActionId: action.id
2174
+ };
2175
+ emit();
2176
+ try {
2177
+ const result = await runVoiceOpsAction(action, options);
2178
+ snapshot = {
2179
+ ...snapshot,
2180
+ error: null,
2181
+ isRunning: false,
2182
+ lastResult: result,
2183
+ runningActionId: undefined,
2184
+ updatedAt: Date.now()
2185
+ };
2186
+ emit();
2187
+ return result;
2188
+ } catch (error) {
2189
+ snapshot = {
2190
+ ...snapshot,
2191
+ error: error instanceof Error ? error.message : String(error),
2192
+ isRunning: false,
2193
+ runningActionId: undefined
2194
+ };
2195
+ emit();
2196
+ throw error;
2197
+ }
2198
+ };
2199
+ const close = () => {
2200
+ closed = true;
2201
+ if (timer) {
2202
+ clearInterval(timer);
2203
+ timer = undefined;
2204
+ }
2205
+ listeners.clear();
2206
+ };
2207
+ if (options.intervalMs && options.intervalMs > 0) {
2208
+ timer = setInterval(() => {
2209
+ emit();
2210
+ }, options.intervalMs);
2211
+ }
2212
+ return {
2213
+ close,
2214
+ getServerSnapshot: () => snapshot,
2215
+ getSnapshot: () => snapshot,
2216
+ run,
2217
+ setActions,
2218
+ subscribe: (listener) => {
2219
+ listeners.add(listener);
2220
+ return () => {
2221
+ listeners.delete(listener);
2222
+ };
2223
+ }
2224
+ };
2225
+ };
2065
2226
  // src/client/deliveryRuntime.ts
2227
+ var getDefaultActionPath = (path, action, options) => {
2228
+ if (action === "tick") {
2229
+ return options.tickPath ?? `${path.replace(/\/$/, "")}/tick`;
2230
+ }
2231
+ return options.requeueDeadLettersPath ?? `${path.replace(/\/$/, "")}/requeue-dead-letters`;
2232
+ };
2066
2233
  var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
2067
2234
  const fetchImpl = options.fetch ?? globalThis.fetch;
2068
2235
  const response = await fetchImpl(path);
@@ -2071,11 +2238,29 @@ var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", opt
2071
2238
  }
2072
2239
  return await response.json();
2073
2240
  };
2241
+ var runVoiceDeliveryRuntimeAction = async (action, path = "/api/voice-delivery-runtime", options = {}) => {
2242
+ const fetchImpl = options.fetch ?? globalThis.fetch;
2243
+ const response = await fetchImpl(getDefaultActionPath(path, action, options), {
2244
+ method: "POST"
2245
+ });
2246
+ if (!response.ok) {
2247
+ throw new Error(`Voice delivery runtime ${action} failed: HTTP ${response.status}`);
2248
+ }
2249
+ const body = await response.json();
2250
+ return {
2251
+ action,
2252
+ result: body.result,
2253
+ summary: body.summary,
2254
+ updatedAt: Date.now()
2255
+ };
2256
+ };
2074
2257
  var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", options = {}) => {
2075
2258
  const listeners = new Set;
2076
2259
  let closed = false;
2077
2260
  let timer;
2078
2261
  let snapshot = {
2262
+ actionError: null,
2263
+ actionStatus: "idle",
2079
2264
  error: null,
2080
2265
  isLoading: false
2081
2266
  };
@@ -2097,6 +2282,7 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
2097
2282
  try {
2098
2283
  const report = await fetchVoiceDeliveryRuntime(path, options);
2099
2284
  snapshot = {
2285
+ ...snapshot,
2100
2286
  error: null,
2101
2287
  isLoading: false,
2102
2288
  report,
@@ -2114,6 +2300,37 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
2114
2300
  throw error;
2115
2301
  }
2116
2302
  };
2303
+ const runAction = async (action) => {
2304
+ if (closed) {
2305
+ return snapshot.lastAction;
2306
+ }
2307
+ snapshot = {
2308
+ ...snapshot,
2309
+ actionError: null,
2310
+ actionStatus: "running"
2311
+ };
2312
+ emit();
2313
+ try {
2314
+ const result = await runVoiceDeliveryRuntimeAction(action, path, options);
2315
+ snapshot = {
2316
+ ...snapshot,
2317
+ actionError: null,
2318
+ actionStatus: "completed",
2319
+ lastAction: result
2320
+ };
2321
+ emit();
2322
+ await refresh();
2323
+ return result;
2324
+ } catch (error) {
2325
+ snapshot = {
2326
+ ...snapshot,
2327
+ actionError: error instanceof Error ? error.message : String(error),
2328
+ actionStatus: "failed"
2329
+ };
2330
+ emit();
2331
+ throw error;
2332
+ }
2333
+ };
2117
2334
  const close = () => {
2118
2335
  closed = true;
2119
2336
  if (timer) {
@@ -2131,7 +2348,9 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
2131
2348
  close,
2132
2349
  getServerSnapshot: () => snapshot,
2133
2350
  getSnapshot: () => snapshot,
2351
+ requeueDeadLetters: () => runAction("requeue-dead-letters"),
2134
2352
  refresh,
2353
+ tick: () => runAction("tick"),
2135
2354
  subscribe: (listener) => {
2136
2355
  listeners.add(listener);
2137
2356
  return () => {
@@ -2264,10 +2483,97 @@ var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
2264
2483
  }
2265
2484
  });
2266
2485
  };
2267
- // src/client/deliveryRuntimeWidget.ts
2268
- var DEFAULT_TITLE2 = "Voice Delivery Runtime";
2269
- var DEFAULT_DESCRIPTION2 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
2486
+ // src/client/opsActionCenterWidget.ts
2487
+ var DEFAULT_TITLE2 = "Voice Ops Action Center";
2488
+ var DEFAULT_DESCRIPTION2 = "Run production voice proofs and operator actions from one primitive panel.";
2270
2489
  var escapeHtml2 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2490
+ var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
2491
+ const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
2492
+ return {
2493
+ actions: snapshot.actions.map((action) => ({
2494
+ description: action.description ?? "",
2495
+ disabled: Boolean(action.disabled || snapshot.isRunning),
2496
+ id: action.id,
2497
+ isRunning: snapshot.runningActionId === action.id,
2498
+ label: action.label
2499
+ })),
2500
+ description: options.description ?? DEFAULT_DESCRIPTION2,
2501
+ error: snapshot.error,
2502
+ isRunning: snapshot.isRunning,
2503
+ label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
2504
+ lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
2505
+ status,
2506
+ title: options.title ?? DEFAULT_TITLE2
2507
+ };
2508
+ };
2509
+ var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
2510
+ const model = createVoiceOpsActionCenterViewModel(snapshot, options);
2511
+ const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml2(action.id)}"${action.disabled ? " disabled" : ""}>
2512
+ ${escapeHtml2(action.isRunning ? "Working..." : action.label)}
2513
+ </button>`).join("");
2514
+ return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml2(model.status)}">
2515
+ <header class="absolute-voice-ops-action-center__header">
2516
+ <span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml2(model.title)}</span>
2517
+ <strong class="absolute-voice-ops-action-center__label">${escapeHtml2(model.label)}</strong>
2518
+ </header>
2519
+ <p class="absolute-voice-ops-action-center__description">${escapeHtml2(model.description)}</p>
2520
+ <div class="absolute-voice-ops-action-center__actions">${actions}</div>
2521
+ <p class="absolute-voice-ops-action-center__result">${escapeHtml2(model.lastResultLabel)}</p>
2522
+ ${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml2(model.error)}</p>` : ""}
2523
+ </section>`;
2524
+ };
2525
+ var getVoiceOpsActionCenterCSS = () => `.absolute-voice-ops-action-center{border:1px solid #d5cbb8;border-radius:20px;background:#fffaf1;color:#17130b;padding:18px;box-shadow:0 18px 40px rgba(58,42,16,.12);font-family:inherit}.absolute-voice-ops-action-center--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-action-center__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-action-center__eyebrow{color:#725d37;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-action-center__label{font-size:28px;line-height:1}.absolute-voice-ops-action-center__description,.absolute-voice-ops-action-center__result{color:#5b4b2f;margin:12px 0 0}.absolute-voice-ops-action-center__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-action-center__actions button{background:#7c4a03;border:0;border-radius:999px;color:#fff8e8;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-ops-action-center__actions button:disabled{cursor:not-allowed;opacity:.5}.absolute-voice-ops-action-center__error{color:#9f1239;font-weight:700}`;
2526
+ var mountVoiceOpsActionCenter = (element, options = {}) => {
2527
+ const store = createVoiceOpsActionCenterStore(options);
2528
+ const render = () => {
2529
+ element.innerHTML = renderVoiceOpsActionCenterHTML(store.getSnapshot(), options);
2530
+ };
2531
+ const unsubscribe = store.subscribe(render);
2532
+ const handleClick = (event) => {
2533
+ const target = event.target;
2534
+ if (!(target instanceof Element)) {
2535
+ return;
2536
+ }
2537
+ const action = target.closest("[data-absolute-voice-ops-action]");
2538
+ const actionId = action?.getAttribute("data-absolute-voice-ops-action");
2539
+ if (actionId) {
2540
+ store.run(actionId).catch(() => {});
2541
+ }
2542
+ };
2543
+ element.addEventListener?.("click", handleClick);
2544
+ render();
2545
+ return {
2546
+ close: () => {
2547
+ element.removeEventListener?.("click", handleClick);
2548
+ unsubscribe();
2549
+ store.close();
2550
+ },
2551
+ run: store.run
2552
+ };
2553
+ };
2554
+ var defineVoiceOpsActionCenterElement = (tagName = "absolute-voice-ops-action-center", options = {}) => {
2555
+ if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
2556
+ return;
2557
+ }
2558
+ customElements.define(tagName, class AbsoluteVoiceOpsActionCenterElement extends HTMLElement {
2559
+ mounted;
2560
+ connectedCallback() {
2561
+ this.mounted = mountVoiceOpsActionCenter(this, {
2562
+ ...options,
2563
+ description: this.getAttribute("description") ?? options.description,
2564
+ title: this.getAttribute("title") ?? options.title
2565
+ });
2566
+ }
2567
+ disconnectedCallback() {
2568
+ this.mounted?.close();
2569
+ this.mounted = undefined;
2570
+ }
2571
+ });
2572
+ };
2573
+ // src/client/deliveryRuntimeWidget.ts
2574
+ var DEFAULT_TITLE3 = "Voice Delivery Runtime";
2575
+ var DEFAULT_DESCRIPTION3 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
2576
+ var escapeHtml3 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2271
2577
  var createSurface = (id, summary) => {
2272
2578
  if (!summary) {
2273
2579
  return {
@@ -2301,45 +2607,70 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
2301
2607
  ];
2302
2608
  const hasWarnings = surfaces.some((surface) => surface.status === "warn");
2303
2609
  return {
2304
- description: options.description ?? DEFAULT_DESCRIPTION2,
2610
+ description: options.description ?? DEFAULT_DESCRIPTION3,
2305
2611
  error: snapshot.error,
2612
+ actionError: snapshot.actionError,
2613
+ actionStatus: snapshot.actionStatus,
2306
2614
  isLoading: snapshot.isLoading,
2307
2615
  isRunning: Boolean(report?.isRunning),
2308
2616
  label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
2309
2617
  status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
2310
2618
  surfaces,
2311
- title: options.title ?? DEFAULT_TITLE2,
2619
+ title: options.title ?? DEFAULT_TITLE3,
2312
2620
  updatedAt: snapshot.updatedAt
2313
2621
  };
2314
2622
  };
2315
2623
  var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
2316
2624
  const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
2317
- const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml2(surface.status)}">
2318
- <span>${escapeHtml2(surface.label)}</span>
2319
- <strong>${escapeHtml2(surface.detail)}</strong>
2625
+ const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml3(surface.status)}">
2626
+ <span>${escapeHtml3(surface.label)}</span>
2627
+ <strong>${escapeHtml3(surface.detail)}</strong>
2320
2628
  <small>${String(surface.failed)} failed &middot; ${String(surface.deadLettered)} dead-lettered</small>
2321
2629
  </li>`).join("");
2322
- return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml2(model.status)}">
2630
+ const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
2631
+ <button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
2632
+ <button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
2633
+ </div>`;
2634
+ const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.actionError)}</p>` : "";
2635
+ return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml3(model.status)}">
2323
2636
  <header class="absolute-voice-delivery-runtime__header">
2324
- <span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml2(model.title)}</span>
2325
- <strong class="absolute-voice-delivery-runtime__label">${escapeHtml2(model.label)}</strong>
2637
+ <span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml3(model.title)}</span>
2638
+ <strong class="absolute-voice-delivery-runtime__label">${escapeHtml3(model.label)}</strong>
2326
2639
  </header>
2327
- <p class="absolute-voice-delivery-runtime__description">${escapeHtml2(model.description)}</p>
2640
+ <p class="absolute-voice-delivery-runtime__description">${escapeHtml3(model.description)}</p>
2328
2641
  <ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
2329
- ${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml2(model.error)}</p>` : ""}
2642
+ ${actions}
2643
+ ${actionError}
2644
+ ${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.error)}</p>` : ""}
2330
2645
  </section>`;
2331
2646
  };
2332
- var getVoiceDeliveryRuntimeCSS = () => `.absolute-voice-delivery-runtime{border:1px solid #c9d8cf;border-radius:20px;background:#f6fff9;color:#0d1b12;padding:18px;box-shadow:0 18px 40px rgba(19,55,35,.12);font-family:inherit}.absolute-voice-delivery-runtime--warn,.absolute-voice-delivery-runtime--error{border-color:#f2b56b;background:#fff9ed}.absolute-voice-delivery-runtime__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-delivery-runtime__eyebrow{color:#4e6b59;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-delivery-runtime__label{font-size:28px;line-height:1}.absolute-voice-delivery-runtime__description{color:#33483b;margin:12px 0 0}.absolute-voice-delivery-runtime__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-delivery-runtime__surface{background:#fff;border:1px solid #d9eadf;border-radius:14px;display:grid;gap:4px;padding:10px 12px}.absolute-voice-delivery-runtime__surface--warn{border-color:#f2b56b}.absolute-voice-delivery-runtime__surface--disabled{opacity:.72}.absolute-voice-delivery-runtime__surface span,.absolute-voice-delivery-runtime__surface small{color:#587063}.absolute-voice-delivery-runtime__error{color:#9f1239;font-weight:700}`;
2647
+ var getVoiceDeliveryRuntimeCSS = () => `.absolute-voice-delivery-runtime{border:1px solid #c9d8cf;border-radius:20px;background:#f6fff9;color:#0d1b12;padding:18px;box-shadow:0 18px 40px rgba(19,55,35,.12);font-family:inherit}.absolute-voice-delivery-runtime--warn,.absolute-voice-delivery-runtime--error{border-color:#f2b56b;background:#fff9ed}.absolute-voice-delivery-runtime__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-delivery-runtime__eyebrow{color:#4e6b59;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-delivery-runtime__label{font-size:28px;line-height:1}.absolute-voice-delivery-runtime__description{color:#33483b;margin:12px 0 0}.absolute-voice-delivery-runtime__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-delivery-runtime__surface{background:#fff;border:1px solid #d9eadf;border-radius:14px;display:grid;gap:4px;padding:10px 12px}.absolute-voice-delivery-runtime__surface--warn{border-color:#f2b56b}.absolute-voice-delivery-runtime__surface--disabled{opacity:.72}.absolute-voice-delivery-runtime__surface span,.absolute-voice-delivery-runtime__surface small{color:#587063}.absolute-voice-delivery-runtime__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-delivery-runtime__actions button{background:#134e2d;border:0;border-radius:999px;color:#f6fff9;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-delivery-runtime__actions button:disabled{cursor:not-allowed;opacity:.48}.absolute-voice-delivery-runtime__error{color:#9f1239;font-weight:700}`;
2333
2648
  var mountVoiceDeliveryRuntime = (element, path = "/api/voice-delivery-runtime", options = {}) => {
2334
2649
  const store = createVoiceDeliveryRuntimeStore(path, options);
2335
2650
  const render = () => {
2336
2651
  element.innerHTML = renderVoiceDeliveryRuntimeHTML(store.getSnapshot(), options);
2337
2652
  };
2338
2653
  const unsubscribe = store.subscribe(render);
2654
+ const handleClick = (event) => {
2655
+ const target = event.target;
2656
+ if (!(target instanceof Element)) {
2657
+ return;
2658
+ }
2659
+ const action = target.closest("[data-absolute-voice-delivery-runtime-action]");
2660
+ const actionName = action?.getAttribute("data-absolute-voice-delivery-runtime-action");
2661
+ if (actionName === "tick") {
2662
+ store.tick().catch(() => {});
2663
+ }
2664
+ if (actionName === "requeue-dead-letters") {
2665
+ store.requeueDeadLetters().catch(() => {});
2666
+ }
2667
+ };
2668
+ element.addEventListener?.("click", handleClick);
2339
2669
  render();
2340
2670
  store.refresh().catch(() => {});
2341
2671
  return {
2342
2672
  close: () => {
2673
+ element.removeEventListener?.("click", handleClick);
2343
2674
  unsubscribe();
2344
2675
  store.close();
2345
2676
  },
@@ -2446,9 +2777,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
2446
2777
  };
2447
2778
  };
2448
2779
  // src/client/routingStatusWidget.ts
2449
- var DEFAULT_TITLE3 = "Voice Routing";
2450
- var DEFAULT_DESCRIPTION3 = "Latest provider routing decision from the self-hosted trace store.";
2451
- var escapeHtml3 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2780
+ var DEFAULT_TITLE4 = "Voice Routing";
2781
+ var DEFAULT_DESCRIPTION4 = "Latest provider routing decision from the self-hosted trace store.";
2782
+ var escapeHtml4 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
2452
2783
  var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
2453
2784
  var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
2454
2785
  const decision = snapshot.decision;
@@ -2472,30 +2803,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
2472
2803
  ] : [];
2473
2804
  return {
2474
2805
  decision,
2475
- description: options.description ?? DEFAULT_DESCRIPTION3,
2806
+ description: options.description ?? DEFAULT_DESCRIPTION4,
2476
2807
  error: snapshot.error,
2477
2808
  isLoading: snapshot.isLoading,
2478
2809
  label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
2479
2810
  rows,
2480
2811
  status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
2481
- title: options.title ?? DEFAULT_TITLE3,
2812
+ title: options.title ?? DEFAULT_TITLE4,
2482
2813
  updatedAt: snapshot.updatedAt
2483
2814
  };
2484
2815
  };
2485
2816
  var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
2486
2817
  const model = createVoiceRoutingStatusViewModel(snapshot, options);
2487
2818
  const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
2488
- <span>${escapeHtml3(row.label)}</span>
2489
- <strong>${escapeHtml3(row.value)}</strong>
2819
+ <span>${escapeHtml4(row.label)}</span>
2820
+ <strong>${escapeHtml4(row.value)}</strong>
2490
2821
  </div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
2491
- return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml3(model.status)}">
2822
+ return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml4(model.status)}">
2492
2823
  <header class="absolute-voice-routing-status__header">
2493
- <span class="absolute-voice-routing-status__eyebrow">${escapeHtml3(model.title)}</span>
2494
- <strong class="absolute-voice-routing-status__label">${escapeHtml3(model.label)}</strong>
2824
+ <span class="absolute-voice-routing-status__eyebrow">${escapeHtml4(model.title)}</span>
2825
+ <strong class="absolute-voice-routing-status__label">${escapeHtml4(model.label)}</strong>
2495
2826
  </header>
2496
- <p class="absolute-voice-routing-status__description">${escapeHtml3(model.description)}</p>
2827
+ <p class="absolute-voice-routing-status__description">${escapeHtml4(model.description)}</p>
2497
2828
  ${rows}
2498
- ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml3(model.error)}</p>` : ""}
2829
+ ${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml4(model.error)}</p>` : ""}
2499
2830
  </section>`;
2500
2831
  };
2501
2832
  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}`;
@@ -3147,7 +3478,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
3147
3478
  };
3148
3479
  };
3149
3480
  // src/client/providerSimulationControlsWidget.ts
3150
- var escapeHtml4 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3481
+ var escapeHtml5 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3151
3482
  var formatKind = (kind) => (kind ?? "stt").toUpperCase();
3152
3483
  var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
3153
3484
  const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
@@ -3167,18 +3498,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
3167
3498
  };
3168
3499
  var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
3169
3500
  const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
3170
- 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("");
3171
- 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("");
3501
+ 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("");
3502
+ 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("");
3172
3503
  return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
3173
3504
  <header class="absolute-voice-provider-simulation__header">
3174
- <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml4(model.title)}</span>
3175
- <strong class="absolute-voice-provider-simulation__label">${escapeHtml4(model.label)}</strong>
3505
+ <span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml5(model.title)}</span>
3506
+ <strong class="absolute-voice-provider-simulation__label">${escapeHtml5(model.label)}</strong>
3176
3507
  </header>
3177
- <p class="absolute-voice-provider-simulation__description">${escapeHtml4(model.description)}</p>
3178
- ${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml4(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
3508
+ <p class="absolute-voice-provider-simulation__description">${escapeHtml5(model.description)}</p>
3509
+ ${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml5(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
3179
3510
  <div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
3180
- ${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml4(snapshot.error)}</p>` : ""}
3181
- ${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml4(model.resultText)}</pre>` : ""}
3511
+ ${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml5(snapshot.error)}</p>` : ""}
3512
+ ${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml5(model.resultText)}</pre>` : ""}
3182
3513
  </section>`;
3183
3514
  };
3184
3515
  var bindVoiceProviderSimulationControls = (element, store) => {
@@ -3243,9 +3574,9 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
3243
3574
  });
3244
3575
  };
3245
3576
  // src/client/providerStatusWidget.ts
3246
- var DEFAULT_TITLE4 = "Voice Providers";
3247
- var DEFAULT_DESCRIPTION4 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
3248
- var escapeHtml5 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3577
+ var DEFAULT_TITLE5 = "Voice Providers";
3578
+ var DEFAULT_DESCRIPTION5 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
3579
+ var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3249
3580
  var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
3250
3581
  var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
3251
3582
  var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
@@ -3289,37 +3620,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
3289
3620
  const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
3290
3621
  const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
3291
3622
  return {
3292
- description: options.description ?? DEFAULT_DESCRIPTION4,
3623
+ description: options.description ?? DEFAULT_DESCRIPTION5,
3293
3624
  error: snapshot.error,
3294
3625
  isLoading: snapshot.isLoading,
3295
3626
  label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
3296
3627
  providers,
3297
3628
  status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
3298
- title: options.title ?? DEFAULT_TITLE4,
3629
+ title: options.title ?? DEFAULT_TITLE5,
3299
3630
  updatedAt: snapshot.updatedAt
3300
3631
  };
3301
3632
  };
3302
3633
  var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
3303
3634
  const model = createVoiceProviderStatusViewModel(snapshot, options);
3304
- 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--${escapeHtml5(provider.status)}">
3635
+ 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--${escapeHtml6(provider.status)}">
3305
3636
  <header>
3306
- <strong>${escapeHtml5(provider.label)}</strong>
3307
- <span>${escapeHtml5(formatStatus(provider.status))}</span>
3637
+ <strong>${escapeHtml6(provider.label)}</strong>
3638
+ <span>${escapeHtml6(formatStatus(provider.status))}</span>
3308
3639
  </header>
3309
- <p>${escapeHtml5(provider.detail)}</p>
3640
+ <p>${escapeHtml6(provider.detail)}</p>
3310
3641
  <dl>${provider.rows.map((row) => `<div>
3311
- <dt>${escapeHtml5(row.label)}</dt>
3312
- <dd>${escapeHtml5(row.value)}</dd>
3642
+ <dt>${escapeHtml6(row.label)}</dt>
3643
+ <dd>${escapeHtml6(row.value)}</dd>
3313
3644
  </div>`).join("")}</dl>
3314
3645
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
3315
- return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml5(model.status)}">
3646
+ return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml6(model.status)}">
3316
3647
  <header class="absolute-voice-provider-status__header">
3317
- <span class="absolute-voice-provider-status__eyebrow">${escapeHtml5(model.title)}</span>
3318
- <strong class="absolute-voice-provider-status__label">${escapeHtml5(model.label)}</strong>
3648
+ <span class="absolute-voice-provider-status__eyebrow">${escapeHtml6(model.title)}</span>
3649
+ <strong class="absolute-voice-provider-status__label">${escapeHtml6(model.label)}</strong>
3319
3650
  </header>
3320
- <p class="absolute-voice-provider-status__description">${escapeHtml5(model.description)}</p>
3651
+ <p class="absolute-voice-provider-status__description">${escapeHtml6(model.description)}</p>
3321
3652
  ${providers}
3322
- ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml5(model.error)}</p>` : ""}
3653
+ ${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml6(model.error)}</p>` : ""}
3323
3654
  </section>`;
3324
3655
  };
3325
3656
  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}`;
@@ -3360,9 +3691,9 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
3360
3691
  });
3361
3692
  };
3362
3693
  // src/client/providerCapabilitiesWidget.ts
3363
- var DEFAULT_TITLE5 = "Provider Capabilities";
3364
- var DEFAULT_DESCRIPTION5 = "Configured, selected, and healthy voice providers for this deployment.";
3365
- var escapeHtml6 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3694
+ var DEFAULT_TITLE6 = "Provider Capabilities";
3695
+ var DEFAULT_DESCRIPTION6 = "Configured, selected, and healthy voice providers for this deployment.";
3696
+ var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3366
3697
  var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
3367
3698
  var formatKind2 = (kind) => kind.toUpperCase();
3368
3699
  var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
@@ -3406,36 +3737,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
3406
3737
  const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
3407
3738
  return {
3408
3739
  capabilities,
3409
- description: options.description ?? DEFAULT_DESCRIPTION5,
3740
+ description: options.description ?? DEFAULT_DESCRIPTION6,
3410
3741
  error: snapshot.error,
3411
3742
  isLoading: snapshot.isLoading,
3412
3743
  label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
3413
3744
  status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
3414
- title: options.title ?? DEFAULT_TITLE5,
3745
+ title: options.title ?? DEFAULT_TITLE6,
3415
3746
  updatedAt: snapshot.updatedAt
3416
3747
  };
3417
3748
  };
3418
3749
  var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
3419
3750
  const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
3420
- 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)}">
3751
+ 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--${escapeHtml7(capability.status)}">
3421
3752
  <header>
3422
- <strong>${escapeHtml6(capability.label)}</strong>
3423
- <span>${escapeHtml6(formatStatus2(capability.status))}</span>
3753
+ <strong>${escapeHtml7(capability.label)}</strong>
3754
+ <span>${escapeHtml7(formatStatus2(capability.status))}</span>
3424
3755
  </header>
3425
- <p>${escapeHtml6(capability.detail)}</p>
3756
+ <p>${escapeHtml7(capability.detail)}</p>
3426
3757
  <dl>${capability.rows.map((row) => `<div>
3427
- <dt>${escapeHtml6(row.label)}</dt>
3428
- <dd>${escapeHtml6(row.value)}</dd>
3758
+ <dt>${escapeHtml7(row.label)}</dt>
3759
+ <dd>${escapeHtml7(row.value)}</dd>
3429
3760
  </div>`).join("")}</dl>
3430
3761
  </article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
3431
- return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml6(model.status)}">
3762
+ return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml7(model.status)}">
3432
3763
  <header class="absolute-voice-provider-capabilities__header">
3433
- <span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml6(model.title)}</span>
3434
- <strong class="absolute-voice-provider-capabilities__label">${escapeHtml6(model.label)}</strong>
3764
+ <span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml7(model.title)}</span>
3765
+ <strong class="absolute-voice-provider-capabilities__label">${escapeHtml7(model.label)}</strong>
3435
3766
  </header>
3436
- <p class="absolute-voice-provider-capabilities__description">${escapeHtml6(model.description)}</p>
3767
+ <p class="absolute-voice-provider-capabilities__description">${escapeHtml7(model.description)}</p>
3437
3768
  ${capabilities}
3438
- ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml6(model.error)}</p>` : ""}
3769
+ ${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml7(model.error)}</p>` : ""}
3439
3770
  </section>`;
3440
3771
  };
3441
3772
  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}`;
@@ -3476,9 +3807,9 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
3476
3807
  });
3477
3808
  };
3478
3809
  // src/client/turnQualityWidget.ts
3479
- var DEFAULT_TITLE6 = "Turn Quality";
3480
- var DEFAULT_DESCRIPTION6 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
3481
- var escapeHtml7 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3810
+ var DEFAULT_TITLE7 = "Turn Quality";
3811
+ var DEFAULT_DESCRIPTION7 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
3812
+ var escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3482
3813
  var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
3483
3814
  var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
3484
3815
  var getTurnDetail = (turn) => {
@@ -3516,37 +3847,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
3516
3847
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
3517
3848
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
3518
3849
  return {
3519
- description: options.description ?? DEFAULT_DESCRIPTION6,
3850
+ description: options.description ?? DEFAULT_DESCRIPTION7,
3520
3851
  error: snapshot.error,
3521
3852
  isLoading: snapshot.isLoading,
3522
3853
  label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
3523
3854
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
3524
- title: options.title ?? DEFAULT_TITLE6,
3855
+ title: options.title ?? DEFAULT_TITLE7,
3525
3856
  turns,
3526
3857
  updatedAt: snapshot.updatedAt
3527
3858
  };
3528
3859
  };
3529
3860
  var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
3530
3861
  const model = createVoiceTurnQualityViewModel(snapshot, options);
3531
- 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--${escapeHtml7(turn.status)}">
3862
+ 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--${escapeHtml8(turn.status)}">
3532
3863
  <header>
3533
- <strong>${escapeHtml7(turn.label)}</strong>
3534
- <span>${escapeHtml7(turn.status)}</span>
3864
+ <strong>${escapeHtml8(turn.label)}</strong>
3865
+ <span>${escapeHtml8(turn.status)}</span>
3535
3866
  </header>
3536
- <p>${escapeHtml7(turn.detail)}</p>
3867
+ <p>${escapeHtml8(turn.detail)}</p>
3537
3868
  <dl>${turn.rows.map((row) => `<div>
3538
- <dt>${escapeHtml7(row.label)}</dt>
3539
- <dd>${escapeHtml7(row.value)}</dd>
3869
+ <dt>${escapeHtml8(row.label)}</dt>
3870
+ <dd>${escapeHtml8(row.value)}</dd>
3540
3871
  </div>`).join("")}</dl>
3541
3872
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
3542
- return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml7(model.status)}">
3873
+ return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml8(model.status)}">
3543
3874
  <header class="absolute-voice-turn-quality__header">
3544
- <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml7(model.title)}</span>
3545
- <strong class="absolute-voice-turn-quality__label">${escapeHtml7(model.label)}</strong>
3875
+ <span class="absolute-voice-turn-quality__eyebrow">${escapeHtml8(model.title)}</span>
3876
+ <strong class="absolute-voice-turn-quality__label">${escapeHtml8(model.label)}</strong>
3546
3877
  </header>
3547
- <p class="absolute-voice-turn-quality__description">${escapeHtml7(model.description)}</p>
3878
+ <p class="absolute-voice-turn-quality__description">${escapeHtml8(model.description)}</p>
3548
3879
  ${turns}
3549
- ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml7(model.error)}</p>` : ""}
3880
+ ${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml8(model.error)}</p>` : ""}
3550
3881
  </section>`;
3551
3882
  };
3552
3883
  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}`;
@@ -3587,10 +3918,10 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
3587
3918
  });
3588
3919
  };
3589
3920
  // src/client/turnLatencyWidget.ts
3590
- var DEFAULT_TITLE7 = "Turn Latency";
3591
- var DEFAULT_DESCRIPTION7 = "Per-turn timing from first transcript to commit and assistant response start.";
3921
+ var DEFAULT_TITLE8 = "Turn Latency";
3922
+ var DEFAULT_DESCRIPTION8 = "Per-turn timing from first transcript to commit and assistant response start.";
3592
3923
  var DEFAULT_PROOF_LABEL = "Run latency proof";
3593
- var escapeHtml8 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3924
+ var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3594
3925
  var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
3595
3926
  var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
3596
3927
  const turns = (snapshot.report?.turns ?? []).map((turn) => ({
@@ -3604,39 +3935,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
3604
3935
  const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
3605
3936
  const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
3606
3937
  return {
3607
- description: options.description ?? DEFAULT_DESCRIPTION7,
3938
+ description: options.description ?? DEFAULT_DESCRIPTION8,
3608
3939
  error: snapshot.error,
3609
3940
  isLoading: snapshot.isLoading,
3610
3941
  label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
3611
3942
  proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
3612
3943
  showProofAction: Boolean(options.proofPath),
3613
3944
  status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
3614
- title: options.title ?? DEFAULT_TITLE7,
3945
+ title: options.title ?? DEFAULT_TITLE8,
3615
3946
  turns,
3616
3947
  updatedAt: snapshot.updatedAt
3617
3948
  };
3618
3949
  };
3619
3950
  var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
3620
3951
  const model = createVoiceTurnLatencyViewModel(snapshot, options);
3621
- 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--${escapeHtml8(turn.status)}">
3952
+ 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)}">
3622
3953
  <header>
3623
- <strong>${escapeHtml8(turn.label)}</strong>
3624
- <span>${escapeHtml8(turn.status)}</span>
3954
+ <strong>${escapeHtml9(turn.label)}</strong>
3955
+ <span>${escapeHtml9(turn.status)}</span>
3625
3956
  </header>
3626
3957
  <dl>${turn.rows.map((row) => `<div>
3627
- <dt>${escapeHtml8(row.label)}</dt>
3628
- <dd>${escapeHtml8(row.value)}</dd>
3958
+ <dt>${escapeHtml9(row.label)}</dt>
3959
+ <dd>${escapeHtml9(row.value)}</dd>
3629
3960
  </div>`).join("")}</dl>
3630
3961
  </article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
3631
- return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml8(model.status)}">
3962
+ return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml9(model.status)}">
3632
3963
  <header class="absolute-voice-turn-latency__header">
3633
- <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml8(model.title)}</span>
3634
- <strong class="absolute-voice-turn-latency__label">${escapeHtml8(model.label)}</strong>
3964
+ <span class="absolute-voice-turn-latency__eyebrow">${escapeHtml9(model.title)}</span>
3965
+ <strong class="absolute-voice-turn-latency__label">${escapeHtml9(model.label)}</strong>
3635
3966
  </header>
3636
- <p class="absolute-voice-turn-latency__description">${escapeHtml8(model.description)}</p>
3637
- ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml8(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
3967
+ <p class="absolute-voice-turn-latency__description">${escapeHtml9(model.description)}</p>
3968
+ ${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml9(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
3638
3969
  ${turns}
3639
- ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml8(model.error)}</p>` : ""}
3970
+ ${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml9(model.error)}</p>` : ""}
3640
3971
  </section>`;
3641
3972
  };
3642
3973
  var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
@@ -3686,9 +4017,9 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
3686
4017
  });
3687
4018
  };
3688
4019
  // src/client/traceTimelineWidget.ts
3689
- var DEFAULT_TITLE8 = "Voice Traces";
3690
- var DEFAULT_DESCRIPTION8 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
3691
- var escapeHtml9 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
4020
+ var DEFAULT_TITLE9 = "Voice Traces";
4021
+ var DEFAULT_DESCRIPTION9 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
4022
+ var escapeHtml10 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
3692
4023
  var formatMs2 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
3693
4024
  var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
3694
4025
  var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
@@ -3702,34 +4033,34 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
3702
4033
  const failed = sessions.filter((session) => session.status === "failed").length;
3703
4034
  const warnings = sessions.filter((session) => session.status === "warning").length;
3704
4035
  return {
3705
- description: options.description ?? DEFAULT_DESCRIPTION8,
4036
+ description: options.description ?? DEFAULT_DESCRIPTION9,
3706
4037
  error: snapshot.error,
3707
4038
  isLoading: snapshot.isLoading,
3708
4039
  label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
3709
4040
  sessions,
3710
4041
  status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
3711
- title: options.title ?? DEFAULT_TITLE8,
4042
+ title: options.title ?? DEFAULT_TITLE9,
3712
4043
  updatedAt: snapshot.updatedAt
3713
4044
  };
3714
4045
  };
3715
4046
  var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
3716
4047
  const model = createVoiceTraceTimelineViewModel(snapshot, options);
3717
- const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml9(session.status)}">
4048
+ const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml10(session.status)}">
3718
4049
  <header>
3719
- <strong>${escapeHtml9(session.sessionId)}</strong>
3720
- <span>${escapeHtml9(session.status)}</span>
4050
+ <strong>${escapeHtml10(session.sessionId)}</strong>
4051
+ <span>${escapeHtml10(session.status)}</span>
3721
4052
  </header>
3722
- <p>${escapeHtml9(session.label)} \xB7 ${escapeHtml9(session.durationLabel)} \xB7 ${escapeHtml9(session.providerLabel)}</p>
3723
- <a href="${escapeHtml9(session.detailHref)}">Open timeline</a>
4053
+ <p>${escapeHtml10(session.label)} \xB7 ${escapeHtml10(session.durationLabel)} \xB7 ${escapeHtml10(session.providerLabel)}</p>
4054
+ <a href="${escapeHtml10(session.detailHref)}">Open timeline</a>
3724
4055
  </article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
3725
- return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml9(model.status)}">
4056
+ return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml10(model.status)}">
3726
4057
  <header class="absolute-voice-trace-timeline__header">
3727
- <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml9(model.title)}</span>
3728
- <strong class="absolute-voice-trace-timeline__label">${escapeHtml9(model.label)}</strong>
4058
+ <span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml10(model.title)}</span>
4059
+ <strong class="absolute-voice-trace-timeline__label">${escapeHtml10(model.label)}</strong>
3729
4060
  </header>
3730
- <p class="absolute-voice-trace-timeline__description">${escapeHtml9(model.description)}</p>
4061
+ <p class="absolute-voice-trace-timeline__description">${escapeHtml10(model.description)}</p>
3731
4062
  ${sessions}
3732
- ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml9(model.error)}</p>` : ""}
4063
+ ${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml10(model.error)}</p>` : ""}
3733
4064
  </section>`;
3734
4065
  };
3735
4066
  var getVoiceTraceTimelineCSS = () => `.absolute-voice-trace-timeline{border:1px solid #bad7d3;border-radius:20px;background:#f3fffb;color:#09201c;padding:18px;box-shadow:0 18px 40px rgba(9,32,28,.12);font-family:inherit}.absolute-voice-trace-timeline--error,.absolute-voice-trace-timeline--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-trace-timeline--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-trace-timeline__header,.absolute-voice-trace-timeline__session header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-trace-timeline__eyebrow{color:#17665b;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-trace-timeline__label{font-size:24px;line-height:1}.absolute-voice-trace-timeline__description,.absolute-voice-trace-timeline__session p,.absolute-voice-trace-timeline__empty{color:#35544f}.absolute-voice-trace-timeline__sessions{display:grid;gap:12px;margin-top:14px}.absolute-voice-trace-timeline__session{background:#fff;border:1px solid #cfe7e2;border-radius:16px;padding:14px}.absolute-voice-trace-timeline__session--failed{border-color:#f2a7a7}.absolute-voice-trace-timeline__session--warning{border-color:#fbbf24}.absolute-voice-trace-timeline__session p{margin:10px 0}.absolute-voice-trace-timeline__session a{color:#0f766e;font-weight:800}.absolute-voice-trace-timeline__empty{margin:14px 0 0}.absolute-voice-trace-timeline__error{color:#9f1239;font-weight:700}`;
@@ -3852,6 +4183,8 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
3852
4183
  };
3853
4184
  export {
3854
4185
  runVoiceTurnLatencyProof,
4186
+ runVoiceOpsAction,
4187
+ runVoiceDeliveryRuntimeAction,
3855
4188
  runVoiceCampaignDialerProofAction,
3856
4189
  renderVoiceTurnQualityHTML,
3857
4190
  renderVoiceTurnLatencyHTML,
@@ -3861,6 +4194,7 @@ export {
3861
4194
  renderVoiceProviderSimulationControlsHTML,
3862
4195
  renderVoiceProviderCapabilitiesHTML,
3863
4196
  renderVoiceOpsStatusHTML,
4197
+ renderVoiceOpsActionCenterHTML,
3864
4198
  renderVoiceDeliveryRuntimeHTML,
3865
4199
  mountVoiceTurnQuality,
3866
4200
  mountVoiceTurnLatency,
@@ -3870,6 +4204,7 @@ export {
3870
4204
  mountVoiceProviderSimulationControls,
3871
4205
  mountVoiceProviderCapabilities,
3872
4206
  mountVoiceOpsStatus,
4207
+ mountVoiceOpsActionCenter,
3873
4208
  mountVoiceDeliveryRuntime,
3874
4209
  getVoiceTurnQualityCSS,
3875
4210
  getVoiceTraceTimelineCSS,
@@ -3878,6 +4213,7 @@ export {
3878
4213
  getVoiceProviderCapabilitiesCSS,
3879
4214
  getVoiceOpsStatusLabel,
3880
4215
  getVoiceOpsStatusCSS,
4216
+ getVoiceOpsActionCenterCSS,
3881
4217
  getVoiceDeliveryRuntimeCSS,
3882
4218
  fetchVoiceWorkflowStatus,
3883
4219
  fetchVoiceTurnQuality,
@@ -3897,6 +4233,7 @@ export {
3897
4233
  defineVoiceProviderSimulationControlsElement,
3898
4234
  defineVoiceProviderCapabilitiesElement,
3899
4235
  defineVoiceOpsStatusElement,
4236
+ defineVoiceOpsActionCenterElement,
3900
4237
  defineVoiceDeliveryRuntimeElement,
3901
4238
  decodeVoiceAudioChunk,
3902
4239
  createVoiceWorkflowStatusStore,
@@ -3917,6 +4254,9 @@ export {
3917
4254
  createVoiceProviderCapabilitiesStore,
3918
4255
  createVoiceOpsStatusViewModel,
3919
4256
  createVoiceOpsStatusStore,
4257
+ createVoiceOpsActionCenterViewModel,
4258
+ createVoiceOpsActionCenterStore,
4259
+ createVoiceOpsActionCenterActions,
3920
4260
  createVoiceLiveTurnLatencyMonitor,
3921
4261
  createVoiceDuplexController,
3922
4262
  createVoiceDeliveryRuntimeViewModel,