@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/svelte/index.js
CHANGED
|
@@ -189,6 +189,200 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
|
|
|
189
189
|
|
|
190
190
|
// src/svelte/createVoiceCampaignDialerProof.ts
|
|
191
191
|
var createVoiceCampaignDialerProof = (path = "/api/voice/campaigns/dialer-proof", options = {}) => createVoiceCampaignDialerProofStore(path, options);
|
|
192
|
+
// src/client/deliveryRuntime.ts
|
|
193
|
+
var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
194
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
195
|
+
const response = await fetchImpl(path);
|
|
196
|
+
if (!response.ok) {
|
|
197
|
+
throw new Error(`Voice delivery runtime failed: HTTP ${response.status}`);
|
|
198
|
+
}
|
|
199
|
+
return await response.json();
|
|
200
|
+
};
|
|
201
|
+
var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
202
|
+
const listeners = new Set;
|
|
203
|
+
let closed = false;
|
|
204
|
+
let timer;
|
|
205
|
+
let snapshot = {
|
|
206
|
+
error: null,
|
|
207
|
+
isLoading: false
|
|
208
|
+
};
|
|
209
|
+
const emit = () => {
|
|
210
|
+
for (const listener of listeners) {
|
|
211
|
+
listener();
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
const refresh = async () => {
|
|
215
|
+
if (closed) {
|
|
216
|
+
return snapshot.report;
|
|
217
|
+
}
|
|
218
|
+
snapshot = {
|
|
219
|
+
...snapshot,
|
|
220
|
+
error: null,
|
|
221
|
+
isLoading: true
|
|
222
|
+
};
|
|
223
|
+
emit();
|
|
224
|
+
try {
|
|
225
|
+
const report = await fetchVoiceDeliveryRuntime(path, options);
|
|
226
|
+
snapshot = {
|
|
227
|
+
error: null,
|
|
228
|
+
isLoading: false,
|
|
229
|
+
report,
|
|
230
|
+
updatedAt: Date.now()
|
|
231
|
+
};
|
|
232
|
+
emit();
|
|
233
|
+
return report;
|
|
234
|
+
} catch (error) {
|
|
235
|
+
snapshot = {
|
|
236
|
+
...snapshot,
|
|
237
|
+
error: error instanceof Error ? error.message : String(error),
|
|
238
|
+
isLoading: false
|
|
239
|
+
};
|
|
240
|
+
emit();
|
|
241
|
+
throw error;
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
const close = () => {
|
|
245
|
+
closed = true;
|
|
246
|
+
if (timer) {
|
|
247
|
+
clearInterval(timer);
|
|
248
|
+
timer = undefined;
|
|
249
|
+
}
|
|
250
|
+
listeners.clear();
|
|
251
|
+
};
|
|
252
|
+
if (typeof window !== "undefined" && options.intervalMs && options.intervalMs > 0) {
|
|
253
|
+
timer = setInterval(() => {
|
|
254
|
+
refresh().catch(() => {});
|
|
255
|
+
}, options.intervalMs);
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
close,
|
|
259
|
+
getServerSnapshot: () => snapshot,
|
|
260
|
+
getSnapshot: () => snapshot,
|
|
261
|
+
refresh,
|
|
262
|
+
subscribe: (listener) => {
|
|
263
|
+
listeners.add(listener);
|
|
264
|
+
return () => {
|
|
265
|
+
listeners.delete(listener);
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// src/client/deliveryRuntimeWidget.ts
|
|
272
|
+
var DEFAULT_TITLE = "Voice Delivery Runtime";
|
|
273
|
+
var DEFAULT_DESCRIPTION = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
274
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
275
|
+
var createSurface = (id, summary) => {
|
|
276
|
+
if (!summary) {
|
|
277
|
+
return {
|
|
278
|
+
deadLettered: 0,
|
|
279
|
+
detail: "Worker disabled",
|
|
280
|
+
failed: 0,
|
|
281
|
+
id,
|
|
282
|
+
label: id === "audit" ? "Audit delivery" : "Trace delivery",
|
|
283
|
+
pending: 0,
|
|
284
|
+
status: "disabled",
|
|
285
|
+
total: 0
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
const blocked = summary.failed + summary.deadLettered;
|
|
289
|
+
return {
|
|
290
|
+
deadLettered: summary.deadLettered,
|
|
291
|
+
detail: `${summary.delivered}/${summary.total} delivered, ${summary.pending} pending`,
|
|
292
|
+
failed: summary.failed,
|
|
293
|
+
id,
|
|
294
|
+
label: id === "audit" ? "Audit delivery" : "Trace delivery",
|
|
295
|
+
pending: summary.pending,
|
|
296
|
+
status: blocked > 0 ? "warn" : "pass",
|
|
297
|
+
total: summary.total
|
|
298
|
+
};
|
|
299
|
+
};
|
|
300
|
+
var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
301
|
+
const report = snapshot.report;
|
|
302
|
+
const surfaces = [
|
|
303
|
+
createSurface("audit", report?.summary.audit),
|
|
304
|
+
createSurface("trace", report?.summary.trace)
|
|
305
|
+
];
|
|
306
|
+
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
307
|
+
return {
|
|
308
|
+
description: options.description ?? DEFAULT_DESCRIPTION,
|
|
309
|
+
error: snapshot.error,
|
|
310
|
+
isLoading: snapshot.isLoading,
|
|
311
|
+
isRunning: Boolean(report?.isRunning),
|
|
312
|
+
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
313
|
+
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
314
|
+
surfaces,
|
|
315
|
+
title: options.title ?? DEFAULT_TITLE,
|
|
316
|
+
updatedAt: snapshot.updatedAt
|
|
317
|
+
};
|
|
318
|
+
};
|
|
319
|
+
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
320
|
+
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
321
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml(surface.status)}">
|
|
322
|
+
<span>${escapeHtml(surface.label)}</span>
|
|
323
|
+
<strong>${escapeHtml(surface.detail)}</strong>
|
|
324
|
+
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
325
|
+
</li>`).join("");
|
|
326
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml(model.status)}">
|
|
327
|
+
<header class="absolute-voice-delivery-runtime__header">
|
|
328
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml(model.title)}</span>
|
|
329
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml(model.label)}</strong>
|
|
330
|
+
</header>
|
|
331
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml(model.description)}</p>
|
|
332
|
+
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
333
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml(model.error)}</p>` : ""}
|
|
334
|
+
</section>`;
|
|
335
|
+
};
|
|
336
|
+
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}`;
|
|
337
|
+
var mountVoiceDeliveryRuntime = (element, path = "/api/voice-delivery-runtime", options = {}) => {
|
|
338
|
+
const store = createVoiceDeliveryRuntimeStore(path, options);
|
|
339
|
+
const render = () => {
|
|
340
|
+
element.innerHTML = renderVoiceDeliveryRuntimeHTML(store.getSnapshot(), options);
|
|
341
|
+
};
|
|
342
|
+
const unsubscribe = store.subscribe(render);
|
|
343
|
+
render();
|
|
344
|
+
store.refresh().catch(() => {});
|
|
345
|
+
return {
|
|
346
|
+
close: () => {
|
|
347
|
+
unsubscribe();
|
|
348
|
+
store.close();
|
|
349
|
+
},
|
|
350
|
+
refresh: store.refresh
|
|
351
|
+
};
|
|
352
|
+
};
|
|
353
|
+
var defineVoiceDeliveryRuntimeElement = (tagName = "absolute-voice-delivery-runtime") => {
|
|
354
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
customElements.define(tagName, class AbsoluteVoiceDeliveryRuntimeElement extends HTMLElement {
|
|
358
|
+
mounted;
|
|
359
|
+
connectedCallback() {
|
|
360
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
361
|
+
this.mounted = mountVoiceDeliveryRuntime(this, this.getAttribute("path") ?? "/api/voice-delivery-runtime", {
|
|
362
|
+
description: this.getAttribute("description") ?? undefined,
|
|
363
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
364
|
+
title: this.getAttribute("title") ?? undefined
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
disconnectedCallback() {
|
|
368
|
+
this.mounted?.close();
|
|
369
|
+
this.mounted = undefined;
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
// src/svelte/createVoiceDeliveryRuntime.ts
|
|
375
|
+
var createVoiceDeliveryRuntime = (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
376
|
+
const store = createVoiceDeliveryRuntimeStore(path, options);
|
|
377
|
+
return {
|
|
378
|
+
close: store.close,
|
|
379
|
+
getHTML: () => renderVoiceDeliveryRuntimeHTML(store.getSnapshot(), options),
|
|
380
|
+
getSnapshot: store.getSnapshot,
|
|
381
|
+
getViewModel: () => createVoiceDeliveryRuntimeViewModel(store.getSnapshot(), options),
|
|
382
|
+
refresh: store.refresh,
|
|
383
|
+
subscribe: store.subscribe
|
|
384
|
+
};
|
|
385
|
+
};
|
|
192
386
|
// src/client/opsStatus.ts
|
|
193
387
|
var fetchVoiceOpsStatus = async (path = "/api/voice/ops-status", options = {}) => {
|
|
194
388
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -269,8 +463,8 @@ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) =
|
|
|
269
463
|
};
|
|
270
464
|
|
|
271
465
|
// src/client/opsStatusWidget.ts
|
|
272
|
-
var
|
|
273
|
-
var
|
|
466
|
+
var DEFAULT_TITLE2 = "Voice Ops Status";
|
|
467
|
+
var DEFAULT_DESCRIPTION2 = "Certified workflow, provider, and handoff readiness from your AbsoluteJS voice app.";
|
|
274
468
|
var SURFACE_LABELS = {
|
|
275
469
|
handoffs: "Handoffs",
|
|
276
470
|
providers: "Providers",
|
|
@@ -278,7 +472,7 @@ var SURFACE_LABELS = {
|
|
|
278
472
|
sessions: "Sessions",
|
|
279
473
|
workflows: "Workflows"
|
|
280
474
|
};
|
|
281
|
-
var
|
|
475
|
+
var escapeHtml2 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
282
476
|
var readNumber = (value, key) => value && typeof value === "object" && (key in value) ? Number(value[key] ?? 0) : 0;
|
|
283
477
|
var surfaceDetail = (surface) => {
|
|
284
478
|
const total = readNumber(surface, "total");
|
|
@@ -318,7 +512,7 @@ var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
|
|
|
318
512
|
};
|
|
319
513
|
});
|
|
320
514
|
return {
|
|
321
|
-
description: options.description ??
|
|
515
|
+
description: options.description ?? DEFAULT_DESCRIPTION2,
|
|
322
516
|
error: snapshot.error,
|
|
323
517
|
isLoading: snapshot.isLoading,
|
|
324
518
|
label: getVoiceOpsStatusLabel(report, snapshot.error),
|
|
@@ -326,31 +520,31 @@ var createVoiceOpsStatusViewModel = (snapshot, options = {}) => {
|
|
|
326
520
|
passed: report?.passed ?? 0,
|
|
327
521
|
status: snapshot.error ? "error" : report ? report.status : snapshot.isLoading ? "loading" : "loading",
|
|
328
522
|
surfaces,
|
|
329
|
-
title: options.title ??
|
|
523
|
+
title: options.title ?? DEFAULT_TITLE2,
|
|
330
524
|
total: report?.total ?? 0,
|
|
331
525
|
updatedAt: snapshot.updatedAt
|
|
332
526
|
};
|
|
333
527
|
};
|
|
334
528
|
var renderVoiceOpsStatusHTML = (snapshot, options = {}) => {
|
|
335
529
|
const model = createVoiceOpsStatusViewModel(snapshot, options);
|
|
336
|
-
const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${
|
|
337
|
-
<span>${
|
|
338
|
-
<strong>${
|
|
530
|
+
const surfaces = model.surfaces.length ? model.surfaces.map((surface) => `<li class="absolute-voice-ops-status__surface absolute-voice-ops-status__surface--${escapeHtml2(surface.status)}">
|
|
531
|
+
<span>${escapeHtml2(surface.label)}</span>
|
|
532
|
+
<strong>${escapeHtml2(surface.detail)}</strong>
|
|
339
533
|
</li>`).join("") : '<li class="absolute-voice-ops-status__surface"><span>Status</span><strong>Waiting for first check</strong></li>';
|
|
340
|
-
const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${
|
|
341
|
-
return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${
|
|
534
|
+
const links = model.links.length ? `<nav class="absolute-voice-ops-status__links">${model.links.slice(0, 4).map((link) => `<a href="${escapeHtml2(link.href)}">${escapeHtml2(link.label)}</a>`).join("")}</nav>` : "";
|
|
535
|
+
return `<section class="absolute-voice-ops-status absolute-voice-ops-status--${escapeHtml2(model.status)}">
|
|
342
536
|
<header class="absolute-voice-ops-status__header">
|
|
343
|
-
<span class="absolute-voice-ops-status__eyebrow">${
|
|
344
|
-
<strong class="absolute-voice-ops-status__label">${
|
|
537
|
+
<span class="absolute-voice-ops-status__eyebrow">${escapeHtml2(model.title)}</span>
|
|
538
|
+
<strong class="absolute-voice-ops-status__label">${escapeHtml2(model.label)}</strong>
|
|
345
539
|
</header>
|
|
346
|
-
<p class="absolute-voice-ops-status__description">${
|
|
540
|
+
<p class="absolute-voice-ops-status__description">${escapeHtml2(model.description)}</p>
|
|
347
541
|
<div class="absolute-voice-ops-status__summary">
|
|
348
542
|
<span>${model.passed} passing</span>
|
|
349
543
|
<span>${Math.max(model.total - model.passed, 0)} failing</span>
|
|
350
544
|
<span>${model.total} checks</span>
|
|
351
545
|
</div>
|
|
352
546
|
<ul class="absolute-voice-ops-status__surfaces">${surfaces}</ul>
|
|
353
|
-
${model.error ? `<p class="absolute-voice-ops-status__error">${
|
|
547
|
+
${model.error ? `<p class="absolute-voice-ops-status__error">${escapeHtml2(model.error)}</p>` : ""}
|
|
354
548
|
${links}
|
|
355
549
|
</section>`;
|
|
356
550
|
};
|
|
@@ -485,7 +679,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
485
679
|
};
|
|
486
680
|
|
|
487
681
|
// src/client/providerSimulationControlsWidget.ts
|
|
488
|
-
var
|
|
682
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
489
683
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
490
684
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
491
685
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -505,18 +699,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
505
699
|
};
|
|
506
700
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
507
701
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
508
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
509
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
702
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml3(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml3(provider.provider)} ${escapeHtml3(formatKind(options.kind))} failure</button>`).join("");
|
|
703
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml3(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml3(provider.provider)} recovered</button>`).join("");
|
|
510
704
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
511
705
|
<header class="absolute-voice-provider-simulation__header">
|
|
512
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
513
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
706
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml3(model.title)}</span>
|
|
707
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml3(model.label)}</strong>
|
|
514
708
|
</header>
|
|
515
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
516
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
709
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml3(model.description)}</p>
|
|
710
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml3(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
517
711
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
518
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
519
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
712
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml3(snapshot.error)}</p>` : ""}
|
|
713
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml3(model.resultText)}</pre>` : ""}
|
|
520
714
|
</section>`;
|
|
521
715
|
};
|
|
522
716
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -671,9 +865,9 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
|
|
|
671
865
|
};
|
|
672
866
|
|
|
673
867
|
// src/client/providerCapabilitiesWidget.ts
|
|
674
|
-
var
|
|
675
|
-
var
|
|
676
|
-
var
|
|
868
|
+
var DEFAULT_TITLE3 = "Provider Capabilities";
|
|
869
|
+
var DEFAULT_DESCRIPTION3 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
870
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
677
871
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
678
872
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
679
873
|
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -717,36 +911,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
717
911
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
718
912
|
return {
|
|
719
913
|
capabilities,
|
|
720
|
-
description: options.description ??
|
|
914
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
721
915
|
error: snapshot.error,
|
|
722
916
|
isLoading: snapshot.isLoading,
|
|
723
917
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
724
918
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
725
|
-
title: options.title ??
|
|
919
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
726
920
|
updatedAt: snapshot.updatedAt
|
|
727
921
|
};
|
|
728
922
|
};
|
|
729
923
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
730
924
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
731
|
-
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--${
|
|
925
|
+
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--${escapeHtml4(capability.status)}">
|
|
732
926
|
<header>
|
|
733
|
-
<strong>${
|
|
734
|
-
<span>${
|
|
927
|
+
<strong>${escapeHtml4(capability.label)}</strong>
|
|
928
|
+
<span>${escapeHtml4(formatStatus(capability.status))}</span>
|
|
735
929
|
</header>
|
|
736
|
-
<p>${
|
|
930
|
+
<p>${escapeHtml4(capability.detail)}</p>
|
|
737
931
|
<dl>${capability.rows.map((row) => `<div>
|
|
738
|
-
<dt>${
|
|
739
|
-
<dd>${
|
|
932
|
+
<dt>${escapeHtml4(row.label)}</dt>
|
|
933
|
+
<dd>${escapeHtml4(row.value)}</dd>
|
|
740
934
|
</div>`).join("")}</dl>
|
|
741
935
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
742
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
936
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml4(model.status)}">
|
|
743
937
|
<header class="absolute-voice-provider-capabilities__header">
|
|
744
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
745
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
938
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml4(model.title)}</span>
|
|
939
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml4(model.label)}</strong>
|
|
746
940
|
</header>
|
|
747
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
941
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml4(model.description)}</p>
|
|
748
942
|
${capabilities}
|
|
749
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
943
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml4(model.error)}</p>` : ""}
|
|
750
944
|
</section>`;
|
|
751
945
|
};
|
|
752
946
|
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}`;
|
|
@@ -1519,9 +1713,9 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
1519
1713
|
};
|
|
1520
1714
|
|
|
1521
1715
|
// src/client/providerStatusWidget.ts
|
|
1522
|
-
var
|
|
1523
|
-
var
|
|
1524
|
-
var
|
|
1716
|
+
var DEFAULT_TITLE4 = "Voice Providers";
|
|
1717
|
+
var DEFAULT_DESCRIPTION4 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
1718
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1525
1719
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1526
1720
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
1527
1721
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -1565,37 +1759,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
1565
1759
|
const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
|
|
1566
1760
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
1567
1761
|
return {
|
|
1568
|
-
description: options.description ??
|
|
1762
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
1569
1763
|
error: snapshot.error,
|
|
1570
1764
|
isLoading: snapshot.isLoading,
|
|
1571
1765
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
1572
1766
|
providers,
|
|
1573
1767
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1574
|
-
title: options.title ??
|
|
1768
|
+
title: options.title ?? DEFAULT_TITLE4,
|
|
1575
1769
|
updatedAt: snapshot.updatedAt
|
|
1576
1770
|
};
|
|
1577
1771
|
};
|
|
1578
1772
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
1579
1773
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
1580
|
-
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--${
|
|
1774
|
+
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)}">
|
|
1581
1775
|
<header>
|
|
1582
|
-
<strong>${
|
|
1583
|
-
<span>${
|
|
1776
|
+
<strong>${escapeHtml5(provider.label)}</strong>
|
|
1777
|
+
<span>${escapeHtml5(formatStatus2(provider.status))}</span>
|
|
1584
1778
|
</header>
|
|
1585
|
-
<p>${
|
|
1779
|
+
<p>${escapeHtml5(provider.detail)}</p>
|
|
1586
1780
|
<dl>${provider.rows.map((row) => `<div>
|
|
1587
|
-
<dt>${
|
|
1588
|
-
<dd>${
|
|
1781
|
+
<dt>${escapeHtml5(row.label)}</dt>
|
|
1782
|
+
<dd>${escapeHtml5(row.value)}</dd>
|
|
1589
1783
|
</div>`).join("")}</dl>
|
|
1590
1784
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
1591
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
1785
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml5(model.status)}">
|
|
1592
1786
|
<header class="absolute-voice-provider-status__header">
|
|
1593
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
1594
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
1787
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml5(model.title)}</span>
|
|
1788
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml5(model.label)}</strong>
|
|
1595
1789
|
</header>
|
|
1596
|
-
<p class="absolute-voice-provider-status__description">${
|
|
1790
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml5(model.description)}</p>
|
|
1597
1791
|
${providers}
|
|
1598
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
1792
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
1599
1793
|
</section>`;
|
|
1600
1794
|
};
|
|
1601
1795
|
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}`;
|
|
@@ -1726,9 +1920,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
1726
1920
|
};
|
|
1727
1921
|
|
|
1728
1922
|
// src/client/routingStatusWidget.ts
|
|
1729
|
-
var
|
|
1730
|
-
var
|
|
1731
|
-
var
|
|
1923
|
+
var DEFAULT_TITLE5 = "Voice Routing";
|
|
1924
|
+
var DEFAULT_DESCRIPTION5 = "Latest provider routing decision from the self-hosted trace store.";
|
|
1925
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1732
1926
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
1733
1927
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
1734
1928
|
const decision = snapshot.decision;
|
|
@@ -1752,30 +1946,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
1752
1946
|
] : [];
|
|
1753
1947
|
return {
|
|
1754
1948
|
decision,
|
|
1755
|
-
description: options.description ??
|
|
1949
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
1756
1950
|
error: snapshot.error,
|
|
1757
1951
|
isLoading: snapshot.isLoading,
|
|
1758
1952
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
1759
1953
|
rows,
|
|
1760
1954
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1761
|
-
title: options.title ??
|
|
1955
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
1762
1956
|
updatedAt: snapshot.updatedAt
|
|
1763
1957
|
};
|
|
1764
1958
|
};
|
|
1765
1959
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
1766
1960
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
1767
1961
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
1768
|
-
<span>${
|
|
1769
|
-
<strong>${
|
|
1962
|
+
<span>${escapeHtml6(row.label)}</span>
|
|
1963
|
+
<strong>${escapeHtml6(row.value)}</strong>
|
|
1770
1964
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
1771
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
1965
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml6(model.status)}">
|
|
1772
1966
|
<header class="absolute-voice-routing-status__header">
|
|
1773
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
1774
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
1967
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml6(model.title)}</span>
|
|
1968
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml6(model.label)}</strong>
|
|
1775
1969
|
</header>
|
|
1776
|
-
<p class="absolute-voice-routing-status__description">${
|
|
1970
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml6(model.description)}</p>
|
|
1777
1971
|
${rows}
|
|
1778
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
1972
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
1779
1973
|
</section>`;
|
|
1780
1974
|
};
|
|
1781
1975
|
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}`;
|
|
@@ -1906,9 +2100,9 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
|
|
|
1906
2100
|
};
|
|
1907
2101
|
|
|
1908
2102
|
// src/client/traceTimelineWidget.ts
|
|
1909
|
-
var
|
|
1910
|
-
var
|
|
1911
|
-
var
|
|
2103
|
+
var DEFAULT_TITLE6 = "Voice Traces";
|
|
2104
|
+
var DEFAULT_DESCRIPTION6 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
2105
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1912
2106
|
var formatMs = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
1913
2107
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
1914
2108
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -1922,34 +2116,34 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
1922
2116
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
1923
2117
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
1924
2118
|
return {
|
|
1925
|
-
description: options.description ??
|
|
2119
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
1926
2120
|
error: snapshot.error,
|
|
1927
2121
|
isLoading: snapshot.isLoading,
|
|
1928
2122
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
1929
2123
|
sessions,
|
|
1930
2124
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1931
|
-
title: options.title ??
|
|
2125
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
1932
2126
|
updatedAt: snapshot.updatedAt
|
|
1933
2127
|
};
|
|
1934
2128
|
};
|
|
1935
2129
|
var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
1936
2130
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
1937
|
-
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--${
|
|
2131
|
+
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--${escapeHtml7(session.status)}">
|
|
1938
2132
|
<header>
|
|
1939
|
-
<strong>${
|
|
1940
|
-
<span>${
|
|
2133
|
+
<strong>${escapeHtml7(session.sessionId)}</strong>
|
|
2134
|
+
<span>${escapeHtml7(session.status)}</span>
|
|
1941
2135
|
</header>
|
|
1942
|
-
<p>${
|
|
1943
|
-
<a href="${
|
|
2136
|
+
<p>${escapeHtml7(session.label)} \xB7 ${escapeHtml7(session.durationLabel)} \xB7 ${escapeHtml7(session.providerLabel)}</p>
|
|
2137
|
+
<a href="${escapeHtml7(session.detailHref)}">Open timeline</a>
|
|
1944
2138
|
</article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
1945
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
2139
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml7(model.status)}">
|
|
1946
2140
|
<header class="absolute-voice-trace-timeline__header">
|
|
1947
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
1948
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
2141
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml7(model.title)}</span>
|
|
2142
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml7(model.label)}</strong>
|
|
1949
2143
|
</header>
|
|
1950
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
2144
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml7(model.description)}</p>
|
|
1951
2145
|
${sessions}
|
|
1952
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
2146
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
1953
2147
|
</section>`;
|
|
1954
2148
|
};
|
|
1955
2149
|
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}`;
|
|
@@ -2106,10 +2300,10 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
|
|
|
2106
2300
|
};
|
|
2107
2301
|
|
|
2108
2302
|
// src/client/turnLatencyWidget.ts
|
|
2109
|
-
var
|
|
2110
|
-
var
|
|
2303
|
+
var DEFAULT_TITLE7 = "Turn Latency";
|
|
2304
|
+
var DEFAULT_DESCRIPTION7 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
2111
2305
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
2112
|
-
var
|
|
2306
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2113
2307
|
var formatMs2 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
2114
2308
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
2115
2309
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -2123,39 +2317,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
2123
2317
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2124
2318
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2125
2319
|
return {
|
|
2126
|
-
description: options.description ??
|
|
2320
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
2127
2321
|
error: snapshot.error,
|
|
2128
2322
|
isLoading: snapshot.isLoading,
|
|
2129
2323
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs2(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
2130
2324
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
2131
2325
|
showProofAction: Boolean(options.proofPath),
|
|
2132
2326
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2133
|
-
title: options.title ??
|
|
2327
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
2134
2328
|
turns,
|
|
2135
2329
|
updatedAt: snapshot.updatedAt
|
|
2136
2330
|
};
|
|
2137
2331
|
};
|
|
2138
2332
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
2139
2333
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
2140
|
-
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--${
|
|
2334
|
+
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)}">
|
|
2141
2335
|
<header>
|
|
2142
|
-
<strong>${
|
|
2143
|
-
<span>${
|
|
2336
|
+
<strong>${escapeHtml8(turn.label)}</strong>
|
|
2337
|
+
<span>${escapeHtml8(turn.status)}</span>
|
|
2144
2338
|
</header>
|
|
2145
2339
|
<dl>${turn.rows.map((row) => `<div>
|
|
2146
|
-
<dt>${
|
|
2147
|
-
<dd>${
|
|
2340
|
+
<dt>${escapeHtml8(row.label)}</dt>
|
|
2341
|
+
<dd>${escapeHtml8(row.value)}</dd>
|
|
2148
2342
|
</div>`).join("")}</dl>
|
|
2149
2343
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
2150
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
2344
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml8(model.status)}">
|
|
2151
2345
|
<header class="absolute-voice-turn-latency__header">
|
|
2152
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
2153
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
2346
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml8(model.title)}</span>
|
|
2347
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml8(model.label)}</strong>
|
|
2154
2348
|
</header>
|
|
2155
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
2156
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
2349
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml8(model.description)}</p>
|
|
2350
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml8(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
2157
2351
|
${turns}
|
|
2158
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
2352
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
2159
2353
|
</section>`;
|
|
2160
2354
|
};
|
|
2161
2355
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -2294,9 +2488,9 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
|
|
|
2294
2488
|
};
|
|
2295
2489
|
|
|
2296
2490
|
// src/client/turnQualityWidget.ts
|
|
2297
|
-
var
|
|
2298
|
-
var
|
|
2299
|
-
var
|
|
2491
|
+
var DEFAULT_TITLE8 = "Turn Quality";
|
|
2492
|
+
var DEFAULT_DESCRIPTION8 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
2493
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2300
2494
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
2301
2495
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
2302
2496
|
var getTurnDetail = (turn) => {
|
|
@@ -2334,37 +2528,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
2334
2528
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2335
2529
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2336
2530
|
return {
|
|
2337
|
-
description: options.description ??
|
|
2531
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
2338
2532
|
error: snapshot.error,
|
|
2339
2533
|
isLoading: snapshot.isLoading,
|
|
2340
2534
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
2341
2535
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2342
|
-
title: options.title ??
|
|
2536
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
2343
2537
|
turns,
|
|
2344
2538
|
updatedAt: snapshot.updatedAt
|
|
2345
2539
|
};
|
|
2346
2540
|
};
|
|
2347
2541
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
2348
2542
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
2349
|
-
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--${
|
|
2543
|
+
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--${escapeHtml9(turn.status)}">
|
|
2350
2544
|
<header>
|
|
2351
|
-
<strong>${
|
|
2352
|
-
<span>${
|
|
2545
|
+
<strong>${escapeHtml9(turn.label)}</strong>
|
|
2546
|
+
<span>${escapeHtml9(turn.status)}</span>
|
|
2353
2547
|
</header>
|
|
2354
|
-
<p>${
|
|
2548
|
+
<p>${escapeHtml9(turn.detail)}</p>
|
|
2355
2549
|
<dl>${turn.rows.map((row) => `<div>
|
|
2356
|
-
<dt>${
|
|
2357
|
-
<dd>${
|
|
2550
|
+
<dt>${escapeHtml9(row.label)}</dt>
|
|
2551
|
+
<dd>${escapeHtml9(row.value)}</dd>
|
|
2358
2552
|
</div>`).join("")}</dl>
|
|
2359
2553
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
2360
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
2554
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml9(model.status)}">
|
|
2361
2555
|
<header class="absolute-voice-turn-quality__header">
|
|
2362
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
2363
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
2556
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml9(model.title)}</span>
|
|
2557
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml9(model.label)}</strong>
|
|
2364
2558
|
</header>
|
|
2365
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
2559
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml9(model.description)}</p>
|
|
2366
2560
|
${turns}
|
|
2367
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
2561
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
2368
2562
|
</section>`;
|
|
2369
2563
|
};
|
|
2370
2564
|
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}`;
|
|
@@ -3146,6 +3340,7 @@ export {
|
|
|
3146
3340
|
createVoiceProviderSimulationControls,
|
|
3147
3341
|
createVoiceProviderCapabilities,
|
|
3148
3342
|
createVoiceOpsStatus,
|
|
3343
|
+
createVoiceDeliveryRuntime,
|
|
3149
3344
|
createVoiceController,
|
|
3150
3345
|
createVoiceCampaignDialerProof
|
|
3151
3346
|
};
|