@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/react/index.js
CHANGED
|
@@ -387,6 +387,326 @@ var VoiceOpsStatus = ({
|
|
|
387
387
|
]
|
|
388
388
|
}, undefined, true, undefined, this);
|
|
389
389
|
};
|
|
390
|
+
// src/client/opsActionCenter.ts
|
|
391
|
+
var createVoiceOpsActionCenterActions = (options = {}) => {
|
|
392
|
+
const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
|
|
393
|
+
const actions = [];
|
|
394
|
+
if (options.includeProductionReadiness !== false) {
|
|
395
|
+
actions.push({
|
|
396
|
+
description: "Refresh the production readiness report.",
|
|
397
|
+
id: "production-readiness",
|
|
398
|
+
label: "Refresh readiness",
|
|
399
|
+
method: "GET",
|
|
400
|
+
path: options.productionReadinessPath ?? "/api/production-readiness"
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
if (options.includeDeliveryRuntime !== false) {
|
|
404
|
+
actions.push({
|
|
405
|
+
description: "Drain pending and failed audit/trace deliveries.",
|
|
406
|
+
id: "delivery-runtime.tick",
|
|
407
|
+
label: "Tick delivery workers",
|
|
408
|
+
method: "POST",
|
|
409
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/tick`
|
|
410
|
+
}, {
|
|
411
|
+
description: "Move reviewed dead letters back to live delivery queues.",
|
|
412
|
+
id: "delivery-runtime.requeue-dead-letters",
|
|
413
|
+
label: "Requeue dead letters",
|
|
414
|
+
method: "POST",
|
|
415
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/requeue-dead-letters`
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
if (options.includeTurnLatencyProof !== false) {
|
|
419
|
+
actions.push({
|
|
420
|
+
description: "Run the synthetic turn latency proof.",
|
|
421
|
+
id: "turn-latency.proof",
|
|
422
|
+
label: "Run latency proof",
|
|
423
|
+
method: "POST",
|
|
424
|
+
path: options.turnLatencyProofPath ?? "/api/turn-latency/proof"
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
if (options.includeProviderSimulation !== false) {
|
|
428
|
+
const pathPrefix = options.providerSimulationPathPrefix ?? "/api/stt-simulate";
|
|
429
|
+
for (const provider of options.providers ?? []) {
|
|
430
|
+
actions.push({
|
|
431
|
+
description: `Simulate ${provider} provider failure.`,
|
|
432
|
+
id: `provider.${provider}.failure`,
|
|
433
|
+
label: `Simulate ${provider} failure`,
|
|
434
|
+
method: "POST",
|
|
435
|
+
path: `${pathPrefix}/failure?provider=${encodeURIComponent(provider)}`
|
|
436
|
+
}, {
|
|
437
|
+
description: `Mark ${provider} provider recovered.`,
|
|
438
|
+
id: `provider.${provider}.recovery`,
|
|
439
|
+
label: `Recover ${provider}`,
|
|
440
|
+
method: "POST",
|
|
441
|
+
path: `${pathPrefix}/recovery?provider=${encodeURIComponent(provider)}`
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return actions;
|
|
446
|
+
};
|
|
447
|
+
var runVoiceOpsAction = async (action, options = {}) => {
|
|
448
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
449
|
+
const response = await fetchImpl(action.path, {
|
|
450
|
+
method: action.method ?? "POST"
|
|
451
|
+
});
|
|
452
|
+
const body = await response.json().catch(() => null);
|
|
453
|
+
if (!response.ok) {
|
|
454
|
+
const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
|
|
455
|
+
throw new Error(message);
|
|
456
|
+
}
|
|
457
|
+
return {
|
|
458
|
+
actionId: action.id,
|
|
459
|
+
body,
|
|
460
|
+
ok: response.ok,
|
|
461
|
+
ranAt: Date.now(),
|
|
462
|
+
status: response.status
|
|
463
|
+
};
|
|
464
|
+
};
|
|
465
|
+
var createVoiceOpsActionCenterStore = (options = {}) => {
|
|
466
|
+
const listeners = new Set;
|
|
467
|
+
let closed = false;
|
|
468
|
+
let timer;
|
|
469
|
+
let snapshot = {
|
|
470
|
+
actions: options.actions ?? createVoiceOpsActionCenterActions(),
|
|
471
|
+
error: null,
|
|
472
|
+
isRunning: false
|
|
473
|
+
};
|
|
474
|
+
const emit = () => {
|
|
475
|
+
for (const listener of listeners) {
|
|
476
|
+
listener();
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
const setActions = (actions) => {
|
|
480
|
+
snapshot = { ...snapshot, actions, updatedAt: Date.now() };
|
|
481
|
+
emit();
|
|
482
|
+
};
|
|
483
|
+
const run = async (actionId) => {
|
|
484
|
+
if (closed) {
|
|
485
|
+
return snapshot.lastResult;
|
|
486
|
+
}
|
|
487
|
+
const action = snapshot.actions.find((item) => item.id === actionId);
|
|
488
|
+
if (!action) {
|
|
489
|
+
throw new Error(`Voice ops action "${actionId}" is not configured.`);
|
|
490
|
+
}
|
|
491
|
+
if (action.disabled) {
|
|
492
|
+
throw new Error(`Voice ops action "${actionId}" is disabled.`);
|
|
493
|
+
}
|
|
494
|
+
snapshot = {
|
|
495
|
+
...snapshot,
|
|
496
|
+
error: null,
|
|
497
|
+
isRunning: true,
|
|
498
|
+
runningActionId: action.id
|
|
499
|
+
};
|
|
500
|
+
emit();
|
|
501
|
+
try {
|
|
502
|
+
const result = await runVoiceOpsAction(action, options);
|
|
503
|
+
snapshot = {
|
|
504
|
+
...snapshot,
|
|
505
|
+
error: null,
|
|
506
|
+
isRunning: false,
|
|
507
|
+
lastResult: result,
|
|
508
|
+
runningActionId: undefined,
|
|
509
|
+
updatedAt: Date.now()
|
|
510
|
+
};
|
|
511
|
+
emit();
|
|
512
|
+
return result;
|
|
513
|
+
} catch (error) {
|
|
514
|
+
snapshot = {
|
|
515
|
+
...snapshot,
|
|
516
|
+
error: error instanceof Error ? error.message : String(error),
|
|
517
|
+
isRunning: false,
|
|
518
|
+
runningActionId: undefined
|
|
519
|
+
};
|
|
520
|
+
emit();
|
|
521
|
+
throw error;
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
const close = () => {
|
|
525
|
+
closed = true;
|
|
526
|
+
if (timer) {
|
|
527
|
+
clearInterval(timer);
|
|
528
|
+
timer = undefined;
|
|
529
|
+
}
|
|
530
|
+
listeners.clear();
|
|
531
|
+
};
|
|
532
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
533
|
+
timer = setInterval(() => {
|
|
534
|
+
emit();
|
|
535
|
+
}, options.intervalMs);
|
|
536
|
+
}
|
|
537
|
+
return {
|
|
538
|
+
close,
|
|
539
|
+
getServerSnapshot: () => snapshot,
|
|
540
|
+
getSnapshot: () => snapshot,
|
|
541
|
+
run,
|
|
542
|
+
setActions,
|
|
543
|
+
subscribe: (listener) => {
|
|
544
|
+
listeners.add(listener);
|
|
545
|
+
return () => {
|
|
546
|
+
listeners.delete(listener);
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
// src/client/opsActionCenterWidget.ts
|
|
553
|
+
var DEFAULT_TITLE2 = "Voice Ops Action Center";
|
|
554
|
+
var DEFAULT_DESCRIPTION2 = "Run production voice proofs and operator actions from one primitive panel.";
|
|
555
|
+
var escapeHtml2 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
556
|
+
var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
557
|
+
const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
|
|
558
|
+
return {
|
|
559
|
+
actions: snapshot.actions.map((action) => ({
|
|
560
|
+
description: action.description ?? "",
|
|
561
|
+
disabled: Boolean(action.disabled || snapshot.isRunning),
|
|
562
|
+
id: action.id,
|
|
563
|
+
isRunning: snapshot.runningActionId === action.id,
|
|
564
|
+
label: action.label
|
|
565
|
+
})),
|
|
566
|
+
description: options.description ?? DEFAULT_DESCRIPTION2,
|
|
567
|
+
error: snapshot.error,
|
|
568
|
+
isRunning: snapshot.isRunning,
|
|
569
|
+
label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
|
|
570
|
+
lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
|
|
571
|
+
status,
|
|
572
|
+
title: options.title ?? DEFAULT_TITLE2
|
|
573
|
+
};
|
|
574
|
+
};
|
|
575
|
+
var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
|
|
576
|
+
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
577
|
+
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml2(action.id)}"${action.disabled ? " disabled" : ""}>
|
|
578
|
+
${escapeHtml2(action.isRunning ? "Working..." : action.label)}
|
|
579
|
+
</button>`).join("");
|
|
580
|
+
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml2(model.status)}">
|
|
581
|
+
<header class="absolute-voice-ops-action-center__header">
|
|
582
|
+
<span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml2(model.title)}</span>
|
|
583
|
+
<strong class="absolute-voice-ops-action-center__label">${escapeHtml2(model.label)}</strong>
|
|
584
|
+
</header>
|
|
585
|
+
<p class="absolute-voice-ops-action-center__description">${escapeHtml2(model.description)}</p>
|
|
586
|
+
<div class="absolute-voice-ops-action-center__actions">${actions}</div>
|
|
587
|
+
<p class="absolute-voice-ops-action-center__result">${escapeHtml2(model.lastResultLabel)}</p>
|
|
588
|
+
${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml2(model.error)}</p>` : ""}
|
|
589
|
+
</section>`;
|
|
590
|
+
};
|
|
591
|
+
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}`;
|
|
592
|
+
var mountVoiceOpsActionCenter = (element, options = {}) => {
|
|
593
|
+
const store = createVoiceOpsActionCenterStore(options);
|
|
594
|
+
const render = () => {
|
|
595
|
+
element.innerHTML = renderVoiceOpsActionCenterHTML(store.getSnapshot(), options);
|
|
596
|
+
};
|
|
597
|
+
const unsubscribe = store.subscribe(render);
|
|
598
|
+
const handleClick = (event) => {
|
|
599
|
+
const target = event.target;
|
|
600
|
+
if (!(target instanceof Element)) {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
const action = target.closest("[data-absolute-voice-ops-action]");
|
|
604
|
+
const actionId = action?.getAttribute("data-absolute-voice-ops-action");
|
|
605
|
+
if (actionId) {
|
|
606
|
+
store.run(actionId).catch(() => {});
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
element.addEventListener?.("click", handleClick);
|
|
610
|
+
render();
|
|
611
|
+
return {
|
|
612
|
+
close: () => {
|
|
613
|
+
element.removeEventListener?.("click", handleClick);
|
|
614
|
+
unsubscribe();
|
|
615
|
+
store.close();
|
|
616
|
+
},
|
|
617
|
+
run: store.run
|
|
618
|
+
};
|
|
619
|
+
};
|
|
620
|
+
var defineVoiceOpsActionCenterElement = (tagName = "absolute-voice-ops-action-center", options = {}) => {
|
|
621
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
customElements.define(tagName, class AbsoluteVoiceOpsActionCenterElement extends HTMLElement {
|
|
625
|
+
mounted;
|
|
626
|
+
connectedCallback() {
|
|
627
|
+
this.mounted = mountVoiceOpsActionCenter(this, {
|
|
628
|
+
...options,
|
|
629
|
+
description: this.getAttribute("description") ?? options.description,
|
|
630
|
+
title: this.getAttribute("title") ?? options.title
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
disconnectedCallback() {
|
|
634
|
+
this.mounted?.close();
|
|
635
|
+
this.mounted = undefined;
|
|
636
|
+
}
|
|
637
|
+
});
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
// src/react/useVoiceOpsActionCenter.tsx
|
|
641
|
+
import { useEffect as useEffect2, useRef as useRef2, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
642
|
+
var useVoiceOpsActionCenter = (options = {}) => {
|
|
643
|
+
const storeRef = useRef2(null);
|
|
644
|
+
if (!storeRef.current) {
|
|
645
|
+
storeRef.current = createVoiceOpsActionCenterStore(options);
|
|
646
|
+
}
|
|
647
|
+
const store = storeRef.current;
|
|
648
|
+
useEffect2(() => () => store.close(), [store]);
|
|
649
|
+
return {
|
|
650
|
+
...useSyncExternalStore2(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
651
|
+
run: store.run,
|
|
652
|
+
setActions: store.setActions
|
|
653
|
+
};
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
// src/react/VoiceOpsActionCenter.tsx
|
|
657
|
+
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
658
|
+
var VoiceOpsActionCenter = ({
|
|
659
|
+
className,
|
|
660
|
+
...options
|
|
661
|
+
}) => {
|
|
662
|
+
const snapshot = useVoiceOpsActionCenter(options);
|
|
663
|
+
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
664
|
+
return /* @__PURE__ */ jsxDEV2("section", {
|
|
665
|
+
className: [
|
|
666
|
+
"absolute-voice-ops-action-center",
|
|
667
|
+
`absolute-voice-ops-action-center--${model.status}`,
|
|
668
|
+
className
|
|
669
|
+
].filter(Boolean).join(" "),
|
|
670
|
+
children: [
|
|
671
|
+
/* @__PURE__ */ jsxDEV2("header", {
|
|
672
|
+
className: "absolute-voice-ops-action-center__header",
|
|
673
|
+
children: [
|
|
674
|
+
/* @__PURE__ */ jsxDEV2("span", {
|
|
675
|
+
className: "absolute-voice-ops-action-center__eyebrow",
|
|
676
|
+
children: model.title
|
|
677
|
+
}, undefined, false, undefined, this),
|
|
678
|
+
/* @__PURE__ */ jsxDEV2("strong", {
|
|
679
|
+
className: "absolute-voice-ops-action-center__label",
|
|
680
|
+
children: model.label
|
|
681
|
+
}, undefined, false, undefined, this)
|
|
682
|
+
]
|
|
683
|
+
}, undefined, true, undefined, this),
|
|
684
|
+
/* @__PURE__ */ jsxDEV2("p", {
|
|
685
|
+
className: "absolute-voice-ops-action-center__description",
|
|
686
|
+
children: model.description
|
|
687
|
+
}, undefined, false, undefined, this),
|
|
688
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
689
|
+
className: "absolute-voice-ops-action-center__actions",
|
|
690
|
+
children: model.actions.map((action) => /* @__PURE__ */ jsxDEV2("button", {
|
|
691
|
+
disabled: action.disabled,
|
|
692
|
+
onClick: () => {
|
|
693
|
+
snapshot.run(action.id).catch(() => {});
|
|
694
|
+
},
|
|
695
|
+
type: "button",
|
|
696
|
+
children: action.isRunning ? "Working..." : action.label
|
|
697
|
+
}, action.id, false, undefined, this))
|
|
698
|
+
}, undefined, false, undefined, this),
|
|
699
|
+
/* @__PURE__ */ jsxDEV2("p", {
|
|
700
|
+
className: "absolute-voice-ops-action-center__result",
|
|
701
|
+
children: model.lastResultLabel
|
|
702
|
+
}, undefined, false, undefined, this),
|
|
703
|
+
model.error ? /* @__PURE__ */ jsxDEV2("p", {
|
|
704
|
+
className: "absolute-voice-ops-action-center__error",
|
|
705
|
+
children: model.error
|
|
706
|
+
}, undefined, false, undefined, this) : null
|
|
707
|
+
]
|
|
708
|
+
}, undefined, true, undefined, this);
|
|
709
|
+
};
|
|
390
710
|
// src/client/deliveryRuntime.ts
|
|
391
711
|
var getDefaultActionPath = (path, action, options) => {
|
|
392
712
|
if (action === "tick") {
|
|
@@ -525,9 +845,9 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
|
|
|
525
845
|
};
|
|
526
846
|
|
|
527
847
|
// src/client/deliveryRuntimeWidget.ts
|
|
528
|
-
var
|
|
529
|
-
var
|
|
530
|
-
var
|
|
848
|
+
var DEFAULT_TITLE3 = "Voice Delivery Runtime";
|
|
849
|
+
var DEFAULT_DESCRIPTION3 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
850
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
531
851
|
var createSurface = (id, summary) => {
|
|
532
852
|
if (!summary) {
|
|
533
853
|
return {
|
|
@@ -561,7 +881,7 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
561
881
|
];
|
|
562
882
|
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
563
883
|
return {
|
|
564
|
-
description: options.description ??
|
|
884
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
565
885
|
error: snapshot.error,
|
|
566
886
|
actionError: snapshot.actionError,
|
|
567
887
|
actionStatus: snapshot.actionStatus,
|
|
@@ -570,32 +890,32 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
570
890
|
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
571
891
|
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
572
892
|
surfaces,
|
|
573
|
-
title: options.title ??
|
|
893
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
574
894
|
updatedAt: snapshot.updatedAt
|
|
575
895
|
};
|
|
576
896
|
};
|
|
577
897
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
578
898
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
579
|
-
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${
|
|
580
|
-
<span>${
|
|
581
|
-
<strong>${
|
|
899
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml3(surface.status)}">
|
|
900
|
+
<span>${escapeHtml3(surface.label)}</span>
|
|
901
|
+
<strong>${escapeHtml3(surface.detail)}</strong>
|
|
582
902
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
583
903
|
</li>`).join("");
|
|
584
904
|
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
585
905
|
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
586
906
|
<button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
|
|
587
907
|
</div>`;
|
|
588
|
-
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
589
|
-
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${
|
|
908
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.actionError)}</p>` : "";
|
|
909
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml3(model.status)}">
|
|
590
910
|
<header class="absolute-voice-delivery-runtime__header">
|
|
591
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
592
|
-
<strong class="absolute-voice-delivery-runtime__label">${
|
|
911
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml3(model.title)}</span>
|
|
912
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml3(model.label)}</strong>
|
|
593
913
|
</header>
|
|
594
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
914
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml3(model.description)}</p>
|
|
595
915
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
596
916
|
${actions}
|
|
597
917
|
${actionError}
|
|
598
|
-
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
918
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.error)}</p>` : ""}
|
|
599
919
|
</section>`;
|
|
600
920
|
};
|
|
601
921
|
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}`;
|
|
@@ -653,19 +973,19 @@ var defineVoiceDeliveryRuntimeElement = (tagName = "absolute-voice-delivery-runt
|
|
|
653
973
|
};
|
|
654
974
|
|
|
655
975
|
// src/react/useVoiceDeliveryRuntime.tsx
|
|
656
|
-
import { useEffect as
|
|
976
|
+
import { useEffect as useEffect3, useRef as useRef3, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
657
977
|
var useVoiceDeliveryRuntime = (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
658
|
-
const storeRef =
|
|
978
|
+
const storeRef = useRef3(null);
|
|
659
979
|
if (!storeRef.current) {
|
|
660
980
|
storeRef.current = createVoiceDeliveryRuntimeStore(path, options);
|
|
661
981
|
}
|
|
662
982
|
const store = storeRef.current;
|
|
663
|
-
|
|
983
|
+
useEffect3(() => {
|
|
664
984
|
store.refresh().catch(() => {});
|
|
665
985
|
return () => store.close();
|
|
666
986
|
}, [store]);
|
|
667
987
|
return {
|
|
668
|
-
...
|
|
988
|
+
...useSyncExternalStore3(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
669
989
|
requeueDeadLetters: store.requeueDeadLetters,
|
|
670
990
|
refresh: store.refresh,
|
|
671
991
|
tick: store.tick
|
|
@@ -673,7 +993,7 @@ var useVoiceDeliveryRuntime = (path = "/api/voice-delivery-runtime", options = {
|
|
|
673
993
|
};
|
|
674
994
|
|
|
675
995
|
// src/react/VoiceDeliveryRuntime.tsx
|
|
676
|
-
import { jsxDEV as
|
|
996
|
+
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
677
997
|
var VoiceDeliveryRuntime = ({
|
|
678
998
|
className,
|
|
679
999
|
includeActions = true,
|
|
@@ -683,42 +1003,42 @@ var VoiceDeliveryRuntime = ({
|
|
|
683
1003
|
const snapshot = useVoiceDeliveryRuntime(path, options);
|
|
684
1004
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
685
1005
|
const hasDeadLetters = model.surfaces.some((surface) => surface.deadLettered > 0);
|
|
686
|
-
return /* @__PURE__ */
|
|
1006
|
+
return /* @__PURE__ */ jsxDEV3("section", {
|
|
687
1007
|
className: [
|
|
688
1008
|
"absolute-voice-delivery-runtime",
|
|
689
1009
|
`absolute-voice-delivery-runtime--${model.status}`,
|
|
690
1010
|
className
|
|
691
1011
|
].filter(Boolean).join(" "),
|
|
692
1012
|
children: [
|
|
693
|
-
/* @__PURE__ */
|
|
1013
|
+
/* @__PURE__ */ jsxDEV3("header", {
|
|
694
1014
|
className: "absolute-voice-delivery-runtime__header",
|
|
695
1015
|
children: [
|
|
696
|
-
/* @__PURE__ */
|
|
1016
|
+
/* @__PURE__ */ jsxDEV3("span", {
|
|
697
1017
|
className: "absolute-voice-delivery-runtime__eyebrow",
|
|
698
1018
|
children: model.title
|
|
699
1019
|
}, undefined, false, undefined, this),
|
|
700
|
-
/* @__PURE__ */
|
|
1020
|
+
/* @__PURE__ */ jsxDEV3("strong", {
|
|
701
1021
|
className: "absolute-voice-delivery-runtime__label",
|
|
702
1022
|
children: model.label
|
|
703
1023
|
}, undefined, false, undefined, this)
|
|
704
1024
|
]
|
|
705
1025
|
}, undefined, true, undefined, this),
|
|
706
|
-
/* @__PURE__ */
|
|
1026
|
+
/* @__PURE__ */ jsxDEV3("p", {
|
|
707
1027
|
className: "absolute-voice-delivery-runtime__description",
|
|
708
1028
|
children: model.description
|
|
709
1029
|
}, undefined, false, undefined, this),
|
|
710
|
-
/* @__PURE__ */
|
|
1030
|
+
/* @__PURE__ */ jsxDEV3("ul", {
|
|
711
1031
|
className: "absolute-voice-delivery-runtime__surfaces",
|
|
712
|
-
children: model.surfaces.map((surface) => /* @__PURE__ */
|
|
1032
|
+
children: model.surfaces.map((surface) => /* @__PURE__ */ jsxDEV3("li", {
|
|
713
1033
|
className: `absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${surface.status}`,
|
|
714
1034
|
children: [
|
|
715
|
-
/* @__PURE__ */
|
|
1035
|
+
/* @__PURE__ */ jsxDEV3("span", {
|
|
716
1036
|
children: surface.label
|
|
717
1037
|
}, undefined, false, undefined, this),
|
|
718
|
-
/* @__PURE__ */
|
|
1038
|
+
/* @__PURE__ */ jsxDEV3("strong", {
|
|
719
1039
|
children: surface.detail
|
|
720
1040
|
}, undefined, false, undefined, this),
|
|
721
|
-
/* @__PURE__ */
|
|
1041
|
+
/* @__PURE__ */ jsxDEV3("small", {
|
|
722
1042
|
children: [
|
|
723
1043
|
surface.failed,
|
|
724
1044
|
" failed / ",
|
|
@@ -729,10 +1049,10 @@ var VoiceDeliveryRuntime = ({
|
|
|
729
1049
|
]
|
|
730
1050
|
}, surface.id, true, undefined, this))
|
|
731
1051
|
}, undefined, false, undefined, this),
|
|
732
|
-
includeActions ? /* @__PURE__ */
|
|
1052
|
+
includeActions ? /* @__PURE__ */ jsxDEV3("div", {
|
|
733
1053
|
className: "absolute-voice-delivery-runtime__actions",
|
|
734
1054
|
children: [
|
|
735
|
-
/* @__PURE__ */
|
|
1055
|
+
/* @__PURE__ */ jsxDEV3("button", {
|
|
736
1056
|
disabled: model.actionStatus === "running",
|
|
737
1057
|
onClick: () => {
|
|
738
1058
|
snapshot.tick().catch(() => {});
|
|
@@ -740,7 +1060,7 @@ var VoiceDeliveryRuntime = ({
|
|
|
740
1060
|
type: "button",
|
|
741
1061
|
children: model.actionStatus === "running" ? "Working..." : "Tick workers"
|
|
742
1062
|
}, undefined, false, undefined, this),
|
|
743
|
-
/* @__PURE__ */
|
|
1063
|
+
/* @__PURE__ */ jsxDEV3("button", {
|
|
744
1064
|
disabled: model.actionStatus === "running" || !hasDeadLetters,
|
|
745
1065
|
onClick: () => {
|
|
746
1066
|
snapshot.requeueDeadLetters().catch(() => {});
|
|
@@ -750,11 +1070,11 @@ var VoiceDeliveryRuntime = ({
|
|
|
750
1070
|
}, undefined, false, undefined, this)
|
|
751
1071
|
]
|
|
752
1072
|
}, undefined, true, undefined, this) : null,
|
|
753
|
-
model.actionError ? /* @__PURE__ */
|
|
1073
|
+
model.actionError ? /* @__PURE__ */ jsxDEV3("p", {
|
|
754
1074
|
className: "absolute-voice-delivery-runtime__error",
|
|
755
1075
|
children: model.actionError
|
|
756
1076
|
}, undefined, false, undefined, this) : null,
|
|
757
|
-
model.error ? /* @__PURE__ */
|
|
1077
|
+
model.error ? /* @__PURE__ */ jsxDEV3("p", {
|
|
758
1078
|
className: "absolute-voice-delivery-runtime__error",
|
|
759
1079
|
children: model.error
|
|
760
1080
|
}, undefined, false, undefined, this) : null
|
|
@@ -841,7 +1161,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
841
1161
|
};
|
|
842
1162
|
|
|
843
1163
|
// src/client/providerSimulationControlsWidget.ts
|
|
844
|
-
var
|
|
1164
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
845
1165
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
846
1166
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
847
1167
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -861,18 +1181,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
861
1181
|
};
|
|
862
1182
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
863
1183
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
864
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
865
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
1184
|
+
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("");
|
|
1185
|
+
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("");
|
|
866
1186
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
867
1187
|
<header class="absolute-voice-provider-simulation__header">
|
|
868
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
869
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
1188
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml4(model.title)}</span>
|
|
1189
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml4(model.label)}</strong>
|
|
870
1190
|
</header>
|
|
871
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
872
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
1191
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml4(model.description)}</p>
|
|
1192
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml4(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
873
1193
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
874
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
875
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
1194
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml4(snapshot.error)}</p>` : ""}
|
|
1195
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml4(model.resultText)}</pre>` : ""}
|
|
876
1196
|
</section>`;
|
|
877
1197
|
};
|
|
878
1198
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -938,22 +1258,22 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
938
1258
|
};
|
|
939
1259
|
|
|
940
1260
|
// src/react/useVoiceProviderSimulationControls.tsx
|
|
941
|
-
import { useEffect as
|
|
1261
|
+
import { useEffect as useEffect4, useRef as useRef4, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
942
1262
|
var useVoiceProviderSimulationControls = (options) => {
|
|
943
|
-
const storeRef =
|
|
1263
|
+
const storeRef = useRef4(null);
|
|
944
1264
|
if (!storeRef.current) {
|
|
945
1265
|
storeRef.current = createVoiceProviderSimulationControlsStore(options);
|
|
946
1266
|
}
|
|
947
1267
|
const store = storeRef.current;
|
|
948
|
-
|
|
1268
|
+
useEffect4(() => () => store.close(), [store]);
|
|
949
1269
|
return {
|
|
950
|
-
...
|
|
1270
|
+
...useSyncExternalStore4(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
951
1271
|
run: store.run
|
|
952
1272
|
};
|
|
953
1273
|
};
|
|
954
1274
|
|
|
955
1275
|
// src/react/VoiceProviderSimulationControls.tsx
|
|
956
|
-
import { jsxDEV as
|
|
1276
|
+
import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
|
|
957
1277
|
var VoiceProviderSimulationControls = ({
|
|
958
1278
|
className,
|
|
959
1279
|
...options
|
|
@@ -963,38 +1283,38 @@ var VoiceProviderSimulationControls = ({
|
|
|
963
1283
|
const run = (provider, mode) => {
|
|
964
1284
|
snapshot.run(provider, mode).catch(() => {});
|
|
965
1285
|
};
|
|
966
|
-
return /* @__PURE__ */
|
|
1286
|
+
return /* @__PURE__ */ jsxDEV4("section", {
|
|
967
1287
|
className: [
|
|
968
1288
|
"absolute-voice-provider-simulation",
|
|
969
1289
|
`absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}`,
|
|
970
1290
|
className
|
|
971
1291
|
].filter(Boolean).join(" "),
|
|
972
1292
|
children: [
|
|
973
|
-
/* @__PURE__ */
|
|
1293
|
+
/* @__PURE__ */ jsxDEV4("header", {
|
|
974
1294
|
className: "absolute-voice-provider-simulation__header",
|
|
975
1295
|
children: [
|
|
976
|
-
/* @__PURE__ */
|
|
1296
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
977
1297
|
className: "absolute-voice-provider-simulation__eyebrow",
|
|
978
1298
|
children: model.title
|
|
979
1299
|
}, undefined, false, undefined, this),
|
|
980
|
-
/* @__PURE__ */
|
|
1300
|
+
/* @__PURE__ */ jsxDEV4("strong", {
|
|
981
1301
|
className: "absolute-voice-provider-simulation__label",
|
|
982
1302
|
children: model.label
|
|
983
1303
|
}, undefined, false, undefined, this)
|
|
984
1304
|
]
|
|
985
1305
|
}, undefined, true, undefined, this),
|
|
986
|
-
/* @__PURE__ */
|
|
1306
|
+
/* @__PURE__ */ jsxDEV4("p", {
|
|
987
1307
|
className: "absolute-voice-provider-simulation__description",
|
|
988
1308
|
children: model.description
|
|
989
1309
|
}, undefined, false, undefined, this),
|
|
990
|
-
model.canSimulateFailure ? null : /* @__PURE__ */
|
|
1310
|
+
model.canSimulateFailure ? null : /* @__PURE__ */ jsxDEV4("p", {
|
|
991
1311
|
className: "absolute-voice-provider-simulation__empty",
|
|
992
1312
|
children: options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure."
|
|
993
1313
|
}, undefined, false, undefined, this),
|
|
994
|
-
/* @__PURE__ */
|
|
1314
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
995
1315
|
className: "absolute-voice-provider-simulation__actions",
|
|
996
1316
|
children: [
|
|
997
|
-
model.failureProviders.map((provider) => /* @__PURE__ */
|
|
1317
|
+
model.failureProviders.map((provider) => /* @__PURE__ */ jsxDEV4("button", {
|
|
998
1318
|
disabled: !model.canSimulateFailure || snapshot.isRunning,
|
|
999
1319
|
onClick: () => run(provider.provider, "failure"),
|
|
1000
1320
|
type: "button",
|
|
@@ -1007,7 +1327,7 @@ var VoiceProviderSimulationControls = ({
|
|
|
1007
1327
|
"failure"
|
|
1008
1328
|
]
|
|
1009
1329
|
}, `fail-${provider.provider}`, true, undefined, this)),
|
|
1010
|
-
model.providers.map((provider) => /* @__PURE__ */
|
|
1330
|
+
model.providers.map((provider) => /* @__PURE__ */ jsxDEV4("button", {
|
|
1011
1331
|
disabled: snapshot.isRunning,
|
|
1012
1332
|
onClick: () => run(provider.provider, "recovery"),
|
|
1013
1333
|
type: "button",
|
|
@@ -1019,11 +1339,11 @@ var VoiceProviderSimulationControls = ({
|
|
|
1019
1339
|
}, `recover-${provider.provider}`, true, undefined, this))
|
|
1020
1340
|
]
|
|
1021
1341
|
}, undefined, true, undefined, this),
|
|
1022
|
-
snapshot.error ? /* @__PURE__ */
|
|
1342
|
+
snapshot.error ? /* @__PURE__ */ jsxDEV4("p", {
|
|
1023
1343
|
className: "absolute-voice-provider-simulation__error",
|
|
1024
1344
|
children: snapshot.error
|
|
1025
1345
|
}, undefined, false, undefined, this) : null,
|
|
1026
|
-
model.resultText ? /* @__PURE__ */
|
|
1346
|
+
model.resultText ? /* @__PURE__ */ jsxDEV4("pre", {
|
|
1027
1347
|
className: "absolute-voice-provider-simulation__result",
|
|
1028
1348
|
children: model.resultText
|
|
1029
1349
|
}, undefined, false, undefined, this) : null
|
|
@@ -1031,7 +1351,7 @@ var VoiceProviderSimulationControls = ({
|
|
|
1031
1351
|
}, undefined, true, undefined, this);
|
|
1032
1352
|
};
|
|
1033
1353
|
// src/react/useVoiceProviderCapabilities.tsx
|
|
1034
|
-
import { useEffect as
|
|
1354
|
+
import { useEffect as useEffect5, useRef as useRef5, useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
1035
1355
|
|
|
1036
1356
|
// src/client/providerCapabilities.ts
|
|
1037
1357
|
var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
|
|
@@ -1114,25 +1434,25 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
|
|
|
1114
1434
|
|
|
1115
1435
|
// src/react/useVoiceProviderCapabilities.tsx
|
|
1116
1436
|
var useVoiceProviderCapabilities = (path = "/api/provider-capabilities", options = {}) => {
|
|
1117
|
-
const storeRef =
|
|
1437
|
+
const storeRef = useRef5(null);
|
|
1118
1438
|
if (!storeRef.current) {
|
|
1119
1439
|
storeRef.current = createVoiceProviderCapabilitiesStore(path, options);
|
|
1120
1440
|
}
|
|
1121
1441
|
const store = storeRef.current;
|
|
1122
|
-
|
|
1442
|
+
useEffect5(() => {
|
|
1123
1443
|
store.refresh().catch(() => {});
|
|
1124
1444
|
return () => store.close();
|
|
1125
1445
|
}, [store]);
|
|
1126
1446
|
return {
|
|
1127
|
-
...
|
|
1447
|
+
...useSyncExternalStore5(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1128
1448
|
refresh: store.refresh
|
|
1129
1449
|
};
|
|
1130
1450
|
};
|
|
1131
1451
|
|
|
1132
1452
|
// src/client/providerCapabilitiesWidget.ts
|
|
1133
|
-
var
|
|
1134
|
-
var
|
|
1135
|
-
var
|
|
1453
|
+
var DEFAULT_TITLE4 = "Provider Capabilities";
|
|
1454
|
+
var DEFAULT_DESCRIPTION4 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
1455
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1136
1456
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1137
1457
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
1138
1458
|
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -1176,36 +1496,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
1176
1496
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
1177
1497
|
return {
|
|
1178
1498
|
capabilities,
|
|
1179
|
-
description: options.description ??
|
|
1499
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
1180
1500
|
error: snapshot.error,
|
|
1181
1501
|
isLoading: snapshot.isLoading,
|
|
1182
1502
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
1183
1503
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1184
|
-
title: options.title ??
|
|
1504
|
+
title: options.title ?? DEFAULT_TITLE4,
|
|
1185
1505
|
updatedAt: snapshot.updatedAt
|
|
1186
1506
|
};
|
|
1187
1507
|
};
|
|
1188
1508
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
1189
1509
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
1190
|
-
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--${
|
|
1510
|
+
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)}">
|
|
1191
1511
|
<header>
|
|
1192
|
-
<strong>${
|
|
1193
|
-
<span>${
|
|
1512
|
+
<strong>${escapeHtml5(capability.label)}</strong>
|
|
1513
|
+
<span>${escapeHtml5(formatStatus(capability.status))}</span>
|
|
1194
1514
|
</header>
|
|
1195
|
-
<p>${
|
|
1515
|
+
<p>${escapeHtml5(capability.detail)}</p>
|
|
1196
1516
|
<dl>${capability.rows.map((row) => `<div>
|
|
1197
|
-
<dt>${
|
|
1198
|
-
<dd>${
|
|
1517
|
+
<dt>${escapeHtml5(row.label)}</dt>
|
|
1518
|
+
<dd>${escapeHtml5(row.value)}</dd>
|
|
1199
1519
|
</div>`).join("")}</dl>
|
|
1200
1520
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
1201
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
1521
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml5(model.status)}">
|
|
1202
1522
|
<header class="absolute-voice-provider-capabilities__header">
|
|
1203
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
1204
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
1523
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml5(model.title)}</span>
|
|
1524
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml5(model.label)}</strong>
|
|
1205
1525
|
</header>
|
|
1206
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
1526
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml5(model.description)}</p>
|
|
1207
1527
|
${capabilities}
|
|
1208
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
1528
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
1209
1529
|
</section>`;
|
|
1210
1530
|
};
|
|
1211
1531
|
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}`;
|
|
@@ -1247,7 +1567,7 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
1247
1567
|
};
|
|
1248
1568
|
|
|
1249
1569
|
// src/react/VoiceProviderCapabilities.tsx
|
|
1250
|
-
import { jsxDEV as
|
|
1570
|
+
import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
|
|
1251
1571
|
var VoiceProviderCapabilities = ({
|
|
1252
1572
|
className,
|
|
1253
1573
|
path = "/api/provider-capabilities",
|
|
@@ -1255,58 +1575,58 @@ var VoiceProviderCapabilities = ({
|
|
|
1255
1575
|
}) => {
|
|
1256
1576
|
const snapshot = useVoiceProviderCapabilities(path, options);
|
|
1257
1577
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
1258
|
-
return /* @__PURE__ */
|
|
1578
|
+
return /* @__PURE__ */ jsxDEV5("section", {
|
|
1259
1579
|
className: [
|
|
1260
1580
|
"absolute-voice-provider-capabilities",
|
|
1261
1581
|
`absolute-voice-provider-capabilities--${model.status}`,
|
|
1262
1582
|
className
|
|
1263
1583
|
].filter(Boolean).join(" "),
|
|
1264
1584
|
children: [
|
|
1265
|
-
/* @__PURE__ */
|
|
1585
|
+
/* @__PURE__ */ jsxDEV5("header", {
|
|
1266
1586
|
className: "absolute-voice-provider-capabilities__header",
|
|
1267
1587
|
children: [
|
|
1268
|
-
/* @__PURE__ */
|
|
1588
|
+
/* @__PURE__ */ jsxDEV5("span", {
|
|
1269
1589
|
className: "absolute-voice-provider-capabilities__eyebrow",
|
|
1270
1590
|
children: model.title
|
|
1271
1591
|
}, undefined, false, undefined, this),
|
|
1272
|
-
/* @__PURE__ */
|
|
1592
|
+
/* @__PURE__ */ jsxDEV5("strong", {
|
|
1273
1593
|
className: "absolute-voice-provider-capabilities__label",
|
|
1274
1594
|
children: model.label
|
|
1275
1595
|
}, undefined, false, undefined, this)
|
|
1276
1596
|
]
|
|
1277
1597
|
}, undefined, true, undefined, this),
|
|
1278
|
-
/* @__PURE__ */
|
|
1598
|
+
/* @__PURE__ */ jsxDEV5("p", {
|
|
1279
1599
|
className: "absolute-voice-provider-capabilities__description",
|
|
1280
1600
|
children: model.description
|
|
1281
1601
|
}, undefined, false, undefined, this),
|
|
1282
|
-
model.capabilities.length ? /* @__PURE__ */
|
|
1602
|
+
model.capabilities.length ? /* @__PURE__ */ jsxDEV5("div", {
|
|
1283
1603
|
className: "absolute-voice-provider-capabilities__providers",
|
|
1284
|
-
children: model.capabilities.map((capability) => /* @__PURE__ */
|
|
1604
|
+
children: model.capabilities.map((capability) => /* @__PURE__ */ jsxDEV5("article", {
|
|
1285
1605
|
className: [
|
|
1286
1606
|
"absolute-voice-provider-capabilities__provider",
|
|
1287
1607
|
`absolute-voice-provider-capabilities__provider--${capability.status}`
|
|
1288
1608
|
].join(" "),
|
|
1289
1609
|
children: [
|
|
1290
|
-
/* @__PURE__ */
|
|
1610
|
+
/* @__PURE__ */ jsxDEV5("header", {
|
|
1291
1611
|
children: [
|
|
1292
|
-
/* @__PURE__ */
|
|
1612
|
+
/* @__PURE__ */ jsxDEV5("strong", {
|
|
1293
1613
|
children: capability.label
|
|
1294
1614
|
}, undefined, false, undefined, this),
|
|
1295
|
-
/* @__PURE__ */
|
|
1615
|
+
/* @__PURE__ */ jsxDEV5("span", {
|
|
1296
1616
|
children: capability.status
|
|
1297
1617
|
}, undefined, false, undefined, this)
|
|
1298
1618
|
]
|
|
1299
1619
|
}, undefined, true, undefined, this),
|
|
1300
|
-
/* @__PURE__ */
|
|
1620
|
+
/* @__PURE__ */ jsxDEV5("p", {
|
|
1301
1621
|
children: capability.detail
|
|
1302
1622
|
}, undefined, false, undefined, this),
|
|
1303
|
-
/* @__PURE__ */
|
|
1304
|
-
children: capability.rows.map((row) => /* @__PURE__ */
|
|
1623
|
+
/* @__PURE__ */ jsxDEV5("dl", {
|
|
1624
|
+
children: capability.rows.map((row) => /* @__PURE__ */ jsxDEV5("div", {
|
|
1305
1625
|
children: [
|
|
1306
|
-
/* @__PURE__ */
|
|
1626
|
+
/* @__PURE__ */ jsxDEV5("dt", {
|
|
1307
1627
|
children: row.label
|
|
1308
1628
|
}, undefined, false, undefined, this),
|
|
1309
|
-
/* @__PURE__ */
|
|
1629
|
+
/* @__PURE__ */ jsxDEV5("dd", {
|
|
1310
1630
|
children: row.value
|
|
1311
1631
|
}, undefined, false, undefined, this)
|
|
1312
1632
|
]
|
|
@@ -1314,11 +1634,11 @@ var VoiceProviderCapabilities = ({
|
|
|
1314
1634
|
}, undefined, false, undefined, this)
|
|
1315
1635
|
]
|
|
1316
1636
|
}, `${capability.kind}:${capability.provider}`, true, undefined, this))
|
|
1317
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
1637
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV5("p", {
|
|
1318
1638
|
className: "absolute-voice-provider-capabilities__empty",
|
|
1319
1639
|
children: "Configure provider capabilities to see deployment coverage."
|
|
1320
1640
|
}, undefined, false, undefined, this),
|
|
1321
|
-
model.error ? /* @__PURE__ */
|
|
1641
|
+
model.error ? /* @__PURE__ */ jsxDEV5("p", {
|
|
1322
1642
|
className: "absolute-voice-provider-capabilities__error",
|
|
1323
1643
|
children: model.error
|
|
1324
1644
|
}, undefined, false, undefined, this) : null
|
|
@@ -1326,7 +1646,7 @@ var VoiceProviderCapabilities = ({
|
|
|
1326
1646
|
}, undefined, true, undefined, this);
|
|
1327
1647
|
};
|
|
1328
1648
|
// src/react/useVoiceProviderStatus.tsx
|
|
1329
|
-
import { useEffect as
|
|
1649
|
+
import { useEffect as useEffect6, useRef as useRef6, useSyncExternalStore as useSyncExternalStore6 } from "react";
|
|
1330
1650
|
|
|
1331
1651
|
// src/client/providerStatus.ts
|
|
1332
1652
|
var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
|
|
@@ -1410,25 +1730,25 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
1410
1730
|
|
|
1411
1731
|
// src/react/useVoiceProviderStatus.tsx
|
|
1412
1732
|
var useVoiceProviderStatus = (path = "/api/provider-status", options = {}) => {
|
|
1413
|
-
const storeRef =
|
|
1733
|
+
const storeRef = useRef6(null);
|
|
1414
1734
|
if (!storeRef.current) {
|
|
1415
1735
|
storeRef.current = createVoiceProviderStatusStore(path, options);
|
|
1416
1736
|
}
|
|
1417
1737
|
const store = storeRef.current;
|
|
1418
|
-
|
|
1738
|
+
useEffect6(() => {
|
|
1419
1739
|
store.refresh().catch(() => {});
|
|
1420
1740
|
return () => store.close();
|
|
1421
1741
|
}, [store]);
|
|
1422
1742
|
return {
|
|
1423
|
-
...
|
|
1743
|
+
...useSyncExternalStore6(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1424
1744
|
refresh: store.refresh
|
|
1425
1745
|
};
|
|
1426
1746
|
};
|
|
1427
1747
|
|
|
1428
1748
|
// src/client/providerStatusWidget.ts
|
|
1429
|
-
var
|
|
1430
|
-
var
|
|
1431
|
-
var
|
|
1749
|
+
var DEFAULT_TITLE5 = "Voice Providers";
|
|
1750
|
+
var DEFAULT_DESCRIPTION5 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
1751
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1432
1752
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1433
1753
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
1434
1754
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -1472,37 +1792,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
1472
1792
|
const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
|
|
1473
1793
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
1474
1794
|
return {
|
|
1475
|
-
description: options.description ??
|
|
1795
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
1476
1796
|
error: snapshot.error,
|
|
1477
1797
|
isLoading: snapshot.isLoading,
|
|
1478
1798
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
1479
1799
|
providers,
|
|
1480
1800
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1481
|
-
title: options.title ??
|
|
1801
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
1482
1802
|
updatedAt: snapshot.updatedAt
|
|
1483
1803
|
};
|
|
1484
1804
|
};
|
|
1485
1805
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
1486
1806
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
1487
|
-
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--${
|
|
1807
|
+
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)}">
|
|
1488
1808
|
<header>
|
|
1489
|
-
<strong>${
|
|
1490
|
-
<span>${
|
|
1809
|
+
<strong>${escapeHtml6(provider.label)}</strong>
|
|
1810
|
+
<span>${escapeHtml6(formatStatus2(provider.status))}</span>
|
|
1491
1811
|
</header>
|
|
1492
|
-
<p>${
|
|
1812
|
+
<p>${escapeHtml6(provider.detail)}</p>
|
|
1493
1813
|
<dl>${provider.rows.map((row) => `<div>
|
|
1494
|
-
<dt>${
|
|
1495
|
-
<dd>${
|
|
1814
|
+
<dt>${escapeHtml6(row.label)}</dt>
|
|
1815
|
+
<dd>${escapeHtml6(row.value)}</dd>
|
|
1496
1816
|
</div>`).join("")}</dl>
|
|
1497
1817
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
1498
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
1818
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml6(model.status)}">
|
|
1499
1819
|
<header class="absolute-voice-provider-status__header">
|
|
1500
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
1501
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
1820
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml6(model.title)}</span>
|
|
1821
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml6(model.label)}</strong>
|
|
1502
1822
|
</header>
|
|
1503
|
-
<p class="absolute-voice-provider-status__description">${
|
|
1823
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml6(model.description)}</p>
|
|
1504
1824
|
${providers}
|
|
1505
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
1825
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
1506
1826
|
</section>`;
|
|
1507
1827
|
};
|
|
1508
1828
|
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}`;
|
|
@@ -1544,7 +1864,7 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
1544
1864
|
};
|
|
1545
1865
|
|
|
1546
1866
|
// src/react/VoiceProviderStatus.tsx
|
|
1547
|
-
import { jsxDEV as
|
|
1867
|
+
import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
|
|
1548
1868
|
var VoiceProviderStatus = ({
|
|
1549
1869
|
className,
|
|
1550
1870
|
path = "/api/provider-status",
|
|
@@ -1552,58 +1872,58 @@ var VoiceProviderStatus = ({
|
|
|
1552
1872
|
}) => {
|
|
1553
1873
|
const snapshot = useVoiceProviderStatus(path, options);
|
|
1554
1874
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
1555
|
-
return /* @__PURE__ */
|
|
1875
|
+
return /* @__PURE__ */ jsxDEV6("section", {
|
|
1556
1876
|
className: [
|
|
1557
1877
|
"absolute-voice-provider-status",
|
|
1558
1878
|
`absolute-voice-provider-status--${model.status}`,
|
|
1559
1879
|
className
|
|
1560
1880
|
].filter(Boolean).join(" "),
|
|
1561
1881
|
children: [
|
|
1562
|
-
/* @__PURE__ */
|
|
1882
|
+
/* @__PURE__ */ jsxDEV6("header", {
|
|
1563
1883
|
className: "absolute-voice-provider-status__header",
|
|
1564
1884
|
children: [
|
|
1565
|
-
/* @__PURE__ */
|
|
1885
|
+
/* @__PURE__ */ jsxDEV6("span", {
|
|
1566
1886
|
className: "absolute-voice-provider-status__eyebrow",
|
|
1567
1887
|
children: model.title
|
|
1568
1888
|
}, undefined, false, undefined, this),
|
|
1569
|
-
/* @__PURE__ */
|
|
1889
|
+
/* @__PURE__ */ jsxDEV6("strong", {
|
|
1570
1890
|
className: "absolute-voice-provider-status__label",
|
|
1571
1891
|
children: model.label
|
|
1572
1892
|
}, undefined, false, undefined, this)
|
|
1573
1893
|
]
|
|
1574
1894
|
}, undefined, true, undefined, this),
|
|
1575
|
-
/* @__PURE__ */
|
|
1895
|
+
/* @__PURE__ */ jsxDEV6("p", {
|
|
1576
1896
|
className: "absolute-voice-provider-status__description",
|
|
1577
1897
|
children: model.description
|
|
1578
1898
|
}, undefined, false, undefined, this),
|
|
1579
|
-
model.providers.length ? /* @__PURE__ */
|
|
1899
|
+
model.providers.length ? /* @__PURE__ */ jsxDEV6("div", {
|
|
1580
1900
|
className: "absolute-voice-provider-status__providers",
|
|
1581
|
-
children: model.providers.map((provider) => /* @__PURE__ */
|
|
1901
|
+
children: model.providers.map((provider) => /* @__PURE__ */ jsxDEV6("article", {
|
|
1582
1902
|
className: [
|
|
1583
1903
|
"absolute-voice-provider-status__provider",
|
|
1584
1904
|
`absolute-voice-provider-status__provider--${provider.status}`
|
|
1585
1905
|
].join(" "),
|
|
1586
1906
|
children: [
|
|
1587
|
-
/* @__PURE__ */
|
|
1907
|
+
/* @__PURE__ */ jsxDEV6("header", {
|
|
1588
1908
|
children: [
|
|
1589
|
-
/* @__PURE__ */
|
|
1909
|
+
/* @__PURE__ */ jsxDEV6("strong", {
|
|
1590
1910
|
children: provider.label
|
|
1591
1911
|
}, undefined, false, undefined, this),
|
|
1592
|
-
/* @__PURE__ */
|
|
1912
|
+
/* @__PURE__ */ jsxDEV6("span", {
|
|
1593
1913
|
children: provider.status
|
|
1594
1914
|
}, undefined, false, undefined, this)
|
|
1595
1915
|
]
|
|
1596
1916
|
}, undefined, true, undefined, this),
|
|
1597
|
-
/* @__PURE__ */
|
|
1917
|
+
/* @__PURE__ */ jsxDEV6("p", {
|
|
1598
1918
|
children: provider.detail
|
|
1599
1919
|
}, undefined, false, undefined, this),
|
|
1600
|
-
/* @__PURE__ */
|
|
1601
|
-
children: provider.rows.map((row) => /* @__PURE__ */
|
|
1920
|
+
/* @__PURE__ */ jsxDEV6("dl", {
|
|
1921
|
+
children: provider.rows.map((row) => /* @__PURE__ */ jsxDEV6("div", {
|
|
1602
1922
|
children: [
|
|
1603
|
-
/* @__PURE__ */
|
|
1923
|
+
/* @__PURE__ */ jsxDEV6("dt", {
|
|
1604
1924
|
children: row.label
|
|
1605
1925
|
}, undefined, false, undefined, this),
|
|
1606
|
-
/* @__PURE__ */
|
|
1926
|
+
/* @__PURE__ */ jsxDEV6("dd", {
|
|
1607
1927
|
children: row.value
|
|
1608
1928
|
}, undefined, false, undefined, this)
|
|
1609
1929
|
]
|
|
@@ -1611,11 +1931,11 @@ var VoiceProviderStatus = ({
|
|
|
1611
1931
|
}, undefined, false, undefined, this)
|
|
1612
1932
|
]
|
|
1613
1933
|
}, provider.provider, true, undefined, this))
|
|
1614
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
1934
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV6("p", {
|
|
1615
1935
|
className: "absolute-voice-provider-status__empty",
|
|
1616
1936
|
children: "Run voice traffic to see provider health."
|
|
1617
1937
|
}, undefined, false, undefined, this),
|
|
1618
|
-
model.error ? /* @__PURE__ */
|
|
1938
|
+
model.error ? /* @__PURE__ */ jsxDEV6("p", {
|
|
1619
1939
|
className: "absolute-voice-provider-status__error",
|
|
1620
1940
|
children: model.error
|
|
1621
1941
|
}, undefined, false, undefined, this) : null
|
|
@@ -1623,7 +1943,7 @@ var VoiceProviderStatus = ({
|
|
|
1623
1943
|
}, undefined, true, undefined, this);
|
|
1624
1944
|
};
|
|
1625
1945
|
// src/react/useVoiceRoutingStatus.tsx
|
|
1626
|
-
import { useEffect as
|
|
1946
|
+
import { useEffect as useEffect7, useRef as useRef7, useSyncExternalStore as useSyncExternalStore7 } from "react";
|
|
1627
1947
|
|
|
1628
1948
|
// src/client/routingStatus.ts
|
|
1629
1949
|
var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
|
|
@@ -1707,25 +2027,25 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
1707
2027
|
|
|
1708
2028
|
// src/react/useVoiceRoutingStatus.tsx
|
|
1709
2029
|
var useVoiceRoutingStatus = (path = "/api/routing/latest", options = {}) => {
|
|
1710
|
-
const storeRef =
|
|
2030
|
+
const storeRef = useRef7(null);
|
|
1711
2031
|
if (!storeRef.current) {
|
|
1712
2032
|
storeRef.current = createVoiceRoutingStatusStore(path, options);
|
|
1713
2033
|
}
|
|
1714
2034
|
const store = storeRef.current;
|
|
1715
|
-
|
|
2035
|
+
useEffect7(() => {
|
|
1716
2036
|
store.refresh().catch(() => {});
|
|
1717
2037
|
return () => store.close();
|
|
1718
2038
|
}, [store]);
|
|
1719
2039
|
return {
|
|
1720
|
-
...
|
|
2040
|
+
...useSyncExternalStore7(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1721
2041
|
refresh: store.refresh
|
|
1722
2042
|
};
|
|
1723
2043
|
};
|
|
1724
2044
|
|
|
1725
2045
|
// src/client/routingStatusWidget.ts
|
|
1726
|
-
var
|
|
1727
|
-
var
|
|
1728
|
-
var
|
|
2046
|
+
var DEFAULT_TITLE6 = "Voice Routing";
|
|
2047
|
+
var DEFAULT_DESCRIPTION6 = "Latest provider routing decision from the self-hosted trace store.";
|
|
2048
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1729
2049
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
1730
2050
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
1731
2051
|
const decision = snapshot.decision;
|
|
@@ -1749,30 +2069,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
1749
2069
|
] : [];
|
|
1750
2070
|
return {
|
|
1751
2071
|
decision,
|
|
1752
|
-
description: options.description ??
|
|
2072
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
1753
2073
|
error: snapshot.error,
|
|
1754
2074
|
isLoading: snapshot.isLoading,
|
|
1755
2075
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
1756
2076
|
rows,
|
|
1757
2077
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1758
|
-
title: options.title ??
|
|
2078
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
1759
2079
|
updatedAt: snapshot.updatedAt
|
|
1760
2080
|
};
|
|
1761
2081
|
};
|
|
1762
2082
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
1763
2083
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
1764
2084
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
1765
|
-
<span>${
|
|
1766
|
-
<strong>${
|
|
2085
|
+
<span>${escapeHtml7(row.label)}</span>
|
|
2086
|
+
<strong>${escapeHtml7(row.value)}</strong>
|
|
1767
2087
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
1768
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
2088
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml7(model.status)}">
|
|
1769
2089
|
<header class="absolute-voice-routing-status__header">
|
|
1770
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
1771
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
2090
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml7(model.title)}</span>
|
|
2091
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml7(model.label)}</strong>
|
|
1772
2092
|
</header>
|
|
1773
|
-
<p class="absolute-voice-routing-status__description">${
|
|
2093
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml7(model.description)}</p>
|
|
1774
2094
|
${rows}
|
|
1775
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
2095
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
1776
2096
|
</section>`;
|
|
1777
2097
|
};
|
|
1778
2098
|
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}`;
|
|
@@ -1814,7 +2134,7 @@ var defineVoiceRoutingStatusElement = (tagName = "absolute-voice-routing-status"
|
|
|
1814
2134
|
};
|
|
1815
2135
|
|
|
1816
2136
|
// src/react/VoiceRoutingStatus.tsx
|
|
1817
|
-
import { jsxDEV as
|
|
2137
|
+
import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
|
|
1818
2138
|
var VoiceRoutingStatus = ({
|
|
1819
2139
|
className,
|
|
1820
2140
|
path = "/api/routing/latest",
|
|
@@ -1822,47 +2142,47 @@ var VoiceRoutingStatus = ({
|
|
|
1822
2142
|
}) => {
|
|
1823
2143
|
const snapshot = useVoiceRoutingStatus(path, options);
|
|
1824
2144
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
1825
|
-
return /* @__PURE__ */
|
|
2145
|
+
return /* @__PURE__ */ jsxDEV7("section", {
|
|
1826
2146
|
className: [
|
|
1827
2147
|
"absolute-voice-routing-status",
|
|
1828
2148
|
`absolute-voice-routing-status--${model.status}`,
|
|
1829
2149
|
className
|
|
1830
2150
|
].filter(Boolean).join(" "),
|
|
1831
2151
|
children: [
|
|
1832
|
-
/* @__PURE__ */
|
|
2152
|
+
/* @__PURE__ */ jsxDEV7("header", {
|
|
1833
2153
|
className: "absolute-voice-routing-status__header",
|
|
1834
2154
|
children: [
|
|
1835
|
-
/* @__PURE__ */
|
|
2155
|
+
/* @__PURE__ */ jsxDEV7("span", {
|
|
1836
2156
|
className: "absolute-voice-routing-status__eyebrow",
|
|
1837
2157
|
children: model.title
|
|
1838
2158
|
}, undefined, false, undefined, this),
|
|
1839
|
-
/* @__PURE__ */
|
|
2159
|
+
/* @__PURE__ */ jsxDEV7("strong", {
|
|
1840
2160
|
className: "absolute-voice-routing-status__label",
|
|
1841
2161
|
children: model.label
|
|
1842
2162
|
}, undefined, false, undefined, this)
|
|
1843
2163
|
]
|
|
1844
2164
|
}, undefined, true, undefined, this),
|
|
1845
|
-
/* @__PURE__ */
|
|
2165
|
+
/* @__PURE__ */ jsxDEV7("p", {
|
|
1846
2166
|
className: "absolute-voice-routing-status__description",
|
|
1847
2167
|
children: model.description
|
|
1848
2168
|
}, undefined, false, undefined, this),
|
|
1849
|
-
model.rows.length ? /* @__PURE__ */
|
|
2169
|
+
model.rows.length ? /* @__PURE__ */ jsxDEV7("div", {
|
|
1850
2170
|
className: "absolute-voice-routing-status__grid",
|
|
1851
|
-
children: model.rows.map((row) => /* @__PURE__ */
|
|
2171
|
+
children: model.rows.map((row) => /* @__PURE__ */ jsxDEV7("div", {
|
|
1852
2172
|
children: [
|
|
1853
|
-
/* @__PURE__ */
|
|
2173
|
+
/* @__PURE__ */ jsxDEV7("span", {
|
|
1854
2174
|
children: row.label
|
|
1855
2175
|
}, undefined, false, undefined, this),
|
|
1856
|
-
/* @__PURE__ */
|
|
2176
|
+
/* @__PURE__ */ jsxDEV7("strong", {
|
|
1857
2177
|
children: row.value
|
|
1858
2178
|
}, undefined, false, undefined, this)
|
|
1859
2179
|
]
|
|
1860
2180
|
}, row.label, true, undefined, this))
|
|
1861
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2181
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV7("p", {
|
|
1862
2182
|
className: "absolute-voice-routing-status__empty",
|
|
1863
2183
|
children: "Start a voice session to see the selected provider."
|
|
1864
2184
|
}, undefined, false, undefined, this),
|
|
1865
|
-
model.error ? /* @__PURE__ */
|
|
2185
|
+
model.error ? /* @__PURE__ */ jsxDEV7("p", {
|
|
1866
2186
|
className: "absolute-voice-routing-status__error",
|
|
1867
2187
|
children: model.error
|
|
1868
2188
|
}, undefined, false, undefined, this) : null
|
|
@@ -1950,9 +2270,9 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
|
|
|
1950
2270
|
};
|
|
1951
2271
|
|
|
1952
2272
|
// src/client/traceTimelineWidget.ts
|
|
1953
|
-
var
|
|
1954
|
-
var
|
|
1955
|
-
var
|
|
2273
|
+
var DEFAULT_TITLE7 = "Voice Traces";
|
|
2274
|
+
var DEFAULT_DESCRIPTION7 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
2275
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1956
2276
|
var formatMs = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
1957
2277
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
1958
2278
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -1966,34 +2286,34 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
1966
2286
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
1967
2287
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
1968
2288
|
return {
|
|
1969
|
-
description: options.description ??
|
|
2289
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
1970
2290
|
error: snapshot.error,
|
|
1971
2291
|
isLoading: snapshot.isLoading,
|
|
1972
2292
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
1973
2293
|
sessions,
|
|
1974
2294
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1975
|
-
title: options.title ??
|
|
2295
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
1976
2296
|
updatedAt: snapshot.updatedAt
|
|
1977
2297
|
};
|
|
1978
2298
|
};
|
|
1979
2299
|
var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
1980
2300
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
1981
|
-
const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${
|
|
2301
|
+
const sessions = model.sessions.length ? `<div class="absolute-voice-trace-timeline__sessions">${model.sessions.map((session) => `<article class="absolute-voice-trace-timeline__session absolute-voice-trace-timeline__session--${escapeHtml8(session.status)}">
|
|
1982
2302
|
<header>
|
|
1983
|
-
<strong>${
|
|
1984
|
-
<span>${
|
|
2303
|
+
<strong>${escapeHtml8(session.sessionId)}</strong>
|
|
2304
|
+
<span>${escapeHtml8(session.status)}</span>
|
|
1985
2305
|
</header>
|
|
1986
|
-
<p>${
|
|
1987
|
-
<a href="${
|
|
2306
|
+
<p>${escapeHtml8(session.label)} \xB7 ${escapeHtml8(session.durationLabel)} \xB7 ${escapeHtml8(session.providerLabel)}</p>
|
|
2307
|
+
<a href="${escapeHtml8(session.detailHref)}">Open timeline</a>
|
|
1988
2308
|
</article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
1989
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
2309
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml8(model.status)}">
|
|
1990
2310
|
<header class="absolute-voice-trace-timeline__header">
|
|
1991
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
1992
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
2311
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml8(model.title)}</span>
|
|
2312
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml8(model.label)}</strong>
|
|
1993
2313
|
</header>
|
|
1994
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
2314
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml8(model.description)}</p>
|
|
1995
2315
|
${sessions}
|
|
1996
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
2316
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
1997
2317
|
</section>`;
|
|
1998
2318
|
};
|
|
1999
2319
|
var getVoiceTraceTimelineCSS = () => `.absolute-voice-trace-timeline{border:1px solid #bad7d3;border-radius:20px;background:#f3fffb;color:#09201c;padding:18px;box-shadow:0 18px 40px rgba(9,32,28,.12);font-family:inherit}.absolute-voice-trace-timeline--error,.absolute-voice-trace-timeline--failed{border-color:#f2a7a7;background:#fff5f3}.absolute-voice-trace-timeline--warning{border-color:#fbbf24;background:#fffaf0}.absolute-voice-trace-timeline__header,.absolute-voice-trace-timeline__session header{align-items:start;display:flex;gap:12px;justify-content:space-between}.absolute-voice-trace-timeline__eyebrow{color:#17665b;font-size:12px;font-weight:800;letter-spacing:.08em;text-transform:uppercase}.absolute-voice-trace-timeline__label{font-size:24px;line-height:1}.absolute-voice-trace-timeline__description,.absolute-voice-trace-timeline__session p,.absolute-voice-trace-timeline__empty{color:#35544f}.absolute-voice-trace-timeline__sessions{display:grid;gap:12px;margin-top:14px}.absolute-voice-trace-timeline__session{background:#fff;border:1px solid #cfe7e2;border-radius:16px;padding:14px}.absolute-voice-trace-timeline__session--failed{border-color:#f2a7a7}.absolute-voice-trace-timeline__session--warning{border-color:#fbbf24}.absolute-voice-trace-timeline__session p{margin:10px 0}.absolute-voice-trace-timeline__session a{color:#0f766e;font-weight:800}.absolute-voice-trace-timeline__empty{margin:14px 0 0}.absolute-voice-trace-timeline__error{color:#9f1239;font-weight:700}`;
|
|
@@ -2038,25 +2358,25 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
|
|
|
2038
2358
|
};
|
|
2039
2359
|
|
|
2040
2360
|
// src/react/useVoiceTraceTimeline.tsx
|
|
2041
|
-
import { useEffect as
|
|
2361
|
+
import { useEffect as useEffect8, useRef as useRef8, useSyncExternalStore as useSyncExternalStore8 } from "react";
|
|
2042
2362
|
var useVoiceTraceTimeline = (path = "/api/voice-traces", options = {}) => {
|
|
2043
|
-
const storeRef =
|
|
2363
|
+
const storeRef = useRef8(null);
|
|
2044
2364
|
if (!storeRef.current) {
|
|
2045
2365
|
storeRef.current = createVoiceTraceTimelineStore(path, options);
|
|
2046
2366
|
}
|
|
2047
2367
|
const store = storeRef.current;
|
|
2048
|
-
|
|
2368
|
+
useEffect8(() => {
|
|
2049
2369
|
store.refresh().catch(() => {});
|
|
2050
2370
|
return () => store.close();
|
|
2051
2371
|
}, [store]);
|
|
2052
2372
|
return {
|
|
2053
|
-
...
|
|
2373
|
+
...useSyncExternalStore8(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2054
2374
|
refresh: store.refresh
|
|
2055
2375
|
};
|
|
2056
2376
|
};
|
|
2057
2377
|
|
|
2058
2378
|
// src/react/VoiceTraceTimeline.tsx
|
|
2059
|
-
import { jsxDEV as
|
|
2379
|
+
import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
|
|
2060
2380
|
var VoiceTraceTimeline = ({
|
|
2061
2381
|
className,
|
|
2062
2382
|
path = "/api/voice-traces",
|
|
@@ -2064,49 +2384,49 @@ var VoiceTraceTimeline = ({
|
|
|
2064
2384
|
}) => {
|
|
2065
2385
|
const snapshot = useVoiceTraceTimeline(path, options);
|
|
2066
2386
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
2067
|
-
return /* @__PURE__ */
|
|
2387
|
+
return /* @__PURE__ */ jsxDEV8("section", {
|
|
2068
2388
|
className: [
|
|
2069
2389
|
"absolute-voice-trace-timeline",
|
|
2070
2390
|
`absolute-voice-trace-timeline--${model.status}`,
|
|
2071
2391
|
className
|
|
2072
2392
|
].filter(Boolean).join(" "),
|
|
2073
2393
|
children: [
|
|
2074
|
-
/* @__PURE__ */
|
|
2394
|
+
/* @__PURE__ */ jsxDEV8("header", {
|
|
2075
2395
|
className: "absolute-voice-trace-timeline__header",
|
|
2076
2396
|
children: [
|
|
2077
|
-
/* @__PURE__ */
|
|
2397
|
+
/* @__PURE__ */ jsxDEV8("span", {
|
|
2078
2398
|
className: "absolute-voice-trace-timeline__eyebrow",
|
|
2079
2399
|
children: model.title
|
|
2080
2400
|
}, undefined, false, undefined, this),
|
|
2081
|
-
/* @__PURE__ */
|
|
2401
|
+
/* @__PURE__ */ jsxDEV8("strong", {
|
|
2082
2402
|
className: "absolute-voice-trace-timeline__label",
|
|
2083
2403
|
children: model.label
|
|
2084
2404
|
}, undefined, false, undefined, this)
|
|
2085
2405
|
]
|
|
2086
2406
|
}, undefined, true, undefined, this),
|
|
2087
|
-
/* @__PURE__ */
|
|
2407
|
+
/* @__PURE__ */ jsxDEV8("p", {
|
|
2088
2408
|
className: "absolute-voice-trace-timeline__description",
|
|
2089
2409
|
children: model.description
|
|
2090
2410
|
}, undefined, false, undefined, this),
|
|
2091
|
-
model.sessions.length ? /* @__PURE__ */
|
|
2411
|
+
model.sessions.length ? /* @__PURE__ */ jsxDEV8("div", {
|
|
2092
2412
|
className: "absolute-voice-trace-timeline__sessions",
|
|
2093
|
-
children: model.sessions.map((session) => /* @__PURE__ */
|
|
2413
|
+
children: model.sessions.map((session) => /* @__PURE__ */ jsxDEV8("article", {
|
|
2094
2414
|
className: [
|
|
2095
2415
|
"absolute-voice-trace-timeline__session",
|
|
2096
2416
|
`absolute-voice-trace-timeline__session--${session.status}`
|
|
2097
2417
|
].join(" "),
|
|
2098
2418
|
children: [
|
|
2099
|
-
/* @__PURE__ */
|
|
2419
|
+
/* @__PURE__ */ jsxDEV8("header", {
|
|
2100
2420
|
children: [
|
|
2101
|
-
/* @__PURE__ */
|
|
2421
|
+
/* @__PURE__ */ jsxDEV8("strong", {
|
|
2102
2422
|
children: session.sessionId
|
|
2103
2423
|
}, undefined, false, undefined, this),
|
|
2104
|
-
/* @__PURE__ */
|
|
2424
|
+
/* @__PURE__ */ jsxDEV8("span", {
|
|
2105
2425
|
children: session.status
|
|
2106
2426
|
}, undefined, false, undefined, this)
|
|
2107
2427
|
]
|
|
2108
2428
|
}, undefined, true, undefined, this),
|
|
2109
|
-
/* @__PURE__ */
|
|
2429
|
+
/* @__PURE__ */ jsxDEV8("p", {
|
|
2110
2430
|
children: [
|
|
2111
2431
|
session.label,
|
|
2112
2432
|
" \xB7 ",
|
|
@@ -2116,17 +2436,17 @@ var VoiceTraceTimeline = ({
|
|
|
2116
2436
|
session.providerLabel
|
|
2117
2437
|
]
|
|
2118
2438
|
}, undefined, true, undefined, this),
|
|
2119
|
-
/* @__PURE__ */
|
|
2439
|
+
/* @__PURE__ */ jsxDEV8("a", {
|
|
2120
2440
|
href: session.detailHref,
|
|
2121
2441
|
children: "Open timeline"
|
|
2122
2442
|
}, undefined, false, undefined, this)
|
|
2123
2443
|
]
|
|
2124
2444
|
}, session.sessionId, true, undefined, this))
|
|
2125
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2445
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV8("p", {
|
|
2126
2446
|
className: "absolute-voice-trace-timeline__empty",
|
|
2127
2447
|
children: "Run a voice session to see call timelines."
|
|
2128
2448
|
}, undefined, false, undefined, this),
|
|
2129
|
-
model.error ? /* @__PURE__ */
|
|
2449
|
+
model.error ? /* @__PURE__ */ jsxDEV8("p", {
|
|
2130
2450
|
className: "absolute-voice-trace-timeline__error",
|
|
2131
2451
|
children: model.error
|
|
2132
2452
|
}, undefined, false, undefined, this) : null
|
|
@@ -2134,7 +2454,7 @@ var VoiceTraceTimeline = ({
|
|
|
2134
2454
|
}, undefined, true, undefined, this);
|
|
2135
2455
|
};
|
|
2136
2456
|
// src/react/useVoiceTurnLatency.tsx
|
|
2137
|
-
import { useEffect as
|
|
2457
|
+
import { useEffect as useEffect9, useRef as useRef9, useSyncExternalStore as useSyncExternalStore9 } from "react";
|
|
2138
2458
|
|
|
2139
2459
|
// src/client/turnLatency.ts
|
|
2140
2460
|
var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
|
|
@@ -2241,27 +2561,27 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
|
|
|
2241
2561
|
|
|
2242
2562
|
// src/react/useVoiceTurnLatency.tsx
|
|
2243
2563
|
var useVoiceTurnLatency = (path = "/api/turn-latency", options = {}) => {
|
|
2244
|
-
const storeRef =
|
|
2564
|
+
const storeRef = useRef9(null);
|
|
2245
2565
|
if (!storeRef.current) {
|
|
2246
2566
|
storeRef.current = createVoiceTurnLatencyStore(path, options);
|
|
2247
2567
|
}
|
|
2248
2568
|
const store = storeRef.current;
|
|
2249
|
-
|
|
2569
|
+
useEffect9(() => {
|
|
2250
2570
|
store.refresh().catch(() => {});
|
|
2251
2571
|
return () => store.close();
|
|
2252
2572
|
}, [store]);
|
|
2253
2573
|
return {
|
|
2254
|
-
...
|
|
2574
|
+
...useSyncExternalStore9(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2255
2575
|
refresh: store.refresh,
|
|
2256
2576
|
runProof: store.runProof
|
|
2257
2577
|
};
|
|
2258
2578
|
};
|
|
2259
2579
|
|
|
2260
2580
|
// src/client/turnLatencyWidget.ts
|
|
2261
|
-
var
|
|
2262
|
-
var
|
|
2581
|
+
var DEFAULT_TITLE8 = "Turn Latency";
|
|
2582
|
+
var DEFAULT_DESCRIPTION8 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
2263
2583
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
2264
|
-
var
|
|
2584
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2265
2585
|
var formatMs2 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
2266
2586
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
2267
2587
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -2275,39 +2595,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
2275
2595
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2276
2596
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2277
2597
|
return {
|
|
2278
|
-
description: options.description ??
|
|
2598
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
2279
2599
|
error: snapshot.error,
|
|
2280
2600
|
isLoading: snapshot.isLoading,
|
|
2281
2601
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs2(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
2282
2602
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
2283
2603
|
showProofAction: Boolean(options.proofPath),
|
|
2284
2604
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2285
|
-
title: options.title ??
|
|
2605
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
2286
2606
|
turns,
|
|
2287
2607
|
updatedAt: snapshot.updatedAt
|
|
2288
2608
|
};
|
|
2289
2609
|
};
|
|
2290
2610
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
2291
2611
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
2292
|
-
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--${
|
|
2612
|
+
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--${escapeHtml9(turn.status)}">
|
|
2293
2613
|
<header>
|
|
2294
|
-
<strong>${
|
|
2295
|
-
<span>${
|
|
2614
|
+
<strong>${escapeHtml9(turn.label)}</strong>
|
|
2615
|
+
<span>${escapeHtml9(turn.status)}</span>
|
|
2296
2616
|
</header>
|
|
2297
2617
|
<dl>${turn.rows.map((row) => `<div>
|
|
2298
|
-
<dt>${
|
|
2299
|
-
<dd>${
|
|
2618
|
+
<dt>${escapeHtml9(row.label)}</dt>
|
|
2619
|
+
<dd>${escapeHtml9(row.value)}</dd>
|
|
2300
2620
|
</div>`).join("")}</dl>
|
|
2301
2621
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
2302
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
2622
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml9(model.status)}">
|
|
2303
2623
|
<header class="absolute-voice-turn-latency__header">
|
|
2304
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
2305
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
2624
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml9(model.title)}</span>
|
|
2625
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml9(model.label)}</strong>
|
|
2306
2626
|
</header>
|
|
2307
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
2308
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
2627
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml9(model.description)}</p>
|
|
2628
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml9(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
2309
2629
|
${turns}
|
|
2310
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
2630
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
2311
2631
|
</section>`;
|
|
2312
2632
|
};
|
|
2313
2633
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -2358,7 +2678,7 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
2358
2678
|
};
|
|
2359
2679
|
|
|
2360
2680
|
// src/react/VoiceTurnLatency.tsx
|
|
2361
|
-
import { jsxDEV as
|
|
2681
|
+
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
2362
2682
|
var VoiceTurnLatency = ({
|
|
2363
2683
|
className,
|
|
2364
2684
|
path = "/api/turn-latency",
|
|
@@ -2366,31 +2686,31 @@ var VoiceTurnLatency = ({
|
|
|
2366
2686
|
}) => {
|
|
2367
2687
|
const latency = useVoiceTurnLatency(path, options);
|
|
2368
2688
|
const model = createVoiceTurnLatencyViewModel(latency, options);
|
|
2369
|
-
return /* @__PURE__ */
|
|
2689
|
+
return /* @__PURE__ */ jsxDEV9("section", {
|
|
2370
2690
|
className: [
|
|
2371
2691
|
"absolute-voice-turn-latency",
|
|
2372
2692
|
`absolute-voice-turn-latency--${model.status}`,
|
|
2373
2693
|
className
|
|
2374
2694
|
].filter(Boolean).join(" "),
|
|
2375
2695
|
children: [
|
|
2376
|
-
/* @__PURE__ */
|
|
2696
|
+
/* @__PURE__ */ jsxDEV9("header", {
|
|
2377
2697
|
className: "absolute-voice-turn-latency__header",
|
|
2378
2698
|
children: [
|
|
2379
|
-
/* @__PURE__ */
|
|
2699
|
+
/* @__PURE__ */ jsxDEV9("span", {
|
|
2380
2700
|
className: "absolute-voice-turn-latency__eyebrow",
|
|
2381
2701
|
children: model.title
|
|
2382
2702
|
}, undefined, false, undefined, this),
|
|
2383
|
-
/* @__PURE__ */
|
|
2703
|
+
/* @__PURE__ */ jsxDEV9("strong", {
|
|
2384
2704
|
className: "absolute-voice-turn-latency__label",
|
|
2385
2705
|
children: model.label
|
|
2386
2706
|
}, undefined, false, undefined, this)
|
|
2387
2707
|
]
|
|
2388
2708
|
}, undefined, true, undefined, this),
|
|
2389
|
-
/* @__PURE__ */
|
|
2709
|
+
/* @__PURE__ */ jsxDEV9("p", {
|
|
2390
2710
|
className: "absolute-voice-turn-latency__description",
|
|
2391
2711
|
children: model.description
|
|
2392
2712
|
}, undefined, false, undefined, this),
|
|
2393
|
-
model.showProofAction ? /* @__PURE__ */
|
|
2713
|
+
model.showProofAction ? /* @__PURE__ */ jsxDEV9("button", {
|
|
2394
2714
|
className: "absolute-voice-turn-latency__proof",
|
|
2395
2715
|
onClick: () => {
|
|
2396
2716
|
latency.runProof().catch(() => {});
|
|
@@ -2398,31 +2718,31 @@ var VoiceTurnLatency = ({
|
|
|
2398
2718
|
type: "button",
|
|
2399
2719
|
children: model.proofLabel
|
|
2400
2720
|
}, undefined, false, undefined, this) : null,
|
|
2401
|
-
model.turns.length ? /* @__PURE__ */
|
|
2721
|
+
model.turns.length ? /* @__PURE__ */ jsxDEV9("div", {
|
|
2402
2722
|
className: "absolute-voice-turn-latency__turns",
|
|
2403
|
-
children: model.turns.map((turn) => /* @__PURE__ */
|
|
2723
|
+
children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV9("article", {
|
|
2404
2724
|
className: [
|
|
2405
2725
|
"absolute-voice-turn-latency__turn",
|
|
2406
2726
|
`absolute-voice-turn-latency__turn--${turn.status}`
|
|
2407
2727
|
].join(" "),
|
|
2408
2728
|
children: [
|
|
2409
|
-
/* @__PURE__ */
|
|
2729
|
+
/* @__PURE__ */ jsxDEV9("header", {
|
|
2410
2730
|
children: [
|
|
2411
|
-
/* @__PURE__ */
|
|
2731
|
+
/* @__PURE__ */ jsxDEV9("strong", {
|
|
2412
2732
|
children: turn.label
|
|
2413
2733
|
}, undefined, false, undefined, this),
|
|
2414
|
-
/* @__PURE__ */
|
|
2734
|
+
/* @__PURE__ */ jsxDEV9("span", {
|
|
2415
2735
|
children: turn.status
|
|
2416
2736
|
}, undefined, false, undefined, this)
|
|
2417
2737
|
]
|
|
2418
2738
|
}, undefined, true, undefined, this),
|
|
2419
|
-
/* @__PURE__ */
|
|
2420
|
-
children: turn.rows.map((row) => /* @__PURE__ */
|
|
2739
|
+
/* @__PURE__ */ jsxDEV9("dl", {
|
|
2740
|
+
children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV9("div", {
|
|
2421
2741
|
children: [
|
|
2422
|
-
/* @__PURE__ */
|
|
2742
|
+
/* @__PURE__ */ jsxDEV9("dt", {
|
|
2423
2743
|
children: row.label
|
|
2424
2744
|
}, undefined, false, undefined, this),
|
|
2425
|
-
/* @__PURE__ */
|
|
2745
|
+
/* @__PURE__ */ jsxDEV9("dd", {
|
|
2426
2746
|
children: row.value
|
|
2427
2747
|
}, undefined, false, undefined, this)
|
|
2428
2748
|
]
|
|
@@ -2430,11 +2750,11 @@ var VoiceTurnLatency = ({
|
|
|
2430
2750
|
}, undefined, false, undefined, this)
|
|
2431
2751
|
]
|
|
2432
2752
|
}, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
|
|
2433
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2753
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV9("p", {
|
|
2434
2754
|
className: "absolute-voice-turn-latency__empty",
|
|
2435
2755
|
children: "Complete a voice turn to see latency diagnostics."
|
|
2436
2756
|
}, undefined, false, undefined, this),
|
|
2437
|
-
model.error ? /* @__PURE__ */
|
|
2757
|
+
model.error ? /* @__PURE__ */ jsxDEV9("p", {
|
|
2438
2758
|
className: "absolute-voice-turn-latency__error",
|
|
2439
2759
|
children: model.error
|
|
2440
2760
|
}, undefined, false, undefined, this) : null
|
|
@@ -2442,7 +2762,7 @@ var VoiceTurnLatency = ({
|
|
|
2442
2762
|
}, undefined, true, undefined, this);
|
|
2443
2763
|
};
|
|
2444
2764
|
// src/react/useVoiceTurnQuality.tsx
|
|
2445
|
-
import { useEffect as
|
|
2765
|
+
import { useEffect as useEffect10, useRef as useRef10, useSyncExternalStore as useSyncExternalStore10 } from "react";
|
|
2446
2766
|
|
|
2447
2767
|
// src/client/turnQuality.ts
|
|
2448
2768
|
var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
|
|
@@ -2525,25 +2845,25 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
|
|
|
2525
2845
|
|
|
2526
2846
|
// src/react/useVoiceTurnQuality.tsx
|
|
2527
2847
|
var useVoiceTurnQuality = (path = "/api/turn-quality", options = {}) => {
|
|
2528
|
-
const storeRef =
|
|
2848
|
+
const storeRef = useRef10(null);
|
|
2529
2849
|
if (!storeRef.current) {
|
|
2530
2850
|
storeRef.current = createVoiceTurnQualityStore(path, options);
|
|
2531
2851
|
}
|
|
2532
2852
|
const store = storeRef.current;
|
|
2533
|
-
|
|
2853
|
+
useEffect10(() => {
|
|
2534
2854
|
store.refresh().catch(() => {});
|
|
2535
2855
|
return () => store.close();
|
|
2536
2856
|
}, [store]);
|
|
2537
2857
|
return {
|
|
2538
|
-
...
|
|
2858
|
+
...useSyncExternalStore10(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2539
2859
|
refresh: store.refresh
|
|
2540
2860
|
};
|
|
2541
2861
|
};
|
|
2542
2862
|
|
|
2543
2863
|
// src/client/turnQualityWidget.ts
|
|
2544
|
-
var
|
|
2545
|
-
var
|
|
2546
|
-
var
|
|
2864
|
+
var DEFAULT_TITLE9 = "Turn Quality";
|
|
2865
|
+
var DEFAULT_DESCRIPTION9 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
2866
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2547
2867
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
2548
2868
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
2549
2869
|
var getTurnDetail = (turn) => {
|
|
@@ -2581,37 +2901,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
2581
2901
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2582
2902
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2583
2903
|
return {
|
|
2584
|
-
description: options.description ??
|
|
2904
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
2585
2905
|
error: snapshot.error,
|
|
2586
2906
|
isLoading: snapshot.isLoading,
|
|
2587
2907
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
2588
2908
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2589
|
-
title: options.title ??
|
|
2909
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
2590
2910
|
turns,
|
|
2591
2911
|
updatedAt: snapshot.updatedAt
|
|
2592
2912
|
};
|
|
2593
2913
|
};
|
|
2594
2914
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
2595
2915
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
2596
|
-
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--${
|
|
2916
|
+
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--${escapeHtml10(turn.status)}">
|
|
2597
2917
|
<header>
|
|
2598
|
-
<strong>${
|
|
2599
|
-
<span>${
|
|
2918
|
+
<strong>${escapeHtml10(turn.label)}</strong>
|
|
2919
|
+
<span>${escapeHtml10(turn.status)}</span>
|
|
2600
2920
|
</header>
|
|
2601
|
-
<p>${
|
|
2921
|
+
<p>${escapeHtml10(turn.detail)}</p>
|
|
2602
2922
|
<dl>${turn.rows.map((row) => `<div>
|
|
2603
|
-
<dt>${
|
|
2604
|
-
<dd>${
|
|
2923
|
+
<dt>${escapeHtml10(row.label)}</dt>
|
|
2924
|
+
<dd>${escapeHtml10(row.value)}</dd>
|
|
2605
2925
|
</div>`).join("")}</dl>
|
|
2606
2926
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
2607
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
2927
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml10(model.status)}">
|
|
2608
2928
|
<header class="absolute-voice-turn-quality__header">
|
|
2609
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
2610
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
2929
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml10(model.title)}</span>
|
|
2930
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml10(model.label)}</strong>
|
|
2611
2931
|
</header>
|
|
2612
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
2932
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml10(model.description)}</p>
|
|
2613
2933
|
${turns}
|
|
2614
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
2934
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
2615
2935
|
</section>`;
|
|
2616
2936
|
};
|
|
2617
2937
|
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}`;
|
|
@@ -2653,7 +2973,7 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
2653
2973
|
};
|
|
2654
2974
|
|
|
2655
2975
|
// src/react/VoiceTurnQuality.tsx
|
|
2656
|
-
import { jsxDEV as
|
|
2976
|
+
import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
|
|
2657
2977
|
var VoiceTurnQuality = ({
|
|
2658
2978
|
className,
|
|
2659
2979
|
path = "/api/turn-quality",
|
|
@@ -2661,58 +2981,58 @@ var VoiceTurnQuality = ({
|
|
|
2661
2981
|
}) => {
|
|
2662
2982
|
const snapshot = useVoiceTurnQuality(path, options);
|
|
2663
2983
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
2664
|
-
return /* @__PURE__ */
|
|
2984
|
+
return /* @__PURE__ */ jsxDEV10("section", {
|
|
2665
2985
|
className: [
|
|
2666
2986
|
"absolute-voice-turn-quality",
|
|
2667
2987
|
`absolute-voice-turn-quality--${model.status}`,
|
|
2668
2988
|
className
|
|
2669
2989
|
].filter(Boolean).join(" "),
|
|
2670
2990
|
children: [
|
|
2671
|
-
/* @__PURE__ */
|
|
2991
|
+
/* @__PURE__ */ jsxDEV10("header", {
|
|
2672
2992
|
className: "absolute-voice-turn-quality__header",
|
|
2673
2993
|
children: [
|
|
2674
|
-
/* @__PURE__ */
|
|
2994
|
+
/* @__PURE__ */ jsxDEV10("span", {
|
|
2675
2995
|
className: "absolute-voice-turn-quality__eyebrow",
|
|
2676
2996
|
children: model.title
|
|
2677
2997
|
}, undefined, false, undefined, this),
|
|
2678
|
-
/* @__PURE__ */
|
|
2998
|
+
/* @__PURE__ */ jsxDEV10("strong", {
|
|
2679
2999
|
className: "absolute-voice-turn-quality__label",
|
|
2680
3000
|
children: model.label
|
|
2681
3001
|
}, undefined, false, undefined, this)
|
|
2682
3002
|
]
|
|
2683
3003
|
}, undefined, true, undefined, this),
|
|
2684
|
-
/* @__PURE__ */
|
|
3004
|
+
/* @__PURE__ */ jsxDEV10("p", {
|
|
2685
3005
|
className: "absolute-voice-turn-quality__description",
|
|
2686
3006
|
children: model.description
|
|
2687
3007
|
}, undefined, false, undefined, this),
|
|
2688
|
-
model.turns.length ? /* @__PURE__ */
|
|
3008
|
+
model.turns.length ? /* @__PURE__ */ jsxDEV10("div", {
|
|
2689
3009
|
className: "absolute-voice-turn-quality__turns",
|
|
2690
|
-
children: model.turns.map((turn) => /* @__PURE__ */
|
|
3010
|
+
children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV10("article", {
|
|
2691
3011
|
className: [
|
|
2692
3012
|
"absolute-voice-turn-quality__turn",
|
|
2693
3013
|
`absolute-voice-turn-quality__turn--${turn.status}`
|
|
2694
3014
|
].join(" "),
|
|
2695
3015
|
children: [
|
|
2696
|
-
/* @__PURE__ */
|
|
3016
|
+
/* @__PURE__ */ jsxDEV10("header", {
|
|
2697
3017
|
children: [
|
|
2698
|
-
/* @__PURE__ */
|
|
3018
|
+
/* @__PURE__ */ jsxDEV10("strong", {
|
|
2699
3019
|
children: turn.label
|
|
2700
3020
|
}, undefined, false, undefined, this),
|
|
2701
|
-
/* @__PURE__ */
|
|
3021
|
+
/* @__PURE__ */ jsxDEV10("span", {
|
|
2702
3022
|
children: turn.status
|
|
2703
3023
|
}, undefined, false, undefined, this)
|
|
2704
3024
|
]
|
|
2705
3025
|
}, undefined, true, undefined, this),
|
|
2706
|
-
/* @__PURE__ */
|
|
3026
|
+
/* @__PURE__ */ jsxDEV10("p", {
|
|
2707
3027
|
children: turn.detail
|
|
2708
3028
|
}, undefined, false, undefined, this),
|
|
2709
|
-
/* @__PURE__ */
|
|
2710
|
-
children: turn.rows.map((row) => /* @__PURE__ */
|
|
3029
|
+
/* @__PURE__ */ jsxDEV10("dl", {
|
|
3030
|
+
children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV10("div", {
|
|
2711
3031
|
children: [
|
|
2712
|
-
/* @__PURE__ */
|
|
3032
|
+
/* @__PURE__ */ jsxDEV10("dt", {
|
|
2713
3033
|
children: row.label
|
|
2714
3034
|
}, undefined, false, undefined, this),
|
|
2715
|
-
/* @__PURE__ */
|
|
3035
|
+
/* @__PURE__ */ jsxDEV10("dd", {
|
|
2716
3036
|
children: row.value
|
|
2717
3037
|
}, undefined, false, undefined, this)
|
|
2718
3038
|
]
|
|
@@ -2720,11 +3040,11 @@ var VoiceTurnQuality = ({
|
|
|
2720
3040
|
}, undefined, false, undefined, this)
|
|
2721
3041
|
]
|
|
2722
3042
|
}, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
|
|
2723
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
3043
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV10("p", {
|
|
2724
3044
|
className: "absolute-voice-turn-quality__empty",
|
|
2725
3045
|
children: "Complete a voice turn to see STT quality diagnostics."
|
|
2726
3046
|
}, undefined, false, undefined, this),
|
|
2727
|
-
model.error ? /* @__PURE__ */
|
|
3047
|
+
model.error ? /* @__PURE__ */ jsxDEV10("p", {
|
|
2728
3048
|
className: "absolute-voice-turn-quality__error",
|
|
2729
3049
|
children: model.error
|
|
2730
3050
|
}, undefined, false, undefined, this) : null
|
|
@@ -2732,7 +3052,7 @@ var VoiceTurnQuality = ({
|
|
|
2732
3052
|
}, undefined, true, undefined, this);
|
|
2733
3053
|
};
|
|
2734
3054
|
// src/react/useVoiceCampaignDialerProof.tsx
|
|
2735
|
-
import { useEffect as
|
|
3055
|
+
import { useEffect as useEffect11, useRef as useRef11, useSyncExternalStore as useSyncExternalStore11 } from "react";
|
|
2736
3056
|
|
|
2737
3057
|
// src/client/campaignDialerProof.ts
|
|
2738
3058
|
var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
|
|
@@ -2854,23 +3174,23 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
|
|
|
2854
3174
|
|
|
2855
3175
|
// src/react/useVoiceCampaignDialerProof.tsx
|
|
2856
3176
|
var useVoiceCampaignDialerProof = (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
|
|
2857
|
-
const storeRef =
|
|
3177
|
+
const storeRef = useRef11(null);
|
|
2858
3178
|
if (!storeRef.current) {
|
|
2859
3179
|
storeRef.current = createVoiceCampaignDialerProofStore(path, options);
|
|
2860
3180
|
}
|
|
2861
3181
|
const store = storeRef.current;
|
|
2862
|
-
|
|
3182
|
+
useEffect11(() => {
|
|
2863
3183
|
store.refresh().catch(() => {});
|
|
2864
3184
|
return () => store.close();
|
|
2865
3185
|
}, [store]);
|
|
2866
3186
|
return {
|
|
2867
|
-
...
|
|
3187
|
+
...useSyncExternalStore11(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2868
3188
|
refresh: store.refresh,
|
|
2869
3189
|
runProof: store.runProof
|
|
2870
3190
|
};
|
|
2871
3191
|
};
|
|
2872
3192
|
// src/react/useVoiceStream.tsx
|
|
2873
|
-
import { useEffect as
|
|
3193
|
+
import { useEffect as useEffect12, useRef as useRef12, useSyncExternalStore as useSyncExternalStore12 } from "react";
|
|
2874
3194
|
|
|
2875
3195
|
// src/client/actions.ts
|
|
2876
3196
|
var normalizeErrorMessage = (value) => {
|
|
@@ -3530,13 +3850,13 @@ var EMPTY_SNAPSHOT = {
|
|
|
3530
3850
|
turns: []
|
|
3531
3851
|
};
|
|
3532
3852
|
var useVoiceStream = (path, options = {}) => {
|
|
3533
|
-
const streamRef =
|
|
3853
|
+
const streamRef = useRef12(null);
|
|
3534
3854
|
if (!streamRef.current) {
|
|
3535
3855
|
streamRef.current = createVoiceStream(path, options);
|
|
3536
3856
|
}
|
|
3537
3857
|
const stream = streamRef.current;
|
|
3538
|
-
|
|
3539
|
-
const snapshot =
|
|
3858
|
+
useEffect12(() => () => stream.close(), [stream]);
|
|
3859
|
+
const snapshot = useSyncExternalStore12(stream.subscribe, stream.getSnapshot, stream.getServerSnapshot) ?? EMPTY_SNAPSHOT;
|
|
3540
3860
|
return {
|
|
3541
3861
|
...snapshot,
|
|
3542
3862
|
callControl: (message) => stream.callControl(message),
|
|
@@ -3546,7 +3866,7 @@ var useVoiceStream = (path, options = {}) => {
|
|
|
3546
3866
|
};
|
|
3547
3867
|
};
|
|
3548
3868
|
// src/react/useVoiceController.tsx
|
|
3549
|
-
import { useEffect as
|
|
3869
|
+
import { useEffect as useEffect13, useRef as useRef13, useSyncExternalStore as useSyncExternalStore13 } from "react";
|
|
3550
3870
|
|
|
3551
3871
|
// src/client/htmx.ts
|
|
3552
3872
|
var DEFAULT_EVENT_NAME = "voice-refresh";
|
|
@@ -4209,13 +4529,13 @@ var EMPTY_SNAPSHOT2 = {
|
|
|
4209
4529
|
turns: []
|
|
4210
4530
|
};
|
|
4211
4531
|
var useVoiceController = (path, options = {}) => {
|
|
4212
|
-
const controllerRef =
|
|
4532
|
+
const controllerRef = useRef13(null);
|
|
4213
4533
|
if (!controllerRef.current) {
|
|
4214
4534
|
controllerRef.current = createVoiceController(path, options);
|
|
4215
4535
|
}
|
|
4216
4536
|
const controller = controllerRef.current;
|
|
4217
|
-
|
|
4218
|
-
const snapshot =
|
|
4537
|
+
useEffect13(() => () => controller.close(), [controller]);
|
|
4538
|
+
const snapshot = useSyncExternalStore13(controller.subscribe, controller.getSnapshot, controller.getServerSnapshot) ?? EMPTY_SNAPSHOT2;
|
|
4219
4539
|
return {
|
|
4220
4540
|
...snapshot,
|
|
4221
4541
|
bindHTMX: controller.bindHTMX,
|
|
@@ -4229,7 +4549,7 @@ var useVoiceController = (path, options = {}) => {
|
|
|
4229
4549
|
};
|
|
4230
4550
|
};
|
|
4231
4551
|
// src/react/useVoiceWorkflowStatus.tsx
|
|
4232
|
-
import { useEffect as
|
|
4552
|
+
import { useEffect as useEffect14, useRef as useRef14, useSyncExternalStore as useSyncExternalStore14 } from "react";
|
|
4233
4553
|
|
|
4234
4554
|
// src/client/workflowStatus.ts
|
|
4235
4555
|
var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
|
|
@@ -4312,17 +4632,17 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
|
|
|
4312
4632
|
|
|
4313
4633
|
// src/react/useVoiceWorkflowStatus.tsx
|
|
4314
4634
|
var useVoiceWorkflowStatus = (path = "/evals/scenarios/json", options = {}) => {
|
|
4315
|
-
const storeRef =
|
|
4635
|
+
const storeRef = useRef14(null);
|
|
4316
4636
|
if (!storeRef.current) {
|
|
4317
4637
|
storeRef.current = createVoiceWorkflowStatusStore(path, options);
|
|
4318
4638
|
}
|
|
4319
4639
|
const store = storeRef.current;
|
|
4320
|
-
|
|
4640
|
+
useEffect14(() => {
|
|
4321
4641
|
store.refresh().catch(() => {});
|
|
4322
4642
|
return () => store.close();
|
|
4323
4643
|
}, [store]);
|
|
4324
4644
|
return {
|
|
4325
|
-
...
|
|
4645
|
+
...useSyncExternalStore14(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
4326
4646
|
refresh: store.refresh
|
|
4327
4647
|
};
|
|
4328
4648
|
};
|
|
@@ -4337,6 +4657,7 @@ export {
|
|
|
4337
4657
|
useVoiceProviderSimulationControls,
|
|
4338
4658
|
useVoiceProviderCapabilities,
|
|
4339
4659
|
useVoiceOpsStatus,
|
|
4660
|
+
useVoiceOpsActionCenter,
|
|
4340
4661
|
useVoiceDeliveryRuntime,
|
|
4341
4662
|
useVoiceController,
|
|
4342
4663
|
useVoiceCampaignDialerProof,
|
|
@@ -4348,5 +4669,6 @@ export {
|
|
|
4348
4669
|
VoiceProviderSimulationControls,
|
|
4349
4670
|
VoiceProviderCapabilities,
|
|
4350
4671
|
VoiceOpsStatus,
|
|
4672
|
+
VoiceOpsActionCenter,
|
|
4351
4673
|
VoiceDeliveryRuntime
|
|
4352
4674
|
};
|