@absolutejs/voice 0.0.22-beta.153 → 0.0.22-beta.154
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/angular/index.d.ts +1 -0
- package/dist/angular/index.js +349 -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 +370 -114
- package/dist/client/opsActionCenter.d.ts +50 -0
- package/dist/client/opsActionCenterWidget.d.ts +29 -0
- package/dist/react/VoiceOpsActionCenter.d.ts +5 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +611 -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 +378 -114
- package/dist/vue/VoiceOpsActionCenter.d.ts +13 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +639 -298
- package/dist/vue/useVoiceOpsActionCenter.d.ts +11 -0
- package/package.json +1 -1
package/dist/vue/index.js
CHANGED
|
@@ -374,9 +374,348 @@ 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 createVoiceOpsActionCenterActions = (options = {}) => {
|
|
382
|
+
const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
|
|
383
|
+
const actions = [];
|
|
384
|
+
if (options.includeProductionReadiness !== false) {
|
|
385
|
+
actions.push({
|
|
386
|
+
description: "Refresh the production readiness report.",
|
|
387
|
+
id: "production-readiness",
|
|
388
|
+
label: "Refresh readiness",
|
|
389
|
+
method: "GET",
|
|
390
|
+
path: options.productionReadinessPath ?? "/api/production-readiness"
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
if (options.includeDeliveryRuntime !== false) {
|
|
394
|
+
actions.push({
|
|
395
|
+
description: "Drain pending and failed audit/trace deliveries.",
|
|
396
|
+
id: "delivery-runtime.tick",
|
|
397
|
+
label: "Tick delivery workers",
|
|
398
|
+
method: "POST",
|
|
399
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/tick`
|
|
400
|
+
}, {
|
|
401
|
+
description: "Move reviewed dead letters back to live delivery queues.",
|
|
402
|
+
id: "delivery-runtime.requeue-dead-letters",
|
|
403
|
+
label: "Requeue dead letters",
|
|
404
|
+
method: "POST",
|
|
405
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/requeue-dead-letters`
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
if (options.includeTurnLatencyProof !== false) {
|
|
409
|
+
actions.push({
|
|
410
|
+
description: "Run the synthetic turn latency proof.",
|
|
411
|
+
id: "turn-latency.proof",
|
|
412
|
+
label: "Run latency proof",
|
|
413
|
+
method: "POST",
|
|
414
|
+
path: options.turnLatencyProofPath ?? "/api/turn-latency/proof"
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
if (options.includeProviderSimulation !== false) {
|
|
418
|
+
const pathPrefix = options.providerSimulationPathPrefix ?? "/api/stt-simulate";
|
|
419
|
+
for (const provider of options.providers ?? []) {
|
|
420
|
+
actions.push({
|
|
421
|
+
description: `Simulate ${provider} provider failure.`,
|
|
422
|
+
id: `provider.${provider}.failure`,
|
|
423
|
+
label: `Simulate ${provider} failure`,
|
|
424
|
+
method: "POST",
|
|
425
|
+
path: `${pathPrefix}/failure?provider=${encodeURIComponent(provider)}`
|
|
426
|
+
}, {
|
|
427
|
+
description: `Mark ${provider} provider recovered.`,
|
|
428
|
+
id: `provider.${provider}.recovery`,
|
|
429
|
+
label: `Recover ${provider}`,
|
|
430
|
+
method: "POST",
|
|
431
|
+
path: `${pathPrefix}/recovery?provider=${encodeURIComponent(provider)}`
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
return actions;
|
|
436
|
+
};
|
|
437
|
+
var runVoiceOpsAction = async (action, options = {}) => {
|
|
438
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
439
|
+
const response = await fetchImpl(action.path, {
|
|
440
|
+
method: action.method ?? "POST"
|
|
441
|
+
});
|
|
442
|
+
const body = await response.json().catch(() => null);
|
|
443
|
+
if (!response.ok) {
|
|
444
|
+
const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
|
|
445
|
+
throw new Error(message);
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
actionId: action.id,
|
|
449
|
+
body,
|
|
450
|
+
ok: response.ok,
|
|
451
|
+
ranAt: Date.now(),
|
|
452
|
+
status: response.status
|
|
453
|
+
};
|
|
454
|
+
};
|
|
455
|
+
var createVoiceOpsActionCenterStore = (options = {}) => {
|
|
456
|
+
const listeners = new Set;
|
|
457
|
+
let closed = false;
|
|
458
|
+
let timer;
|
|
459
|
+
let snapshot = {
|
|
460
|
+
actions: options.actions ?? createVoiceOpsActionCenterActions(),
|
|
461
|
+
error: null,
|
|
462
|
+
isRunning: false
|
|
463
|
+
};
|
|
464
|
+
const emit = () => {
|
|
465
|
+
for (const listener of listeners) {
|
|
466
|
+
listener();
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
const setActions = (actions) => {
|
|
470
|
+
snapshot = { ...snapshot, actions, updatedAt: Date.now() };
|
|
471
|
+
emit();
|
|
472
|
+
};
|
|
473
|
+
const run = async (actionId) => {
|
|
474
|
+
if (closed) {
|
|
475
|
+
return snapshot.lastResult;
|
|
476
|
+
}
|
|
477
|
+
const action = snapshot.actions.find((item) => item.id === actionId);
|
|
478
|
+
if (!action) {
|
|
479
|
+
throw new Error(`Voice ops action "${actionId}" is not configured.`);
|
|
480
|
+
}
|
|
481
|
+
if (action.disabled) {
|
|
482
|
+
throw new Error(`Voice ops action "${actionId}" is disabled.`);
|
|
483
|
+
}
|
|
484
|
+
snapshot = {
|
|
485
|
+
...snapshot,
|
|
486
|
+
error: null,
|
|
487
|
+
isRunning: true,
|
|
488
|
+
runningActionId: action.id
|
|
489
|
+
};
|
|
490
|
+
emit();
|
|
491
|
+
try {
|
|
492
|
+
const result = await runVoiceOpsAction(action, options);
|
|
493
|
+
snapshot = {
|
|
494
|
+
...snapshot,
|
|
495
|
+
error: null,
|
|
496
|
+
isRunning: false,
|
|
497
|
+
lastResult: result,
|
|
498
|
+
runningActionId: undefined,
|
|
499
|
+
updatedAt: Date.now()
|
|
500
|
+
};
|
|
501
|
+
emit();
|
|
502
|
+
return result;
|
|
503
|
+
} catch (error) {
|
|
504
|
+
snapshot = {
|
|
505
|
+
...snapshot,
|
|
506
|
+
error: error instanceof Error ? error.message : String(error),
|
|
507
|
+
isRunning: false,
|
|
508
|
+
runningActionId: undefined
|
|
509
|
+
};
|
|
510
|
+
emit();
|
|
511
|
+
throw error;
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
const close = () => {
|
|
515
|
+
closed = true;
|
|
516
|
+
if (timer) {
|
|
517
|
+
clearInterval(timer);
|
|
518
|
+
timer = undefined;
|
|
519
|
+
}
|
|
520
|
+
listeners.clear();
|
|
521
|
+
};
|
|
522
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
523
|
+
timer = setInterval(() => {
|
|
524
|
+
emit();
|
|
525
|
+
}, options.intervalMs);
|
|
526
|
+
}
|
|
527
|
+
return {
|
|
528
|
+
close,
|
|
529
|
+
getServerSnapshot: () => snapshot,
|
|
530
|
+
getSnapshot: () => snapshot,
|
|
531
|
+
run,
|
|
532
|
+
setActions,
|
|
533
|
+
subscribe: (listener) => {
|
|
534
|
+
listeners.add(listener);
|
|
535
|
+
return () => {
|
|
536
|
+
listeners.delete(listener);
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
// src/client/opsActionCenterWidget.ts
|
|
543
|
+
var DEFAULT_TITLE2 = "Voice Ops Action Center";
|
|
544
|
+
var DEFAULT_DESCRIPTION2 = "Run production voice proofs and operator actions from one primitive panel.";
|
|
545
|
+
var escapeHtml2 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
546
|
+
var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
547
|
+
const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
|
|
548
|
+
return {
|
|
549
|
+
actions: snapshot.actions.map((action) => ({
|
|
550
|
+
description: action.description ?? "",
|
|
551
|
+
disabled: Boolean(action.disabled || snapshot.isRunning),
|
|
552
|
+
id: action.id,
|
|
553
|
+
isRunning: snapshot.runningActionId === action.id,
|
|
554
|
+
label: action.label
|
|
555
|
+
})),
|
|
556
|
+
description: options.description ?? DEFAULT_DESCRIPTION2,
|
|
557
|
+
error: snapshot.error,
|
|
558
|
+
isRunning: snapshot.isRunning,
|
|
559
|
+
label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
|
|
560
|
+
lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
|
|
561
|
+
status,
|
|
562
|
+
title: options.title ?? DEFAULT_TITLE2
|
|
563
|
+
};
|
|
564
|
+
};
|
|
565
|
+
var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
|
|
566
|
+
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
567
|
+
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml2(action.id)}"${action.disabled ? " disabled" : ""}>
|
|
568
|
+
${escapeHtml2(action.isRunning ? "Working..." : action.label)}
|
|
569
|
+
</button>`).join("");
|
|
570
|
+
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml2(model.status)}">
|
|
571
|
+
<header class="absolute-voice-ops-action-center__header">
|
|
572
|
+
<span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml2(model.title)}</span>
|
|
573
|
+
<strong class="absolute-voice-ops-action-center__label">${escapeHtml2(model.label)}</strong>
|
|
574
|
+
</header>
|
|
575
|
+
<p class="absolute-voice-ops-action-center__description">${escapeHtml2(model.description)}</p>
|
|
576
|
+
<div class="absolute-voice-ops-action-center__actions">${actions}</div>
|
|
577
|
+
<p class="absolute-voice-ops-action-center__result">${escapeHtml2(model.lastResultLabel)}</p>
|
|
578
|
+
${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml2(model.error)}</p>` : ""}
|
|
579
|
+
</section>`;
|
|
580
|
+
};
|
|
581
|
+
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}`;
|
|
582
|
+
var mountVoiceOpsActionCenter = (element, options = {}) => {
|
|
583
|
+
const store = createVoiceOpsActionCenterStore(options);
|
|
584
|
+
const render = () => {
|
|
585
|
+
element.innerHTML = renderVoiceOpsActionCenterHTML(store.getSnapshot(), options);
|
|
586
|
+
};
|
|
587
|
+
const unsubscribe = store.subscribe(render);
|
|
588
|
+
const handleClick = (event) => {
|
|
589
|
+
const target = event.target;
|
|
590
|
+
if (!(target instanceof Element)) {
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
const action = target.closest("[data-absolute-voice-ops-action]");
|
|
594
|
+
const actionId = action?.getAttribute("data-absolute-voice-ops-action");
|
|
595
|
+
if (actionId) {
|
|
596
|
+
store.run(actionId).catch(() => {});
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
element.addEventListener?.("click", handleClick);
|
|
600
|
+
render();
|
|
601
|
+
return {
|
|
602
|
+
close: () => {
|
|
603
|
+
element.removeEventListener?.("click", handleClick);
|
|
604
|
+
unsubscribe();
|
|
605
|
+
store.close();
|
|
606
|
+
},
|
|
607
|
+
run: store.run
|
|
608
|
+
};
|
|
609
|
+
};
|
|
610
|
+
var defineVoiceOpsActionCenterElement = (tagName = "absolute-voice-ops-action-center", options = {}) => {
|
|
611
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
customElements.define(tagName, class AbsoluteVoiceOpsActionCenterElement extends HTMLElement {
|
|
615
|
+
mounted;
|
|
616
|
+
connectedCallback() {
|
|
617
|
+
this.mounted = mountVoiceOpsActionCenter(this, {
|
|
618
|
+
...options,
|
|
619
|
+
description: this.getAttribute("description") ?? options.description,
|
|
620
|
+
title: this.getAttribute("title") ?? options.title
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
disconnectedCallback() {
|
|
624
|
+
this.mounted?.close();
|
|
625
|
+
this.mounted = undefined;
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
// src/vue/useVoiceOpsActionCenter.ts
|
|
631
|
+
import { onUnmounted as onUnmounted2, ref as ref2, shallowRef as shallowRef2 } from "vue";
|
|
632
|
+
function useVoiceOpsActionCenter(options = {}) {
|
|
633
|
+
const store = createVoiceOpsActionCenterStore(options);
|
|
634
|
+
const actions = shallowRef2([]);
|
|
635
|
+
const error = ref2(null);
|
|
636
|
+
const isRunning = ref2(false);
|
|
637
|
+
const lastResult = shallowRef2(undefined);
|
|
638
|
+
const runningActionId = ref2(undefined);
|
|
639
|
+
const updatedAt = ref2(undefined);
|
|
640
|
+
const sync = () => {
|
|
641
|
+
const snapshot = store.getSnapshot();
|
|
642
|
+
actions.value = snapshot.actions;
|
|
643
|
+
error.value = snapshot.error;
|
|
644
|
+
isRunning.value = snapshot.isRunning;
|
|
645
|
+
lastResult.value = snapshot.lastResult;
|
|
646
|
+
runningActionId.value = snapshot.runningActionId;
|
|
647
|
+
updatedAt.value = snapshot.updatedAt;
|
|
648
|
+
};
|
|
649
|
+
const unsubscribe = store.subscribe(sync);
|
|
650
|
+
sync();
|
|
651
|
+
onUnmounted2(() => {
|
|
652
|
+
unsubscribe();
|
|
653
|
+
store.close();
|
|
654
|
+
});
|
|
655
|
+
return {
|
|
656
|
+
actions,
|
|
657
|
+
error,
|
|
658
|
+
isRunning,
|
|
659
|
+
lastResult,
|
|
660
|
+
run: store.run,
|
|
661
|
+
runningActionId,
|
|
662
|
+
setActions: store.setActions,
|
|
663
|
+
updatedAt
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// src/vue/VoiceOpsActionCenter.ts
|
|
668
|
+
var VoiceOpsActionCenter = defineComponent2({
|
|
669
|
+
name: "VoiceOpsActionCenter",
|
|
670
|
+
props: {
|
|
671
|
+
actions: Array,
|
|
672
|
+
description: String,
|
|
673
|
+
title: String
|
|
674
|
+
},
|
|
675
|
+
setup(props) {
|
|
676
|
+
const options = {
|
|
677
|
+
actions: props.actions,
|
|
678
|
+
description: props.description,
|
|
679
|
+
title: props.title
|
|
680
|
+
};
|
|
681
|
+
const center = useVoiceOpsActionCenter(options);
|
|
682
|
+
return () => {
|
|
683
|
+
const model = createVoiceOpsActionCenterViewModel({
|
|
684
|
+
actions: center.actions.value,
|
|
685
|
+
error: center.error.value,
|
|
686
|
+
isRunning: center.isRunning.value,
|
|
687
|
+
lastResult: center.lastResult.value,
|
|
688
|
+
runningActionId: center.runningActionId.value,
|
|
689
|
+
updatedAt: center.updatedAt.value
|
|
690
|
+
}, options);
|
|
691
|
+
return h2("section", {
|
|
692
|
+
class: [
|
|
693
|
+
"absolute-voice-ops-action-center",
|
|
694
|
+
`absolute-voice-ops-action-center--${model.status}`
|
|
695
|
+
]
|
|
696
|
+
}, [
|
|
697
|
+
h2("header", { class: "absolute-voice-ops-action-center__header" }, [
|
|
698
|
+
h2("span", { class: "absolute-voice-ops-action-center__eyebrow" }, model.title),
|
|
699
|
+
h2("strong", { class: "absolute-voice-ops-action-center__label" }, model.label)
|
|
700
|
+
]),
|
|
701
|
+
h2("p", { class: "absolute-voice-ops-action-center__description" }, model.description),
|
|
702
|
+
h2("div", { class: "absolute-voice-ops-action-center__actions" }, model.actions.map((action) => h2("button", {
|
|
703
|
+
disabled: action.disabled,
|
|
704
|
+
key: action.id,
|
|
705
|
+
onClick: () => {
|
|
706
|
+
center.run(action.id).catch(() => {});
|
|
707
|
+
},
|
|
708
|
+
type: "button"
|
|
709
|
+
}, action.isRunning ? "Working..." : action.label))),
|
|
710
|
+
h2("p", { class: "absolute-voice-ops-action-center__result" }, model.lastResultLabel),
|
|
711
|
+
model.error ? h2("p", { class: "absolute-voice-ops-action-center__error" }, model.error) : null
|
|
712
|
+
]);
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
// src/vue/VoiceDeliveryRuntime.ts
|
|
717
|
+
import { defineComponent as defineComponent3, h as h3 } from "vue";
|
|
718
|
+
|
|
380
719
|
// src/client/deliveryRuntime.ts
|
|
381
720
|
var getDefaultActionPath = (path, action, options) => {
|
|
382
721
|
if (action === "tick") {
|
|
@@ -515,9 +854,9 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
|
|
|
515
854
|
};
|
|
516
855
|
|
|
517
856
|
// src/client/deliveryRuntimeWidget.ts
|
|
518
|
-
var
|
|
519
|
-
var
|
|
520
|
-
var
|
|
857
|
+
var DEFAULT_TITLE3 = "Voice Delivery Runtime";
|
|
858
|
+
var DEFAULT_DESCRIPTION3 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
859
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
521
860
|
var createSurface = (id, summary) => {
|
|
522
861
|
if (!summary) {
|
|
523
862
|
return {
|
|
@@ -551,7 +890,7 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
551
890
|
];
|
|
552
891
|
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
553
892
|
return {
|
|
554
|
-
description: options.description ??
|
|
893
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
555
894
|
error: snapshot.error,
|
|
556
895
|
actionError: snapshot.actionError,
|
|
557
896
|
actionStatus: snapshot.actionStatus,
|
|
@@ -560,32 +899,32 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
560
899
|
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
561
900
|
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
562
901
|
surfaces,
|
|
563
|
-
title: options.title ??
|
|
902
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
564
903
|
updatedAt: snapshot.updatedAt
|
|
565
904
|
};
|
|
566
905
|
};
|
|
567
906
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
568
907
|
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>${
|
|
908
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml3(surface.status)}">
|
|
909
|
+
<span>${escapeHtml3(surface.label)}</span>
|
|
910
|
+
<strong>${escapeHtml3(surface.detail)}</strong>
|
|
572
911
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
573
912
|
</li>`).join("");
|
|
574
913
|
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
575
914
|
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
576
915
|
<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
916
|
</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--${
|
|
917
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.actionError)}</p>` : "";
|
|
918
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml3(model.status)}">
|
|
580
919
|
<header class="absolute-voice-delivery-runtime__header">
|
|
581
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
582
|
-
<strong class="absolute-voice-delivery-runtime__label">${
|
|
920
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml3(model.title)}</span>
|
|
921
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml3(model.label)}</strong>
|
|
583
922
|
</header>
|
|
584
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
923
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml3(model.description)}</p>
|
|
585
924
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
586
925
|
${actions}
|
|
587
926
|
${actionError}
|
|
588
|
-
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
927
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.error)}</p>` : ""}
|
|
589
928
|
</section>`;
|
|
590
929
|
};
|
|
591
930
|
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 +982,15 @@ var defineVoiceDeliveryRuntimeElement = (tagName = "absolute-voice-delivery-runt
|
|
|
643
982
|
};
|
|
644
983
|
|
|
645
984
|
// src/vue/useVoiceDeliveryRuntime.ts
|
|
646
|
-
import { onUnmounted as
|
|
985
|
+
import { onUnmounted as onUnmounted3, ref as ref3, shallowRef as shallowRef3 } from "vue";
|
|
647
986
|
function useVoiceDeliveryRuntime(path = "/api/voice-delivery-runtime", options = {}) {
|
|
648
987
|
const store = createVoiceDeliveryRuntimeStore(path, options);
|
|
649
|
-
const actionError =
|
|
650
|
-
const actionStatus =
|
|
651
|
-
const error =
|
|
652
|
-
const isLoading =
|
|
653
|
-
const report =
|
|
654
|
-
const updatedAt =
|
|
988
|
+
const actionError = ref3(null);
|
|
989
|
+
const actionStatus = ref3("idle");
|
|
990
|
+
const error = ref3(null);
|
|
991
|
+
const isLoading = ref3(false);
|
|
992
|
+
const report = shallowRef3(undefined);
|
|
993
|
+
const updatedAt = ref3(undefined);
|
|
655
994
|
const sync = () => {
|
|
656
995
|
const snapshot = store.getSnapshot();
|
|
657
996
|
actionError.value = snapshot.actionError;
|
|
@@ -666,7 +1005,7 @@ function useVoiceDeliveryRuntime(path = "/api/voice-delivery-runtime", options =
|
|
|
666
1005
|
if (typeof window !== "undefined") {
|
|
667
1006
|
store.refresh().catch(() => {});
|
|
668
1007
|
}
|
|
669
|
-
|
|
1008
|
+
onUnmounted3(() => {
|
|
670
1009
|
unsubscribe();
|
|
671
1010
|
store.close();
|
|
672
1011
|
});
|
|
@@ -684,7 +1023,7 @@ function useVoiceDeliveryRuntime(path = "/api/voice-delivery-runtime", options =
|
|
|
684
1023
|
}
|
|
685
1024
|
|
|
686
1025
|
// src/vue/VoiceDeliveryRuntime.ts
|
|
687
|
-
var VoiceDeliveryRuntime =
|
|
1026
|
+
var VoiceDeliveryRuntime = defineComponent3({
|
|
688
1027
|
name: "VoiceDeliveryRuntime",
|
|
689
1028
|
props: {
|
|
690
1029
|
description: String,
|
|
@@ -716,37 +1055,37 @@ var VoiceDeliveryRuntime = defineComponent2({
|
|
|
716
1055
|
updatedAt: runtime.updatedAt.value
|
|
717
1056
|
}, options);
|
|
718
1057
|
const hasDeadLetters = model.surfaces.some((surface) => surface.deadLettered > 0);
|
|
719
|
-
return
|
|
1058
|
+
return h3("section", {
|
|
720
1059
|
class: [
|
|
721
1060
|
"absolute-voice-delivery-runtime",
|
|
722
1061
|
`absolute-voice-delivery-runtime--${model.status}`
|
|
723
1062
|
]
|
|
724
1063
|
}, [
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
1064
|
+
h3("header", { class: "absolute-voice-delivery-runtime__header" }, [
|
|
1065
|
+
h3("span", { class: "absolute-voice-delivery-runtime__eyebrow" }, model.title),
|
|
1066
|
+
h3("strong", { class: "absolute-voice-delivery-runtime__label" }, model.label)
|
|
728
1067
|
]),
|
|
729
|
-
|
|
730
|
-
|
|
1068
|
+
h3("p", { class: "absolute-voice-delivery-runtime__description" }, model.description),
|
|
1069
|
+
h3("ul", { class: "absolute-voice-delivery-runtime__surfaces" }, model.surfaces.map((surface) => h3("li", {
|
|
731
1070
|
class: [
|
|
732
1071
|
"absolute-voice-delivery-runtime__surface",
|
|
733
1072
|
`absolute-voice-delivery-runtime__surface--${surface.status}`
|
|
734
1073
|
],
|
|
735
1074
|
key: surface.id
|
|
736
1075
|
}, [
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
1076
|
+
h3("span", surface.label),
|
|
1077
|
+
h3("strong", surface.detail),
|
|
1078
|
+
h3("small", `${surface.failed} failed / ${surface.deadLettered} dead-lettered`)
|
|
740
1079
|
]))),
|
|
741
|
-
props.includeActions ?
|
|
742
|
-
|
|
1080
|
+
props.includeActions ? h3("div", { class: "absolute-voice-delivery-runtime__actions" }, [
|
|
1081
|
+
h3("button", {
|
|
743
1082
|
disabled: model.actionStatus === "running",
|
|
744
1083
|
onClick: () => {
|
|
745
1084
|
runtime.tick().catch(() => {});
|
|
746
1085
|
},
|
|
747
1086
|
type: "button"
|
|
748
1087
|
}, model.actionStatus === "running" ? "Working..." : "Tick workers"),
|
|
749
|
-
|
|
1088
|
+
h3("button", {
|
|
750
1089
|
disabled: model.actionStatus === "running" || !hasDeadLetters,
|
|
751
1090
|
onClick: () => {
|
|
752
1091
|
runtime.requeueDeadLetters().catch(() => {});
|
|
@@ -754,14 +1093,14 @@ var VoiceDeliveryRuntime = defineComponent2({
|
|
|
754
1093
|
type: "button"
|
|
755
1094
|
}, "Requeue dead letters")
|
|
756
1095
|
]) : null,
|
|
757
|
-
model.actionError ?
|
|
758
|
-
model.error ?
|
|
1096
|
+
model.actionError ? h3("p", { class: "absolute-voice-delivery-runtime__error" }, model.actionError) : null,
|
|
1097
|
+
model.error ? h3("p", { class: "absolute-voice-delivery-runtime__error" }, model.error) : null
|
|
759
1098
|
]);
|
|
760
1099
|
};
|
|
761
1100
|
}
|
|
762
1101
|
});
|
|
763
1102
|
// src/vue/VoiceProviderSimulationControls.ts
|
|
764
|
-
import { computed, defineComponent as
|
|
1103
|
+
import { computed, defineComponent as defineComponent4, h as h4 } from "vue";
|
|
765
1104
|
|
|
766
1105
|
// src/client/providerSimulationControls.ts
|
|
767
1106
|
var postSimulation = async (pathPrefix, mode, provider, fetchImpl) => {
|
|
@@ -843,7 +1182,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
843
1182
|
};
|
|
844
1183
|
|
|
845
1184
|
// src/client/providerSimulationControlsWidget.ts
|
|
846
|
-
var
|
|
1185
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
847
1186
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
848
1187
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
849
1188
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -863,18 +1202,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
863
1202
|
};
|
|
864
1203
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
865
1204
|
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="${
|
|
1205
|
+
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("");
|
|
1206
|
+
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
1207
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
869
1208
|
<header class="absolute-voice-provider-simulation__header">
|
|
870
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
871
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
1209
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml4(model.title)}</span>
|
|
1210
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml4(model.label)}</strong>
|
|
872
1211
|
</header>
|
|
873
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
874
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
1212
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml4(model.description)}</p>
|
|
1213
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml4(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
875
1214
|
<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">${
|
|
1215
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml4(snapshot.error)}</p>` : ""}
|
|
1216
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml4(model.resultText)}</pre>` : ""}
|
|
878
1217
|
</section>`;
|
|
879
1218
|
};
|
|
880
1219
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -940,15 +1279,15 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
940
1279
|
};
|
|
941
1280
|
|
|
942
1281
|
// src/vue/useVoiceProviderSimulationControls.ts
|
|
943
|
-
import { onUnmounted as
|
|
1282
|
+
import { onUnmounted as onUnmounted4, ref as ref4 } from "vue";
|
|
944
1283
|
function useVoiceProviderSimulationControls(options) {
|
|
945
1284
|
const store = createVoiceProviderSimulationControlsStore(options);
|
|
946
|
-
const error =
|
|
947
|
-
const isRunning =
|
|
948
|
-
const lastResult =
|
|
949
|
-
const mode =
|
|
950
|
-
const provider =
|
|
951
|
-
const updatedAt =
|
|
1285
|
+
const error = ref4(null);
|
|
1286
|
+
const isRunning = ref4(false);
|
|
1287
|
+
const lastResult = ref4(null);
|
|
1288
|
+
const mode = ref4(null);
|
|
1289
|
+
const provider = ref4(null);
|
|
1290
|
+
const updatedAt = ref4(undefined);
|
|
952
1291
|
const sync = () => {
|
|
953
1292
|
const snapshot = store.getSnapshot();
|
|
954
1293
|
error.value = snapshot.error;
|
|
@@ -960,7 +1299,7 @@ function useVoiceProviderSimulationControls(options) {
|
|
|
960
1299
|
};
|
|
961
1300
|
const unsubscribe = store.subscribe(sync);
|
|
962
1301
|
sync();
|
|
963
|
-
|
|
1302
|
+
onUnmounted4(() => {
|
|
964
1303
|
unsubscribe();
|
|
965
1304
|
store.close();
|
|
966
1305
|
});
|
|
@@ -976,7 +1315,7 @@ function useVoiceProviderSimulationControls(options) {
|
|
|
976
1315
|
}
|
|
977
1316
|
|
|
978
1317
|
// src/vue/VoiceProviderSimulationControls.ts
|
|
979
|
-
var VoiceProviderSimulationControls =
|
|
1318
|
+
var VoiceProviderSimulationControls = defineComponent4({
|
|
980
1319
|
name: "VoiceProviderSimulationControls",
|
|
981
1320
|
props: {
|
|
982
1321
|
class: { default: "", type: String },
|
|
@@ -1018,40 +1357,40 @@ var VoiceProviderSimulationControls = defineComponent3({
|
|
|
1018
1357
|
const run = (provider, mode) => {
|
|
1019
1358
|
controls.run(provider, mode).catch(() => {});
|
|
1020
1359
|
};
|
|
1021
|
-
return () =>
|
|
1360
|
+
return () => h4("section", {
|
|
1022
1361
|
class: [
|
|
1023
1362
|
"absolute-voice-provider-simulation",
|
|
1024
1363
|
`absolute-voice-provider-simulation--${controls.error.value ? "error" : controls.isRunning.value ? "running" : "ready"}`,
|
|
1025
1364
|
props.class
|
|
1026
1365
|
]
|
|
1027
1366
|
}, [
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1367
|
+
h4("header", { class: "absolute-voice-provider-simulation__header" }, [
|
|
1368
|
+
h4("span", { class: "absolute-voice-provider-simulation__eyebrow" }, model.value.title),
|
|
1369
|
+
h4("strong", { class: "absolute-voice-provider-simulation__label" }, model.value.label)
|
|
1031
1370
|
]),
|
|
1032
|
-
|
|
1033
|
-
model.value.canSimulateFailure ? null :
|
|
1034
|
-
|
|
1035
|
-
...model.value.failureProviders.map((provider) =>
|
|
1371
|
+
h4("p", { class: "absolute-voice-provider-simulation__description" }, model.value.description),
|
|
1372
|
+
model.value.canSimulateFailure ? null : h4("p", { class: "absolute-voice-provider-simulation__empty" }, props.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure."),
|
|
1373
|
+
h4("div", { class: "absolute-voice-provider-simulation__actions" }, [
|
|
1374
|
+
...model.value.failureProviders.map((provider) => h4("button", {
|
|
1036
1375
|
disabled: !model.value.canSimulateFailure || controls.isRunning.value,
|
|
1037
1376
|
key: `fail-${provider.provider}`,
|
|
1038
1377
|
onClick: () => run(provider.provider, "failure"),
|
|
1039
1378
|
type: "button"
|
|
1040
1379
|
}, `Simulate ${provider.provider} ${props.kind.toUpperCase()} failure`)),
|
|
1041
|
-
...model.value.providers.map((provider) =>
|
|
1380
|
+
...model.value.providers.map((provider) => h4("button", {
|
|
1042
1381
|
disabled: controls.isRunning.value,
|
|
1043
1382
|
key: `recover-${provider.provider}`,
|
|
1044
1383
|
onClick: () => run(provider.provider, "recovery"),
|
|
1045
1384
|
type: "button"
|
|
1046
1385
|
}, `Mark ${provider.provider} recovered`))
|
|
1047
1386
|
]),
|
|
1048
|
-
controls.error.value ?
|
|
1049
|
-
model.value.resultText ?
|
|
1387
|
+
controls.error.value ? h4("p", { class: "absolute-voice-provider-simulation__error" }, controls.error.value) : null,
|
|
1388
|
+
model.value.resultText ? h4("pre", { class: "absolute-voice-provider-simulation__result" }, model.value.resultText) : null
|
|
1050
1389
|
]);
|
|
1051
1390
|
}
|
|
1052
1391
|
});
|
|
1053
1392
|
// src/vue/VoiceProviderCapabilities.ts
|
|
1054
|
-
import { computed as computed2, defineComponent as
|
|
1393
|
+
import { computed as computed2, defineComponent as defineComponent5, h as h5 } from "vue";
|
|
1055
1394
|
|
|
1056
1395
|
// src/client/providerCapabilities.ts
|
|
1057
1396
|
var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
|
|
@@ -1133,9 +1472,9 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
|
|
|
1133
1472
|
};
|
|
1134
1473
|
|
|
1135
1474
|
// src/client/providerCapabilitiesWidget.ts
|
|
1136
|
-
var
|
|
1137
|
-
var
|
|
1138
|
-
var
|
|
1475
|
+
var DEFAULT_TITLE4 = "Provider Capabilities";
|
|
1476
|
+
var DEFAULT_DESCRIPTION4 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
1477
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1139
1478
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1140
1479
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
1141
1480
|
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -1179,36 +1518,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
1179
1518
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
1180
1519
|
return {
|
|
1181
1520
|
capabilities,
|
|
1182
|
-
description: options.description ??
|
|
1521
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
1183
1522
|
error: snapshot.error,
|
|
1184
1523
|
isLoading: snapshot.isLoading,
|
|
1185
1524
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
1186
1525
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1187
|
-
title: options.title ??
|
|
1526
|
+
title: options.title ?? DEFAULT_TITLE4,
|
|
1188
1527
|
updatedAt: snapshot.updatedAt
|
|
1189
1528
|
};
|
|
1190
1529
|
};
|
|
1191
1530
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
1192
1531
|
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--${
|
|
1532
|
+
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
1533
|
<header>
|
|
1195
|
-
<strong>${
|
|
1196
|
-
<span>${
|
|
1534
|
+
<strong>${escapeHtml5(capability.label)}</strong>
|
|
1535
|
+
<span>${escapeHtml5(formatStatus(capability.status))}</span>
|
|
1197
1536
|
</header>
|
|
1198
|
-
<p>${
|
|
1537
|
+
<p>${escapeHtml5(capability.detail)}</p>
|
|
1199
1538
|
<dl>${capability.rows.map((row) => `<div>
|
|
1200
|
-
<dt>${
|
|
1201
|
-
<dd>${
|
|
1539
|
+
<dt>${escapeHtml5(row.label)}</dt>
|
|
1540
|
+
<dd>${escapeHtml5(row.value)}</dd>
|
|
1202
1541
|
</div>`).join("")}</dl>
|
|
1203
1542
|
</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--${
|
|
1543
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml5(model.status)}">
|
|
1205
1544
|
<header class="absolute-voice-provider-capabilities__header">
|
|
1206
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
1207
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
1545
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml5(model.title)}</span>
|
|
1546
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml5(model.label)}</strong>
|
|
1208
1547
|
</header>
|
|
1209
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
1548
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml5(model.description)}</p>
|
|
1210
1549
|
${capabilities}
|
|
1211
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
1550
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
1212
1551
|
</section>`;
|
|
1213
1552
|
};
|
|
1214
1553
|
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 +1589,13 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
1250
1589
|
};
|
|
1251
1590
|
|
|
1252
1591
|
// src/vue/useVoiceProviderCapabilities.ts
|
|
1253
|
-
import { onUnmounted as
|
|
1592
|
+
import { onUnmounted as onUnmounted5, shallowRef as shallowRef4 } from "vue";
|
|
1254
1593
|
function useVoiceProviderCapabilities(path = "/api/provider-capabilities", options = {}) {
|
|
1255
1594
|
const store = createVoiceProviderCapabilitiesStore(path, options);
|
|
1256
|
-
const error =
|
|
1257
|
-
const isLoading =
|
|
1258
|
-
const report =
|
|
1259
|
-
const updatedAt =
|
|
1595
|
+
const error = shallowRef4(null);
|
|
1596
|
+
const isLoading = shallowRef4(false);
|
|
1597
|
+
const report = shallowRef4();
|
|
1598
|
+
const updatedAt = shallowRef4(undefined);
|
|
1260
1599
|
const sync = () => {
|
|
1261
1600
|
const snapshot = store.getSnapshot();
|
|
1262
1601
|
error.value = snapshot.error;
|
|
@@ -1267,7 +1606,7 @@ function useVoiceProviderCapabilities(path = "/api/provider-capabilities", optio
|
|
|
1267
1606
|
const unsubscribe = store.subscribe(sync);
|
|
1268
1607
|
sync();
|
|
1269
1608
|
store.refresh().catch(() => {});
|
|
1270
|
-
|
|
1609
|
+
onUnmounted5(() => {
|
|
1271
1610
|
unsubscribe();
|
|
1272
1611
|
store.close();
|
|
1273
1612
|
});
|
|
@@ -1281,7 +1620,7 @@ function useVoiceProviderCapabilities(path = "/api/provider-capabilities", optio
|
|
|
1281
1620
|
}
|
|
1282
1621
|
|
|
1283
1622
|
// src/vue/VoiceProviderCapabilities.ts
|
|
1284
|
-
var VoiceProviderCapabilities =
|
|
1623
|
+
var VoiceProviderCapabilities = defineComponent5({
|
|
1285
1624
|
name: "VoiceProviderCapabilities",
|
|
1286
1625
|
props: {
|
|
1287
1626
|
class: {
|
|
@@ -1318,41 +1657,41 @@ var VoiceProviderCapabilities = defineComponent4({
|
|
|
1318
1657
|
report: capabilities.report.value,
|
|
1319
1658
|
updatedAt: capabilities.updatedAt.value
|
|
1320
1659
|
}, options));
|
|
1321
|
-
return () =>
|
|
1660
|
+
return () => h5("section", {
|
|
1322
1661
|
class: [
|
|
1323
1662
|
"absolute-voice-provider-capabilities",
|
|
1324
1663
|
`absolute-voice-provider-capabilities--${model.value.status}`,
|
|
1325
1664
|
props.class
|
|
1326
1665
|
]
|
|
1327
1666
|
}, [
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1667
|
+
h5("header", { class: "absolute-voice-provider-capabilities__header" }, [
|
|
1668
|
+
h5("span", { class: "absolute-voice-provider-capabilities__eyebrow" }, model.value.title),
|
|
1669
|
+
h5("strong", { class: "absolute-voice-provider-capabilities__label" }, model.value.label)
|
|
1331
1670
|
]),
|
|
1332
|
-
|
|
1333
|
-
model.value.capabilities.length ?
|
|
1671
|
+
h5("p", { class: "absolute-voice-provider-capabilities__description" }, model.value.description),
|
|
1672
|
+
model.value.capabilities.length ? h5("div", { class: "absolute-voice-provider-capabilities__providers" }, model.value.capabilities.map((capability) => h5("article", {
|
|
1334
1673
|
class: [
|
|
1335
1674
|
"absolute-voice-provider-capabilities__provider",
|
|
1336
1675
|
`absolute-voice-provider-capabilities__provider--${capability.status}`
|
|
1337
1676
|
],
|
|
1338
1677
|
key: `${capability.kind}:${capability.provider}`
|
|
1339
1678
|
}, [
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1679
|
+
h5("header", [
|
|
1680
|
+
h5("strong", capability.label),
|
|
1681
|
+
h5("span", capability.status)
|
|
1343
1682
|
]),
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1683
|
+
h5("p", capability.detail),
|
|
1684
|
+
h5("dl", capability.rows.map((row) => h5("div", { key: row.label }, [
|
|
1685
|
+
h5("dt", row.label),
|
|
1686
|
+
h5("dd", row.value)
|
|
1348
1687
|
])))
|
|
1349
|
-
]))) :
|
|
1350
|
-
model.value.error ?
|
|
1688
|
+
]))) : h5("p", { class: "absolute-voice-provider-capabilities__empty" }, "Configure provider capabilities to see deployment coverage."),
|
|
1689
|
+
model.value.error ? h5("p", { class: "absolute-voice-provider-capabilities__error" }, model.value.error) : null
|
|
1351
1690
|
]);
|
|
1352
1691
|
}
|
|
1353
1692
|
});
|
|
1354
1693
|
// src/vue/VoiceProviderStatus.ts
|
|
1355
|
-
import { computed as computed3, defineComponent as
|
|
1694
|
+
import { computed as computed3, defineComponent as defineComponent6, h as h6 } from "vue";
|
|
1356
1695
|
|
|
1357
1696
|
// src/client/providerStatus.ts
|
|
1358
1697
|
var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
|
|
@@ -1435,9 +1774,9 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
1435
1774
|
};
|
|
1436
1775
|
|
|
1437
1776
|
// src/client/providerStatusWidget.ts
|
|
1438
|
-
var
|
|
1439
|
-
var
|
|
1440
|
-
var
|
|
1777
|
+
var DEFAULT_TITLE5 = "Voice Providers";
|
|
1778
|
+
var DEFAULT_DESCRIPTION5 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
1779
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1441
1780
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1442
1781
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
1443
1782
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -1481,37 +1820,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
1481
1820
|
const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
|
|
1482
1821
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
1483
1822
|
return {
|
|
1484
|
-
description: options.description ??
|
|
1823
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
1485
1824
|
error: snapshot.error,
|
|
1486
1825
|
isLoading: snapshot.isLoading,
|
|
1487
1826
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
1488
1827
|
providers,
|
|
1489
1828
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1490
|
-
title: options.title ??
|
|
1829
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
1491
1830
|
updatedAt: snapshot.updatedAt
|
|
1492
1831
|
};
|
|
1493
1832
|
};
|
|
1494
1833
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
1495
1834
|
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--${
|
|
1835
|
+
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
1836
|
<header>
|
|
1498
|
-
<strong>${
|
|
1499
|
-
<span>${
|
|
1837
|
+
<strong>${escapeHtml6(provider.label)}</strong>
|
|
1838
|
+
<span>${escapeHtml6(formatStatus2(provider.status))}</span>
|
|
1500
1839
|
</header>
|
|
1501
|
-
<p>${
|
|
1840
|
+
<p>${escapeHtml6(provider.detail)}</p>
|
|
1502
1841
|
<dl>${provider.rows.map((row) => `<div>
|
|
1503
|
-
<dt>${
|
|
1504
|
-
<dd>${
|
|
1842
|
+
<dt>${escapeHtml6(row.label)}</dt>
|
|
1843
|
+
<dd>${escapeHtml6(row.value)}</dd>
|
|
1505
1844
|
</div>`).join("")}</dl>
|
|
1506
1845
|
</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--${
|
|
1846
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml6(model.status)}">
|
|
1508
1847
|
<header class="absolute-voice-provider-status__header">
|
|
1509
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
1510
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
1848
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml6(model.title)}</span>
|
|
1849
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml6(model.label)}</strong>
|
|
1511
1850
|
</header>
|
|
1512
|
-
<p class="absolute-voice-provider-status__description">${
|
|
1851
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml6(model.description)}</p>
|
|
1513
1852
|
${providers}
|
|
1514
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
1853
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
1515
1854
|
</section>`;
|
|
1516
1855
|
};
|
|
1517
1856
|
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 +1892,13 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
1553
1892
|
};
|
|
1554
1893
|
|
|
1555
1894
|
// src/vue/useVoiceProviderStatus.ts
|
|
1556
|
-
import { onUnmounted as
|
|
1895
|
+
import { onUnmounted as onUnmounted6, ref as ref5, shallowRef as shallowRef5 } from "vue";
|
|
1557
1896
|
function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
|
|
1558
1897
|
const store = createVoiceProviderStatusStore(path, options);
|
|
1559
|
-
const error =
|
|
1560
|
-
const isLoading =
|
|
1561
|
-
const providers =
|
|
1562
|
-
const updatedAt =
|
|
1898
|
+
const error = ref5(null);
|
|
1899
|
+
const isLoading = ref5(false);
|
|
1900
|
+
const providers = shallowRef5([]);
|
|
1901
|
+
const updatedAt = ref5(undefined);
|
|
1563
1902
|
const sync = () => {
|
|
1564
1903
|
const snapshot = store.getSnapshot();
|
|
1565
1904
|
error.value = snapshot.error;
|
|
@@ -1570,7 +1909,7 @@ function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
|
|
|
1570
1909
|
const unsubscribe = store.subscribe(sync);
|
|
1571
1910
|
sync();
|
|
1572
1911
|
store.refresh().catch(() => {});
|
|
1573
|
-
|
|
1912
|
+
onUnmounted6(() => {
|
|
1574
1913
|
unsubscribe();
|
|
1575
1914
|
store.close();
|
|
1576
1915
|
});
|
|
@@ -1584,7 +1923,7 @@ function useVoiceProviderStatus(path = "/api/provider-status", options = {}) {
|
|
|
1584
1923
|
}
|
|
1585
1924
|
|
|
1586
1925
|
// src/vue/VoiceProviderStatus.ts
|
|
1587
|
-
var VoiceProviderStatus =
|
|
1926
|
+
var VoiceProviderStatus = defineComponent6({
|
|
1588
1927
|
name: "VoiceProviderStatus",
|
|
1589
1928
|
props: {
|
|
1590
1929
|
class: {
|
|
@@ -1621,41 +1960,41 @@ var VoiceProviderStatus = defineComponent5({
|
|
|
1621
1960
|
providers: status.providers.value,
|
|
1622
1961
|
updatedAt: status.updatedAt.value
|
|
1623
1962
|
}, options));
|
|
1624
|
-
return () =>
|
|
1963
|
+
return () => h6("section", {
|
|
1625
1964
|
class: [
|
|
1626
1965
|
"absolute-voice-provider-status",
|
|
1627
1966
|
`absolute-voice-provider-status--${model.value.status}`,
|
|
1628
1967
|
props.class
|
|
1629
1968
|
]
|
|
1630
1969
|
}, [
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1970
|
+
h6("header", { class: "absolute-voice-provider-status__header" }, [
|
|
1971
|
+
h6("span", { class: "absolute-voice-provider-status__eyebrow" }, model.value.title),
|
|
1972
|
+
h6("strong", { class: "absolute-voice-provider-status__label" }, model.value.label)
|
|
1634
1973
|
]),
|
|
1635
|
-
|
|
1636
|
-
model.value.providers.length ?
|
|
1974
|
+
h6("p", { class: "absolute-voice-provider-status__description" }, model.value.description),
|
|
1975
|
+
model.value.providers.length ? h6("div", { class: "absolute-voice-provider-status__providers" }, model.value.providers.map((provider) => h6("article", {
|
|
1637
1976
|
class: [
|
|
1638
1977
|
"absolute-voice-provider-status__provider",
|
|
1639
1978
|
`absolute-voice-provider-status__provider--${provider.status}`
|
|
1640
1979
|
],
|
|
1641
1980
|
key: provider.provider
|
|
1642
1981
|
}, [
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1982
|
+
h6("header", [
|
|
1983
|
+
h6("strong", provider.label),
|
|
1984
|
+
h6("span", provider.status)
|
|
1646
1985
|
]),
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1986
|
+
h6("p", provider.detail),
|
|
1987
|
+
h6("dl", provider.rows.map((row) => h6("div", { key: row.label }, [
|
|
1988
|
+
h6("dt", row.label),
|
|
1989
|
+
h6("dd", row.value)
|
|
1651
1990
|
])))
|
|
1652
|
-
]))) :
|
|
1653
|
-
model.value.error ?
|
|
1991
|
+
]))) : h6("p", { class: "absolute-voice-provider-status__empty" }, "Run voice traffic to see provider health."),
|
|
1992
|
+
model.value.error ? h6("p", { class: "absolute-voice-provider-status__error" }, model.value.error) : null
|
|
1654
1993
|
]);
|
|
1655
1994
|
}
|
|
1656
1995
|
});
|
|
1657
1996
|
// src/vue/VoiceRoutingStatus.ts
|
|
1658
|
-
import { computed as computed4, defineComponent as
|
|
1997
|
+
import { computed as computed4, defineComponent as defineComponent7, h as h7 } from "vue";
|
|
1659
1998
|
|
|
1660
1999
|
// src/client/routingStatus.ts
|
|
1661
2000
|
var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
|
|
@@ -1738,9 +2077,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
1738
2077
|
};
|
|
1739
2078
|
|
|
1740
2079
|
// src/client/routingStatusWidget.ts
|
|
1741
|
-
var
|
|
1742
|
-
var
|
|
1743
|
-
var
|
|
2080
|
+
var DEFAULT_TITLE6 = "Voice Routing";
|
|
2081
|
+
var DEFAULT_DESCRIPTION6 = "Latest provider routing decision from the self-hosted trace store.";
|
|
2082
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1744
2083
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
1745
2084
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
1746
2085
|
const decision = snapshot.decision;
|
|
@@ -1764,30 +2103,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
1764
2103
|
] : [];
|
|
1765
2104
|
return {
|
|
1766
2105
|
decision,
|
|
1767
|
-
description: options.description ??
|
|
2106
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
1768
2107
|
error: snapshot.error,
|
|
1769
2108
|
isLoading: snapshot.isLoading,
|
|
1770
2109
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
1771
2110
|
rows,
|
|
1772
2111
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1773
|
-
title: options.title ??
|
|
2112
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
1774
2113
|
updatedAt: snapshot.updatedAt
|
|
1775
2114
|
};
|
|
1776
2115
|
};
|
|
1777
2116
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
1778
2117
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
1779
2118
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
1780
|
-
<span>${
|
|
1781
|
-
<strong>${
|
|
2119
|
+
<span>${escapeHtml7(row.label)}</span>
|
|
2120
|
+
<strong>${escapeHtml7(row.value)}</strong>
|
|
1782
2121
|
</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--${
|
|
2122
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml7(model.status)}">
|
|
1784
2123
|
<header class="absolute-voice-routing-status__header">
|
|
1785
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
1786
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
2124
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml7(model.title)}</span>
|
|
2125
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml7(model.label)}</strong>
|
|
1787
2126
|
</header>
|
|
1788
|
-
<p class="absolute-voice-routing-status__description">${
|
|
2127
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml7(model.description)}</p>
|
|
1789
2128
|
${rows}
|
|
1790
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
2129
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
1791
2130
|
</section>`;
|
|
1792
2131
|
};
|
|
1793
2132
|
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 +2168,13 @@ var defineVoiceRoutingStatusElement = (tagName = "absolute-voice-routing-status"
|
|
|
1829
2168
|
};
|
|
1830
2169
|
|
|
1831
2170
|
// src/vue/useVoiceRoutingStatus.ts
|
|
1832
|
-
import { onUnmounted as
|
|
2171
|
+
import { onUnmounted as onUnmounted7, ref as ref6, shallowRef as shallowRef6 } from "vue";
|
|
1833
2172
|
function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
|
|
1834
2173
|
const store = createVoiceRoutingStatusStore(path, options);
|
|
1835
|
-
const decision =
|
|
1836
|
-
const error =
|
|
1837
|
-
const isLoading =
|
|
1838
|
-
const updatedAt =
|
|
2174
|
+
const decision = shallowRef6(null);
|
|
2175
|
+
const error = ref6(null);
|
|
2176
|
+
const isLoading = ref6(false);
|
|
2177
|
+
const updatedAt = ref6(undefined);
|
|
1839
2178
|
const sync = () => {
|
|
1840
2179
|
const snapshot = store.getSnapshot();
|
|
1841
2180
|
decision.value = snapshot.decision;
|
|
@@ -1846,7 +2185,7 @@ function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
|
|
|
1846
2185
|
const unsubscribe = store.subscribe(sync);
|
|
1847
2186
|
sync();
|
|
1848
2187
|
store.refresh().catch(() => {});
|
|
1849
|
-
|
|
2188
|
+
onUnmounted7(() => {
|
|
1850
2189
|
unsubscribe();
|
|
1851
2190
|
store.close();
|
|
1852
2191
|
});
|
|
@@ -1860,7 +2199,7 @@ function useVoiceRoutingStatus(path = "/api/routing/latest", options = {}) {
|
|
|
1860
2199
|
}
|
|
1861
2200
|
|
|
1862
2201
|
// src/vue/VoiceRoutingStatus.ts
|
|
1863
|
-
var VoiceRoutingStatus =
|
|
2202
|
+
var VoiceRoutingStatus = defineComponent7({
|
|
1864
2203
|
name: "VoiceRoutingStatus",
|
|
1865
2204
|
props: {
|
|
1866
2205
|
class: {
|
|
@@ -1897,28 +2236,28 @@ var VoiceRoutingStatus = defineComponent6({
|
|
|
1897
2236
|
isLoading: status.isLoading.value,
|
|
1898
2237
|
updatedAt: status.updatedAt.value
|
|
1899
2238
|
}, options));
|
|
1900
|
-
return () =>
|
|
2239
|
+
return () => h7("section", {
|
|
1901
2240
|
class: [
|
|
1902
2241
|
"absolute-voice-routing-status",
|
|
1903
2242
|
`absolute-voice-routing-status--${model.value.status}`,
|
|
1904
2243
|
props.class
|
|
1905
2244
|
]
|
|
1906
2245
|
}, [
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
2246
|
+
h7("header", { class: "absolute-voice-routing-status__header" }, [
|
|
2247
|
+
h7("span", { class: "absolute-voice-routing-status__eyebrow" }, model.value.title),
|
|
2248
|
+
h7("strong", { class: "absolute-voice-routing-status__label" }, model.value.label)
|
|
1910
2249
|
]),
|
|
1911
|
-
|
|
1912
|
-
model.value.rows.length ?
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
]))) :
|
|
1916
|
-
model.value.error ?
|
|
2250
|
+
h7("p", { class: "absolute-voice-routing-status__description" }, model.value.description),
|
|
2251
|
+
model.value.rows.length ? h7("div", { class: "absolute-voice-routing-status__grid" }, model.value.rows.map((row) => h7("div", { key: row.label }, [
|
|
2252
|
+
h7("span", row.label),
|
|
2253
|
+
h7("strong", row.value)
|
|
2254
|
+
]))) : h7("p", { class: "absolute-voice-routing-status__empty" }, "Start a voice session to see the selected provider."),
|
|
2255
|
+
model.value.error ? h7("p", { class: "absolute-voice-routing-status__error" }, model.value.error) : null
|
|
1917
2256
|
]);
|
|
1918
2257
|
}
|
|
1919
2258
|
});
|
|
1920
2259
|
// src/vue/VoiceTurnLatency.ts
|
|
1921
|
-
import { computed as computed5, defineComponent as
|
|
2260
|
+
import { computed as computed5, defineComponent as defineComponent8, h as h8 } from "vue";
|
|
1922
2261
|
|
|
1923
2262
|
// src/client/turnLatency.ts
|
|
1924
2263
|
var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
|
|
@@ -2024,10 +2363,10 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
|
|
|
2024
2363
|
};
|
|
2025
2364
|
|
|
2026
2365
|
// src/client/turnLatencyWidget.ts
|
|
2027
|
-
var
|
|
2028
|
-
var
|
|
2366
|
+
var DEFAULT_TITLE7 = "Turn Latency";
|
|
2367
|
+
var DEFAULT_DESCRIPTION7 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
2029
2368
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
2030
|
-
var
|
|
2369
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2031
2370
|
var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
2032
2371
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
2033
2372
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -2041,39 +2380,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
2041
2380
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2042
2381
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2043
2382
|
return {
|
|
2044
|
-
description: options.description ??
|
|
2383
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
2045
2384
|
error: snapshot.error,
|
|
2046
2385
|
isLoading: snapshot.isLoading,
|
|
2047
2386
|
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
2387
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
2049
2388
|
showProofAction: Boolean(options.proofPath),
|
|
2050
2389
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2051
|
-
title: options.title ??
|
|
2390
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
2052
2391
|
turns,
|
|
2053
2392
|
updatedAt: snapshot.updatedAt
|
|
2054
2393
|
};
|
|
2055
2394
|
};
|
|
2056
2395
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
2057
2396
|
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--${
|
|
2397
|
+
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
2398
|
<header>
|
|
2060
|
-
<strong>${
|
|
2061
|
-
<span>${
|
|
2399
|
+
<strong>${escapeHtml8(turn.label)}</strong>
|
|
2400
|
+
<span>${escapeHtml8(turn.status)}</span>
|
|
2062
2401
|
</header>
|
|
2063
2402
|
<dl>${turn.rows.map((row) => `<div>
|
|
2064
|
-
<dt>${
|
|
2065
|
-
<dd>${
|
|
2403
|
+
<dt>${escapeHtml8(row.label)}</dt>
|
|
2404
|
+
<dd>${escapeHtml8(row.value)}</dd>
|
|
2066
2405
|
</div>`).join("")}</dl>
|
|
2067
2406
|
</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--${
|
|
2407
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml8(model.status)}">
|
|
2069
2408
|
<header class="absolute-voice-turn-latency__header">
|
|
2070
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
2071
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
2409
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml8(model.title)}</span>
|
|
2410
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml8(model.label)}</strong>
|
|
2072
2411
|
</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">${
|
|
2412
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml8(model.description)}</p>
|
|
2413
|
+
${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
2414
|
${turns}
|
|
2076
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
2415
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
2077
2416
|
</section>`;
|
|
2078
2417
|
};
|
|
2079
2418
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -2124,13 +2463,13 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
2124
2463
|
};
|
|
2125
2464
|
|
|
2126
2465
|
// src/vue/useVoiceTurnLatency.ts
|
|
2127
|
-
import { onUnmounted as
|
|
2466
|
+
import { onUnmounted as onUnmounted8, shallowRef as shallowRef7 } from "vue";
|
|
2128
2467
|
function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
|
|
2129
2468
|
const store = createVoiceTurnLatencyStore(path, options);
|
|
2130
|
-
const error =
|
|
2131
|
-
const isLoading =
|
|
2132
|
-
const report =
|
|
2133
|
-
const updatedAt =
|
|
2469
|
+
const error = shallowRef7(null);
|
|
2470
|
+
const isLoading = shallowRef7(false);
|
|
2471
|
+
const report = shallowRef7();
|
|
2472
|
+
const updatedAt = shallowRef7(undefined);
|
|
2134
2473
|
const sync = () => {
|
|
2135
2474
|
const snapshot = store.getSnapshot();
|
|
2136
2475
|
error.value = snapshot.error;
|
|
@@ -2141,7 +2480,7 @@ function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
|
|
|
2141
2480
|
const unsubscribe = store.subscribe(sync);
|
|
2142
2481
|
sync();
|
|
2143
2482
|
store.refresh().catch(() => {});
|
|
2144
|
-
|
|
2483
|
+
onUnmounted8(() => {
|
|
2145
2484
|
unsubscribe();
|
|
2146
2485
|
store.close();
|
|
2147
2486
|
});
|
|
@@ -2156,7 +2495,7 @@ function useVoiceTurnLatency(path = "/api/turn-latency", options = {}) {
|
|
|
2156
2495
|
}
|
|
2157
2496
|
|
|
2158
2497
|
// src/vue/VoiceTurnLatency.ts
|
|
2159
|
-
var VoiceTurnLatency =
|
|
2498
|
+
var VoiceTurnLatency = defineComponent8({
|
|
2160
2499
|
name: "VoiceTurnLatency",
|
|
2161
2500
|
props: {
|
|
2162
2501
|
class: { default: "", type: String },
|
|
@@ -2182,47 +2521,47 @@ var VoiceTurnLatency = defineComponent7({
|
|
|
2182
2521
|
report: latency.report.value,
|
|
2183
2522
|
updatedAt: latency.updatedAt.value
|
|
2184
2523
|
}, options));
|
|
2185
|
-
return () =>
|
|
2524
|
+
return () => h8("section", {
|
|
2186
2525
|
class: [
|
|
2187
2526
|
"absolute-voice-turn-latency",
|
|
2188
2527
|
`absolute-voice-turn-latency--${model.value.status}`,
|
|
2189
2528
|
props.class
|
|
2190
2529
|
]
|
|
2191
2530
|
}, [
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2531
|
+
h8("header", { class: "absolute-voice-turn-latency__header" }, [
|
|
2532
|
+
h8("span", { class: "absolute-voice-turn-latency__eyebrow" }, model.value.title),
|
|
2533
|
+
h8("strong", { class: "absolute-voice-turn-latency__label" }, model.value.label)
|
|
2195
2534
|
]),
|
|
2196
|
-
|
|
2197
|
-
model.value.showProofAction ?
|
|
2535
|
+
h8("p", { class: "absolute-voice-turn-latency__description" }, model.value.description),
|
|
2536
|
+
model.value.showProofAction ? h8("button", {
|
|
2198
2537
|
class: "absolute-voice-turn-latency__proof",
|
|
2199
2538
|
onClick: () => {
|
|
2200
2539
|
latency.runProof().catch(() => {});
|
|
2201
2540
|
},
|
|
2202
2541
|
type: "button"
|
|
2203
2542
|
}, model.value.proofLabel) : null,
|
|
2204
|
-
model.value.turns.length ?
|
|
2543
|
+
model.value.turns.length ? h8("div", { class: "absolute-voice-turn-latency__turns" }, model.value.turns.map((turn) => h8("article", {
|
|
2205
2544
|
class: [
|
|
2206
2545
|
"absolute-voice-turn-latency__turn",
|
|
2207
2546
|
`absolute-voice-turn-latency__turn--${turn.status}`
|
|
2208
2547
|
],
|
|
2209
2548
|
key: `${turn.sessionId}:${turn.turnId}`
|
|
2210
2549
|
}, [
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2550
|
+
h8("header", [
|
|
2551
|
+
h8("strong", turn.label),
|
|
2552
|
+
h8("span", turn.status)
|
|
2214
2553
|
]),
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2554
|
+
h8("dl", turn.rows.map((row) => h8("div", { key: row.label }, [
|
|
2555
|
+
h8("dt", row.label),
|
|
2556
|
+
h8("dd", row.value)
|
|
2218
2557
|
])))
|
|
2219
|
-
]))) :
|
|
2220
|
-
model.value.error ?
|
|
2558
|
+
]))) : h8("p", { class: "absolute-voice-turn-latency__empty" }, "Complete a voice turn to see latency diagnostics."),
|
|
2559
|
+
model.value.error ? h8("p", { class: "absolute-voice-turn-latency__error" }, model.value.error) : null
|
|
2221
2560
|
]);
|
|
2222
2561
|
}
|
|
2223
2562
|
});
|
|
2224
2563
|
// src/vue/VoiceTurnQuality.ts
|
|
2225
|
-
import { computed as computed6, defineComponent as
|
|
2564
|
+
import { computed as computed6, defineComponent as defineComponent9, h as h9 } from "vue";
|
|
2226
2565
|
|
|
2227
2566
|
// src/client/turnQuality.ts
|
|
2228
2567
|
var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
|
|
@@ -2304,9 +2643,9 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
|
|
|
2304
2643
|
};
|
|
2305
2644
|
|
|
2306
2645
|
// src/client/turnQualityWidget.ts
|
|
2307
|
-
var
|
|
2308
|
-
var
|
|
2309
|
-
var
|
|
2646
|
+
var DEFAULT_TITLE8 = "Turn Quality";
|
|
2647
|
+
var DEFAULT_DESCRIPTION8 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
2648
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2310
2649
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
2311
2650
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
2312
2651
|
var getTurnDetail = (turn) => {
|
|
@@ -2344,37 +2683,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
2344
2683
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2345
2684
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2346
2685
|
return {
|
|
2347
|
-
description: options.description ??
|
|
2686
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
2348
2687
|
error: snapshot.error,
|
|
2349
2688
|
isLoading: snapshot.isLoading,
|
|
2350
2689
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
2351
2690
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2352
|
-
title: options.title ??
|
|
2691
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
2353
2692
|
turns,
|
|
2354
2693
|
updatedAt: snapshot.updatedAt
|
|
2355
2694
|
};
|
|
2356
2695
|
};
|
|
2357
2696
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
2358
2697
|
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--${
|
|
2698
|
+
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
2699
|
<header>
|
|
2361
|
-
<strong>${
|
|
2362
|
-
<span>${
|
|
2700
|
+
<strong>${escapeHtml9(turn.label)}</strong>
|
|
2701
|
+
<span>${escapeHtml9(turn.status)}</span>
|
|
2363
2702
|
</header>
|
|
2364
|
-
<p>${
|
|
2703
|
+
<p>${escapeHtml9(turn.detail)}</p>
|
|
2365
2704
|
<dl>${turn.rows.map((row) => `<div>
|
|
2366
|
-
<dt>${
|
|
2367
|
-
<dd>${
|
|
2705
|
+
<dt>${escapeHtml9(row.label)}</dt>
|
|
2706
|
+
<dd>${escapeHtml9(row.value)}</dd>
|
|
2368
2707
|
</div>`).join("")}</dl>
|
|
2369
2708
|
</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--${
|
|
2709
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml9(model.status)}">
|
|
2371
2710
|
<header class="absolute-voice-turn-quality__header">
|
|
2372
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
2373
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
2711
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml9(model.title)}</span>
|
|
2712
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml9(model.label)}</strong>
|
|
2374
2713
|
</header>
|
|
2375
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
2714
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml9(model.description)}</p>
|
|
2376
2715
|
${turns}
|
|
2377
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
2716
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
2378
2717
|
</section>`;
|
|
2379
2718
|
};
|
|
2380
2719
|
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 +2755,13 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
2416
2755
|
};
|
|
2417
2756
|
|
|
2418
2757
|
// src/vue/useVoiceTurnQuality.ts
|
|
2419
|
-
import { onUnmounted as
|
|
2758
|
+
import { onUnmounted as onUnmounted9, shallowRef as shallowRef8 } from "vue";
|
|
2420
2759
|
function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
|
|
2421
2760
|
const store = createVoiceTurnQualityStore(path, options);
|
|
2422
|
-
const error =
|
|
2423
|
-
const isLoading =
|
|
2424
|
-
const report =
|
|
2425
|
-
const updatedAt =
|
|
2761
|
+
const error = shallowRef8(null);
|
|
2762
|
+
const isLoading = shallowRef8(false);
|
|
2763
|
+
const report = shallowRef8();
|
|
2764
|
+
const updatedAt = shallowRef8(undefined);
|
|
2426
2765
|
const sync = () => {
|
|
2427
2766
|
const snapshot = store.getSnapshot();
|
|
2428
2767
|
error.value = snapshot.error;
|
|
@@ -2433,7 +2772,7 @@ function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
|
|
|
2433
2772
|
const unsubscribe = store.subscribe(sync);
|
|
2434
2773
|
sync();
|
|
2435
2774
|
store.refresh().catch(() => {});
|
|
2436
|
-
|
|
2775
|
+
onUnmounted9(() => {
|
|
2437
2776
|
unsubscribe();
|
|
2438
2777
|
store.close();
|
|
2439
2778
|
});
|
|
@@ -2441,7 +2780,7 @@ function useVoiceTurnQuality(path = "/api/turn-quality", options = {}) {
|
|
|
2441
2780
|
}
|
|
2442
2781
|
|
|
2443
2782
|
// src/vue/VoiceTurnQuality.ts
|
|
2444
|
-
var VoiceTurnQuality =
|
|
2783
|
+
var VoiceTurnQuality = defineComponent9({
|
|
2445
2784
|
name: "VoiceTurnQuality",
|
|
2446
2785
|
props: {
|
|
2447
2786
|
class: { default: "", type: String },
|
|
@@ -2463,41 +2802,41 @@ var VoiceTurnQuality = defineComponent8({
|
|
|
2463
2802
|
report: quality.report.value,
|
|
2464
2803
|
updatedAt: quality.updatedAt.value
|
|
2465
2804
|
}, options));
|
|
2466
|
-
return () =>
|
|
2805
|
+
return () => h9("section", {
|
|
2467
2806
|
class: [
|
|
2468
2807
|
"absolute-voice-turn-quality",
|
|
2469
2808
|
`absolute-voice-turn-quality--${model.value.status}`,
|
|
2470
2809
|
props.class
|
|
2471
2810
|
]
|
|
2472
2811
|
}, [
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2812
|
+
h9("header", { class: "absolute-voice-turn-quality__header" }, [
|
|
2813
|
+
h9("span", { class: "absolute-voice-turn-quality__eyebrow" }, model.value.title),
|
|
2814
|
+
h9("strong", { class: "absolute-voice-turn-quality__label" }, model.value.label)
|
|
2476
2815
|
]),
|
|
2477
|
-
|
|
2478
|
-
model.value.turns.length ?
|
|
2816
|
+
h9("p", { class: "absolute-voice-turn-quality__description" }, model.value.description),
|
|
2817
|
+
model.value.turns.length ? h9("div", { class: "absolute-voice-turn-quality__turns" }, model.value.turns.map((turn) => h9("article", {
|
|
2479
2818
|
class: [
|
|
2480
2819
|
"absolute-voice-turn-quality__turn",
|
|
2481
2820
|
`absolute-voice-turn-quality__turn--${turn.status}`
|
|
2482
2821
|
],
|
|
2483
2822
|
key: `${turn.sessionId}:${turn.turnId}`
|
|
2484
2823
|
}, [
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2824
|
+
h9("header", [
|
|
2825
|
+
h9("strong", turn.label),
|
|
2826
|
+
h9("span", turn.status)
|
|
2488
2827
|
]),
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2828
|
+
h9("p", turn.detail),
|
|
2829
|
+
h9("dl", turn.rows.map((row) => h9("div", { key: row.label }, [
|
|
2830
|
+
h9("dt", row.label),
|
|
2831
|
+
h9("dd", row.value)
|
|
2493
2832
|
])))
|
|
2494
|
-
]))) :
|
|
2495
|
-
model.value.error ?
|
|
2833
|
+
]))) : h9("p", { class: "absolute-voice-turn-quality__empty" }, "Complete a voice turn to see STT quality diagnostics."),
|
|
2834
|
+
model.value.error ? h9("p", { class: "absolute-voice-turn-quality__error" }, model.value.error) : null
|
|
2496
2835
|
]);
|
|
2497
2836
|
}
|
|
2498
2837
|
});
|
|
2499
2838
|
// src/vue/useVoiceCampaignDialerProof.ts
|
|
2500
|
-
import { onUnmounted as
|
|
2839
|
+
import { onUnmounted as onUnmounted10, shallowRef as shallowRef9 } from "vue";
|
|
2501
2840
|
|
|
2502
2841
|
// src/client/campaignDialerProof.ts
|
|
2503
2842
|
var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
|
|
@@ -2620,11 +2959,11 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
|
|
|
2620
2959
|
// src/vue/useVoiceCampaignDialerProof.ts
|
|
2621
2960
|
function useVoiceCampaignDialerProof(path = "/api/voice/campaigns/dialer-proof", options = {}) {
|
|
2622
2961
|
const store = createVoiceCampaignDialerProofStore(path, options);
|
|
2623
|
-
const error =
|
|
2624
|
-
const isLoading =
|
|
2625
|
-
const report =
|
|
2626
|
-
const status =
|
|
2627
|
-
const updatedAt =
|
|
2962
|
+
const error = shallowRef9(null);
|
|
2963
|
+
const isLoading = shallowRef9(false);
|
|
2964
|
+
const report = shallowRef9();
|
|
2965
|
+
const status = shallowRef9();
|
|
2966
|
+
const updatedAt = shallowRef9(undefined);
|
|
2628
2967
|
const sync = () => {
|
|
2629
2968
|
const snapshot = store.getSnapshot();
|
|
2630
2969
|
error.value = snapshot.error;
|
|
@@ -2638,7 +2977,7 @@ function useVoiceCampaignDialerProof(path = "/api/voice/campaigns/dialer-proof",
|
|
|
2638
2977
|
if (typeof window !== "undefined") {
|
|
2639
2978
|
store.refresh().catch(() => {});
|
|
2640
2979
|
}
|
|
2641
|
-
|
|
2980
|
+
onUnmounted10(() => {
|
|
2642
2981
|
unsubscribe();
|
|
2643
2982
|
store.close();
|
|
2644
2983
|
});
|
|
@@ -2653,7 +2992,7 @@ function useVoiceCampaignDialerProof(path = "/api/voice/campaigns/dialer-proof",
|
|
|
2653
2992
|
};
|
|
2654
2993
|
}
|
|
2655
2994
|
// src/vue/useVoiceStream.ts
|
|
2656
|
-
import { onUnmounted as
|
|
2995
|
+
import { onUnmounted as onUnmounted11, ref as ref7, shallowRef as shallowRef10 } from "vue";
|
|
2657
2996
|
|
|
2658
2997
|
// src/client/actions.ts
|
|
2659
2998
|
var normalizeErrorMessage = (value) => {
|
|
@@ -3298,16 +3637,16 @@ var createVoiceStream = (path, options = {}) => {
|
|
|
3298
3637
|
// src/vue/useVoiceStream.ts
|
|
3299
3638
|
function useVoiceStream(path, options = {}) {
|
|
3300
3639
|
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 =
|
|
3640
|
+
const assistantAudio = shallowRef10([]);
|
|
3641
|
+
const assistantTexts = shallowRef10([]);
|
|
3642
|
+
const call = shallowRef10(null);
|
|
3643
|
+
const error = ref7(null);
|
|
3644
|
+
const isConnected = ref7(false);
|
|
3645
|
+
const partial = ref7("");
|
|
3646
|
+
const reconnect = shallowRef10(stream.reconnect);
|
|
3647
|
+
const sessionId = ref7(stream.sessionId);
|
|
3648
|
+
const status = ref7(stream.status);
|
|
3649
|
+
const turns = shallowRef10([]);
|
|
3311
3650
|
const sync = () => {
|
|
3312
3651
|
assistantAudio.value = [...stream.assistantAudio];
|
|
3313
3652
|
assistantTexts.value = [...stream.assistantTexts];
|
|
@@ -3326,7 +3665,7 @@ function useVoiceStream(path, options = {}) {
|
|
|
3326
3665
|
unsubscribe();
|
|
3327
3666
|
stream.close();
|
|
3328
3667
|
};
|
|
3329
|
-
|
|
3668
|
+
onUnmounted11(destroy);
|
|
3330
3669
|
return {
|
|
3331
3670
|
assistantAudio,
|
|
3332
3671
|
assistantTexts,
|
|
@@ -3345,7 +3684,7 @@ function useVoiceStream(path, options = {}) {
|
|
|
3345
3684
|
};
|
|
3346
3685
|
}
|
|
3347
3686
|
// src/vue/useVoiceController.ts
|
|
3348
|
-
import { onUnmounted as
|
|
3687
|
+
import { onUnmounted as onUnmounted12, ref as ref8, shallowRef as shallowRef11 } from "vue";
|
|
3349
3688
|
|
|
3350
3689
|
// src/client/htmx.ts
|
|
3351
3690
|
var DEFAULT_EVENT_NAME = "voice-refresh";
|
|
@@ -3991,17 +4330,17 @@ var createVoiceController = (path, options = {}) => {
|
|
|
3991
4330
|
// src/vue/useVoiceController.ts
|
|
3992
4331
|
function useVoiceController(path, options = {}) {
|
|
3993
4332
|
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 =
|
|
4333
|
+
const assistantAudio = shallowRef11([]);
|
|
4334
|
+
const assistantTexts = shallowRef11([]);
|
|
4335
|
+
const error = ref8(null);
|
|
4336
|
+
const isConnected = ref8(false);
|
|
4337
|
+
const isRecording = ref8(false);
|
|
4338
|
+
const partial = ref8("");
|
|
4339
|
+
const reconnect = shallowRef11(controller.reconnect);
|
|
4340
|
+
const recordingError = ref8(null);
|
|
4341
|
+
const sessionId = ref8(controller.sessionId);
|
|
4342
|
+
const status = ref8(controller.status);
|
|
4343
|
+
const turns = shallowRef11([]);
|
|
4005
4344
|
const sync = () => {
|
|
4006
4345
|
assistantAudio.value = [...controller.assistantAudio];
|
|
4007
4346
|
assistantTexts.value = [...controller.assistantTexts];
|
|
@@ -4021,7 +4360,7 @@ function useVoiceController(path, options = {}) {
|
|
|
4021
4360
|
unsubscribe();
|
|
4022
4361
|
controller.close();
|
|
4023
4362
|
};
|
|
4024
|
-
|
|
4363
|
+
onUnmounted12(destroy);
|
|
4025
4364
|
return {
|
|
4026
4365
|
assistantAudio,
|
|
4027
4366
|
assistantTexts,
|
|
@@ -4044,7 +4383,7 @@ function useVoiceController(path, options = {}) {
|
|
|
4044
4383
|
};
|
|
4045
4384
|
}
|
|
4046
4385
|
// src/vue/useVoiceTraceTimeline.ts
|
|
4047
|
-
import { onUnmounted as
|
|
4386
|
+
import { onUnmounted as onUnmounted13, ref as ref9, shallowRef as shallowRef12 } from "vue";
|
|
4048
4387
|
|
|
4049
4388
|
// src/client/traceTimeline.ts
|
|
4050
4389
|
var fetchVoiceTraceTimeline = async (path = "/api/voice-traces", options = {}) => {
|
|
@@ -4129,10 +4468,10 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
|
|
|
4129
4468
|
// src/vue/useVoiceTraceTimeline.ts
|
|
4130
4469
|
function useVoiceTraceTimeline(path = "/api/voice-traces", options = {}) {
|
|
4131
4470
|
const store = createVoiceTraceTimelineStore(path, options);
|
|
4132
|
-
const error =
|
|
4133
|
-
const isLoading =
|
|
4134
|
-
const report =
|
|
4135
|
-
const updatedAt =
|
|
4471
|
+
const error = ref9(null);
|
|
4472
|
+
const isLoading = ref9(false);
|
|
4473
|
+
const report = shallowRef12(null);
|
|
4474
|
+
const updatedAt = ref9(undefined);
|
|
4136
4475
|
const sync = () => {
|
|
4137
4476
|
const snapshot = store.getSnapshot();
|
|
4138
4477
|
error.value = snapshot.error;
|
|
@@ -4143,7 +4482,7 @@ function useVoiceTraceTimeline(path = "/api/voice-traces", options = {}) {
|
|
|
4143
4482
|
const unsubscribe = store.subscribe(sync);
|
|
4144
4483
|
sync();
|
|
4145
4484
|
store.refresh().catch(() => {});
|
|
4146
|
-
|
|
4485
|
+
onUnmounted13(() => {
|
|
4147
4486
|
unsubscribe();
|
|
4148
4487
|
store.close();
|
|
4149
4488
|
});
|
|
@@ -4156,7 +4495,7 @@ function useVoiceTraceTimeline(path = "/api/voice-traces", options = {}) {
|
|
|
4156
4495
|
};
|
|
4157
4496
|
}
|
|
4158
4497
|
// src/vue/useVoiceWorkflowStatus.ts
|
|
4159
|
-
import { onUnmounted as
|
|
4498
|
+
import { onUnmounted as onUnmounted14, ref as ref10, shallowRef as shallowRef13 } from "vue";
|
|
4160
4499
|
|
|
4161
4500
|
// src/client/workflowStatus.ts
|
|
4162
4501
|
var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
|
|
@@ -4240,10 +4579,10 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
|
|
|
4240
4579
|
// src/vue/useVoiceWorkflowStatus.ts
|
|
4241
4580
|
function useVoiceWorkflowStatus(path = "/evals/scenarios/json", options = {}) {
|
|
4242
4581
|
const store = createVoiceWorkflowStatusStore(path, options);
|
|
4243
|
-
const error =
|
|
4244
|
-
const isLoading =
|
|
4245
|
-
const report =
|
|
4246
|
-
const updatedAt =
|
|
4582
|
+
const error = ref10(null);
|
|
4583
|
+
const isLoading = ref10(false);
|
|
4584
|
+
const report = shallowRef13(undefined);
|
|
4585
|
+
const updatedAt = ref10(undefined);
|
|
4247
4586
|
const sync = () => {
|
|
4248
4587
|
const snapshot = store.getSnapshot();
|
|
4249
4588
|
error.value = snapshot.error;
|
|
@@ -4256,7 +4595,7 @@ function useVoiceWorkflowStatus(path = "/evals/scenarios/json", options = {}) {
|
|
|
4256
4595
|
if (typeof window !== "undefined") {
|
|
4257
4596
|
store.refresh().catch(() => {});
|
|
4258
4597
|
}
|
|
4259
|
-
|
|
4598
|
+
onUnmounted14(() => {
|
|
4260
4599
|
unsubscribe();
|
|
4261
4600
|
store.close();
|
|
4262
4601
|
});
|
|
@@ -4279,6 +4618,7 @@ export {
|
|
|
4279
4618
|
useVoiceProviderSimulationControls,
|
|
4280
4619
|
useVoiceProviderCapabilities,
|
|
4281
4620
|
useVoiceOpsStatus,
|
|
4621
|
+
useVoiceOpsActionCenter,
|
|
4282
4622
|
useVoiceDeliveryRuntime,
|
|
4283
4623
|
useVoiceController,
|
|
4284
4624
|
useVoiceCampaignDialerProof,
|
|
@@ -4289,5 +4629,6 @@ export {
|
|
|
4289
4629
|
VoiceProviderSimulationControls,
|
|
4290
4630
|
VoiceProviderCapabilities,
|
|
4291
4631
|
VoiceOpsStatus,
|
|
4632
|
+
VoiceOpsActionCenter,
|
|
4292
4633
|
VoiceDeliveryRuntime
|
|
4293
4634
|
};
|