@absolutejs/voice 0.0.22-beta.153 → 0.0.22-beta.155
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 +50 -0
- package/dist/angular/index.d.ts +1 -0
- package/dist/angular/index.js +378 -140
- package/dist/angular/voice-ops-action-center.service.d.ts +13 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +400 -114
- package/dist/client/opsActionCenter.d.ts +54 -0
- package/dist/client/opsActionCenterWidget.d.ts +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +144 -53
- package/dist/opsActionAuditRoutes.d.ts +79 -0
- package/dist/react/VoiceOpsActionCenter.d.ts +5 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +640 -289
- package/dist/react/useVoiceOpsActionCenter.d.ts +11 -0
- package/dist/svelte/createVoiceOpsActionCenter.d.ts +10 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +407 -114
- package/dist/trace.d.ts +1 -1
- package/dist/vue/VoiceOpsActionCenter.d.ts +13 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +668 -298
- package/dist/vue/useVoiceOpsActionCenter.d.ts +11 -0
- package/package.json +1 -1
package/dist/vue/index.js
CHANGED
|
@@ -374,9 +374,377 @@ var VoiceOpsStatus = defineComponent({
|
|
|
374
374
|
};
|
|
375
375
|
}
|
|
376
376
|
});
|
|
377
|
-
// src/vue/
|
|
377
|
+
// src/vue/VoiceOpsActionCenter.ts
|
|
378
378
|
import { defineComponent as defineComponent2, h as h2 } from "vue";
|
|
379
379
|
|
|
380
|
+
// src/client/opsActionCenter.ts
|
|
381
|
+
var recordVoiceOpsActionResult = async (result, options = {}) => {
|
|
382
|
+
if (options.auditPath === false) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const path = options.auditPath ?? "/api/voice/ops-actions/audit";
|
|
386
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
387
|
+
const response = await fetchImpl(path, {
|
|
388
|
+
body: JSON.stringify(result),
|
|
389
|
+
headers: {
|
|
390
|
+
"Content-Type": "application/json"
|
|
391
|
+
},
|
|
392
|
+
method: "POST"
|
|
393
|
+
});
|
|
394
|
+
if (!response.ok) {
|
|
395
|
+
throw new Error(`Voice ops action audit failed: HTTP ${response.status}`);
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
var createVoiceOpsActionCenterActions = (options = {}) => {
|
|
399
|
+
const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
|
|
400
|
+
const actions = [];
|
|
401
|
+
if (options.includeProductionReadiness !== false) {
|
|
402
|
+
actions.push({
|
|
403
|
+
description: "Refresh the production readiness report.",
|
|
404
|
+
id: "production-readiness",
|
|
405
|
+
label: "Refresh readiness",
|
|
406
|
+
method: "GET",
|
|
407
|
+
path: options.productionReadinessPath ?? "/api/production-readiness"
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
if (options.includeDeliveryRuntime !== false) {
|
|
411
|
+
actions.push({
|
|
412
|
+
description: "Drain pending and failed audit/trace deliveries.",
|
|
413
|
+
id: "delivery-runtime.tick",
|
|
414
|
+
label: "Tick delivery workers",
|
|
415
|
+
method: "POST",
|
|
416
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/tick`
|
|
417
|
+
}, {
|
|
418
|
+
description: "Move reviewed dead letters back to live delivery queues.",
|
|
419
|
+
id: "delivery-runtime.requeue-dead-letters",
|
|
420
|
+
label: "Requeue dead letters",
|
|
421
|
+
method: "POST",
|
|
422
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/requeue-dead-letters`
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
if (options.includeTurnLatencyProof !== false) {
|
|
426
|
+
actions.push({
|
|
427
|
+
description: "Run the synthetic turn latency proof.",
|
|
428
|
+
id: "turn-latency.proof",
|
|
429
|
+
label: "Run latency proof",
|
|
430
|
+
method: "POST",
|
|
431
|
+
path: options.turnLatencyProofPath ?? "/api/turn-latency/proof"
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
if (options.includeProviderSimulation !== false) {
|
|
435
|
+
const pathPrefix = options.providerSimulationPathPrefix ?? "/api/stt-simulate";
|
|
436
|
+
for (const provider of options.providers ?? []) {
|
|
437
|
+
actions.push({
|
|
438
|
+
description: `Simulate ${provider} provider failure.`,
|
|
439
|
+
id: `provider.${provider}.failure`,
|
|
440
|
+
label: `Simulate ${provider} failure`,
|
|
441
|
+
method: "POST",
|
|
442
|
+
path: `${pathPrefix}/failure?provider=${encodeURIComponent(provider)}`
|
|
443
|
+
}, {
|
|
444
|
+
description: `Mark ${provider} provider recovered.`,
|
|
445
|
+
id: `provider.${provider}.recovery`,
|
|
446
|
+
label: `Recover ${provider}`,
|
|
447
|
+
method: "POST",
|
|
448
|
+
path: `${pathPrefix}/recovery?provider=${encodeURIComponent(provider)}`
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return actions;
|
|
453
|
+
};
|
|
454
|
+
var runVoiceOpsAction = async (action, options = {}) => {
|
|
455
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
456
|
+
const response = await fetchImpl(action.path, {
|
|
457
|
+
method: action.method ?? "POST"
|
|
458
|
+
});
|
|
459
|
+
const body = await response.json().catch(() => null);
|
|
460
|
+
if (!response.ok) {
|
|
461
|
+
const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
|
|
462
|
+
throw new Error(message);
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
actionId: action.id,
|
|
466
|
+
body,
|
|
467
|
+
ok: response.ok,
|
|
468
|
+
ranAt: Date.now(),
|
|
469
|
+
status: response.status
|
|
470
|
+
};
|
|
471
|
+
};
|
|
472
|
+
var createVoiceOpsActionCenterStore = (options = {}) => {
|
|
473
|
+
const listeners = new Set;
|
|
474
|
+
let closed = false;
|
|
475
|
+
let timer;
|
|
476
|
+
let snapshot = {
|
|
477
|
+
actions: options.actions ?? createVoiceOpsActionCenterActions(),
|
|
478
|
+
error: null,
|
|
479
|
+
isRunning: false
|
|
480
|
+
};
|
|
481
|
+
const emit = () => {
|
|
482
|
+
for (const listener of listeners) {
|
|
483
|
+
listener();
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
const setActions = (actions) => {
|
|
487
|
+
snapshot = { ...snapshot, actions, updatedAt: Date.now() };
|
|
488
|
+
emit();
|
|
489
|
+
};
|
|
490
|
+
const run = async (actionId) => {
|
|
491
|
+
if (closed) {
|
|
492
|
+
return snapshot.lastResult;
|
|
493
|
+
}
|
|
494
|
+
const action = snapshot.actions.find((item) => item.id === actionId);
|
|
495
|
+
if (!action) {
|
|
496
|
+
throw new Error(`Voice ops action "${actionId}" is not configured.`);
|
|
497
|
+
}
|
|
498
|
+
if (action.disabled) {
|
|
499
|
+
throw new Error(`Voice ops action "${actionId}" is disabled.`);
|
|
500
|
+
}
|
|
501
|
+
snapshot = {
|
|
502
|
+
...snapshot,
|
|
503
|
+
error: null,
|
|
504
|
+
isRunning: true,
|
|
505
|
+
runningActionId: action.id
|
|
506
|
+
};
|
|
507
|
+
emit();
|
|
508
|
+
try {
|
|
509
|
+
const result = await runVoiceOpsAction(action, options);
|
|
510
|
+
await options.onActionResult?.(result);
|
|
511
|
+
await recordVoiceOpsActionResult(result, options);
|
|
512
|
+
snapshot = {
|
|
513
|
+
...snapshot,
|
|
514
|
+
error: null,
|
|
515
|
+
isRunning: false,
|
|
516
|
+
lastResult: result,
|
|
517
|
+
runningActionId: undefined,
|
|
518
|
+
updatedAt: Date.now()
|
|
519
|
+
};
|
|
520
|
+
emit();
|
|
521
|
+
return result;
|
|
522
|
+
} catch (error) {
|
|
523
|
+
const result = {
|
|
524
|
+
actionId: action.id,
|
|
525
|
+
body: null,
|
|
526
|
+
error: error instanceof Error ? error.message : String(error),
|
|
527
|
+
ok: false,
|
|
528
|
+
ranAt: Date.now(),
|
|
529
|
+
status: 0
|
|
530
|
+
};
|
|
531
|
+
await options.onActionResult?.(result);
|
|
532
|
+
await recordVoiceOpsActionResult(result, options).catch(() => {});
|
|
533
|
+
snapshot = {
|
|
534
|
+
...snapshot,
|
|
535
|
+
error: error instanceof Error ? error.message : String(error),
|
|
536
|
+
isRunning: false,
|
|
537
|
+
runningActionId: undefined
|
|
538
|
+
};
|
|
539
|
+
emit();
|
|
540
|
+
throw error;
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
const close = () => {
|
|
544
|
+
closed = true;
|
|
545
|
+
if (timer) {
|
|
546
|
+
clearInterval(timer);
|
|
547
|
+
timer = undefined;
|
|
548
|
+
}
|
|
549
|
+
listeners.clear();
|
|
550
|
+
};
|
|
551
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
552
|
+
timer = setInterval(() => {
|
|
553
|
+
emit();
|
|
554
|
+
}, options.intervalMs);
|
|
555
|
+
}
|
|
556
|
+
return {
|
|
557
|
+
close,
|
|
558
|
+
getServerSnapshot: () => snapshot,
|
|
559
|
+
getSnapshot: () => snapshot,
|
|
560
|
+
run,
|
|
561
|
+
setActions,
|
|
562
|
+
subscribe: (listener) => {
|
|
563
|
+
listeners.add(listener);
|
|
564
|
+
return () => {
|
|
565
|
+
listeners.delete(listener);
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
};
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
// src/client/opsActionCenterWidget.ts
|
|
572
|
+
var DEFAULT_TITLE2 = "Voice Ops Action Center";
|
|
573
|
+
var DEFAULT_DESCRIPTION2 = "Run production voice proofs and operator actions from one primitive panel.";
|
|
574
|
+
var escapeHtml2 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
575
|
+
var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
576
|
+
const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
|
|
577
|
+
return {
|
|
578
|
+
actions: snapshot.actions.map((action) => ({
|
|
579
|
+
description: action.description ?? "",
|
|
580
|
+
disabled: Boolean(action.disabled || snapshot.isRunning),
|
|
581
|
+
id: action.id,
|
|
582
|
+
isRunning: snapshot.runningActionId === action.id,
|
|
583
|
+
label: action.label
|
|
584
|
+
})),
|
|
585
|
+
description: options.description ?? DEFAULT_DESCRIPTION2,
|
|
586
|
+
error: snapshot.error,
|
|
587
|
+
isRunning: snapshot.isRunning,
|
|
588
|
+
label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
|
|
589
|
+
lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
|
|
590
|
+
status,
|
|
591
|
+
title: options.title ?? DEFAULT_TITLE2
|
|
592
|
+
};
|
|
593
|
+
};
|
|
594
|
+
var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
|
|
595
|
+
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
596
|
+
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml2(action.id)}"${action.disabled ? " disabled" : ""}>
|
|
597
|
+
${escapeHtml2(action.isRunning ? "Working..." : action.label)}
|
|
598
|
+
</button>`).join("");
|
|
599
|
+
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml2(model.status)}">
|
|
600
|
+
<header class="absolute-voice-ops-action-center__header">
|
|
601
|
+
<span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml2(model.title)}</span>
|
|
602
|
+
<strong class="absolute-voice-ops-action-center__label">${escapeHtml2(model.label)}</strong>
|
|
603
|
+
</header>
|
|
604
|
+
<p class="absolute-voice-ops-action-center__description">${escapeHtml2(model.description)}</p>
|
|
605
|
+
<div class="absolute-voice-ops-action-center__actions">${actions}</div>
|
|
606
|
+
<p class="absolute-voice-ops-action-center__result">${escapeHtml2(model.lastResultLabel)}</p>
|
|
607
|
+
${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml2(model.error)}</p>` : ""}
|
|
608
|
+
</section>`;
|
|
609
|
+
};
|
|
610
|
+
var getVoiceOpsActionCenterCSS = () => `.absolute-voice-ops-action-center{border:1px solid #d5cbb8;border-radius:20px;background:#fffaf1;color:#17130b;padding:18px;box-shadow:0 18px 40px rgba(58,42,16,.12);font-family:inherit}.absolute-voice-ops-action-center--error{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-ops-action-center__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-ops-action-center__eyebrow{color:#725d37;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-ops-action-center__label{font-size:28px;line-height:1}.absolute-voice-ops-action-center__description,.absolute-voice-ops-action-center__result{color:#5b4b2f;margin:12px 0 0}.absolute-voice-ops-action-center__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-ops-action-center__actions button{background:#7c4a03;border:0;border-radius:999px;color:#fff8e8;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-ops-action-center__actions button:disabled{cursor:not-allowed;opacity:.5}.absolute-voice-ops-action-center__error{color:#9f1239;font-weight:700}`;
|
|
611
|
+
var mountVoiceOpsActionCenter = (element, options = {}) => {
|
|
612
|
+
const store = createVoiceOpsActionCenterStore(options);
|
|
613
|
+
const render = () => {
|
|
614
|
+
element.innerHTML = renderVoiceOpsActionCenterHTML(store.getSnapshot(), options);
|
|
615
|
+
};
|
|
616
|
+
const unsubscribe = store.subscribe(render);
|
|
617
|
+
const handleClick = (event) => {
|
|
618
|
+
const target = event.target;
|
|
619
|
+
if (!(target instanceof Element)) {
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
const action = target.closest("[data-absolute-voice-ops-action]");
|
|
623
|
+
const actionId = action?.getAttribute("data-absolute-voice-ops-action");
|
|
624
|
+
if (actionId) {
|
|
625
|
+
store.run(actionId).catch(() => {});
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
element.addEventListener?.("click", handleClick);
|
|
629
|
+
render();
|
|
630
|
+
return {
|
|
631
|
+
close: () => {
|
|
632
|
+
element.removeEventListener?.("click", handleClick);
|
|
633
|
+
unsubscribe();
|
|
634
|
+
store.close();
|
|
635
|
+
},
|
|
636
|
+
run: store.run
|
|
637
|
+
};
|
|
638
|
+
};
|
|
639
|
+
var defineVoiceOpsActionCenterElement = (tagName = "absolute-voice-ops-action-center", options = {}) => {
|
|
640
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
641
|
+
return;
|
|
642
|
+
}
|
|
643
|
+
customElements.define(tagName, class AbsoluteVoiceOpsActionCenterElement extends HTMLElement {
|
|
644
|
+
mounted;
|
|
645
|
+
connectedCallback() {
|
|
646
|
+
this.mounted = mountVoiceOpsActionCenter(this, {
|
|
647
|
+
...options,
|
|
648
|
+
description: this.getAttribute("description") ?? options.description,
|
|
649
|
+
title: this.getAttribute("title") ?? options.title
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
disconnectedCallback() {
|
|
653
|
+
this.mounted?.close();
|
|
654
|
+
this.mounted = undefined;
|
|
655
|
+
}
|
|
656
|
+
});
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
// src/vue/useVoiceOpsActionCenter.ts
|
|
660
|
+
import { onUnmounted as onUnmounted2, ref as ref2, shallowRef as shallowRef2 } from "vue";
|
|
661
|
+
function useVoiceOpsActionCenter(options = {}) {
|
|
662
|
+
const store = createVoiceOpsActionCenterStore(options);
|
|
663
|
+
const actions = shallowRef2([]);
|
|
664
|
+
const error = ref2(null);
|
|
665
|
+
const isRunning = ref2(false);
|
|
666
|
+
const lastResult = shallowRef2(undefined);
|
|
667
|
+
const runningActionId = ref2(undefined);
|
|
668
|
+
const updatedAt = ref2(undefined);
|
|
669
|
+
const sync = () => {
|
|
670
|
+
const snapshot = store.getSnapshot();
|
|
671
|
+
actions.value = snapshot.actions;
|
|
672
|
+
error.value = snapshot.error;
|
|
673
|
+
isRunning.value = snapshot.isRunning;
|
|
674
|
+
lastResult.value = snapshot.lastResult;
|
|
675
|
+
runningActionId.value = snapshot.runningActionId;
|
|
676
|
+
updatedAt.value = snapshot.updatedAt;
|
|
677
|
+
};
|
|
678
|
+
const unsubscribe = store.subscribe(sync);
|
|
679
|
+
sync();
|
|
680
|
+
onUnmounted2(() => {
|
|
681
|
+
unsubscribe();
|
|
682
|
+
store.close();
|
|
683
|
+
});
|
|
684
|
+
return {
|
|
685
|
+
actions,
|
|
686
|
+
error,
|
|
687
|
+
isRunning,
|
|
688
|
+
lastResult,
|
|
689
|
+
run: store.run,
|
|
690
|
+
runningActionId,
|
|
691
|
+
setActions: store.setActions,
|
|
692
|
+
updatedAt
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// src/vue/VoiceOpsActionCenter.ts
|
|
697
|
+
var VoiceOpsActionCenter = defineComponent2({
|
|
698
|
+
name: "VoiceOpsActionCenter",
|
|
699
|
+
props: {
|
|
700
|
+
actions: Array,
|
|
701
|
+
description: String,
|
|
702
|
+
title: String
|
|
703
|
+
},
|
|
704
|
+
setup(props) {
|
|
705
|
+
const options = {
|
|
706
|
+
actions: props.actions,
|
|
707
|
+
description: props.description,
|
|
708
|
+
title: props.title
|
|
709
|
+
};
|
|
710
|
+
const center = useVoiceOpsActionCenter(options);
|
|
711
|
+
return () => {
|
|
712
|
+
const model = createVoiceOpsActionCenterViewModel({
|
|
713
|
+
actions: center.actions.value,
|
|
714
|
+
error: center.error.value,
|
|
715
|
+
isRunning: center.isRunning.value,
|
|
716
|
+
lastResult: center.lastResult.value,
|
|
717
|
+
runningActionId: center.runningActionId.value,
|
|
718
|
+
updatedAt: center.updatedAt.value
|
|
719
|
+
}, options);
|
|
720
|
+
return h2("section", {
|
|
721
|
+
class: [
|
|
722
|
+
"absolute-voice-ops-action-center",
|
|
723
|
+
`absolute-voice-ops-action-center--${model.status}`
|
|
724
|
+
]
|
|
725
|
+
}, [
|
|
726
|
+
h2("header", { class: "absolute-voice-ops-action-center__header" }, [
|
|
727
|
+
h2("span", { class: "absolute-voice-ops-action-center__eyebrow" }, model.title),
|
|
728
|
+
h2("strong", { class: "absolute-voice-ops-action-center__label" }, model.label)
|
|
729
|
+
]),
|
|
730
|
+
h2("p", { class: "absolute-voice-ops-action-center__description" }, model.description),
|
|
731
|
+
h2("div", { class: "absolute-voice-ops-action-center__actions" }, model.actions.map((action) => h2("button", {
|
|
732
|
+
disabled: action.disabled,
|
|
733
|
+
key: action.id,
|
|
734
|
+
onClick: () => {
|
|
735
|
+
center.run(action.id).catch(() => {});
|
|
736
|
+
},
|
|
737
|
+
type: "button"
|
|
738
|
+
}, action.isRunning ? "Working..." : action.label))),
|
|
739
|
+
h2("p", { class: "absolute-voice-ops-action-center__result" }, model.lastResultLabel),
|
|
740
|
+
model.error ? h2("p", { class: "absolute-voice-ops-action-center__error" }, model.error) : null
|
|
741
|
+
]);
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
});
|
|
745
|
+
// src/vue/VoiceDeliveryRuntime.ts
|
|
746
|
+
import { defineComponent as defineComponent3, h as h3 } from "vue";
|
|
747
|
+
|
|
380
748
|
// src/client/deliveryRuntime.ts
|
|
381
749
|
var getDefaultActionPath = (path, action, options) => {
|
|
382
750
|
if (action === "tick") {
|
|
@@ -515,9 +883,9 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
|
|
|
515
883
|
};
|
|
516
884
|
|
|
517
885
|
// src/client/deliveryRuntimeWidget.ts
|
|
518
|
-
var
|
|
519
|
-
var
|
|
520
|
-
var
|
|
886
|
+
var DEFAULT_TITLE3 = "Voice Delivery Runtime";
|
|
887
|
+
var DEFAULT_DESCRIPTION3 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
888
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
521
889
|
var createSurface = (id, summary) => {
|
|
522
890
|
if (!summary) {
|
|
523
891
|
return {
|
|
@@ -551,7 +919,7 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
551
919
|
];
|
|
552
920
|
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
553
921
|
return {
|
|
554
|
-
description: options.description ??
|
|
922
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
555
923
|
error: snapshot.error,
|
|
556
924
|
actionError: snapshot.actionError,
|
|
557
925
|
actionStatus: snapshot.actionStatus,
|
|
@@ -560,32 +928,32 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
560
928
|
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
561
929
|
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
562
930
|
surfaces,
|
|
563
|
-
title: options.title ??
|
|
931
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
564
932
|
updatedAt: snapshot.updatedAt
|
|
565
933
|
};
|
|
566
934
|
};
|
|
567
935
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
568
936
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
569
|
-
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${
|
|
570
|
-
<span>${
|
|
571
|
-
<strong>${
|
|
937
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml3(surface.status)}">
|
|
938
|
+
<span>${escapeHtml3(surface.label)}</span>
|
|
939
|
+
<strong>${escapeHtml3(surface.detail)}</strong>
|
|
572
940
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
573
941
|
</li>`).join("");
|
|
574
942
|
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
575
943
|
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
576
944
|
<button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
|
|
577
945
|
</div>`;
|
|
578
|
-
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
579
|
-
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${
|
|
946
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.actionError)}</p>` : "";
|
|
947
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml3(model.status)}">
|
|
580
948
|
<header class="absolute-voice-delivery-runtime__header">
|
|
581
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
582
|
-
<strong class="absolute-voice-delivery-runtime__label">${
|
|
949
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml3(model.title)}</span>
|
|
950
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml3(model.label)}</strong>
|
|
583
951
|
</header>
|
|
584
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
952
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml3(model.description)}</p>
|
|
585
953
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
586
954
|
${actions}
|
|
587
955
|
${actionError}
|
|
588
|
-
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
956
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.error)}</p>` : ""}
|
|
589
957
|
</section>`;
|
|
590
958
|
};
|
|
591
959
|
var getVoiceDeliveryRuntimeCSS = () => `.absolute-voice-delivery-runtime{border:1px solid #c9d8cf;border-radius:20px;background:#f6fff9;color:#0d1b12;padding:18px;box-shadow:0 18px 40px rgba(19,55,35,.12);font-family:inherit}.absolute-voice-delivery-runtime--warn,.absolute-voice-delivery-runtime--error{border-color:#f2b56b;background:#fff9ed}.absolute-voice-delivery-runtime__header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-delivery-runtime__eyebrow{color:#4e6b59;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-delivery-runtime__label{font-size:28px;line-height:1}.absolute-voice-delivery-runtime__description{color:#33483b;margin:12px 0 0}.absolute-voice-delivery-runtime__surfaces{display:grid;gap:8px;list-style:none;margin:16px 0 0;padding:0}.absolute-voice-delivery-runtime__surface{background:#fff;border:1px solid #d9eadf;border-radius:14px;display:grid;gap:4px;padding:10px 12px}.absolute-voice-delivery-runtime__surface--warn{border-color:#f2b56b}.absolute-voice-delivery-runtime__surface--disabled{opacity:.72}.absolute-voice-delivery-runtime__surface span,.absolute-voice-delivery-runtime__surface small{color:#587063}.absolute-voice-delivery-runtime__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.absolute-voice-delivery-runtime__actions button{background:#134e2d;border:0;border-radius:999px;color:#f6fff9;cursor:pointer;font:inherit;font-weight:800;padding:8px 12px}.absolute-voice-delivery-runtime__actions button:disabled{cursor:not-allowed;opacity:.48}.absolute-voice-delivery-runtime__error{color:#9f1239;font-weight:700}`;
|
|
@@ -643,15 +1011,15 @@ var defineVoiceDeliveryRuntimeElement = (tagName = "absolute-voice-delivery-runt
|
|
|
643
1011
|
};
|
|
644
1012
|
|
|
645
1013
|
// src/vue/useVoiceDeliveryRuntime.ts
|
|
646
|
-
import { onUnmounted as
|
|
1014
|
+
import { onUnmounted as onUnmounted3, ref as ref3, shallowRef as shallowRef3 } from "vue";
|
|
647
1015
|
function useVoiceDeliveryRuntime(path = "/api/voice-delivery-runtime", options = {}) {
|
|
648
1016
|
const store = createVoiceDeliveryRuntimeStore(path, options);
|
|
649
|
-
const actionError =
|
|
650
|
-
const actionStatus =
|
|
651
|
-
const error =
|
|
652
|
-
const isLoading =
|
|
653
|
-
const report =
|
|
654
|
-
const updatedAt =
|
|
1017
|
+
const actionError = ref3(null);
|
|
1018
|
+
const actionStatus = ref3("idle");
|
|
1019
|
+
const error = ref3(null);
|
|
1020
|
+
const isLoading = ref3(false);
|
|
1021
|
+
const report = shallowRef3(undefined);
|
|
1022
|
+
const updatedAt = ref3(undefined);
|
|
655
1023
|
const sync = () => {
|
|
656
1024
|
const snapshot = store.getSnapshot();
|
|
657
1025
|
actionError.value = snapshot.actionError;
|
|
@@ -666,7 +1034,7 @@ function useVoiceDeliveryRuntime(path = "/api/voice-delivery-runtime", options =
|
|
|
666
1034
|
if (typeof window !== "undefined") {
|
|
667
1035
|
store.refresh().catch(() => {});
|
|
668
1036
|
}
|
|
669
|
-
|
|
1037
|
+
onUnmounted3(() => {
|
|
670
1038
|
unsubscribe();
|
|
671
1039
|
store.close();
|
|
672
1040
|
});
|
|
@@ -684,7 +1052,7 @@ function useVoiceDeliveryRuntime(path = "/api/voice-delivery-runtime", options =
|
|
|
684
1052
|
}
|
|
685
1053
|
|
|
686
1054
|
// src/vue/VoiceDeliveryRuntime.ts
|
|
687
|
-
var VoiceDeliveryRuntime =
|
|
1055
|
+
var VoiceDeliveryRuntime = defineComponent3({
|
|
688
1056
|
name: "VoiceDeliveryRuntime",
|
|
689
1057
|
props: {
|
|
690
1058
|
description: String,
|
|
@@ -716,37 +1084,37 @@ var VoiceDeliveryRuntime = defineComponent2({
|
|
|
716
1084
|
updatedAt: runtime.updatedAt.value
|
|
717
1085
|
}, options);
|
|
718
1086
|
const hasDeadLetters = model.surfaces.some((surface) => surface.deadLettered > 0);
|
|
719
|
-
return
|
|
1087
|
+
return h3("section", {
|
|
720
1088
|
class: [
|
|
721
1089
|
"absolute-voice-delivery-runtime",
|
|
722
1090
|
`absolute-voice-delivery-runtime--${model.status}`
|
|
723
1091
|
]
|
|
724
1092
|
}, [
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
1093
|
+
h3("header", { class: "absolute-voice-delivery-runtime__header" }, [
|
|
1094
|
+
h3("span", { class: "absolute-voice-delivery-runtime__eyebrow" }, model.title),
|
|
1095
|
+
h3("strong", { class: "absolute-voice-delivery-runtime__label" }, model.label)
|
|
728
1096
|
]),
|
|
729
|
-
|
|
730
|
-
|
|
1097
|
+
h3("p", { class: "absolute-voice-delivery-runtime__description" }, model.description),
|
|
1098
|
+
h3("ul", { class: "absolute-voice-delivery-runtime__surfaces" }, model.surfaces.map((surface) => h3("li", {
|
|
731
1099
|
class: [
|
|
732
1100
|
"absolute-voice-delivery-runtime__surface",
|
|
733
1101
|
`absolute-voice-delivery-runtime__surface--${surface.status}`
|
|
734
1102
|
],
|
|
735
1103
|
key: surface.id
|
|
736
1104
|
}, [
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
1105
|
+
h3("span", surface.label),
|
|
1106
|
+
h3("strong", surface.detail),
|
|
1107
|
+
h3("small", `${surface.failed} failed / ${surface.deadLettered} dead-lettered`)
|
|
740
1108
|
]))),
|
|
741
|
-
props.includeActions ?
|
|
742
|
-
|
|
1109
|
+
props.includeActions ? h3("div", { class: "absolute-voice-delivery-runtime__actions" }, [
|
|
1110
|
+
h3("button", {
|
|
743
1111
|
disabled: model.actionStatus === "running",
|
|
744
1112
|
onClick: () => {
|
|
745
1113
|
runtime.tick().catch(() => {});
|
|
746
1114
|
},
|
|
747
1115
|
type: "button"
|
|
748
1116
|
}, model.actionStatus === "running" ? "Working..." : "Tick workers"),
|
|
749
|
-
|
|
1117
|
+
h3("button", {
|
|
750
1118
|
disabled: model.actionStatus === "running" || !hasDeadLetters,
|
|
751
1119
|
onClick: () => {
|
|
752
1120
|
runtime.requeueDeadLetters().catch(() => {});
|
|
@@ -754,14 +1122,14 @@ var VoiceDeliveryRuntime = defineComponent2({
|
|
|
754
1122
|
type: "button"
|
|
755
1123
|
}, "Requeue dead letters")
|
|
756
1124
|
]) : null,
|
|
757
|
-
model.actionError ?
|
|
758
|
-
model.error ?
|
|
1125
|
+
model.actionError ? h3("p", { class: "absolute-voice-delivery-runtime__error" }, model.actionError) : null,
|
|
1126
|
+
model.error ? h3("p", { class: "absolute-voice-delivery-runtime__error" }, model.error) : null
|
|
759
1127
|
]);
|
|
760
1128
|
};
|
|
761
1129
|
}
|
|
762
1130
|
});
|
|
763
1131
|
// src/vue/VoiceProviderSimulationControls.ts
|
|
764
|
-
import { computed, defineComponent as
|
|
1132
|
+
import { computed, defineComponent as defineComponent4, h as h4 } from "vue";
|
|
765
1133
|
|
|
766
1134
|
// src/client/providerSimulationControls.ts
|
|
767
1135
|
var postSimulation = async (pathPrefix, mode, provider, fetchImpl) => {
|
|
@@ -843,7 +1211,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
843
1211
|
};
|
|
844
1212
|
|
|
845
1213
|
// src/client/providerSimulationControlsWidget.ts
|
|
846
|
-
var
|
|
1214
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
847
1215
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
848
1216
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
849
1217
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -863,18 +1231,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
863
1231
|
};
|
|
864
1232
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
865
1233
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
866
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
867
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
1234
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml4(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml4(provider.provider)} ${escapeHtml4(formatKind(options.kind))} failure</button>`).join("");
|
|
1235
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml4(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml4(provider.provider)} recovered</button>`).join("");
|
|
868
1236
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
869
1237
|
<header class="absolute-voice-provider-simulation__header">
|
|
870
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
871
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
1238
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml4(model.title)}</span>
|
|
1239
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml4(model.label)}</strong>
|
|
872
1240
|
</header>
|
|
873
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
874
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
1241
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml4(model.description)}</p>
|
|
1242
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml4(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
875
1243
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
876
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
877
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
1244
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml4(snapshot.error)}</p>` : ""}
|
|
1245
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml4(model.resultText)}</pre>` : ""}
|
|
878
1246
|
</section>`;
|
|
879
1247
|
};
|
|
880
1248
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -940,15 +1308,15 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
940
1308
|
};
|
|
941
1309
|
|
|
942
1310
|
// src/vue/useVoiceProviderSimulationControls.ts
|
|
943
|
-
import { onUnmounted as
|
|
1311
|
+
import { onUnmounted as onUnmounted4, ref as ref4 } from "vue";
|
|
944
1312
|
function useVoiceProviderSimulationControls(options) {
|
|
945
1313
|
const store = createVoiceProviderSimulationControlsStore(options);
|
|
946
|
-
const error =
|
|
947
|
-
const isRunning =
|
|
948
|
-
const lastResult =
|
|
949
|
-
const mode =
|
|
950
|
-
const provider =
|
|
951
|
-
const updatedAt =
|
|
1314
|
+
const error = ref4(null);
|
|
1315
|
+
const isRunning = ref4(false);
|
|
1316
|
+
const lastResult = ref4(null);
|
|
1317
|
+
const mode = ref4(null);
|
|
1318
|
+
const provider = ref4(null);
|
|
1319
|
+
const updatedAt = ref4(undefined);
|
|
952
1320
|
const sync = () => {
|
|
953
1321
|
const snapshot = store.getSnapshot();
|
|
954
1322
|
error.value = snapshot.error;
|
|
@@ -960,7 +1328,7 @@ function useVoiceProviderSimulationControls(options) {
|
|
|
960
1328
|
};
|
|
961
1329
|
const unsubscribe = store.subscribe(sync);
|
|
962
1330
|
sync();
|
|
963
|
-
|
|
1331
|
+
onUnmounted4(() => {
|
|
964
1332
|
unsubscribe();
|
|
965
1333
|
store.close();
|
|
966
1334
|
});
|
|
@@ -976,7 +1344,7 @@ function useVoiceProviderSimulationControls(options) {
|
|
|
976
1344
|
}
|
|
977
1345
|
|
|
978
1346
|
// src/vue/VoiceProviderSimulationControls.ts
|
|
979
|
-
var VoiceProviderSimulationControls =
|
|
1347
|
+
var VoiceProviderSimulationControls = defineComponent4({
|
|
980
1348
|
name: "VoiceProviderSimulationControls",
|
|
981
1349
|
props: {
|
|
982
1350
|
class: { default: "", type: String },
|
|
@@ -1018,40 +1386,40 @@ var VoiceProviderSimulationControls = defineComponent3({
|
|
|
1018
1386
|
const run = (provider, mode) => {
|
|
1019
1387
|
controls.run(provider, mode).catch(() => {});
|
|
1020
1388
|
};
|
|
1021
|
-
return () =>
|
|
1389
|
+
return () => h4("section", {
|
|
1022
1390
|
class: [
|
|
1023
1391
|
"absolute-voice-provider-simulation",
|
|
1024
1392
|
`absolute-voice-provider-simulation--${controls.error.value ? "error" : controls.isRunning.value ? "running" : "ready"}`,
|
|
1025
1393
|
props.class
|
|
1026
1394
|
]
|
|
1027
1395
|
}, [
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1396
|
+
h4("header", { class: "absolute-voice-provider-simulation__header" }, [
|
|
1397
|
+
h4("span", { class: "absolute-voice-provider-simulation__eyebrow" }, model.value.title),
|
|
1398
|
+
h4("strong", { class: "absolute-voice-provider-simulation__label" }, model.value.label)
|
|
1031
1399
|
]),
|
|
1032
|
-
|
|
1033
|
-
model.value.canSimulateFailure ? null :
|
|
1034
|
-
|
|
1035
|
-
...model.value.failureProviders.map((provider) =>
|
|
1400
|
+
h4("p", { class: "absolute-voice-provider-simulation__description" }, model.value.description),
|
|
1401
|
+
model.value.canSimulateFailure ? null : h4("p", { class: "absolute-voice-provider-simulation__empty" }, props.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure."),
|
|
1402
|
+
h4("div", { class: "absolute-voice-provider-simulation__actions" }, [
|
|
1403
|
+
...model.value.failureProviders.map((provider) => h4("button", {
|
|
1036
1404
|
disabled: !model.value.canSimulateFailure || controls.isRunning.value,
|
|
1037
1405
|
key: `fail-${provider.provider}`,
|
|
1038
1406
|
onClick: () => run(provider.provider, "failure"),
|
|
1039
1407
|
type: "button"
|
|
1040
1408
|
}, `Simulate ${provider.provider} ${props.kind.toUpperCase()} failure`)),
|
|
1041
|
-
...model.value.providers.map((provider) =>
|
|
1409
|
+
...model.value.providers.map((provider) => h4("button", {
|
|
1042
1410
|
disabled: controls.isRunning.value,
|
|
1043
1411
|
key: `recover-${provider.provider}`,
|
|
1044
1412
|
onClick: () => run(provider.provider, "recovery"),
|
|
1045
1413
|
type: "button"
|
|
1046
1414
|
}, `Mark ${provider.provider} recovered`))
|
|
1047
1415
|
]),
|
|
1048
|
-
controls.error.value ?
|
|
1049
|
-
model.value.resultText ?
|
|
1416
|
+
controls.error.value ? h4("p", { class: "absolute-voice-provider-simulation__error" }, controls.error.value) : null,
|
|
1417
|
+
model.value.resultText ? h4("pre", { class: "absolute-voice-provider-simulation__result" }, model.value.resultText) : null
|
|
1050
1418
|
]);
|
|
1051
1419
|
}
|
|
1052
1420
|
});
|
|
1053
1421
|
// src/vue/VoiceProviderCapabilities.ts
|
|
1054
|
-
import { computed as computed2, defineComponent as
|
|
1422
|
+
import { computed as computed2, defineComponent as defineComponent5, h as h5 } from "vue";
|
|
1055
1423
|
|
|
1056
1424
|
// src/client/providerCapabilities.ts
|
|
1057
1425
|
var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
|
|
@@ -1133,9 +1501,9 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
|
|
|
1133
1501
|
};
|
|
1134
1502
|
|
|
1135
1503
|
// src/client/providerCapabilitiesWidget.ts
|
|
1136
|
-
var
|
|
1137
|
-
var
|
|
1138
|
-
var
|
|
1504
|
+
var DEFAULT_TITLE4 = "Provider Capabilities";
|
|
1505
|
+
var DEFAULT_DESCRIPTION4 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
1506
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1139
1507
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1140
1508
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
1141
1509
|
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -1179,36 +1547,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
1179
1547
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
1180
1548
|
return {
|
|
1181
1549
|
capabilities,
|
|
1182
|
-
description: options.description ??
|
|
1550
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
1183
1551
|
error: snapshot.error,
|
|
1184
1552
|
isLoading: snapshot.isLoading,
|
|
1185
1553
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
1186
1554
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1187
|
-
title: options.title ??
|
|
1555
|
+
title: options.title ?? DEFAULT_TITLE4,
|
|
1188
1556
|
updatedAt: snapshot.updatedAt
|
|
1189
1557
|
};
|
|
1190
1558
|
};
|
|
1191
1559
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
1192
1560
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
1193
|
-
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--${
|
|
1561
|
+
const capabilities = model.capabilities.length ? `<div class="absolute-voice-provider-capabilities__providers">${model.capabilities.map((capability) => `<article class="absolute-voice-provider-capabilities__provider absolute-voice-provider-capabilities__provider--${escapeHtml5(capability.status)}">
|
|
1194
1562
|
<header>
|
|
1195
|
-
<strong>${
|
|
1196
|
-
<span>${
|
|
1563
|
+
<strong>${escapeHtml5(capability.label)}</strong>
|
|
1564
|
+
<span>${escapeHtml5(formatStatus(capability.status))}</span>
|
|
1197
1565
|
</header>
|
|
1198
|
-
<p>${
|
|
1566
|
+
<p>${escapeHtml5(capability.detail)}</p>
|
|
1199
1567
|
<dl>${capability.rows.map((row) => `<div>
|
|
1200
|
-
<dt>${
|
|
1201
|
-
<dd>${
|
|
1568
|
+
<dt>${escapeHtml5(row.label)}</dt>
|
|
1569
|
+
<dd>${escapeHtml5(row.value)}</dd>
|
|
1202
1570
|
</div>`).join("")}</dl>
|
|
1203
1571
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
1204
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
1572
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml5(model.status)}">
|
|
1205
1573
|
<header class="absolute-voice-provider-capabilities__header">
|
|
1206
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
1207
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
1574
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml5(model.title)}</span>
|
|
1575
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml5(model.label)}</strong>
|
|
1208
1576
|
</header>
|
|
1209
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
1577
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml5(model.description)}</p>
|
|
1210
1578
|
${capabilities}
|
|
1211
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
1579
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
1212
1580
|
</section>`;
|
|
1213
1581
|
};
|
|
1214
1582
|
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}`;
|
|
@@ -1250,13 +1618,13 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
1250
1618
|
};
|
|
1251
1619
|
|
|
1252
1620
|
// src/vue/useVoiceProviderCapabilities.ts
|
|
1253
|
-
import { onUnmounted as
|
|
1621
|
+
import { onUnmounted as onUnmounted5, shallowRef as shallowRef4 } from "vue";
|
|
1254
1622
|
function useVoiceProviderCapabilities(path = "/api/provider-capabilities", options = {}) {
|
|
1255
1623
|
const store = createVoiceProviderCapabilitiesStore(path, options);
|
|
1256
|
-
const error =
|
|
1257
|
-
const isLoading =
|
|
1258
|
-
const report =
|
|
1259
|
-
const updatedAt =
|
|
1624
|
+
const error = shallowRef4(null);
|
|
1625
|
+
const isLoading = shallowRef4(false);
|
|
1626
|
+
const report = shallowRef4();
|
|
1627
|
+
const updatedAt = shallowRef4(undefined);
|
|
1260
1628
|
const sync = () => {
|
|
1261
1629
|
const snapshot = store.getSnapshot();
|
|
1262
1630
|
error.value = snapshot.error;
|
|
@@ -1267,7 +1635,7 @@ function useVoiceProviderCapabilities(path = "/api/provider-capabilities", optio
|
|
|
1267
1635
|
const unsubscribe = store.subscribe(sync);
|
|
1268
1636
|
sync();
|
|
1269
1637
|
store.refresh().catch(() => {});
|
|
1270
|
-
|
|
1638
|
+
onUnmounted5(() => {
|
|
1271
1639
|
unsubscribe();
|
|
1272
1640
|
store.close();
|
|
1273
1641
|
});
|
|
@@ -1281,7 +1649,7 @@ function useVoiceProviderCapabilities(path = "/api/provider-capabilities", optio
|
|
|
1281
1649
|
}
|
|
1282
1650
|
|
|
1283
1651
|
// src/vue/VoiceProviderCapabilities.ts
|
|
1284
|
-
var VoiceProviderCapabilities =
|
|
1652
|
+
var VoiceProviderCapabilities = defineComponent5({
|
|
1285
1653
|
name: "VoiceProviderCapabilities",
|
|
1286
1654
|
props: {
|
|
1287
1655
|
class: {
|
|
@@ -1318,41 +1686,41 @@ var VoiceProviderCapabilities = defineComponent4({
|
|
|
1318
1686
|
report: capabilities.report.value,
|
|
1319
1687
|
updatedAt: capabilities.updatedAt.value
|
|
1320
1688
|
}, options));
|
|
1321
|
-
return () =>
|
|
1689
|
+
return () => h5("section", {
|
|
1322
1690
|
class: [
|
|
1323
1691
|
"absolute-voice-provider-capabilities",
|
|
1324
1692
|
`absolute-voice-provider-capabilities--${model.value.status}`,
|
|
1325
1693
|
props.class
|
|
1326
1694
|
]
|
|
1327
1695
|
}, [
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1696
|
+
h5("header", { class: "absolute-voice-provider-capabilities__header" }, [
|
|
1697
|
+
h5("span", { class: "absolute-voice-provider-capabilities__eyebrow" }, model.value.title),
|
|
1698
|
+
h5("strong", { class: "absolute-voice-provider-capabilities__label" }, model.value.label)
|
|
1331
1699
|
]),
|
|
1332
|
-
|
|
1333
|
-
model.value.capabilities.length ?
|
|
1700
|
+
h5("p", { class: "absolute-voice-provider-capabilities__description" }, model.value.description),
|
|
1701
|
+
model.value.capabilities.length ? h5("div", { class: "absolute-voice-provider-capabilities__providers" }, model.value.capabilities.map((capability) => h5("article", {
|
|
1334
1702
|
class: [
|
|
1335
1703
|
"absolute-voice-provider-capabilities__provider",
|
|
1336
1704
|
`absolute-voice-provider-capabilities__provider--${capability.status}`
|
|
1337
1705
|
],
|
|
1338
1706
|
key: `${capability.kind}:${capability.provider}`
|
|
1339
1707
|
}, [
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1708
|
+
h5("header", [
|
|
1709
|
+
h5("strong", capability.label),
|
|
1710
|
+
h5("span", capability.status)
|
|
1343
1711
|
]),
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1712
|
+
h5("p", capability.detail),
|
|
1713
|
+
h5("dl", capability.rows.map((row) => h5("div", { key: row.label }, [
|
|
1714
|
+
h5("dt", row.label),
|
|
1715
|
+
h5("dd", row.value)
|
|
1348
1716
|
])))
|
|
1349
|
-
]))) :
|
|
1350
|
-
model.value.error ?
|
|
1717
|
+
]))) : h5("p", { class: "absolute-voice-provider-capabilities__empty" }, "Configure provider capabilities to see deployment coverage."),
|
|
1718
|
+
model.value.error ? h5("p", { class: "absolute-voice-provider-capabilities__error" }, model.value.error) : null
|
|
1351
1719
|
]);
|
|
1352
1720
|
}
|
|
1353
1721
|
});
|
|
1354
1722
|
// src/vue/VoiceProviderStatus.ts
|
|
1355
|
-
import { computed as computed3, defineComponent as
|
|
1723
|
+
import { computed as computed3, defineComponent as defineComponent6, h as h6 } from "vue";
|
|
1356
1724
|
|
|
1357
1725
|
// src/client/providerStatus.ts
|
|
1358
1726
|
var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
|
|
@@ -1435,9 +1803,9 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
1435
1803
|
};
|
|
1436
1804
|
|
|
1437
1805
|
// src/client/providerStatusWidget.ts
|
|
1438
|
-
var
|
|
1439
|
-
var
|
|
1440
|
-
var
|
|
1806
|
+
var DEFAULT_TITLE5 = "Voice Providers";
|
|
1807
|
+
var DEFAULT_DESCRIPTION5 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
1808
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1441
1809
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1442
1810
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
1443
1811
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -1481,37 +1849,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
1481
1849
|
const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
|
|
1482
1850
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
1483
1851
|
return {
|
|
1484
|
-
description: options.description ??
|
|
1852
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
1485
1853
|
error: snapshot.error,
|
|
1486
1854
|
isLoading: snapshot.isLoading,
|
|
1487
1855
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
1488
1856
|
providers,
|
|
1489
1857
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1490
|
-
title: options.title ??
|
|
1858
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
1491
1859
|
updatedAt: snapshot.updatedAt
|
|
1492
1860
|
};
|
|
1493
1861
|
};
|
|
1494
1862
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
1495
1863
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
1496
|
-
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--${
|
|
1864
|
+
const providers = model.providers.length ? `<div class="absolute-voice-provider-status__providers">${model.providers.map((provider) => `<article class="absolute-voice-provider-status__provider absolute-voice-provider-status__provider--${escapeHtml6(provider.status)}">
|
|
1497
1865
|
<header>
|
|
1498
|
-
<strong>${
|
|
1499
|
-
<span>${
|
|
1866
|
+
<strong>${escapeHtml6(provider.label)}</strong>
|
|
1867
|
+
<span>${escapeHtml6(formatStatus2(provider.status))}</span>
|
|
1500
1868
|
</header>
|
|
1501
|
-
<p>${
|
|
1869
|
+
<p>${escapeHtml6(provider.detail)}</p>
|
|
1502
1870
|
<dl>${provider.rows.map((row) => `<div>
|
|
1503
|
-
<dt>${
|
|
1504
|
-
<dd>${
|
|
1871
|
+
<dt>${escapeHtml6(row.label)}</dt>
|
|
1872
|
+
<dd>${escapeHtml6(row.value)}</dd>
|
|
1505
1873
|
</div>`).join("")}</dl>
|
|
1506
1874
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
1507
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
1875
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml6(model.status)}">
|
|
1508
1876
|
<header class="absolute-voice-provider-status__header">
|
|
1509
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
1510
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
1877
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml6(model.title)}</span>
|
|
1878
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml6(model.label)}</strong>
|
|
1511
1879
|
</header>
|
|
1512
|
-
<p class="absolute-voice-provider-status__description">${
|
|
1880
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml6(model.description)}</p>
|
|
1513
1881
|
${providers}
|
|
1514
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
1882
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
1515
1883
|
</section>`;
|
|
1516
1884
|
};
|
|
1517
1885
|
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}`;
|
|
@@ -1553,13 +1921,13 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
1553
1921
|
};
|
|
1554
1922
|
|
|
1555
1923
|
// src/vue/useVoiceProviderStatus.ts
|
|
1556
|
-
import { onUnmounted as
|
|
1924
|
+
import { onUnmounted as onUnmounted6, ref as ref5, shallowRef as shallowRef5 } from "vue";
|
|
1557
1925
|
function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
|
|
1558
1926
|
const store = createVoiceProviderStatusStore(path, options);
|
|
1559
|
-
const error =
|
|
1560
|
-
const isLoading =
|
|
1561
|
-
const providers =
|
|
1562
|
-
const updatedAt =
|
|
1927
|
+
const error = ref5(null);
|
|
1928
|
+
const isLoading = ref5(false);
|
|
1929
|
+
const providers = shallowRef5([]);
|
|
1930
|
+
const updatedAt = ref5(undefined);
|
|
1563
1931
|
const sync = () => {
|
|
1564
1932
|
const snapshot = store.getSnapshot();
|
|
1565
1933
|
error.value = snapshot.error;
|
|
@@ -1570,7 +1938,7 @@ function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
|
|
|
1570
1938
|
const unsubscribe = store.subscribe(sync);
|
|
1571
1939
|
sync();
|
|
1572
1940
|
store.refresh().catch(() => {});
|
|
1573
|
-
|
|
1941
|
+
onUnmounted6(() => {
|
|
1574
1942
|
unsubscribe();
|
|
1575
1943
|
store.close();
|
|
1576
1944
|
});
|
|
@@ -1584,7 +1952,7 @@ function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
|
|
|
1584
1952
|
}
|
|
1585
1953
|
|
|
1586
1954
|
// src/vue/VoiceProviderStatus.ts
|
|
1587
|
-
var VoiceProviderStatus =
|
|
1955
|
+
var VoiceProviderStatus = defineComponent6({
|
|
1588
1956
|
name: "VoiceProviderStatus",
|
|
1589
1957
|
props: {
|
|
1590
1958
|
class: {
|
|
@@ -1621,41 +1989,41 @@ var VoiceProviderStatus = defineComponent5({
|
|
|
1621
1989
|
providers: status.providers.value,
|
|
1622
1990
|
updatedAt: status.updatedAt.value
|
|
1623
1991
|
}, options));
|
|
1624
|
-
return () =>
|
|
1992
|
+
return () => h6("section", {
|
|
1625
1993
|
class: [
|
|
1626
1994
|
"absolute-voice-provider-status",
|
|
1627
1995
|
`absolute-voice-provider-status--${model.value.status}`,
|
|
1628
1996
|
props.class
|
|
1629
1997
|
]
|
|
1630
1998
|
}, [
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1999
|
+
h6("header", { class: "absolute-voice-provider-status__header" }, [
|
|
2000
|
+
h6("span", { class: "absolute-voice-provider-status__eyebrow" }, model.value.title),
|
|
2001
|
+
h6("strong", { class: "absolute-voice-provider-status__label" }, model.value.label)
|
|
1634
2002
|
]),
|
|
1635
|
-
|
|
1636
|
-
model.value.providers.length ?
|
|
2003
|
+
h6("p", { class: "absolute-voice-provider-status__description" }, model.value.description),
|
|
2004
|
+
model.value.providers.length ? h6("div", { class: "absolute-voice-provider-status__providers" }, model.value.providers.map((provider) => h6("article", {
|
|
1637
2005
|
class: [
|
|
1638
2006
|
"absolute-voice-provider-status__provider",
|
|
1639
2007
|
`absolute-voice-provider-status__provider--${provider.status}`
|
|
1640
2008
|
],
|
|
1641
2009
|
key: provider.provider
|
|
1642
2010
|
}, [
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
2011
|
+
h6("header", [
|
|
2012
|
+
h6("strong", provider.label),
|
|
2013
|
+
h6("span", provider.status)
|
|
1646
2014
|
]),
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
2015
|
+
h6("p", provider.detail),
|
|
2016
|
+
h6("dl", provider.rows.map((row) => h6("div", { key: row.label }, [
|
|
2017
|
+
h6("dt", row.label),
|
|
2018
|
+
h6("dd", row.value)
|
|
1651
2019
|
])))
|
|
1652
|
-
]))) :
|
|
1653
|
-
model.value.error ?
|
|
2020
|
+
]))) : h6("p", { class: "absolute-voice-provider-status__empty" }, "Run voice traffic to see provider health."),
|
|
2021
|
+
model.value.error ? h6("p", { class: "absolute-voice-provider-status__error" }, model.value.error) : null
|
|
1654
2022
|
]);
|
|
1655
2023
|
}
|
|
1656
2024
|
});
|
|
1657
2025
|
// src/vue/VoiceRoutingStatus.ts
|
|
1658
|
-
import { computed as computed4, defineComponent as
|
|
2026
|
+
import { computed as computed4, defineComponent as defineComponent7, h as h7 } from "vue";
|
|
1659
2027
|
|
|
1660
2028
|
// src/client/routingStatus.ts
|
|
1661
2029
|
var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
|
|
@@ -1738,9 +2106,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
1738
2106
|
};
|
|
1739
2107
|
|
|
1740
2108
|
// src/client/routingStatusWidget.ts
|
|
1741
|
-
var
|
|
1742
|
-
var
|
|
1743
|
-
var
|
|
2109
|
+
var DEFAULT_TITLE6 = "Voice Routing";
|
|
2110
|
+
var DEFAULT_DESCRIPTION6 = "Latest provider routing decision from the self-hosted trace store.";
|
|
2111
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1744
2112
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
1745
2113
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
1746
2114
|
const decision = snapshot.decision;
|
|
@@ -1764,30 +2132,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
1764
2132
|
] : [];
|
|
1765
2133
|
return {
|
|
1766
2134
|
decision,
|
|
1767
|
-
description: options.description ??
|
|
2135
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
1768
2136
|
error: snapshot.error,
|
|
1769
2137
|
isLoading: snapshot.isLoading,
|
|
1770
2138
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
1771
2139
|
rows,
|
|
1772
2140
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1773
|
-
title: options.title ??
|
|
2141
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
1774
2142
|
updatedAt: snapshot.updatedAt
|
|
1775
2143
|
};
|
|
1776
2144
|
};
|
|
1777
2145
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
1778
2146
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
1779
2147
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
1780
|
-
<span>${
|
|
1781
|
-
<strong>${
|
|
2148
|
+
<span>${escapeHtml7(row.label)}</span>
|
|
2149
|
+
<strong>${escapeHtml7(row.value)}</strong>
|
|
1782
2150
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
1783
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
2151
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml7(model.status)}">
|
|
1784
2152
|
<header class="absolute-voice-routing-status__header">
|
|
1785
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
1786
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
2153
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml7(model.title)}</span>
|
|
2154
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml7(model.label)}</strong>
|
|
1787
2155
|
</header>
|
|
1788
|
-
<p class="absolute-voice-routing-status__description">${
|
|
2156
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml7(model.description)}</p>
|
|
1789
2157
|
${rows}
|
|
1790
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
2158
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
1791
2159
|
</section>`;
|
|
1792
2160
|
};
|
|
1793
2161
|
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}`;
|
|
@@ -1829,13 +2197,13 @@ var defineVoiceRoutingStatusElement = (tagName = "absolute-voice-routing-status"
|
|
|
1829
2197
|
};
|
|
1830
2198
|
|
|
1831
2199
|
// src/vue/useVoiceRoutingStatus.ts
|
|
1832
|
-
import { onUnmounted as
|
|
2200
|
+
import { onUnmounted as onUnmounted7, ref as ref6, shallowRef as shallowRef6 } from "vue";
|
|
1833
2201
|
function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
|
|
1834
2202
|
const store = createVoiceRoutingStatusStore(path, options);
|
|
1835
|
-
const decision =
|
|
1836
|
-
const error =
|
|
1837
|
-
const isLoading =
|
|
1838
|
-
const updatedAt =
|
|
2203
|
+
const decision = shallowRef6(null);
|
|
2204
|
+
const error = ref6(null);
|
|
2205
|
+
const isLoading = ref6(false);
|
|
2206
|
+
const updatedAt = ref6(undefined);
|
|
1839
2207
|
const sync = () => {
|
|
1840
2208
|
const snapshot = store.getSnapshot();
|
|
1841
2209
|
decision.value = snapshot.decision;
|
|
@@ -1846,7 +2214,7 @@ function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
|
|
|
1846
2214
|
const unsubscribe = store.subscribe(sync);
|
|
1847
2215
|
sync();
|
|
1848
2216
|
store.refresh().catch(() => {});
|
|
1849
|
-
|
|
2217
|
+
onUnmounted7(() => {
|
|
1850
2218
|
unsubscribe();
|
|
1851
2219
|
store.close();
|
|
1852
2220
|
});
|
|
@@ -1860,7 +2228,7 @@ function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
|
|
|
1860
2228
|
}
|
|
1861
2229
|
|
|
1862
2230
|
// src/vue/VoiceRoutingStatus.ts
|
|
1863
|
-
var VoiceRoutingStatus =
|
|
2231
|
+
var VoiceRoutingStatus = defineComponent7({
|
|
1864
2232
|
name: "VoiceRoutingStatus",
|
|
1865
2233
|
props: {
|
|
1866
2234
|
class: {
|
|
@@ -1897,28 +2265,28 @@ var VoiceRoutingStatus = defineComponent6({
|
|
|
1897
2265
|
isLoading: status.isLoading.value,
|
|
1898
2266
|
updatedAt: status.updatedAt.value
|
|
1899
2267
|
}, options));
|
|
1900
|
-
return () =>
|
|
2268
|
+
return () => h7("section", {
|
|
1901
2269
|
class: [
|
|
1902
2270
|
"absolute-voice-routing-status",
|
|
1903
2271
|
`absolute-voice-routing-status--${model.value.status}`,
|
|
1904
2272
|
props.class
|
|
1905
2273
|
]
|
|
1906
2274
|
}, [
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
2275
|
+
h7("header", { class: "absolute-voice-routing-status__header" }, [
|
|
2276
|
+
h7("span", { class: "absolute-voice-routing-status__eyebrow" }, model.value.title),
|
|
2277
|
+
h7("strong", { class: "absolute-voice-routing-status__label" }, model.value.label)
|
|
1910
2278
|
]),
|
|
1911
|
-
|
|
1912
|
-
model.value.rows.length ?
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
]))) :
|
|
1916
|
-
model.value.error ?
|
|
2279
|
+
h7("p", { class: "absolute-voice-routing-status__description" }, model.value.description),
|
|
2280
|
+
model.value.rows.length ? h7("div", { class: "absolute-voice-routing-status__grid" }, model.value.rows.map((row) => h7("div", { key: row.label }, [
|
|
2281
|
+
h7("span", row.label),
|
|
2282
|
+
h7("strong", row.value)
|
|
2283
|
+
]))) : h7("p", { class: "absolute-voice-routing-status__empty" }, "Start a voice session to see the selected provider."),
|
|
2284
|
+
model.value.error ? h7("p", { class: "absolute-voice-routing-status__error" }, model.value.error) : null
|
|
1917
2285
|
]);
|
|
1918
2286
|
}
|
|
1919
2287
|
});
|
|
1920
2288
|
// src/vue/VoiceTurnLatency.ts
|
|
1921
|
-
import { computed as computed5, defineComponent as
|
|
2289
|
+
import { computed as computed5, defineComponent as defineComponent8, h as h8 } from "vue";
|
|
1922
2290
|
|
|
1923
2291
|
// src/client/turnLatency.ts
|
|
1924
2292
|
var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
|
|
@@ -2024,10 +2392,10 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
|
|
|
2024
2392
|
};
|
|
2025
2393
|
|
|
2026
2394
|
// src/client/turnLatencyWidget.ts
|
|
2027
|
-
var
|
|
2028
|
-
var
|
|
2395
|
+
var DEFAULT_TITLE7 = "Turn Latency";
|
|
2396
|
+
var DEFAULT_DESCRIPTION7 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
2029
2397
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
2030
|
-
var
|
|
2398
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2031
2399
|
var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
2032
2400
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
2033
2401
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -2041,39 +2409,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
2041
2409
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2042
2410
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2043
2411
|
return {
|
|
2044
|
-
description: options.description ??
|
|
2412
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
2045
2413
|
error: snapshot.error,
|
|
2046
2414
|
isLoading: snapshot.isLoading,
|
|
2047
2415
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
2048
2416
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
2049
2417
|
showProofAction: Boolean(options.proofPath),
|
|
2050
2418
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2051
|
-
title: options.title ??
|
|
2419
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
2052
2420
|
turns,
|
|
2053
2421
|
updatedAt: snapshot.updatedAt
|
|
2054
2422
|
};
|
|
2055
2423
|
};
|
|
2056
2424
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
2057
2425
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
2058
|
-
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--${
|
|
2426
|
+
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)}">
|
|
2059
2427
|
<header>
|
|
2060
|
-
<strong>${
|
|
2061
|
-
<span>${
|
|
2428
|
+
<strong>${escapeHtml8(turn.label)}</strong>
|
|
2429
|
+
<span>${escapeHtml8(turn.status)}</span>
|
|
2062
2430
|
</header>
|
|
2063
2431
|
<dl>${turn.rows.map((row) => `<div>
|
|
2064
|
-
<dt>${
|
|
2065
|
-
<dd>${
|
|
2432
|
+
<dt>${escapeHtml8(row.label)}</dt>
|
|
2433
|
+
<dd>${escapeHtml8(row.value)}</dd>
|
|
2066
2434
|
</div>`).join("")}</dl>
|
|
2067
2435
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
2068
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
2436
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml8(model.status)}">
|
|
2069
2437
|
<header class="absolute-voice-turn-latency__header">
|
|
2070
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
2071
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
2438
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml8(model.title)}</span>
|
|
2439
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml8(model.label)}</strong>
|
|
2072
2440
|
</header>
|
|
2073
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
2074
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
2441
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml8(model.description)}</p>
|
|
2442
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml8(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
2075
2443
|
${turns}
|
|
2076
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
2444
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
2077
2445
|
</section>`;
|
|
2078
2446
|
};
|
|
2079
2447
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -2124,13 +2492,13 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
2124
2492
|
};
|
|
2125
2493
|
|
|
2126
2494
|
// src/vue/useVoiceTurnLatency.ts
|
|
2127
|
-
import { onUnmounted as
|
|
2495
|
+
import { onUnmounted as onUnmounted8, shallowRef as shallowRef7 } from "vue";
|
|
2128
2496
|
function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
|
|
2129
2497
|
const store = createVoiceTurnLatencyStore(path, options);
|
|
2130
|
-
const error =
|
|
2131
|
-
const isLoading =
|
|
2132
|
-
const report =
|
|
2133
|
-
const updatedAt =
|
|
2498
|
+
const error = shallowRef7(null);
|
|
2499
|
+
const isLoading = shallowRef7(false);
|
|
2500
|
+
const report = shallowRef7();
|
|
2501
|
+
const updatedAt = shallowRef7(undefined);
|
|
2134
2502
|
const sync = () => {
|
|
2135
2503
|
const snapshot = store.getSnapshot();
|
|
2136
2504
|
error.value = snapshot.error;
|
|
@@ -2141,7 +2509,7 @@ function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
|
|
|
2141
2509
|
const unsubscribe = store.subscribe(sync);
|
|
2142
2510
|
sync();
|
|
2143
2511
|
store.refresh().catch(() => {});
|
|
2144
|
-
|
|
2512
|
+
onUnmounted8(() => {
|
|
2145
2513
|
unsubscribe();
|
|
2146
2514
|
store.close();
|
|
2147
2515
|
});
|
|
@@ -2156,7 +2524,7 @@ function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
|
|
|
2156
2524
|
}
|
|
2157
2525
|
|
|
2158
2526
|
// src/vue/VoiceTurnLatency.ts
|
|
2159
|
-
var VoiceTurnLatency =
|
|
2527
|
+
var VoiceTurnLatency = defineComponent8({
|
|
2160
2528
|
name: "VoiceTurnLatency",
|
|
2161
2529
|
props: {
|
|
2162
2530
|
class: { default: "", type: String },
|
|
@@ -2182,47 +2550,47 @@ var VoiceTurnLatency = defineComponent7({
|
|
|
2182
2550
|
report: latency.report.value,
|
|
2183
2551
|
updatedAt: latency.updatedAt.value
|
|
2184
2552
|
}, options));
|
|
2185
|
-
return () =>
|
|
2553
|
+
return () => h8("section", {
|
|
2186
2554
|
class: [
|
|
2187
2555
|
"absolute-voice-turn-latency",
|
|
2188
2556
|
`absolute-voice-turn-latency--${model.value.status}`,
|
|
2189
2557
|
props.class
|
|
2190
2558
|
]
|
|
2191
2559
|
}, [
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2560
|
+
h8("header", { class: "absolute-voice-turn-latency__header" }, [
|
|
2561
|
+
h8("span", { class: "absolute-voice-turn-latency__eyebrow" }, model.value.title),
|
|
2562
|
+
h8("strong", { class: "absolute-voice-turn-latency__label" }, model.value.label)
|
|
2195
2563
|
]),
|
|
2196
|
-
|
|
2197
|
-
model.value.showProofAction ?
|
|
2564
|
+
h8("p", { class: "absolute-voice-turn-latency__description" }, model.value.description),
|
|
2565
|
+
model.value.showProofAction ? h8("button", {
|
|
2198
2566
|
class: "absolute-voice-turn-latency__proof",
|
|
2199
2567
|
onClick: () => {
|
|
2200
2568
|
latency.runProof().catch(() => {});
|
|
2201
2569
|
},
|
|
2202
2570
|
type: "button"
|
|
2203
2571
|
}, model.value.proofLabel) : null,
|
|
2204
|
-
model.value.turns.length ?
|
|
2572
|
+
model.value.turns.length ? h8("div", { class: "absolute-voice-turn-latency__turns" }, model.value.turns.map((turn) => h8("article", {
|
|
2205
2573
|
class: [
|
|
2206
2574
|
"absolute-voice-turn-latency__turn",
|
|
2207
2575
|
`absolute-voice-turn-latency__turn--${turn.status}`
|
|
2208
2576
|
],
|
|
2209
2577
|
key: `${turn.sessionId}:${turn.turnId}`
|
|
2210
2578
|
}, [
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2579
|
+
h8("header", [
|
|
2580
|
+
h8("strong", turn.label),
|
|
2581
|
+
h8("span", turn.status)
|
|
2214
2582
|
]),
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2583
|
+
h8("dl", turn.rows.map((row) => h8("div", { key: row.label }, [
|
|
2584
|
+
h8("dt", row.label),
|
|
2585
|
+
h8("dd", row.value)
|
|
2218
2586
|
])))
|
|
2219
|
-
]))) :
|
|
2220
|
-
model.value.error ?
|
|
2587
|
+
]))) : h8("p", { class: "absolute-voice-turn-latency__empty" }, "Complete a voice turn to see latency diagnostics."),
|
|
2588
|
+
model.value.error ? h8("p", { class: "absolute-voice-turn-latency__error" }, model.value.error) : null
|
|
2221
2589
|
]);
|
|
2222
2590
|
}
|
|
2223
2591
|
});
|
|
2224
2592
|
// src/vue/VoiceTurnQuality.ts
|
|
2225
|
-
import { computed as computed6, defineComponent as
|
|
2593
|
+
import { computed as computed6, defineComponent as defineComponent9, h as h9 } from "vue";
|
|
2226
2594
|
|
|
2227
2595
|
// src/client/turnQuality.ts
|
|
2228
2596
|
var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
|
|
@@ -2304,9 +2672,9 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
|
|
|
2304
2672
|
};
|
|
2305
2673
|
|
|
2306
2674
|
// src/client/turnQualityWidget.ts
|
|
2307
|
-
var
|
|
2308
|
-
var
|
|
2309
|
-
var
|
|
2675
|
+
var DEFAULT_TITLE8 = "Turn Quality";
|
|
2676
|
+
var DEFAULT_DESCRIPTION8 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
2677
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2310
2678
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
2311
2679
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
2312
2680
|
var getTurnDetail = (turn) => {
|
|
@@ -2344,37 +2712,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
2344
2712
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2345
2713
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2346
2714
|
return {
|
|
2347
|
-
description: options.description ??
|
|
2715
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
2348
2716
|
error: snapshot.error,
|
|
2349
2717
|
isLoading: snapshot.isLoading,
|
|
2350
2718
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
2351
2719
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2352
|
-
title: options.title ??
|
|
2720
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
2353
2721
|
turns,
|
|
2354
2722
|
updatedAt: snapshot.updatedAt
|
|
2355
2723
|
};
|
|
2356
2724
|
};
|
|
2357
2725
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
2358
2726
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
2359
|
-
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--${
|
|
2727
|
+
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)}">
|
|
2360
2728
|
<header>
|
|
2361
|
-
<strong>${
|
|
2362
|
-
<span>${
|
|
2729
|
+
<strong>${escapeHtml9(turn.label)}</strong>
|
|
2730
|
+
<span>${escapeHtml9(turn.status)}</span>
|
|
2363
2731
|
</header>
|
|
2364
|
-
<p>${
|
|
2732
|
+
<p>${escapeHtml9(turn.detail)}</p>
|
|
2365
2733
|
<dl>${turn.rows.map((row) => `<div>
|
|
2366
|
-
<dt>${
|
|
2367
|
-
<dd>${
|
|
2734
|
+
<dt>${escapeHtml9(row.label)}</dt>
|
|
2735
|
+
<dd>${escapeHtml9(row.value)}</dd>
|
|
2368
2736
|
</div>`).join("")}</dl>
|
|
2369
2737
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
2370
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
2738
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml9(model.status)}">
|
|
2371
2739
|
<header class="absolute-voice-turn-quality__header">
|
|
2372
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
2373
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
2740
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml9(model.title)}</span>
|
|
2741
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml9(model.label)}</strong>
|
|
2374
2742
|
</header>
|
|
2375
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
2743
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml9(model.description)}</p>
|
|
2376
2744
|
${turns}
|
|
2377
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
2745
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
2378
2746
|
</section>`;
|
|
2379
2747
|
};
|
|
2380
2748
|
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}`;
|
|
@@ -2416,13 +2784,13 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
2416
2784
|
};
|
|
2417
2785
|
|
|
2418
2786
|
// src/vue/useVoiceTurnQuality.ts
|
|
2419
|
-
import { onUnmounted as
|
|
2787
|
+
import { onUnmounted as onUnmounted9, shallowRef as shallowRef8 } from "vue";
|
|
2420
2788
|
function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
|
|
2421
2789
|
const store = createVoiceTurnQualityStore(path, options);
|
|
2422
|
-
const error =
|
|
2423
|
-
const isLoading =
|
|
2424
|
-
const report =
|
|
2425
|
-
const updatedAt =
|
|
2790
|
+
const error = shallowRef8(null);
|
|
2791
|
+
const isLoading = shallowRef8(false);
|
|
2792
|
+
const report = shallowRef8();
|
|
2793
|
+
const updatedAt = shallowRef8(undefined);
|
|
2426
2794
|
const sync = () => {
|
|
2427
2795
|
const snapshot = store.getSnapshot();
|
|
2428
2796
|
error.value = snapshot.error;
|
|
@@ -2433,7 +2801,7 @@ function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
|
|
|
2433
2801
|
const unsubscribe = store.subscribe(sync);
|
|
2434
2802
|
sync();
|
|
2435
2803
|
store.refresh().catch(() => {});
|
|
2436
|
-
|
|
2804
|
+
onUnmounted9(() => {
|
|
2437
2805
|
unsubscribe();
|
|
2438
2806
|
store.close();
|
|
2439
2807
|
});
|
|
@@ -2441,7 +2809,7 @@ function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
|
|
|
2441
2809
|
}
|
|
2442
2810
|
|
|
2443
2811
|
// src/vue/VoiceTurnQuality.ts
|
|
2444
|
-
var VoiceTurnQuality =
|
|
2812
|
+
var VoiceTurnQuality = defineComponent9({
|
|
2445
2813
|
name: "VoiceTurnQuality",
|
|
2446
2814
|
props: {
|
|
2447
2815
|
class: { default: "", type: String },
|
|
@@ -2463,41 +2831,41 @@ var VoiceTurnQuality = defineComponent8({
|
|
|
2463
2831
|
report: quality.report.value,
|
|
2464
2832
|
updatedAt: quality.updatedAt.value
|
|
2465
2833
|
}, options));
|
|
2466
|
-
return () =>
|
|
2834
|
+
return () => h9("section", {
|
|
2467
2835
|
class: [
|
|
2468
2836
|
"absolute-voice-turn-quality",
|
|
2469
2837
|
`absolute-voice-turn-quality--${model.value.status}`,
|
|
2470
2838
|
props.class
|
|
2471
2839
|
]
|
|
2472
2840
|
}, [
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2841
|
+
h9("header", { class: "absolute-voice-turn-quality__header" }, [
|
|
2842
|
+
h9("span", { class: "absolute-voice-turn-quality__eyebrow" }, model.value.title),
|
|
2843
|
+
h9("strong", { class: "absolute-voice-turn-quality__label" }, model.value.label)
|
|
2476
2844
|
]),
|
|
2477
|
-
|
|
2478
|
-
model.value.turns.length ?
|
|
2845
|
+
h9("p", { class: "absolute-voice-turn-quality__description" }, model.value.description),
|
|
2846
|
+
model.value.turns.length ? h9("div", { class: "absolute-voice-turn-quality__turns" }, model.value.turns.map((turn) => h9("article", {
|
|
2479
2847
|
class: [
|
|
2480
2848
|
"absolute-voice-turn-quality__turn",
|
|
2481
2849
|
`absolute-voice-turn-quality__turn--${turn.status}`
|
|
2482
2850
|
],
|
|
2483
2851
|
key: `${turn.sessionId}:${turn.turnId}`
|
|
2484
2852
|
}, [
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2853
|
+
h9("header", [
|
|
2854
|
+
h9("strong", turn.label),
|
|
2855
|
+
h9("span", turn.status)
|
|
2488
2856
|
]),
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2857
|
+
h9("p", turn.detail),
|
|
2858
|
+
h9("dl", turn.rows.map((row) => h9("div", { key: row.label }, [
|
|
2859
|
+
h9("dt", row.label),
|
|
2860
|
+
h9("dd", row.value)
|
|
2493
2861
|
])))
|
|
2494
|
-
]))) :
|
|
2495
|
-
model.value.error ?
|
|
2862
|
+
]))) : h9("p", { class: "absolute-voice-turn-quality__empty" }, "Complete a voice turn to see STT quality diagnostics."),
|
|
2863
|
+
model.value.error ? h9("p", { class: "absolute-voice-turn-quality__error" }, model.value.error) : null
|
|
2496
2864
|
]);
|
|
2497
2865
|
}
|
|
2498
2866
|
});
|
|
2499
2867
|
// src/vue/useVoiceCampaignDialerProof.ts
|
|
2500
|
-
import { onUnmounted as
|
|
2868
|
+
import { onUnmounted as onUnmounted10, shallowRef as shallowRef9 } from "vue";
|
|
2501
2869
|
|
|
2502
2870
|
// src/client/campaignDialerProof.ts
|
|
2503
2871
|
var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
|
|
@@ -2620,11 +2988,11 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
|
|
|
2620
2988
|
// src/vue/useVoiceCampaignDialerProof.ts
|
|
2621
2989
|
function useVoiceCampaignDialerProof(path = "/api/voice/campaigns/dialer-proof", options = {}) {
|
|
2622
2990
|
const store = createVoiceCampaignDialerProofStore(path, options);
|
|
2623
|
-
const error =
|
|
2624
|
-
const isLoading =
|
|
2625
|
-
const report =
|
|
2626
|
-
const status =
|
|
2627
|
-
const updatedAt =
|
|
2991
|
+
const error = shallowRef9(null);
|
|
2992
|
+
const isLoading = shallowRef9(false);
|
|
2993
|
+
const report = shallowRef9();
|
|
2994
|
+
const status = shallowRef9();
|
|
2995
|
+
const updatedAt = shallowRef9(undefined);
|
|
2628
2996
|
const sync = () => {
|
|
2629
2997
|
const snapshot = store.getSnapshot();
|
|
2630
2998
|
error.value = snapshot.error;
|
|
@@ -2638,7 +3006,7 @@ function useVoiceCampaignDialerProof(path = "/api/voice/campaigns/dialer-proof",
|
|
|
2638
3006
|
if (typeof window !== "undefined") {
|
|
2639
3007
|
store.refresh().catch(() => {});
|
|
2640
3008
|
}
|
|
2641
|
-
|
|
3009
|
+
onUnmounted10(() => {
|
|
2642
3010
|
unsubscribe();
|
|
2643
3011
|
store.close();
|
|
2644
3012
|
});
|
|
@@ -2653,7 +3021,7 @@ function useVoiceCampaignDialerProof(path = "/api/voice/campaigns/dialer-proof",
|
|
|
2653
3021
|
};
|
|
2654
3022
|
}
|
|
2655
3023
|
// src/vue/useVoiceStream.ts
|
|
2656
|
-
import { onUnmounted as
|
|
3024
|
+
import { onUnmounted as onUnmounted11, ref as ref7, shallowRef as shallowRef10 } from "vue";
|
|
2657
3025
|
|
|
2658
3026
|
// src/client/actions.ts
|
|
2659
3027
|
var normalizeErrorMessage = (value) => {
|
|
@@ -3298,16 +3666,16 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
3298
3666
|
// src/vue/useVoiceStream.ts
|
|
3299
3667
|
function useVoiceStream(path, options = {}) {
|
|
3300
3668
|
const stream = createVoiceStream(path, options);
|
|
3301
|
-
const assistantAudio =
|
|
3302
|
-
const assistantTexts =
|
|
3303
|
-
const call =
|
|
3304
|
-
const error =
|
|
3305
|
-
const isConnected =
|
|
3306
|
-
const partial =
|
|
3307
|
-
const reconnect =
|
|
3308
|
-
const sessionId =
|
|
3309
|
-
const status =
|
|
3310
|
-
const turns =
|
|
3669
|
+
const assistantAudio = shallowRef10([]);
|
|
3670
|
+
const assistantTexts = shallowRef10([]);
|
|
3671
|
+
const call = shallowRef10(null);
|
|
3672
|
+
const error = ref7(null);
|
|
3673
|
+
const isConnected = ref7(false);
|
|
3674
|
+
const partial = ref7("");
|
|
3675
|
+
const reconnect = shallowRef10(stream.reconnect);
|
|
3676
|
+
const sessionId = ref7(stream.sessionId);
|
|
3677
|
+
const status = ref7(stream.status);
|
|
3678
|
+
const turns = shallowRef10([]);
|
|
3311
3679
|
const sync = () => {
|
|
3312
3680
|
assistantAudio.value = [...stream.assistantAudio];
|
|
3313
3681
|
assistantTexts.value = [...stream.assistantTexts];
|
|
@@ -3326,7 +3694,7 @@ function useVoiceStream(path, options = {}) {
|
|
|
3326
3694
|
unsubscribe();
|
|
3327
3695
|
stream.close();
|
|
3328
3696
|
};
|
|
3329
|
-
|
|
3697
|
+
onUnmounted11(destroy);
|
|
3330
3698
|
return {
|
|
3331
3699
|
assistantAudio,
|
|
3332
3700
|
assistantTexts,
|
|
@@ -3345,7 +3713,7 @@ function useVoiceStream(path, options = {}) {
|
|
|
3345
3713
|
};
|
|
3346
3714
|
}
|
|
3347
3715
|
// src/vue/useVoiceController.ts
|
|
3348
|
-
import { onUnmounted as
|
|
3716
|
+
import { onUnmounted as onUnmounted12, ref as ref8, shallowRef as shallowRef11 } from "vue";
|
|
3349
3717
|
|
|
3350
3718
|
// src/client/htmx.ts
|
|
3351
3719
|
var DEFAULT_EVENT_NAME = "voice-refresh";
|
|
@@ -3991,17 +4359,17 @@ var createVoiceController = (path, options = {}) => {
|
|
|
3991
4359
|
// src/vue/useVoiceController.ts
|
|
3992
4360
|
function useVoiceController(path, options = {}) {
|
|
3993
4361
|
const controller = createVoiceController(path, options);
|
|
3994
|
-
const assistantAudio =
|
|
3995
|
-
const assistantTexts =
|
|
3996
|
-
const error =
|
|
3997
|
-
const isConnected =
|
|
3998
|
-
const isRecording =
|
|
3999
|
-
const partial =
|
|
4000
|
-
const reconnect =
|
|
4001
|
-
const recordingError =
|
|
4002
|
-
const sessionId =
|
|
4003
|
-
const status =
|
|
4004
|
-
const turns =
|
|
4362
|
+
const assistantAudio = shallowRef11([]);
|
|
4363
|
+
const assistantTexts = shallowRef11([]);
|
|
4364
|
+
const error = ref8(null);
|
|
4365
|
+
const isConnected = ref8(false);
|
|
4366
|
+
const isRecording = ref8(false);
|
|
4367
|
+
const partial = ref8("");
|
|
4368
|
+
const reconnect = shallowRef11(controller.reconnect);
|
|
4369
|
+
const recordingError = ref8(null);
|
|
4370
|
+
const sessionId = ref8(controller.sessionId);
|
|
4371
|
+
const status = ref8(controller.status);
|
|
4372
|
+
const turns = shallowRef11([]);
|
|
4005
4373
|
const sync = () => {
|
|
4006
4374
|
assistantAudio.value = [...controller.assistantAudio];
|
|
4007
4375
|
assistantTexts.value = [...controller.assistantTexts];
|
|
@@ -4021,7 +4389,7 @@ function useVoiceController(path, options = {}) {
|
|
|
4021
4389
|
unsubscribe();
|
|
4022
4390
|
controller.close();
|
|
4023
4391
|
};
|
|
4024
|
-
|
|
4392
|
+
onUnmounted12(destroy);
|
|
4025
4393
|
return {
|
|
4026
4394
|
assistantAudio,
|
|
4027
4395
|
assistantTexts,
|
|
@@ -4044,7 +4412,7 @@ function useVoiceController(path, options = {}) {
|
|
|
4044
4412
|
};
|
|
4045
4413
|
}
|
|
4046
4414
|
// src/vue/useVoiceTraceTimeline.ts
|
|
4047
|
-
import { onUnmounted as
|
|
4415
|
+
import { onUnmounted as onUnmounted13, ref as ref9, shallowRef as shallowRef12 } from "vue";
|
|
4048
4416
|
|
|
4049
4417
|
// src/client/traceTimeline.ts
|
|
4050
4418
|
var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
|
|
@@ -4129,10 +4497,10 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
|
|
|
4129
4497
|
// src/vue/useVoiceTraceTimeline.ts
|
|
4130
4498
|
function useVoiceTraceTimeline(path = "/api/voice-traces", options = {}) {
|
|
4131
4499
|
const store = createVoiceTraceTimelineStore(path, options);
|
|
4132
|
-
const error =
|
|
4133
|
-
const isLoading =
|
|
4134
|
-
const report =
|
|
4135
|
-
const updatedAt =
|
|
4500
|
+
const error = ref9(null);
|
|
4501
|
+
const isLoading = ref9(false);
|
|
4502
|
+
const report = shallowRef12(null);
|
|
4503
|
+
const updatedAt = ref9(undefined);
|
|
4136
4504
|
const sync = () => {
|
|
4137
4505
|
const snapshot = store.getSnapshot();
|
|
4138
4506
|
error.value = snapshot.error;
|
|
@@ -4143,7 +4511,7 @@ function useVoiceTraceTimeline(path = "/api/voice-traces", options = {}) {
|
|
|
4143
4511
|
const unsubscribe = store.subscribe(sync);
|
|
4144
4512
|
sync();
|
|
4145
4513
|
store.refresh().catch(() => {});
|
|
4146
|
-
|
|
4514
|
+
onUnmounted13(() => {
|
|
4147
4515
|
unsubscribe();
|
|
4148
4516
|
store.close();
|
|
4149
4517
|
});
|
|
@@ -4156,7 +4524,7 @@ function useVoiceTraceTimeline(path = "/api/voice-traces", options = {}) {
|
|
|
4156
4524
|
};
|
|
4157
4525
|
}
|
|
4158
4526
|
// src/vue/useVoiceWorkflowStatus.ts
|
|
4159
|
-
import { onUnmounted as
|
|
4527
|
+
import { onUnmounted as onUnmounted14, ref as ref10, shallowRef as shallowRef13 } from "vue";
|
|
4160
4528
|
|
|
4161
4529
|
// src/client/workflowStatus.ts
|
|
4162
4530
|
var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
|
|
@@ -4240,10 +4608,10 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
|
|
|
4240
4608
|
// src/vue/useVoiceWorkflowStatus.ts
|
|
4241
4609
|
function useVoiceWorkflowStatus(path = "/evals/scenarios/json", options = {}) {
|
|
4242
4610
|
const store = createVoiceWorkflowStatusStore(path, options);
|
|
4243
|
-
const error =
|
|
4244
|
-
const isLoading =
|
|
4245
|
-
const report =
|
|
4246
|
-
const updatedAt =
|
|
4611
|
+
const error = ref10(null);
|
|
4612
|
+
const isLoading = ref10(false);
|
|
4613
|
+
const report = shallowRef13(undefined);
|
|
4614
|
+
const updatedAt = ref10(undefined);
|
|
4247
4615
|
const sync = () => {
|
|
4248
4616
|
const snapshot = store.getSnapshot();
|
|
4249
4617
|
error.value = snapshot.error;
|
|
@@ -4256,7 +4624,7 @@ function useVoiceWorkflowStatus(path = "/evals/scenarios/json", options = {}) {
|
|
|
4256
4624
|
if (typeof window !== "undefined") {
|
|
4257
4625
|
store.refresh().catch(() => {});
|
|
4258
4626
|
}
|
|
4259
|
-
|
|
4627
|
+
onUnmounted14(() => {
|
|
4260
4628
|
unsubscribe();
|
|
4261
4629
|
store.close();
|
|
4262
4630
|
});
|
|
@@ -4279,6 +4647,7 @@ export {
|
|
|
4279
4647
|
useVoiceProviderSimulationControls,
|
|
4280
4648
|
useVoiceProviderCapabilities,
|
|
4281
4649
|
useVoiceOpsStatus,
|
|
4650
|
+
useVoiceOpsActionCenter,
|
|
4282
4651
|
useVoiceDeliveryRuntime,
|
|
4283
4652
|
useVoiceController,
|
|
4284
4653
|
useVoiceCampaignDialerProof,
|
|
@@ -4289,5 +4658,6 @@ export {
|
|
|
4289
4658
|
VoiceProviderSimulationControls,
|
|
4290
4659
|
VoiceProviderCapabilities,
|
|
4291
4660
|
VoiceOpsStatus,
|
|
4661
|
+
VoiceOpsActionCenter,
|
|
4292
4662
|
VoiceDeliveryRuntime
|
|
4293
4663
|
};
|