@absolutejs/voice 0.0.22-beta.151 → 0.0.22-beta.153
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/README.md +30 -0
- package/dist/angular/index.d.ts +2 -0
- package/dist/angular/index.js +604 -124
- package/dist/angular/voice-delivery-runtime.component.d.ts +17 -0
- package/dist/angular/voice-delivery-runtime.service.d.ts +16 -0
- package/dist/client/deliveryRuntime.d.ts +34 -0
- package/dist/client/deliveryRuntimeWidget.d.ts +37 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +371 -100
- package/dist/deliveryRuntime.d.ts +14 -2
- package/dist/index.js +44 -1
- package/dist/react/VoiceDeliveryRuntime.d.ts +7 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +632 -256
- package/dist/react/useVoiceDeliveryRuntime.d.ts +13 -0
- package/dist/svelte/createVoiceDeliveryRuntime.d.ts +11 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +394 -114
- package/dist/vue/VoiceDeliveryRuntime.d.ts +30 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +649 -261
- package/dist/vue/useVoiceDeliveryRuntime.d.ts +13 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -2062,6 +2062,142 @@ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) =
|
|
|
2062
2062
|
}
|
|
2063
2063
|
};
|
|
2064
2064
|
};
|
|
2065
|
+
// src/client/deliveryRuntime.ts
|
|
2066
|
+
var getDefaultActionPath = (path, action, options) => {
|
|
2067
|
+
if (action === "tick") {
|
|
2068
|
+
return options.tickPath ?? `${path.replace(/\/$/, "")}/tick`;
|
|
2069
|
+
}
|
|
2070
|
+
return options.requeueDeadLettersPath ?? `${path.replace(/\/$/, "")}/requeue-dead-letters`;
|
|
2071
|
+
};
|
|
2072
|
+
var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
2073
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2074
|
+
const response = await fetchImpl(path);
|
|
2075
|
+
if (!response.ok) {
|
|
2076
|
+
throw new Error(`Voice delivery runtime failed: HTTP ${response.status}`);
|
|
2077
|
+
}
|
|
2078
|
+
return await response.json();
|
|
2079
|
+
};
|
|
2080
|
+
var runVoiceDeliveryRuntimeAction = async (action, path = "/api/voice-delivery-runtime", options = {}) => {
|
|
2081
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2082
|
+
const response = await fetchImpl(getDefaultActionPath(path, action, options), {
|
|
2083
|
+
method: "POST"
|
|
2084
|
+
});
|
|
2085
|
+
if (!response.ok) {
|
|
2086
|
+
throw new Error(`Voice delivery runtime ${action} failed: HTTP ${response.status}`);
|
|
2087
|
+
}
|
|
2088
|
+
const body = await response.json();
|
|
2089
|
+
return {
|
|
2090
|
+
action,
|
|
2091
|
+
result: body.result,
|
|
2092
|
+
summary: body.summary,
|
|
2093
|
+
updatedAt: Date.now()
|
|
2094
|
+
};
|
|
2095
|
+
};
|
|
2096
|
+
var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
2097
|
+
const listeners = new Set;
|
|
2098
|
+
let closed = false;
|
|
2099
|
+
let timer;
|
|
2100
|
+
let snapshot = {
|
|
2101
|
+
actionError: null,
|
|
2102
|
+
actionStatus: "idle",
|
|
2103
|
+
error: null,
|
|
2104
|
+
isLoading: false
|
|
2105
|
+
};
|
|
2106
|
+
const emit = () => {
|
|
2107
|
+
for (const listener of listeners) {
|
|
2108
|
+
listener();
|
|
2109
|
+
}
|
|
2110
|
+
};
|
|
2111
|
+
const refresh = async () => {
|
|
2112
|
+
if (closed) {
|
|
2113
|
+
return snapshot.report;
|
|
2114
|
+
}
|
|
2115
|
+
snapshot = {
|
|
2116
|
+
...snapshot,
|
|
2117
|
+
error: null,
|
|
2118
|
+
isLoading: true
|
|
2119
|
+
};
|
|
2120
|
+
emit();
|
|
2121
|
+
try {
|
|
2122
|
+
const report = await fetchVoiceDeliveryRuntime(path, options);
|
|
2123
|
+
snapshot = {
|
|
2124
|
+
...snapshot,
|
|
2125
|
+
error: null,
|
|
2126
|
+
isLoading: false,
|
|
2127
|
+
report,
|
|
2128
|
+
updatedAt: Date.now()
|
|
2129
|
+
};
|
|
2130
|
+
emit();
|
|
2131
|
+
return report;
|
|
2132
|
+
} catch (error) {
|
|
2133
|
+
snapshot = {
|
|
2134
|
+
...snapshot,
|
|
2135
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2136
|
+
isLoading: false
|
|
2137
|
+
};
|
|
2138
|
+
emit();
|
|
2139
|
+
throw error;
|
|
2140
|
+
}
|
|
2141
|
+
};
|
|
2142
|
+
const runAction = async (action) => {
|
|
2143
|
+
if (closed) {
|
|
2144
|
+
return snapshot.lastAction;
|
|
2145
|
+
}
|
|
2146
|
+
snapshot = {
|
|
2147
|
+
...snapshot,
|
|
2148
|
+
actionError: null,
|
|
2149
|
+
actionStatus: "running"
|
|
2150
|
+
};
|
|
2151
|
+
emit();
|
|
2152
|
+
try {
|
|
2153
|
+
const result = await runVoiceDeliveryRuntimeAction(action, path, options);
|
|
2154
|
+
snapshot = {
|
|
2155
|
+
...snapshot,
|
|
2156
|
+
actionError: null,
|
|
2157
|
+
actionStatus: "completed",
|
|
2158
|
+
lastAction: result
|
|
2159
|
+
};
|
|
2160
|
+
emit();
|
|
2161
|
+
await refresh();
|
|
2162
|
+
return result;
|
|
2163
|
+
} catch (error) {
|
|
2164
|
+
snapshot = {
|
|
2165
|
+
...snapshot,
|
|
2166
|
+
actionError: error instanceof Error ? error.message : String(error),
|
|
2167
|
+
actionStatus: "failed"
|
|
2168
|
+
};
|
|
2169
|
+
emit();
|
|
2170
|
+
throw error;
|
|
2171
|
+
}
|
|
2172
|
+
};
|
|
2173
|
+
const close = () => {
|
|
2174
|
+
closed = true;
|
|
2175
|
+
if (timer) {
|
|
2176
|
+
clearInterval(timer);
|
|
2177
|
+
timer = undefined;
|
|
2178
|
+
}
|
|
2179
|
+
listeners.clear();
|
|
2180
|
+
};
|
|
2181
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
2182
|
+
timer = setInterval(() => {
|
|
2183
|
+
refresh().catch(() => {});
|
|
2184
|
+
}, options.intervalMs);
|
|
2185
|
+
}
|
|
2186
|
+
return {
|
|
2187
|
+
close,
|
|
2188
|
+
getServerSnapshot: () => snapshot,
|
|
2189
|
+
getSnapshot: () => snapshot,
|
|
2190
|
+
requeueDeadLetters: () => runAction("requeue-dead-letters"),
|
|
2191
|
+
refresh,
|
|
2192
|
+
tick: () => runAction("tick"),
|
|
2193
|
+
subscribe: (listener) => {
|
|
2194
|
+
listeners.add(listener);
|
|
2195
|
+
return () => {
|
|
2196
|
+
listeners.delete(listener);
|
|
2197
|
+
};
|
|
2198
|
+
}
|
|
2199
|
+
};
|
|
2200
|
+
};
|
|
2065
2201
|
// src/client/opsStatusWidget.ts
|
|
2066
2202
|
var DEFAULT_TITLE = "Voice Ops Status";
|
|
2067
2203
|
var DEFAULT_DESCRIPTION = "Certified workflow, provider, and handoff readiness from your AbsoluteJS voice app.";
|
|
@@ -2186,6 +2322,133 @@ var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
|
|
|
2186
2322
|
}
|
|
2187
2323
|
});
|
|
2188
2324
|
};
|
|
2325
|
+
// src/client/deliveryRuntimeWidget.ts
|
|
2326
|
+
var DEFAULT_TITLE2 = "Voice Delivery Runtime";
|
|
2327
|
+
var DEFAULT_DESCRIPTION2 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
2328
|
+
var escapeHtml2 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2329
|
+
var createSurface = (id, summary) => {
|
|
2330
|
+
if (!summary) {
|
|
2331
|
+
return {
|
|
2332
|
+
deadLettered: 0,
|
|
2333
|
+
detail: "Worker disabled",
|
|
2334
|
+
failed: 0,
|
|
2335
|
+
id,
|
|
2336
|
+
label: id === "audit" ? "Audit delivery" : "Trace delivery",
|
|
2337
|
+
pending: 0,
|
|
2338
|
+
status: "disabled",
|
|
2339
|
+
total: 0
|
|
2340
|
+
};
|
|
2341
|
+
}
|
|
2342
|
+
const blocked = summary.failed + summary.deadLettered;
|
|
2343
|
+
return {
|
|
2344
|
+
deadLettered: summary.deadLettered,
|
|
2345
|
+
detail: `${summary.delivered}/${summary.total} delivered, ${summary.pending} pending`,
|
|
2346
|
+
failed: summary.failed,
|
|
2347
|
+
id,
|
|
2348
|
+
label: id === "audit" ? "Audit delivery" : "Trace delivery",
|
|
2349
|
+
pending: summary.pending,
|
|
2350
|
+
status: blocked > 0 ? "warn" : "pass",
|
|
2351
|
+
total: summary.total
|
|
2352
|
+
};
|
|
2353
|
+
};
|
|
2354
|
+
var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
2355
|
+
const report = snapshot.report;
|
|
2356
|
+
const surfaces = [
|
|
2357
|
+
createSurface("audit", report?.summary.audit),
|
|
2358
|
+
createSurface("trace", report?.summary.trace)
|
|
2359
|
+
];
|
|
2360
|
+
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
2361
|
+
return {
|
|
2362
|
+
description: options.description ?? DEFAULT_DESCRIPTION2,
|
|
2363
|
+
error: snapshot.error,
|
|
2364
|
+
actionError: snapshot.actionError,
|
|
2365
|
+
actionStatus: snapshot.actionStatus,
|
|
2366
|
+
isLoading: snapshot.isLoading,
|
|
2367
|
+
isRunning: Boolean(report?.isRunning),
|
|
2368
|
+
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
2369
|
+
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
2370
|
+
surfaces,
|
|
2371
|
+
title: options.title ?? DEFAULT_TITLE2,
|
|
2372
|
+
updatedAt: snapshot.updatedAt
|
|
2373
|
+
};
|
|
2374
|
+
};
|
|
2375
|
+
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
2376
|
+
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
2377
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml2(surface.status)}">
|
|
2378
|
+
<span>${escapeHtml2(surface.label)}</span>
|
|
2379
|
+
<strong>${escapeHtml2(surface.detail)}</strong>
|
|
2380
|
+
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
2381
|
+
</li>`).join("");
|
|
2382
|
+
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
2383
|
+
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
2384
|
+
<button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
|
|
2385
|
+
</div>`;
|
|
2386
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml2(model.actionError)}</p>` : "";
|
|
2387
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml2(model.status)}">
|
|
2388
|
+
<header class="absolute-voice-delivery-runtime__header">
|
|
2389
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml2(model.title)}</span>
|
|
2390
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml2(model.label)}</strong>
|
|
2391
|
+
</header>
|
|
2392
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml2(model.description)}</p>
|
|
2393
|
+
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
2394
|
+
${actions}
|
|
2395
|
+
${actionError}
|
|
2396
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml2(model.error)}</p>` : ""}
|
|
2397
|
+
</section>`;
|
|
2398
|
+
};
|
|
2399
|
+
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}`;
|
|
2400
|
+
var mountVoiceDeliveryRuntime = (element, path = "/api/voice-delivery-runtime", options = {}) => {
|
|
2401
|
+
const store = createVoiceDeliveryRuntimeStore(path, options);
|
|
2402
|
+
const render = () => {
|
|
2403
|
+
element.innerHTML = renderVoiceDeliveryRuntimeHTML(store.getSnapshot(), options);
|
|
2404
|
+
};
|
|
2405
|
+
const unsubscribe = store.subscribe(render);
|
|
2406
|
+
const handleClick = (event) => {
|
|
2407
|
+
const target = event.target;
|
|
2408
|
+
if (!(target instanceof Element)) {
|
|
2409
|
+
return;
|
|
2410
|
+
}
|
|
2411
|
+
const action = target.closest("[data-absolute-voice-delivery-runtime-action]");
|
|
2412
|
+
const actionName = action?.getAttribute("data-absolute-voice-delivery-runtime-action");
|
|
2413
|
+
if (actionName === "tick") {
|
|
2414
|
+
store.tick().catch(() => {});
|
|
2415
|
+
}
|
|
2416
|
+
if (actionName === "requeue-dead-letters") {
|
|
2417
|
+
store.requeueDeadLetters().catch(() => {});
|
|
2418
|
+
}
|
|
2419
|
+
};
|
|
2420
|
+
element.addEventListener?.("click", handleClick);
|
|
2421
|
+
render();
|
|
2422
|
+
store.refresh().catch(() => {});
|
|
2423
|
+
return {
|
|
2424
|
+
close: () => {
|
|
2425
|
+
element.removeEventListener?.("click", handleClick);
|
|
2426
|
+
unsubscribe();
|
|
2427
|
+
store.close();
|
|
2428
|
+
},
|
|
2429
|
+
refresh: store.refresh
|
|
2430
|
+
};
|
|
2431
|
+
};
|
|
2432
|
+
var defineVoiceDeliveryRuntimeElement = (tagName = "absolute-voice-delivery-runtime") => {
|
|
2433
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
2434
|
+
return;
|
|
2435
|
+
}
|
|
2436
|
+
customElements.define(tagName, class AbsoluteVoiceDeliveryRuntimeElement extends HTMLElement {
|
|
2437
|
+
mounted;
|
|
2438
|
+
connectedCallback() {
|
|
2439
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
2440
|
+
this.mounted = mountVoiceDeliveryRuntime(this, this.getAttribute("path") ?? "/api/voice-delivery-runtime", {
|
|
2441
|
+
description: this.getAttribute("description") ?? undefined,
|
|
2442
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
2443
|
+
title: this.getAttribute("title") ?? undefined
|
|
2444
|
+
});
|
|
2445
|
+
}
|
|
2446
|
+
disconnectedCallback() {
|
|
2447
|
+
this.mounted?.close();
|
|
2448
|
+
this.mounted = undefined;
|
|
2449
|
+
}
|
|
2450
|
+
});
|
|
2451
|
+
};
|
|
2189
2452
|
// src/client/routingStatus.ts
|
|
2190
2453
|
var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
|
|
2191
2454
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -2266,9 +2529,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
2266
2529
|
};
|
|
2267
2530
|
};
|
|
2268
2531
|
// src/client/routingStatusWidget.ts
|
|
2269
|
-
var
|
|
2270
|
-
var
|
|
2271
|
-
var
|
|
2532
|
+
var DEFAULT_TITLE3 = "Voice Routing";
|
|
2533
|
+
var DEFAULT_DESCRIPTION3 = "Latest provider routing decision from the self-hosted trace store.";
|
|
2534
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2272
2535
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
2273
2536
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
2274
2537
|
const decision = snapshot.decision;
|
|
@@ -2292,30 +2555,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
2292
2555
|
] : [];
|
|
2293
2556
|
return {
|
|
2294
2557
|
decision,
|
|
2295
|
-
description: options.description ??
|
|
2558
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
2296
2559
|
error: snapshot.error,
|
|
2297
2560
|
isLoading: snapshot.isLoading,
|
|
2298
2561
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
2299
2562
|
rows,
|
|
2300
2563
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2301
|
-
title: options.title ??
|
|
2564
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
2302
2565
|
updatedAt: snapshot.updatedAt
|
|
2303
2566
|
};
|
|
2304
2567
|
};
|
|
2305
2568
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
2306
2569
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
2307
2570
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
2308
|
-
<span>${
|
|
2309
|
-
<strong>${
|
|
2571
|
+
<span>${escapeHtml3(row.label)}</span>
|
|
2572
|
+
<strong>${escapeHtml3(row.value)}</strong>
|
|
2310
2573
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
2311
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
2574
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml3(model.status)}">
|
|
2312
2575
|
<header class="absolute-voice-routing-status__header">
|
|
2313
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
2314
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
2576
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml3(model.title)}</span>
|
|
2577
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml3(model.label)}</strong>
|
|
2315
2578
|
</header>
|
|
2316
|
-
<p class="absolute-voice-routing-status__description">${
|
|
2579
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml3(model.description)}</p>
|
|
2317
2580
|
${rows}
|
|
2318
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
2581
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml3(model.error)}</p>` : ""}
|
|
2319
2582
|
</section>`;
|
|
2320
2583
|
};
|
|
2321
2584
|
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}`;
|
|
@@ -2967,7 +3230,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
2967
3230
|
};
|
|
2968
3231
|
};
|
|
2969
3232
|
// src/client/providerSimulationControlsWidget.ts
|
|
2970
|
-
var
|
|
3233
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2971
3234
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
2972
3235
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
2973
3236
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -2987,18 +3250,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
2987
3250
|
};
|
|
2988
3251
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
2989
3252
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
2990
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
2991
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
3253
|
+
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("");
|
|
3254
|
+
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("");
|
|
2992
3255
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
2993
3256
|
<header class="absolute-voice-provider-simulation__header">
|
|
2994
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
2995
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
3257
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml4(model.title)}</span>
|
|
3258
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml4(model.label)}</strong>
|
|
2996
3259
|
</header>
|
|
2997
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
2998
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
3260
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml4(model.description)}</p>
|
|
3261
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml4(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
2999
3262
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
3000
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
3001
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
3263
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml4(snapshot.error)}</p>` : ""}
|
|
3264
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml4(model.resultText)}</pre>` : ""}
|
|
3002
3265
|
</section>`;
|
|
3003
3266
|
};
|
|
3004
3267
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -3063,9 +3326,9 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
3063
3326
|
});
|
|
3064
3327
|
};
|
|
3065
3328
|
// src/client/providerStatusWidget.ts
|
|
3066
|
-
var
|
|
3067
|
-
var
|
|
3068
|
-
var
|
|
3329
|
+
var DEFAULT_TITLE4 = "Voice Providers";
|
|
3330
|
+
var DEFAULT_DESCRIPTION4 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
3331
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3069
3332
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3070
3333
|
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
3071
3334
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -3109,37 +3372,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
3109
3372
|
const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
|
|
3110
3373
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
3111
3374
|
return {
|
|
3112
|
-
description: options.description ??
|
|
3375
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
3113
3376
|
error: snapshot.error,
|
|
3114
3377
|
isLoading: snapshot.isLoading,
|
|
3115
3378
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
3116
3379
|
providers,
|
|
3117
3380
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3118
|
-
title: options.title ??
|
|
3381
|
+
title: options.title ?? DEFAULT_TITLE4,
|
|
3119
3382
|
updatedAt: snapshot.updatedAt
|
|
3120
3383
|
};
|
|
3121
3384
|
};
|
|
3122
3385
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
3123
3386
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
3124
|
-
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--${
|
|
3387
|
+
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)}">
|
|
3125
3388
|
<header>
|
|
3126
|
-
<strong>${
|
|
3127
|
-
<span>${
|
|
3389
|
+
<strong>${escapeHtml5(provider.label)}</strong>
|
|
3390
|
+
<span>${escapeHtml5(formatStatus(provider.status))}</span>
|
|
3128
3391
|
</header>
|
|
3129
|
-
<p>${
|
|
3392
|
+
<p>${escapeHtml5(provider.detail)}</p>
|
|
3130
3393
|
<dl>${provider.rows.map((row) => `<div>
|
|
3131
|
-
<dt>${
|
|
3132
|
-
<dd>${
|
|
3394
|
+
<dt>${escapeHtml5(row.label)}</dt>
|
|
3395
|
+
<dd>${escapeHtml5(row.value)}</dd>
|
|
3133
3396
|
</div>`).join("")}</dl>
|
|
3134
3397
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
3135
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
3398
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml5(model.status)}">
|
|
3136
3399
|
<header class="absolute-voice-provider-status__header">
|
|
3137
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
3138
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
3400
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml5(model.title)}</span>
|
|
3401
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml5(model.label)}</strong>
|
|
3139
3402
|
</header>
|
|
3140
|
-
<p class="absolute-voice-provider-status__description">${
|
|
3403
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml5(model.description)}</p>
|
|
3141
3404
|
${providers}
|
|
3142
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
3405
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
3143
3406
|
</section>`;
|
|
3144
3407
|
};
|
|
3145
3408
|
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}`;
|
|
@@ -3180,9 +3443,9 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
3180
3443
|
});
|
|
3181
3444
|
};
|
|
3182
3445
|
// src/client/providerCapabilitiesWidget.ts
|
|
3183
|
-
var
|
|
3184
|
-
var
|
|
3185
|
-
var
|
|
3446
|
+
var DEFAULT_TITLE5 = "Provider Capabilities";
|
|
3447
|
+
var DEFAULT_DESCRIPTION5 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
3448
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3186
3449
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3187
3450
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
3188
3451
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -3226,36 +3489,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
3226
3489
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
3227
3490
|
return {
|
|
3228
3491
|
capabilities,
|
|
3229
|
-
description: options.description ??
|
|
3492
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
3230
3493
|
error: snapshot.error,
|
|
3231
3494
|
isLoading: snapshot.isLoading,
|
|
3232
3495
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
3233
3496
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3234
|
-
title: options.title ??
|
|
3497
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
3235
3498
|
updatedAt: snapshot.updatedAt
|
|
3236
3499
|
};
|
|
3237
3500
|
};
|
|
3238
3501
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
3239
3502
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
3240
|
-
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--${
|
|
3503
|
+
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)}">
|
|
3241
3504
|
<header>
|
|
3242
|
-
<strong>${
|
|
3243
|
-
<span>${
|
|
3505
|
+
<strong>${escapeHtml6(capability.label)}</strong>
|
|
3506
|
+
<span>${escapeHtml6(formatStatus2(capability.status))}</span>
|
|
3244
3507
|
</header>
|
|
3245
|
-
<p>${
|
|
3508
|
+
<p>${escapeHtml6(capability.detail)}</p>
|
|
3246
3509
|
<dl>${capability.rows.map((row) => `<div>
|
|
3247
|
-
<dt>${
|
|
3248
|
-
<dd>${
|
|
3510
|
+
<dt>${escapeHtml6(row.label)}</dt>
|
|
3511
|
+
<dd>${escapeHtml6(row.value)}</dd>
|
|
3249
3512
|
</div>`).join("")}</dl>
|
|
3250
3513
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
3251
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
3514
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml6(model.status)}">
|
|
3252
3515
|
<header class="absolute-voice-provider-capabilities__header">
|
|
3253
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
3254
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
3516
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml6(model.title)}</span>
|
|
3517
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml6(model.label)}</strong>
|
|
3255
3518
|
</header>
|
|
3256
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
3519
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml6(model.description)}</p>
|
|
3257
3520
|
${capabilities}
|
|
3258
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
3521
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
3259
3522
|
</section>`;
|
|
3260
3523
|
};
|
|
3261
3524
|
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}`;
|
|
@@ -3296,9 +3559,9 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
3296
3559
|
});
|
|
3297
3560
|
};
|
|
3298
3561
|
// src/client/turnQualityWidget.ts
|
|
3299
|
-
var
|
|
3300
|
-
var
|
|
3301
|
-
var
|
|
3562
|
+
var DEFAULT_TITLE6 = "Turn Quality";
|
|
3563
|
+
var DEFAULT_DESCRIPTION6 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
3564
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3302
3565
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
3303
3566
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
3304
3567
|
var getTurnDetail = (turn) => {
|
|
@@ -3336,37 +3599,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
3336
3599
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
3337
3600
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
3338
3601
|
return {
|
|
3339
|
-
description: options.description ??
|
|
3602
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
3340
3603
|
error: snapshot.error,
|
|
3341
3604
|
isLoading: snapshot.isLoading,
|
|
3342
3605
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
3343
3606
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3344
|
-
title: options.title ??
|
|
3607
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
3345
3608
|
turns,
|
|
3346
3609
|
updatedAt: snapshot.updatedAt
|
|
3347
3610
|
};
|
|
3348
3611
|
};
|
|
3349
3612
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
3350
3613
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
3351
|
-
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--${
|
|
3614
|
+
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)}">
|
|
3352
3615
|
<header>
|
|
3353
|
-
<strong>${
|
|
3354
|
-
<span>${
|
|
3616
|
+
<strong>${escapeHtml7(turn.label)}</strong>
|
|
3617
|
+
<span>${escapeHtml7(turn.status)}</span>
|
|
3355
3618
|
</header>
|
|
3356
|
-
<p>${
|
|
3619
|
+
<p>${escapeHtml7(turn.detail)}</p>
|
|
3357
3620
|
<dl>${turn.rows.map((row) => `<div>
|
|
3358
|
-
<dt>${
|
|
3359
|
-
<dd>${
|
|
3621
|
+
<dt>${escapeHtml7(row.label)}</dt>
|
|
3622
|
+
<dd>${escapeHtml7(row.value)}</dd>
|
|
3360
3623
|
</div>`).join("")}</dl>
|
|
3361
3624
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
3362
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
3625
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml7(model.status)}">
|
|
3363
3626
|
<header class="absolute-voice-turn-quality__header">
|
|
3364
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
3365
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
3627
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml7(model.title)}</span>
|
|
3628
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml7(model.label)}</strong>
|
|
3366
3629
|
</header>
|
|
3367
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
3630
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml7(model.description)}</p>
|
|
3368
3631
|
${turns}
|
|
3369
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
3632
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
3370
3633
|
</section>`;
|
|
3371
3634
|
};
|
|
3372
3635
|
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}`;
|
|
@@ -3407,10 +3670,10 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
3407
3670
|
});
|
|
3408
3671
|
};
|
|
3409
3672
|
// src/client/turnLatencyWidget.ts
|
|
3410
|
-
var
|
|
3411
|
-
var
|
|
3673
|
+
var DEFAULT_TITLE7 = "Turn Latency";
|
|
3674
|
+
var DEFAULT_DESCRIPTION7 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
3412
3675
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
3413
|
-
var
|
|
3676
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3414
3677
|
var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
3415
3678
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
3416
3679
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -3424,39 +3687,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
3424
3687
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
3425
3688
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
3426
3689
|
return {
|
|
3427
|
-
description: options.description ??
|
|
3690
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
3428
3691
|
error: snapshot.error,
|
|
3429
3692
|
isLoading: snapshot.isLoading,
|
|
3430
3693
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
3431
3694
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
3432
3695
|
showProofAction: Boolean(options.proofPath),
|
|
3433
3696
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3434
|
-
title: options.title ??
|
|
3697
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
3435
3698
|
turns,
|
|
3436
3699
|
updatedAt: snapshot.updatedAt
|
|
3437
3700
|
};
|
|
3438
3701
|
};
|
|
3439
3702
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
3440
3703
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
3441
|
-
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--${
|
|
3704
|
+
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)}">
|
|
3442
3705
|
<header>
|
|
3443
|
-
<strong>${
|
|
3444
|
-
<span>${
|
|
3706
|
+
<strong>${escapeHtml8(turn.label)}</strong>
|
|
3707
|
+
<span>${escapeHtml8(turn.status)}</span>
|
|
3445
3708
|
</header>
|
|
3446
3709
|
<dl>${turn.rows.map((row) => `<div>
|
|
3447
|
-
<dt>${
|
|
3448
|
-
<dd>${
|
|
3710
|
+
<dt>${escapeHtml8(row.label)}</dt>
|
|
3711
|
+
<dd>${escapeHtml8(row.value)}</dd>
|
|
3449
3712
|
</div>`).join("")}</dl>
|
|
3450
3713
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
3451
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
3714
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml8(model.status)}">
|
|
3452
3715
|
<header class="absolute-voice-turn-latency__header">
|
|
3453
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
3454
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
3716
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml8(model.title)}</span>
|
|
3717
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml8(model.label)}</strong>
|
|
3455
3718
|
</header>
|
|
3456
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
3457
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
3719
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml8(model.description)}</p>
|
|
3720
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml8(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
3458
3721
|
${turns}
|
|
3459
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
3722
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
3460
3723
|
</section>`;
|
|
3461
3724
|
};
|
|
3462
3725
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -3506,9 +3769,9 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
3506
3769
|
});
|
|
3507
3770
|
};
|
|
3508
3771
|
// src/client/traceTimelineWidget.ts
|
|
3509
|
-
var
|
|
3510
|
-
var
|
|
3511
|
-
var
|
|
3772
|
+
var DEFAULT_TITLE8 = "Voice Traces";
|
|
3773
|
+
var DEFAULT_DESCRIPTION8 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
3774
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3512
3775
|
var formatMs2 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
3513
3776
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
3514
3777
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -3522,34 +3785,34 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
3522
3785
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
3523
3786
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
3524
3787
|
return {
|
|
3525
|
-
description: options.description ??
|
|
3788
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
3526
3789
|
error: snapshot.error,
|
|
3527
3790
|
isLoading: snapshot.isLoading,
|
|
3528
3791
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
3529
3792
|
sessions,
|
|
3530
3793
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3531
|
-
title: options.title ??
|
|
3794
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
3532
3795
|
updatedAt: snapshot.updatedAt
|
|
3533
3796
|
};
|
|
3534
3797
|
};
|
|
3535
3798
|
var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
3536
3799
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
3537
|
-
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--${
|
|
3800
|
+
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)}">
|
|
3538
3801
|
<header>
|
|
3539
|
-
<strong>${
|
|
3540
|
-
<span>${
|
|
3802
|
+
<strong>${escapeHtml9(session.sessionId)}</strong>
|
|
3803
|
+
<span>${escapeHtml9(session.status)}</span>
|
|
3541
3804
|
</header>
|
|
3542
|
-
<p>${
|
|
3543
|
-
<a href="${
|
|
3805
|
+
<p>${escapeHtml9(session.label)} \xB7 ${escapeHtml9(session.durationLabel)} \xB7 ${escapeHtml9(session.providerLabel)}</p>
|
|
3806
|
+
<a href="${escapeHtml9(session.detailHref)}">Open timeline</a>
|
|
3544
3807
|
</article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
3545
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
3808
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml9(model.status)}">
|
|
3546
3809
|
<header class="absolute-voice-trace-timeline__header">
|
|
3547
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
3548
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
3810
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml9(model.title)}</span>
|
|
3811
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml9(model.label)}</strong>
|
|
3549
3812
|
</header>
|
|
3550
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
3813
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml9(model.description)}</p>
|
|
3551
3814
|
${sessions}
|
|
3552
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
3815
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
3553
3816
|
</section>`;
|
|
3554
3817
|
};
|
|
3555
3818
|
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}`;
|
|
@@ -3672,6 +3935,7 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
|
|
|
3672
3935
|
};
|
|
3673
3936
|
export {
|
|
3674
3937
|
runVoiceTurnLatencyProof,
|
|
3938
|
+
runVoiceDeliveryRuntimeAction,
|
|
3675
3939
|
runVoiceCampaignDialerProofAction,
|
|
3676
3940
|
renderVoiceTurnQualityHTML,
|
|
3677
3941
|
renderVoiceTurnLatencyHTML,
|
|
@@ -3681,6 +3945,7 @@ export {
|
|
|
3681
3945
|
renderVoiceProviderSimulationControlsHTML,
|
|
3682
3946
|
renderVoiceProviderCapabilitiesHTML,
|
|
3683
3947
|
renderVoiceOpsStatusHTML,
|
|
3948
|
+
renderVoiceDeliveryRuntimeHTML,
|
|
3684
3949
|
mountVoiceTurnQuality,
|
|
3685
3950
|
mountVoiceTurnLatency,
|
|
3686
3951
|
mountVoiceTraceTimeline,
|
|
@@ -3689,6 +3954,7 @@ export {
|
|
|
3689
3954
|
mountVoiceProviderSimulationControls,
|
|
3690
3955
|
mountVoiceProviderCapabilities,
|
|
3691
3956
|
mountVoiceOpsStatus,
|
|
3957
|
+
mountVoiceDeliveryRuntime,
|
|
3692
3958
|
getVoiceTurnQualityCSS,
|
|
3693
3959
|
getVoiceTraceTimelineCSS,
|
|
3694
3960
|
getVoiceRoutingStatusCSS,
|
|
@@ -3696,6 +3962,7 @@ export {
|
|
|
3696
3962
|
getVoiceProviderCapabilitiesCSS,
|
|
3697
3963
|
getVoiceOpsStatusLabel,
|
|
3698
3964
|
getVoiceOpsStatusCSS,
|
|
3965
|
+
getVoiceDeliveryRuntimeCSS,
|
|
3699
3966
|
fetchVoiceWorkflowStatus,
|
|
3700
3967
|
fetchVoiceTurnQuality,
|
|
3701
3968
|
fetchVoiceTurnLatency,
|
|
@@ -3704,6 +3971,7 @@ export {
|
|
|
3704
3971
|
fetchVoiceProviderStatus,
|
|
3705
3972
|
fetchVoiceProviderCapabilities,
|
|
3706
3973
|
fetchVoiceOpsStatus,
|
|
3974
|
+
fetchVoiceDeliveryRuntime,
|
|
3707
3975
|
fetchVoiceCampaignDialerProofStatus,
|
|
3708
3976
|
defineVoiceTurnQualityElement,
|
|
3709
3977
|
defineVoiceTurnLatencyElement,
|
|
@@ -3713,6 +3981,7 @@ export {
|
|
|
3713
3981
|
defineVoiceProviderSimulationControlsElement,
|
|
3714
3982
|
defineVoiceProviderCapabilitiesElement,
|
|
3715
3983
|
defineVoiceOpsStatusElement,
|
|
3984
|
+
defineVoiceDeliveryRuntimeElement,
|
|
3716
3985
|
decodeVoiceAudioChunk,
|
|
3717
3986
|
createVoiceWorkflowStatusStore,
|
|
3718
3987
|
createVoiceTurnQualityViewModel,
|
|
@@ -3734,6 +4003,8 @@ export {
|
|
|
3734
4003
|
createVoiceOpsStatusStore,
|
|
3735
4004
|
createVoiceLiveTurnLatencyMonitor,
|
|
3736
4005
|
createVoiceDuplexController,
|
|
4006
|
+
createVoiceDeliveryRuntimeViewModel,
|
|
4007
|
+
createVoiceDeliveryRuntimeStore,
|
|
3737
4008
|
createVoiceController,
|
|
3738
4009
|
createVoiceConnection,
|
|
3739
4010
|
createVoiceCampaignDialerProofStore,
|