@absolutejs/voice 0.0.22-beta.151 → 0.0.22-beta.152
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 +28 -0
- package/dist/angular/index.d.ts +2 -0
- package/dist/angular/index.js +479 -124
- package/dist/angular/voice-delivery-runtime.component.d.ts +14 -0
- package/dist/angular/voice-delivery-runtime.service.d.ts +12 -0
- package/dist/client/deliveryRuntime.d.ts +19 -0
- package/dist/client/deliveryRuntimeWidget.d.ts +34 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +287 -100
- package/dist/deliveryRuntime.d.ts +1 -1
- package/dist/react/VoiceDeliveryRuntime.d.ts +6 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +520 -256
- package/dist/react/useVoiceDeliveryRuntime.d.ts +8 -0
- package/dist/svelte/createVoiceDeliveryRuntime.d.ts +9 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +309 -114
- package/dist/vue/VoiceDeliveryRuntime.d.ts +21 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +534 -261
- package/dist/vue/useVoiceDeliveryRuntime.d.ts +9 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -2062,6 +2062,84 @@ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) =
|
|
|
2062
2062
|
}
|
|
2063
2063
|
};
|
|
2064
2064
|
};
|
|
2065
|
+
// src/client/deliveryRuntime.ts
|
|
2066
|
+
var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
2067
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2068
|
+
const response = await fetchImpl(path);
|
|
2069
|
+
if (!response.ok) {
|
|
2070
|
+
throw new Error(`Voice delivery runtime failed: HTTP ${response.status}`);
|
|
2071
|
+
}
|
|
2072
|
+
return await response.json();
|
|
2073
|
+
};
|
|
2074
|
+
var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
2075
|
+
const listeners = new Set;
|
|
2076
|
+
let closed = false;
|
|
2077
|
+
let timer;
|
|
2078
|
+
let snapshot = {
|
|
2079
|
+
error: null,
|
|
2080
|
+
isLoading: false
|
|
2081
|
+
};
|
|
2082
|
+
const emit = () => {
|
|
2083
|
+
for (const listener of listeners) {
|
|
2084
|
+
listener();
|
|
2085
|
+
}
|
|
2086
|
+
};
|
|
2087
|
+
const refresh = async () => {
|
|
2088
|
+
if (closed) {
|
|
2089
|
+
return snapshot.report;
|
|
2090
|
+
}
|
|
2091
|
+
snapshot = {
|
|
2092
|
+
...snapshot,
|
|
2093
|
+
error: null,
|
|
2094
|
+
isLoading: true
|
|
2095
|
+
};
|
|
2096
|
+
emit();
|
|
2097
|
+
try {
|
|
2098
|
+
const report = await fetchVoiceDeliveryRuntime(path, options);
|
|
2099
|
+
snapshot = {
|
|
2100
|
+
error: null,
|
|
2101
|
+
isLoading: false,
|
|
2102
|
+
report,
|
|
2103
|
+
updatedAt: Date.now()
|
|
2104
|
+
};
|
|
2105
|
+
emit();
|
|
2106
|
+
return report;
|
|
2107
|
+
} catch (error) {
|
|
2108
|
+
snapshot = {
|
|
2109
|
+
...snapshot,
|
|
2110
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2111
|
+
isLoading: false
|
|
2112
|
+
};
|
|
2113
|
+
emit();
|
|
2114
|
+
throw error;
|
|
2115
|
+
}
|
|
2116
|
+
};
|
|
2117
|
+
const close = () => {
|
|
2118
|
+
closed = true;
|
|
2119
|
+
if (timer) {
|
|
2120
|
+
clearInterval(timer);
|
|
2121
|
+
timer = undefined;
|
|
2122
|
+
}
|
|
2123
|
+
listeners.clear();
|
|
2124
|
+
};
|
|
2125
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
2126
|
+
timer = setInterval(() => {
|
|
2127
|
+
refresh().catch(() => {});
|
|
2128
|
+
}, options.intervalMs);
|
|
2129
|
+
}
|
|
2130
|
+
return {
|
|
2131
|
+
close,
|
|
2132
|
+
getServerSnapshot: () => snapshot,
|
|
2133
|
+
getSnapshot: () => snapshot,
|
|
2134
|
+
refresh,
|
|
2135
|
+
subscribe: (listener) => {
|
|
2136
|
+
listeners.add(listener);
|
|
2137
|
+
return () => {
|
|
2138
|
+
listeners.delete(listener);
|
|
2139
|
+
};
|
|
2140
|
+
}
|
|
2141
|
+
};
|
|
2142
|
+
};
|
|
2065
2143
|
// src/client/opsStatusWidget.ts
|
|
2066
2144
|
var DEFAULT_TITLE = "Voice Ops Status";
|
|
2067
2145
|
var DEFAULT_DESCRIPTION = "Certified workflow, provider, and handoff readiness from your AbsoluteJS voice app.";
|
|
@@ -2186,6 +2264,108 @@ var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
|
|
|
2186
2264
|
}
|
|
2187
2265
|
});
|
|
2188
2266
|
};
|
|
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.";
|
|
2270
|
+
var escapeHtml2 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2271
|
+
var createSurface = (id, summary) => {
|
|
2272
|
+
if (!summary) {
|
|
2273
|
+
return {
|
|
2274
|
+
deadLettered: 0,
|
|
2275
|
+
detail: "Worker disabled",
|
|
2276
|
+
failed: 0,
|
|
2277
|
+
id,
|
|
2278
|
+
label: id === "audit" ? "Audit delivery" : "Trace delivery",
|
|
2279
|
+
pending: 0,
|
|
2280
|
+
status: "disabled",
|
|
2281
|
+
total: 0
|
|
2282
|
+
};
|
|
2283
|
+
}
|
|
2284
|
+
const blocked = summary.failed + summary.deadLettered;
|
|
2285
|
+
return {
|
|
2286
|
+
deadLettered: summary.deadLettered,
|
|
2287
|
+
detail: `${summary.delivered}/${summary.total} delivered, ${summary.pending} pending`,
|
|
2288
|
+
failed: summary.failed,
|
|
2289
|
+
id,
|
|
2290
|
+
label: id === "audit" ? "Audit delivery" : "Trace delivery",
|
|
2291
|
+
pending: summary.pending,
|
|
2292
|
+
status: blocked > 0 ? "warn" : "pass",
|
|
2293
|
+
total: summary.total
|
|
2294
|
+
};
|
|
2295
|
+
};
|
|
2296
|
+
var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
2297
|
+
const report = snapshot.report;
|
|
2298
|
+
const surfaces = [
|
|
2299
|
+
createSurface("audit", report?.summary.audit),
|
|
2300
|
+
createSurface("trace", report?.summary.trace)
|
|
2301
|
+
];
|
|
2302
|
+
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
2303
|
+
return {
|
|
2304
|
+
description: options.description ?? DEFAULT_DESCRIPTION2,
|
|
2305
|
+
error: snapshot.error,
|
|
2306
|
+
isLoading: snapshot.isLoading,
|
|
2307
|
+
isRunning: Boolean(report?.isRunning),
|
|
2308
|
+
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
2309
|
+
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
2310
|
+
surfaces,
|
|
2311
|
+
title: options.title ?? DEFAULT_TITLE2,
|
|
2312
|
+
updatedAt: snapshot.updatedAt
|
|
2313
|
+
};
|
|
2314
|
+
};
|
|
2315
|
+
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
2316
|
+
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>
|
|
2320
|
+
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
2321
|
+
</li>`).join("");
|
|
2322
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml2(model.status)}">
|
|
2323
|
+
<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>
|
|
2326
|
+
</header>
|
|
2327
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml2(model.description)}</p>
|
|
2328
|
+
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
2329
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml2(model.error)}</p>` : ""}
|
|
2330
|
+
</section>`;
|
|
2331
|
+
};
|
|
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}`;
|
|
2333
|
+
var mountVoiceDeliveryRuntime = (element, path = "/api/voice-delivery-runtime", options = {}) => {
|
|
2334
|
+
const store = createVoiceDeliveryRuntimeStore(path, options);
|
|
2335
|
+
const render = () => {
|
|
2336
|
+
element.innerHTML = renderVoiceDeliveryRuntimeHTML(store.getSnapshot(), options);
|
|
2337
|
+
};
|
|
2338
|
+
const unsubscribe = store.subscribe(render);
|
|
2339
|
+
render();
|
|
2340
|
+
store.refresh().catch(() => {});
|
|
2341
|
+
return {
|
|
2342
|
+
close: () => {
|
|
2343
|
+
unsubscribe();
|
|
2344
|
+
store.close();
|
|
2345
|
+
},
|
|
2346
|
+
refresh: store.refresh
|
|
2347
|
+
};
|
|
2348
|
+
};
|
|
2349
|
+
var defineVoiceDeliveryRuntimeElement = (tagName = "absolute-voice-delivery-runtime") => {
|
|
2350
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2353
|
+
customElements.define(tagName, class AbsoluteVoiceDeliveryRuntimeElement extends HTMLElement {
|
|
2354
|
+
mounted;
|
|
2355
|
+
connectedCallback() {
|
|
2356
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
2357
|
+
this.mounted = mountVoiceDeliveryRuntime(this, this.getAttribute("path") ?? "/api/voice-delivery-runtime", {
|
|
2358
|
+
description: this.getAttribute("description") ?? undefined,
|
|
2359
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
2360
|
+
title: this.getAttribute("title") ?? undefined
|
|
2361
|
+
});
|
|
2362
|
+
}
|
|
2363
|
+
disconnectedCallback() {
|
|
2364
|
+
this.mounted?.close();
|
|
2365
|
+
this.mounted = undefined;
|
|
2366
|
+
}
|
|
2367
|
+
});
|
|
2368
|
+
};
|
|
2189
2369
|
// src/client/routingStatus.ts
|
|
2190
2370
|
var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
|
|
2191
2371
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -2266,9 +2446,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
2266
2446
|
};
|
|
2267
2447
|
};
|
|
2268
2448
|
// src/client/routingStatusWidget.ts
|
|
2269
|
-
var
|
|
2270
|
-
var
|
|
2271
|
-
var
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2272
2452
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
2273
2453
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
2274
2454
|
const decision = snapshot.decision;
|
|
@@ -2292,30 +2472,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
2292
2472
|
] : [];
|
|
2293
2473
|
return {
|
|
2294
2474
|
decision,
|
|
2295
|
-
description: options.description ??
|
|
2475
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
2296
2476
|
error: snapshot.error,
|
|
2297
2477
|
isLoading: snapshot.isLoading,
|
|
2298
2478
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
2299
2479
|
rows,
|
|
2300
2480
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2301
|
-
title: options.title ??
|
|
2481
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
2302
2482
|
updatedAt: snapshot.updatedAt
|
|
2303
2483
|
};
|
|
2304
2484
|
};
|
|
2305
2485
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
2306
2486
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
2307
2487
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
2308
|
-
<span>${
|
|
2309
|
-
<strong>${
|
|
2488
|
+
<span>${escapeHtml3(row.label)}</span>
|
|
2489
|
+
<strong>${escapeHtml3(row.value)}</strong>
|
|
2310
2490
|
</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--${
|
|
2491
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml3(model.status)}">
|
|
2312
2492
|
<header class="absolute-voice-routing-status__header">
|
|
2313
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
2314
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
2493
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml3(model.title)}</span>
|
|
2494
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml3(model.label)}</strong>
|
|
2315
2495
|
</header>
|
|
2316
|
-
<p class="absolute-voice-routing-status__description">${
|
|
2496
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml3(model.description)}</p>
|
|
2317
2497
|
${rows}
|
|
2318
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
2498
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml3(model.error)}</p>` : ""}
|
|
2319
2499
|
</section>`;
|
|
2320
2500
|
};
|
|
2321
2501
|
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 +3147,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
2967
3147
|
};
|
|
2968
3148
|
};
|
|
2969
3149
|
// src/client/providerSimulationControlsWidget.ts
|
|
2970
|
-
var
|
|
3150
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2971
3151
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
2972
3152
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
2973
3153
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -2987,18 +3167,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
2987
3167
|
};
|
|
2988
3168
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
2989
3169
|
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="${
|
|
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("");
|
|
2992
3172
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
2993
3173
|
<header class="absolute-voice-provider-simulation__header">
|
|
2994
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
2995
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
3174
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml4(model.title)}</span>
|
|
3175
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml4(model.label)}</strong>
|
|
2996
3176
|
</header>
|
|
2997
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
2998
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
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>`}
|
|
2999
3179
|
<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">${
|
|
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>` : ""}
|
|
3002
3182
|
</section>`;
|
|
3003
3183
|
};
|
|
3004
3184
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -3063,9 +3243,9 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
3063
3243
|
});
|
|
3064
3244
|
};
|
|
3065
3245
|
// src/client/providerStatusWidget.ts
|
|
3066
|
-
var
|
|
3067
|
-
var
|
|
3068
|
-
var
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3069
3249
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3070
3250
|
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
3071
3251
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -3109,37 +3289,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
3109
3289
|
const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
|
|
3110
3290
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
3111
3291
|
return {
|
|
3112
|
-
description: options.description ??
|
|
3292
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
3113
3293
|
error: snapshot.error,
|
|
3114
3294
|
isLoading: snapshot.isLoading,
|
|
3115
3295
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
3116
3296
|
providers,
|
|
3117
3297
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3118
|
-
title: options.title ??
|
|
3298
|
+
title: options.title ?? DEFAULT_TITLE4,
|
|
3119
3299
|
updatedAt: snapshot.updatedAt
|
|
3120
3300
|
};
|
|
3121
3301
|
};
|
|
3122
3302
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
3123
3303
|
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--${
|
|
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)}">
|
|
3125
3305
|
<header>
|
|
3126
|
-
<strong>${
|
|
3127
|
-
<span>${
|
|
3306
|
+
<strong>${escapeHtml5(provider.label)}</strong>
|
|
3307
|
+
<span>${escapeHtml5(formatStatus(provider.status))}</span>
|
|
3128
3308
|
</header>
|
|
3129
|
-
<p>${
|
|
3309
|
+
<p>${escapeHtml5(provider.detail)}</p>
|
|
3130
3310
|
<dl>${provider.rows.map((row) => `<div>
|
|
3131
|
-
<dt>${
|
|
3132
|
-
<dd>${
|
|
3311
|
+
<dt>${escapeHtml5(row.label)}</dt>
|
|
3312
|
+
<dd>${escapeHtml5(row.value)}</dd>
|
|
3133
3313
|
</div>`).join("")}</dl>
|
|
3134
3314
|
</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--${
|
|
3315
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml5(model.status)}">
|
|
3136
3316
|
<header class="absolute-voice-provider-status__header">
|
|
3137
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
3138
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
3317
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml5(model.title)}</span>
|
|
3318
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml5(model.label)}</strong>
|
|
3139
3319
|
</header>
|
|
3140
|
-
<p class="absolute-voice-provider-status__description">${
|
|
3320
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml5(model.description)}</p>
|
|
3141
3321
|
${providers}
|
|
3142
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
3322
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
3143
3323
|
</section>`;
|
|
3144
3324
|
};
|
|
3145
3325
|
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 +3360,9 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
3180
3360
|
});
|
|
3181
3361
|
};
|
|
3182
3362
|
// src/client/providerCapabilitiesWidget.ts
|
|
3183
|
-
var
|
|
3184
|
-
var
|
|
3185
|
-
var
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3186
3366
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3187
3367
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
3188
3368
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -3226,36 +3406,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
3226
3406
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
3227
3407
|
return {
|
|
3228
3408
|
capabilities,
|
|
3229
|
-
description: options.description ??
|
|
3409
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
3230
3410
|
error: snapshot.error,
|
|
3231
3411
|
isLoading: snapshot.isLoading,
|
|
3232
3412
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
3233
3413
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3234
|
-
title: options.title ??
|
|
3414
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
3235
3415
|
updatedAt: snapshot.updatedAt
|
|
3236
3416
|
};
|
|
3237
3417
|
};
|
|
3238
3418
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
3239
3419
|
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--${
|
|
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)}">
|
|
3241
3421
|
<header>
|
|
3242
|
-
<strong>${
|
|
3243
|
-
<span>${
|
|
3422
|
+
<strong>${escapeHtml6(capability.label)}</strong>
|
|
3423
|
+
<span>${escapeHtml6(formatStatus2(capability.status))}</span>
|
|
3244
3424
|
</header>
|
|
3245
|
-
<p>${
|
|
3425
|
+
<p>${escapeHtml6(capability.detail)}</p>
|
|
3246
3426
|
<dl>${capability.rows.map((row) => `<div>
|
|
3247
|
-
<dt>${
|
|
3248
|
-
<dd>${
|
|
3427
|
+
<dt>${escapeHtml6(row.label)}</dt>
|
|
3428
|
+
<dd>${escapeHtml6(row.value)}</dd>
|
|
3249
3429
|
</div>`).join("")}</dl>
|
|
3250
3430
|
</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--${
|
|
3431
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml6(model.status)}">
|
|
3252
3432
|
<header class="absolute-voice-provider-capabilities__header">
|
|
3253
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
3254
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
3433
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml6(model.title)}</span>
|
|
3434
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml6(model.label)}</strong>
|
|
3255
3435
|
</header>
|
|
3256
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
3436
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml6(model.description)}</p>
|
|
3257
3437
|
${capabilities}
|
|
3258
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
3438
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
3259
3439
|
</section>`;
|
|
3260
3440
|
};
|
|
3261
3441
|
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 +3476,9 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
3296
3476
|
});
|
|
3297
3477
|
};
|
|
3298
3478
|
// src/client/turnQualityWidget.ts
|
|
3299
|
-
var
|
|
3300
|
-
var
|
|
3301
|
-
var
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3302
3482
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
3303
3483
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
3304
3484
|
var getTurnDetail = (turn) => {
|
|
@@ -3336,37 +3516,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
3336
3516
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
3337
3517
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
3338
3518
|
return {
|
|
3339
|
-
description: options.description ??
|
|
3519
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
3340
3520
|
error: snapshot.error,
|
|
3341
3521
|
isLoading: snapshot.isLoading,
|
|
3342
3522
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
3343
3523
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3344
|
-
title: options.title ??
|
|
3524
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
3345
3525
|
turns,
|
|
3346
3526
|
updatedAt: snapshot.updatedAt
|
|
3347
3527
|
};
|
|
3348
3528
|
};
|
|
3349
3529
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
3350
3530
|
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--${
|
|
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)}">
|
|
3352
3532
|
<header>
|
|
3353
|
-
<strong>${
|
|
3354
|
-
<span>${
|
|
3533
|
+
<strong>${escapeHtml7(turn.label)}</strong>
|
|
3534
|
+
<span>${escapeHtml7(turn.status)}</span>
|
|
3355
3535
|
</header>
|
|
3356
|
-
<p>${
|
|
3536
|
+
<p>${escapeHtml7(turn.detail)}</p>
|
|
3357
3537
|
<dl>${turn.rows.map((row) => `<div>
|
|
3358
|
-
<dt>${
|
|
3359
|
-
<dd>${
|
|
3538
|
+
<dt>${escapeHtml7(row.label)}</dt>
|
|
3539
|
+
<dd>${escapeHtml7(row.value)}</dd>
|
|
3360
3540
|
</div>`).join("")}</dl>
|
|
3361
3541
|
</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--${
|
|
3542
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml7(model.status)}">
|
|
3363
3543
|
<header class="absolute-voice-turn-quality__header">
|
|
3364
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
3365
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
3544
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml7(model.title)}</span>
|
|
3545
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml7(model.label)}</strong>
|
|
3366
3546
|
</header>
|
|
3367
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
3547
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml7(model.description)}</p>
|
|
3368
3548
|
${turns}
|
|
3369
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
3549
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
3370
3550
|
</section>`;
|
|
3371
3551
|
};
|
|
3372
3552
|
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 +3587,10 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
3407
3587
|
});
|
|
3408
3588
|
};
|
|
3409
3589
|
// src/client/turnLatencyWidget.ts
|
|
3410
|
-
var
|
|
3411
|
-
var
|
|
3590
|
+
var DEFAULT_TITLE7 = "Turn Latency";
|
|
3591
|
+
var DEFAULT_DESCRIPTION7 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
3412
3592
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
3413
|
-
var
|
|
3593
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3414
3594
|
var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
3415
3595
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
3416
3596
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -3424,39 +3604,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
3424
3604
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
3425
3605
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
3426
3606
|
return {
|
|
3427
|
-
description: options.description ??
|
|
3607
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
3428
3608
|
error: snapshot.error,
|
|
3429
3609
|
isLoading: snapshot.isLoading,
|
|
3430
3610
|
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
3611
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
3432
3612
|
showProofAction: Boolean(options.proofPath),
|
|
3433
3613
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3434
|
-
title: options.title ??
|
|
3614
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
3435
3615
|
turns,
|
|
3436
3616
|
updatedAt: snapshot.updatedAt
|
|
3437
3617
|
};
|
|
3438
3618
|
};
|
|
3439
3619
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
3440
3620
|
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--${
|
|
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)}">
|
|
3442
3622
|
<header>
|
|
3443
|
-
<strong>${
|
|
3444
|
-
<span>${
|
|
3623
|
+
<strong>${escapeHtml8(turn.label)}</strong>
|
|
3624
|
+
<span>${escapeHtml8(turn.status)}</span>
|
|
3445
3625
|
</header>
|
|
3446
3626
|
<dl>${turn.rows.map((row) => `<div>
|
|
3447
|
-
<dt>${
|
|
3448
|
-
<dd>${
|
|
3627
|
+
<dt>${escapeHtml8(row.label)}</dt>
|
|
3628
|
+
<dd>${escapeHtml8(row.value)}</dd>
|
|
3449
3629
|
</div>`).join("")}</dl>
|
|
3450
3630
|
</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--${
|
|
3631
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml8(model.status)}">
|
|
3452
3632
|
<header class="absolute-voice-turn-latency__header">
|
|
3453
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
3454
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
3633
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml8(model.title)}</span>
|
|
3634
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml8(model.label)}</strong>
|
|
3455
3635
|
</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">${
|
|
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>` : ""}
|
|
3458
3638
|
${turns}
|
|
3459
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
3639
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
3460
3640
|
</section>`;
|
|
3461
3641
|
};
|
|
3462
3642
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -3506,9 +3686,9 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
3506
3686
|
});
|
|
3507
3687
|
};
|
|
3508
3688
|
// src/client/traceTimelineWidget.ts
|
|
3509
|
-
var
|
|
3510
|
-
var
|
|
3511
|
-
var
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3512
3692
|
var formatMs2 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
3513
3693
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
3514
3694
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -3522,34 +3702,34 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
3522
3702
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
3523
3703
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
3524
3704
|
return {
|
|
3525
|
-
description: options.description ??
|
|
3705
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
3526
3706
|
error: snapshot.error,
|
|
3527
3707
|
isLoading: snapshot.isLoading,
|
|
3528
3708
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
3529
3709
|
sessions,
|
|
3530
3710
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3531
|
-
title: options.title ??
|
|
3711
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
3532
3712
|
updatedAt: snapshot.updatedAt
|
|
3533
3713
|
};
|
|
3534
3714
|
};
|
|
3535
3715
|
var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
3536
3716
|
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--${
|
|
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)}">
|
|
3538
3718
|
<header>
|
|
3539
|
-
<strong>${
|
|
3540
|
-
<span>${
|
|
3719
|
+
<strong>${escapeHtml9(session.sessionId)}</strong>
|
|
3720
|
+
<span>${escapeHtml9(session.status)}</span>
|
|
3541
3721
|
</header>
|
|
3542
|
-
<p>${
|
|
3543
|
-
<a href="${
|
|
3722
|
+
<p>${escapeHtml9(session.label)} \xB7 ${escapeHtml9(session.durationLabel)} \xB7 ${escapeHtml9(session.providerLabel)}</p>
|
|
3723
|
+
<a href="${escapeHtml9(session.detailHref)}">Open timeline</a>
|
|
3544
3724
|
</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--${
|
|
3725
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml9(model.status)}">
|
|
3546
3726
|
<header class="absolute-voice-trace-timeline__header">
|
|
3547
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
3548
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
3727
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml9(model.title)}</span>
|
|
3728
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml9(model.label)}</strong>
|
|
3549
3729
|
</header>
|
|
3550
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
3730
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml9(model.description)}</p>
|
|
3551
3731
|
${sessions}
|
|
3552
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
3732
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
3553
3733
|
</section>`;
|
|
3554
3734
|
};
|
|
3555
3735
|
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}`;
|
|
@@ -3681,6 +3861,7 @@ export {
|
|
|
3681
3861
|
renderVoiceProviderSimulationControlsHTML,
|
|
3682
3862
|
renderVoiceProviderCapabilitiesHTML,
|
|
3683
3863
|
renderVoiceOpsStatusHTML,
|
|
3864
|
+
renderVoiceDeliveryRuntimeHTML,
|
|
3684
3865
|
mountVoiceTurnQuality,
|
|
3685
3866
|
mountVoiceTurnLatency,
|
|
3686
3867
|
mountVoiceTraceTimeline,
|
|
@@ -3689,6 +3870,7 @@ export {
|
|
|
3689
3870
|
mountVoiceProviderSimulationControls,
|
|
3690
3871
|
mountVoiceProviderCapabilities,
|
|
3691
3872
|
mountVoiceOpsStatus,
|
|
3873
|
+
mountVoiceDeliveryRuntime,
|
|
3692
3874
|
getVoiceTurnQualityCSS,
|
|
3693
3875
|
getVoiceTraceTimelineCSS,
|
|
3694
3876
|
getVoiceRoutingStatusCSS,
|
|
@@ -3696,6 +3878,7 @@ export {
|
|
|
3696
3878
|
getVoiceProviderCapabilitiesCSS,
|
|
3697
3879
|
getVoiceOpsStatusLabel,
|
|
3698
3880
|
getVoiceOpsStatusCSS,
|
|
3881
|
+
getVoiceDeliveryRuntimeCSS,
|
|
3699
3882
|
fetchVoiceWorkflowStatus,
|
|
3700
3883
|
fetchVoiceTurnQuality,
|
|
3701
3884
|
fetchVoiceTurnLatency,
|
|
@@ -3704,6 +3887,7 @@ export {
|
|
|
3704
3887
|
fetchVoiceProviderStatus,
|
|
3705
3888
|
fetchVoiceProviderCapabilities,
|
|
3706
3889
|
fetchVoiceOpsStatus,
|
|
3890
|
+
fetchVoiceDeliveryRuntime,
|
|
3707
3891
|
fetchVoiceCampaignDialerProofStatus,
|
|
3708
3892
|
defineVoiceTurnQualityElement,
|
|
3709
3893
|
defineVoiceTurnLatencyElement,
|
|
@@ -3713,6 +3897,7 @@ export {
|
|
|
3713
3897
|
defineVoiceProviderSimulationControlsElement,
|
|
3714
3898
|
defineVoiceProviderCapabilitiesElement,
|
|
3715
3899
|
defineVoiceOpsStatusElement,
|
|
3900
|
+
defineVoiceDeliveryRuntimeElement,
|
|
3716
3901
|
decodeVoiceAudioChunk,
|
|
3717
3902
|
createVoiceWorkflowStatusStore,
|
|
3718
3903
|
createVoiceTurnQualityViewModel,
|
|
@@ -3734,6 +3919,8 @@ export {
|
|
|
3734
3919
|
createVoiceOpsStatusStore,
|
|
3735
3920
|
createVoiceLiveTurnLatencyMonitor,
|
|
3736
3921
|
createVoiceDuplexController,
|
|
3922
|
+
createVoiceDeliveryRuntimeViewModel,
|
|
3923
|
+
createVoiceDeliveryRuntimeStore,
|
|
3737
3924
|
createVoiceController,
|
|
3738
3925
|
createVoiceConnection,
|
|
3739
3926
|
createVoiceCampaignDialerProofStore,
|