@absolutejs/voice 0.0.22-beta.153 → 0.0.22-beta.155
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -0
- package/dist/angular/index.d.ts +1 -0
- package/dist/angular/index.js +378 -140
- package/dist/angular/voice-ops-action-center.service.d.ts +13 -0
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +400 -114
- package/dist/client/opsActionCenter.d.ts +54 -0
- package/dist/client/opsActionCenterWidget.d.ts +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +144 -53
- package/dist/opsActionAuditRoutes.d.ts +79 -0
- package/dist/react/VoiceOpsActionCenter.d.ts +5 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +640 -289
- package/dist/react/useVoiceOpsActionCenter.d.ts +11 -0
- package/dist/svelte/createVoiceOpsActionCenter.d.ts +10 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +407 -114
- package/dist/trace.d.ts +1 -1
- package/dist/vue/VoiceOpsActionCenter.d.ts +13 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +668 -298
- package/dist/vue/useVoiceOpsActionCenter.d.ts +11 -0
- package/package.json +1 -1
package/dist/react/index.js
CHANGED
|
@@ -387,6 +387,355 @@ var VoiceOpsStatus = ({
|
|
|
387
387
|
]
|
|
388
388
|
}, undefined, true, undefined, this);
|
|
389
389
|
};
|
|
390
|
+
// src/client/opsActionCenter.ts
|
|
391
|
+
var recordVoiceOpsActionResult = async (result, options = {}) => {
|
|
392
|
+
if (options.auditPath === false) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
const path = options.auditPath ?? "/api/voice/ops-actions/audit";
|
|
396
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
397
|
+
const response = await fetchImpl(path, {
|
|
398
|
+
body: JSON.stringify(result),
|
|
399
|
+
headers: {
|
|
400
|
+
"Content-Type": "application/json"
|
|
401
|
+
},
|
|
402
|
+
method: "POST"
|
|
403
|
+
});
|
|
404
|
+
if (!response.ok) {
|
|
405
|
+
throw new Error(`Voice ops action audit failed: HTTP ${response.status}`);
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
var createVoiceOpsActionCenterActions = (options = {}) => {
|
|
409
|
+
const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
|
|
410
|
+
const actions = [];
|
|
411
|
+
if (options.includeProductionReadiness !== false) {
|
|
412
|
+
actions.push({
|
|
413
|
+
description: "Refresh the production readiness report.",
|
|
414
|
+
id: "production-readiness",
|
|
415
|
+
label: "Refresh readiness",
|
|
416
|
+
method: "GET",
|
|
417
|
+
path: options.productionReadinessPath ?? "/api/production-readiness"
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
if (options.includeDeliveryRuntime !== false) {
|
|
421
|
+
actions.push({
|
|
422
|
+
description: "Drain pending and failed audit/trace deliveries.",
|
|
423
|
+
id: "delivery-runtime.tick",
|
|
424
|
+
label: "Tick delivery workers",
|
|
425
|
+
method: "POST",
|
|
426
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/tick`
|
|
427
|
+
}, {
|
|
428
|
+
description: "Move reviewed dead letters back to live delivery queues.",
|
|
429
|
+
id: "delivery-runtime.requeue-dead-letters",
|
|
430
|
+
label: "Requeue dead letters",
|
|
431
|
+
method: "POST",
|
|
432
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/requeue-dead-letters`
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
if (options.includeTurnLatencyProof !== false) {
|
|
436
|
+
actions.push({
|
|
437
|
+
description: "Run the synthetic turn latency proof.",
|
|
438
|
+
id: "turn-latency.proof",
|
|
439
|
+
label: "Run latency proof",
|
|
440
|
+
method: "POST",
|
|
441
|
+
path: options.turnLatencyProofPath ?? "/api/turn-latency/proof"
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
if (options.includeProviderSimulation !== false) {
|
|
445
|
+
const pathPrefix = options.providerSimulationPathPrefix ?? "/api/stt-simulate";
|
|
446
|
+
for (const provider of options.providers ?? []) {
|
|
447
|
+
actions.push({
|
|
448
|
+
description: `Simulate ${provider} provider failure.`,
|
|
449
|
+
id: `provider.${provider}.failure`,
|
|
450
|
+
label: `Simulate ${provider} failure`,
|
|
451
|
+
method: "POST",
|
|
452
|
+
path: `${pathPrefix}/failure?provider=${encodeURIComponent(provider)}`
|
|
453
|
+
}, {
|
|
454
|
+
description: `Mark ${provider} provider recovered.`,
|
|
455
|
+
id: `provider.${provider}.recovery`,
|
|
456
|
+
label: `Recover ${provider}`,
|
|
457
|
+
method: "POST",
|
|
458
|
+
path: `${pathPrefix}/recovery?provider=${encodeURIComponent(provider)}`
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
return actions;
|
|
463
|
+
};
|
|
464
|
+
var runVoiceOpsAction = async (action, options = {}) => {
|
|
465
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
466
|
+
const response = await fetchImpl(action.path, {
|
|
467
|
+
method: action.method ?? "POST"
|
|
468
|
+
});
|
|
469
|
+
const body = await response.json().catch(() => null);
|
|
470
|
+
if (!response.ok) {
|
|
471
|
+
const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
|
|
472
|
+
throw new Error(message);
|
|
473
|
+
}
|
|
474
|
+
return {
|
|
475
|
+
actionId: action.id,
|
|
476
|
+
body,
|
|
477
|
+
ok: response.ok,
|
|
478
|
+
ranAt: Date.now(),
|
|
479
|
+
status: response.status
|
|
480
|
+
};
|
|
481
|
+
};
|
|
482
|
+
var createVoiceOpsActionCenterStore = (options = {}) => {
|
|
483
|
+
const listeners = new Set;
|
|
484
|
+
let closed = false;
|
|
485
|
+
let timer;
|
|
486
|
+
let snapshot = {
|
|
487
|
+
actions: options.actions ?? createVoiceOpsActionCenterActions(),
|
|
488
|
+
error: null,
|
|
489
|
+
isRunning: false
|
|
490
|
+
};
|
|
491
|
+
const emit = () => {
|
|
492
|
+
for (const listener of listeners) {
|
|
493
|
+
listener();
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
const setActions = (actions) => {
|
|
497
|
+
snapshot = { ...snapshot, actions, updatedAt: Date.now() };
|
|
498
|
+
emit();
|
|
499
|
+
};
|
|
500
|
+
const run = async (actionId) => {
|
|
501
|
+
if (closed) {
|
|
502
|
+
return snapshot.lastResult;
|
|
503
|
+
}
|
|
504
|
+
const action = snapshot.actions.find((item) => item.id === actionId);
|
|
505
|
+
if (!action) {
|
|
506
|
+
throw new Error(`Voice ops action "${actionId}" is not configured.`);
|
|
507
|
+
}
|
|
508
|
+
if (action.disabled) {
|
|
509
|
+
throw new Error(`Voice ops action "${actionId}" is disabled.`);
|
|
510
|
+
}
|
|
511
|
+
snapshot = {
|
|
512
|
+
...snapshot,
|
|
513
|
+
error: null,
|
|
514
|
+
isRunning: true,
|
|
515
|
+
runningActionId: action.id
|
|
516
|
+
};
|
|
517
|
+
emit();
|
|
518
|
+
try {
|
|
519
|
+
const result = await runVoiceOpsAction(action, options);
|
|
520
|
+
await options.onActionResult?.(result);
|
|
521
|
+
await recordVoiceOpsActionResult(result, options);
|
|
522
|
+
snapshot = {
|
|
523
|
+
...snapshot,
|
|
524
|
+
error: null,
|
|
525
|
+
isRunning: false,
|
|
526
|
+
lastResult: result,
|
|
527
|
+
runningActionId: undefined,
|
|
528
|
+
updatedAt: Date.now()
|
|
529
|
+
};
|
|
530
|
+
emit();
|
|
531
|
+
return result;
|
|
532
|
+
} catch (error) {
|
|
533
|
+
const result = {
|
|
534
|
+
actionId: action.id,
|
|
535
|
+
body: null,
|
|
536
|
+
error: error instanceof Error ? error.message : String(error),
|
|
537
|
+
ok: false,
|
|
538
|
+
ranAt: Date.now(),
|
|
539
|
+
status: 0
|
|
540
|
+
};
|
|
541
|
+
await options.onActionResult?.(result);
|
|
542
|
+
await recordVoiceOpsActionResult(result, options).catch(() => {});
|
|
543
|
+
snapshot = {
|
|
544
|
+
...snapshot,
|
|
545
|
+
error: error instanceof Error ? error.message : String(error),
|
|
546
|
+
isRunning: false,
|
|
547
|
+
runningActionId: undefined
|
|
548
|
+
};
|
|
549
|
+
emit();
|
|
550
|
+
throw error;
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
const close = () => {
|
|
554
|
+
closed = true;
|
|
555
|
+
if (timer) {
|
|
556
|
+
clearInterval(timer);
|
|
557
|
+
timer = undefined;
|
|
558
|
+
}
|
|
559
|
+
listeners.clear();
|
|
560
|
+
};
|
|
561
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
562
|
+
timer = setInterval(() => {
|
|
563
|
+
emit();
|
|
564
|
+
}, options.intervalMs);
|
|
565
|
+
}
|
|
566
|
+
return {
|
|
567
|
+
close,
|
|
568
|
+
getServerSnapshot: () => snapshot,
|
|
569
|
+
getSnapshot: () => snapshot,
|
|
570
|
+
run,
|
|
571
|
+
setActions,
|
|
572
|
+
subscribe: (listener) => {
|
|
573
|
+
listeners.add(listener);
|
|
574
|
+
return () => {
|
|
575
|
+
listeners.delete(listener);
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
// src/client/opsActionCenterWidget.ts
|
|
582
|
+
var DEFAULT_TITLE2 = "Voice Ops Action Center";
|
|
583
|
+
var DEFAULT_DESCRIPTION2 = "Run production voice proofs and operator actions from one primitive panel.";
|
|
584
|
+
var escapeHtml2 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
585
|
+
var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
586
|
+
const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
|
|
587
|
+
return {
|
|
588
|
+
actions: snapshot.actions.map((action) => ({
|
|
589
|
+
description: action.description ?? "",
|
|
590
|
+
disabled: Boolean(action.disabled || snapshot.isRunning),
|
|
591
|
+
id: action.id,
|
|
592
|
+
isRunning: snapshot.runningActionId === action.id,
|
|
593
|
+
label: action.label
|
|
594
|
+
})),
|
|
595
|
+
description: options.description ?? DEFAULT_DESCRIPTION2,
|
|
596
|
+
error: snapshot.error,
|
|
597
|
+
isRunning: snapshot.isRunning,
|
|
598
|
+
label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
|
|
599
|
+
lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
|
|
600
|
+
status,
|
|
601
|
+
title: options.title ?? DEFAULT_TITLE2
|
|
602
|
+
};
|
|
603
|
+
};
|
|
604
|
+
var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
|
|
605
|
+
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
606
|
+
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml2(action.id)}"${action.disabled ? " disabled" : ""}>
|
|
607
|
+
${escapeHtml2(action.isRunning ? "Working..." : action.label)}
|
|
608
|
+
</button>`).join("");
|
|
609
|
+
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml2(model.status)}">
|
|
610
|
+
<header class="absolute-voice-ops-action-center__header">
|
|
611
|
+
<span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml2(model.title)}</span>
|
|
612
|
+
<strong class="absolute-voice-ops-action-center__label">${escapeHtml2(model.label)}</strong>
|
|
613
|
+
</header>
|
|
614
|
+
<p class="absolute-voice-ops-action-center__description">${escapeHtml2(model.description)}</p>
|
|
615
|
+
<div class="absolute-voice-ops-action-center__actions">${actions}</div>
|
|
616
|
+
<p class="absolute-voice-ops-action-center__result">${escapeHtml2(model.lastResultLabel)}</p>
|
|
617
|
+
${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml2(model.error)}</p>` : ""}
|
|
618
|
+
</section>`;
|
|
619
|
+
};
|
|
620
|
+
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}`;
|
|
621
|
+
var mountVoiceOpsActionCenter = (element, options = {}) => {
|
|
622
|
+
const store = createVoiceOpsActionCenterStore(options);
|
|
623
|
+
const render = () => {
|
|
624
|
+
element.innerHTML = renderVoiceOpsActionCenterHTML(store.getSnapshot(), options);
|
|
625
|
+
};
|
|
626
|
+
const unsubscribe = store.subscribe(render);
|
|
627
|
+
const handleClick = (event) => {
|
|
628
|
+
const target = event.target;
|
|
629
|
+
if (!(target instanceof Element)) {
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
const action = target.closest("[data-absolute-voice-ops-action]");
|
|
633
|
+
const actionId = action?.getAttribute("data-absolute-voice-ops-action");
|
|
634
|
+
if (actionId) {
|
|
635
|
+
store.run(actionId).catch(() => {});
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
element.addEventListener?.("click", handleClick);
|
|
639
|
+
render();
|
|
640
|
+
return {
|
|
641
|
+
close: () => {
|
|
642
|
+
element.removeEventListener?.("click", handleClick);
|
|
643
|
+
unsubscribe();
|
|
644
|
+
store.close();
|
|
645
|
+
},
|
|
646
|
+
run: store.run
|
|
647
|
+
};
|
|
648
|
+
};
|
|
649
|
+
var defineVoiceOpsActionCenterElement = (tagName = "absolute-voice-ops-action-center", options = {}) => {
|
|
650
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
customElements.define(tagName, class AbsoluteVoiceOpsActionCenterElement extends HTMLElement {
|
|
654
|
+
mounted;
|
|
655
|
+
connectedCallback() {
|
|
656
|
+
this.mounted = mountVoiceOpsActionCenter(this, {
|
|
657
|
+
...options,
|
|
658
|
+
description: this.getAttribute("description") ?? options.description,
|
|
659
|
+
title: this.getAttribute("title") ?? options.title
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
disconnectedCallback() {
|
|
663
|
+
this.mounted?.close();
|
|
664
|
+
this.mounted = undefined;
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
// src/react/useVoiceOpsActionCenter.tsx
|
|
670
|
+
import { useEffect as useEffect2, useRef as useRef2, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
671
|
+
var useVoiceOpsActionCenter = (options = {}) => {
|
|
672
|
+
const storeRef = useRef2(null);
|
|
673
|
+
if (!storeRef.current) {
|
|
674
|
+
storeRef.current = createVoiceOpsActionCenterStore(options);
|
|
675
|
+
}
|
|
676
|
+
const store = storeRef.current;
|
|
677
|
+
useEffect2(() => () => store.close(), [store]);
|
|
678
|
+
return {
|
|
679
|
+
...useSyncExternalStore2(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
680
|
+
run: store.run,
|
|
681
|
+
setActions: store.setActions
|
|
682
|
+
};
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
// src/react/VoiceOpsActionCenter.tsx
|
|
686
|
+
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
687
|
+
var VoiceOpsActionCenter = ({
|
|
688
|
+
className,
|
|
689
|
+
...options
|
|
690
|
+
}) => {
|
|
691
|
+
const snapshot = useVoiceOpsActionCenter(options);
|
|
692
|
+
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
693
|
+
return /* @__PURE__ */ jsxDEV2("section", {
|
|
694
|
+
className: [
|
|
695
|
+
"absolute-voice-ops-action-center",
|
|
696
|
+
`absolute-voice-ops-action-center--${model.status}`,
|
|
697
|
+
className
|
|
698
|
+
].filter(Boolean).join(" "),
|
|
699
|
+
children: [
|
|
700
|
+
/* @__PURE__ */ jsxDEV2("header", {
|
|
701
|
+
className: "absolute-voice-ops-action-center__header",
|
|
702
|
+
children: [
|
|
703
|
+
/* @__PURE__ */ jsxDEV2("span", {
|
|
704
|
+
className: "absolute-voice-ops-action-center__eyebrow",
|
|
705
|
+
children: model.title
|
|
706
|
+
}, undefined, false, undefined, this),
|
|
707
|
+
/* @__PURE__ */ jsxDEV2("strong", {
|
|
708
|
+
className: "absolute-voice-ops-action-center__label",
|
|
709
|
+
children: model.label
|
|
710
|
+
}, undefined, false, undefined, this)
|
|
711
|
+
]
|
|
712
|
+
}, undefined, true, undefined, this),
|
|
713
|
+
/* @__PURE__ */ jsxDEV2("p", {
|
|
714
|
+
className: "absolute-voice-ops-action-center__description",
|
|
715
|
+
children: model.description
|
|
716
|
+
}, undefined, false, undefined, this),
|
|
717
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
718
|
+
className: "absolute-voice-ops-action-center__actions",
|
|
719
|
+
children: model.actions.map((action) => /* @__PURE__ */ jsxDEV2("button", {
|
|
720
|
+
disabled: action.disabled,
|
|
721
|
+
onClick: () => {
|
|
722
|
+
snapshot.run(action.id).catch(() => {});
|
|
723
|
+
},
|
|
724
|
+
type: "button",
|
|
725
|
+
children: action.isRunning ? "Working..." : action.label
|
|
726
|
+
}, action.id, false, undefined, this))
|
|
727
|
+
}, undefined, false, undefined, this),
|
|
728
|
+
/* @__PURE__ */ jsxDEV2("p", {
|
|
729
|
+
className: "absolute-voice-ops-action-center__result",
|
|
730
|
+
children: model.lastResultLabel
|
|
731
|
+
}, undefined, false, undefined, this),
|
|
732
|
+
model.error ? /* @__PURE__ */ jsxDEV2("p", {
|
|
733
|
+
className: "absolute-voice-ops-action-center__error",
|
|
734
|
+
children: model.error
|
|
735
|
+
}, undefined, false, undefined, this) : null
|
|
736
|
+
]
|
|
737
|
+
}, undefined, true, undefined, this);
|
|
738
|
+
};
|
|
390
739
|
// src/client/deliveryRuntime.ts
|
|
391
740
|
var getDefaultActionPath = (path, action, options) => {
|
|
392
741
|
if (action === "tick") {
|
|
@@ -525,9 +874,9 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
|
|
|
525
874
|
};
|
|
526
875
|
|
|
527
876
|
// src/client/deliveryRuntimeWidget.ts
|
|
528
|
-
var
|
|
529
|
-
var
|
|
530
|
-
var
|
|
877
|
+
var DEFAULT_TITLE3 = "Voice Delivery Runtime";
|
|
878
|
+
var DEFAULT_DESCRIPTION3 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
879
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
531
880
|
var createSurface = (id, summary) => {
|
|
532
881
|
if (!summary) {
|
|
533
882
|
return {
|
|
@@ -561,7 +910,7 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
561
910
|
];
|
|
562
911
|
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
563
912
|
return {
|
|
564
|
-
description: options.description ??
|
|
913
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
565
914
|
error: snapshot.error,
|
|
566
915
|
actionError: snapshot.actionError,
|
|
567
916
|
actionStatus: snapshot.actionStatus,
|
|
@@ -570,32 +919,32 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
570
919
|
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
571
920
|
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
572
921
|
surfaces,
|
|
573
|
-
title: options.title ??
|
|
922
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
574
923
|
updatedAt: snapshot.updatedAt
|
|
575
924
|
};
|
|
576
925
|
};
|
|
577
926
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
578
927
|
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>${
|
|
928
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml3(surface.status)}">
|
|
929
|
+
<span>${escapeHtml3(surface.label)}</span>
|
|
930
|
+
<strong>${escapeHtml3(surface.detail)}</strong>
|
|
582
931
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
583
932
|
</li>`).join("");
|
|
584
933
|
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
585
934
|
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
586
935
|
<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
936
|
</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--${
|
|
937
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.actionError)}</p>` : "";
|
|
938
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml3(model.status)}">
|
|
590
939
|
<header class="absolute-voice-delivery-runtime__header">
|
|
591
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
592
|
-
<strong class="absolute-voice-delivery-runtime__label">${
|
|
940
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml3(model.title)}</span>
|
|
941
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml3(model.label)}</strong>
|
|
593
942
|
</header>
|
|
594
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
943
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml3(model.description)}</p>
|
|
595
944
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
596
945
|
${actions}
|
|
597
946
|
${actionError}
|
|
598
|
-
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${
|
|
947
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.error)}</p>` : ""}
|
|
599
948
|
</section>`;
|
|
600
949
|
};
|
|
601
950
|
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 +1002,19 @@ var defineVoiceDeliveryRuntimeElement = (tagName = "absolute-voice-delivery-runt
|
|
|
653
1002
|
};
|
|
654
1003
|
|
|
655
1004
|
// src/react/useVoiceDeliveryRuntime.tsx
|
|
656
|
-
import { useEffect as
|
|
1005
|
+
import { useEffect as useEffect3, useRef as useRef3, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
657
1006
|
var useVoiceDeliveryRuntime = (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
658
|
-
const storeRef =
|
|
1007
|
+
const storeRef = useRef3(null);
|
|
659
1008
|
if (!storeRef.current) {
|
|
660
1009
|
storeRef.current = createVoiceDeliveryRuntimeStore(path, options);
|
|
661
1010
|
}
|
|
662
1011
|
const store = storeRef.current;
|
|
663
|
-
|
|
1012
|
+
useEffect3(() => {
|
|
664
1013
|
store.refresh().catch(() => {});
|
|
665
1014
|
return () => store.close();
|
|
666
1015
|
}, [store]);
|
|
667
1016
|
return {
|
|
668
|
-
...
|
|
1017
|
+
...useSyncExternalStore3(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
669
1018
|
requeueDeadLetters: store.requeueDeadLetters,
|
|
670
1019
|
refresh: store.refresh,
|
|
671
1020
|
tick: store.tick
|
|
@@ -673,7 +1022,7 @@ var useVoiceDeliveryRuntime = (path = "/api/voice-delivery-runtime", options = {
|
|
|
673
1022
|
};
|
|
674
1023
|
|
|
675
1024
|
// src/react/VoiceDeliveryRuntime.tsx
|
|
676
|
-
import { jsxDEV as
|
|
1025
|
+
import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
|
|
677
1026
|
var VoiceDeliveryRuntime = ({
|
|
678
1027
|
className,
|
|
679
1028
|
includeActions = true,
|
|
@@ -683,42 +1032,42 @@ var VoiceDeliveryRuntime = ({
|
|
|
683
1032
|
const snapshot = useVoiceDeliveryRuntime(path, options);
|
|
684
1033
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
685
1034
|
const hasDeadLetters = model.surfaces.some((surface) => surface.deadLettered > 0);
|
|
686
|
-
return /* @__PURE__ */
|
|
1035
|
+
return /* @__PURE__ */ jsxDEV3("section", {
|
|
687
1036
|
className: [
|
|
688
1037
|
"absolute-voice-delivery-runtime",
|
|
689
1038
|
`absolute-voice-delivery-runtime--${model.status}`,
|
|
690
1039
|
className
|
|
691
1040
|
].filter(Boolean).join(" "),
|
|
692
1041
|
children: [
|
|
693
|
-
/* @__PURE__ */
|
|
1042
|
+
/* @__PURE__ */ jsxDEV3("header", {
|
|
694
1043
|
className: "absolute-voice-delivery-runtime__header",
|
|
695
1044
|
children: [
|
|
696
|
-
/* @__PURE__ */
|
|
1045
|
+
/* @__PURE__ */ jsxDEV3("span", {
|
|
697
1046
|
className: "absolute-voice-delivery-runtime__eyebrow",
|
|
698
1047
|
children: model.title
|
|
699
1048
|
}, undefined, false, undefined, this),
|
|
700
|
-
/* @__PURE__ */
|
|
1049
|
+
/* @__PURE__ */ jsxDEV3("strong", {
|
|
701
1050
|
className: "absolute-voice-delivery-runtime__label",
|
|
702
1051
|
children: model.label
|
|
703
1052
|
}, undefined, false, undefined, this)
|
|
704
1053
|
]
|
|
705
1054
|
}, undefined, true, undefined, this),
|
|
706
|
-
/* @__PURE__ */
|
|
1055
|
+
/* @__PURE__ */ jsxDEV3("p", {
|
|
707
1056
|
className: "absolute-voice-delivery-runtime__description",
|
|
708
1057
|
children: model.description
|
|
709
1058
|
}, undefined, false, undefined, this),
|
|
710
|
-
/* @__PURE__ */
|
|
1059
|
+
/* @__PURE__ */ jsxDEV3("ul", {
|
|
711
1060
|
className: "absolute-voice-delivery-runtime__surfaces",
|
|
712
|
-
children: model.surfaces.map((surface) => /* @__PURE__ */
|
|
1061
|
+
children: model.surfaces.map((surface) => /* @__PURE__ */ jsxDEV3("li", {
|
|
713
1062
|
className: `absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${surface.status}`,
|
|
714
1063
|
children: [
|
|
715
|
-
/* @__PURE__ */
|
|
1064
|
+
/* @__PURE__ */ jsxDEV3("span", {
|
|
716
1065
|
children: surface.label
|
|
717
1066
|
}, undefined, false, undefined, this),
|
|
718
|
-
/* @__PURE__ */
|
|
1067
|
+
/* @__PURE__ */ jsxDEV3("strong", {
|
|
719
1068
|
children: surface.detail
|
|
720
1069
|
}, undefined, false, undefined, this),
|
|
721
|
-
/* @__PURE__ */
|
|
1070
|
+
/* @__PURE__ */ jsxDEV3("small", {
|
|
722
1071
|
children: [
|
|
723
1072
|
surface.failed,
|
|
724
1073
|
" failed / ",
|
|
@@ -729,10 +1078,10 @@ var VoiceDeliveryRuntime = ({
|
|
|
729
1078
|
]
|
|
730
1079
|
}, surface.id, true, undefined, this))
|
|
731
1080
|
}, undefined, false, undefined, this),
|
|
732
|
-
includeActions ? /* @__PURE__ */
|
|
1081
|
+
includeActions ? /* @__PURE__ */ jsxDEV3("div", {
|
|
733
1082
|
className: "absolute-voice-delivery-runtime__actions",
|
|
734
1083
|
children: [
|
|
735
|
-
/* @__PURE__ */
|
|
1084
|
+
/* @__PURE__ */ jsxDEV3("button", {
|
|
736
1085
|
disabled: model.actionStatus === "running",
|
|
737
1086
|
onClick: () => {
|
|
738
1087
|
snapshot.tick().catch(() => {});
|
|
@@ -740,7 +1089,7 @@ var VoiceDeliveryRuntime = ({
|
|
|
740
1089
|
type: "button",
|
|
741
1090
|
children: model.actionStatus === "running" ? "Working..." : "Tick workers"
|
|
742
1091
|
}, undefined, false, undefined, this),
|
|
743
|
-
/* @__PURE__ */
|
|
1092
|
+
/* @__PURE__ */ jsxDEV3("button", {
|
|
744
1093
|
disabled: model.actionStatus === "running" || !hasDeadLetters,
|
|
745
1094
|
onClick: () => {
|
|
746
1095
|
snapshot.requeueDeadLetters().catch(() => {});
|
|
@@ -750,11 +1099,11 @@ var VoiceDeliveryRuntime = ({
|
|
|
750
1099
|
}, undefined, false, undefined, this)
|
|
751
1100
|
]
|
|
752
1101
|
}, undefined, true, undefined, this) : null,
|
|
753
|
-
model.actionError ? /* @__PURE__ */
|
|
1102
|
+
model.actionError ? /* @__PURE__ */ jsxDEV3("p", {
|
|
754
1103
|
className: "absolute-voice-delivery-runtime__error",
|
|
755
1104
|
children: model.actionError
|
|
756
1105
|
}, undefined, false, undefined, this) : null,
|
|
757
|
-
model.error ? /* @__PURE__ */
|
|
1106
|
+
model.error ? /* @__PURE__ */ jsxDEV3("p", {
|
|
758
1107
|
className: "absolute-voice-delivery-runtime__error",
|
|
759
1108
|
children: model.error
|
|
760
1109
|
}, undefined, false, undefined, this) : null
|
|
@@ -841,7 +1190,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
841
1190
|
};
|
|
842
1191
|
|
|
843
1192
|
// src/client/providerSimulationControlsWidget.ts
|
|
844
|
-
var
|
|
1193
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
845
1194
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
846
1195
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
847
1196
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -861,18 +1210,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
861
1210
|
};
|
|
862
1211
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
863
1212
|
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="${
|
|
1213
|
+
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("");
|
|
1214
|
+
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
1215
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
867
1216
|
<header class="absolute-voice-provider-simulation__header">
|
|
868
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
869
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
1217
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml4(model.title)}</span>
|
|
1218
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml4(model.label)}</strong>
|
|
870
1219
|
</header>
|
|
871
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
872
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
1220
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml4(model.description)}</p>
|
|
1221
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml4(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
873
1222
|
<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">${
|
|
1223
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml4(snapshot.error)}</p>` : ""}
|
|
1224
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml4(model.resultText)}</pre>` : ""}
|
|
876
1225
|
</section>`;
|
|
877
1226
|
};
|
|
878
1227
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -938,22 +1287,22 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
938
1287
|
};
|
|
939
1288
|
|
|
940
1289
|
// src/react/useVoiceProviderSimulationControls.tsx
|
|
941
|
-
import { useEffect as
|
|
1290
|
+
import { useEffect as useEffect4, useRef as useRef4, useSyncExternalStore as useSyncExternalStore4 } from "react";
|
|
942
1291
|
var useVoiceProviderSimulationControls = (options) => {
|
|
943
|
-
const storeRef =
|
|
1292
|
+
const storeRef = useRef4(null);
|
|
944
1293
|
if (!storeRef.current) {
|
|
945
1294
|
storeRef.current = createVoiceProviderSimulationControlsStore(options);
|
|
946
1295
|
}
|
|
947
1296
|
const store = storeRef.current;
|
|
948
|
-
|
|
1297
|
+
useEffect4(() => () => store.close(), [store]);
|
|
949
1298
|
return {
|
|
950
|
-
...
|
|
1299
|
+
...useSyncExternalStore4(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
951
1300
|
run: store.run
|
|
952
1301
|
};
|
|
953
1302
|
};
|
|
954
1303
|
|
|
955
1304
|
// src/react/VoiceProviderSimulationControls.tsx
|
|
956
|
-
import { jsxDEV as
|
|
1305
|
+
import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
|
|
957
1306
|
var VoiceProviderSimulationControls = ({
|
|
958
1307
|
className,
|
|
959
1308
|
...options
|
|
@@ -963,38 +1312,38 @@ var VoiceProviderSimulationControls = ({
|
|
|
963
1312
|
const run = (provider, mode) => {
|
|
964
1313
|
snapshot.run(provider, mode).catch(() => {});
|
|
965
1314
|
};
|
|
966
|
-
return /* @__PURE__ */
|
|
1315
|
+
return /* @__PURE__ */ jsxDEV4("section", {
|
|
967
1316
|
className: [
|
|
968
1317
|
"absolute-voice-provider-simulation",
|
|
969
1318
|
`absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}`,
|
|
970
1319
|
className
|
|
971
1320
|
].filter(Boolean).join(" "),
|
|
972
1321
|
children: [
|
|
973
|
-
/* @__PURE__ */
|
|
1322
|
+
/* @__PURE__ */ jsxDEV4("header", {
|
|
974
1323
|
className: "absolute-voice-provider-simulation__header",
|
|
975
1324
|
children: [
|
|
976
|
-
/* @__PURE__ */
|
|
1325
|
+
/* @__PURE__ */ jsxDEV4("span", {
|
|
977
1326
|
className: "absolute-voice-provider-simulation__eyebrow",
|
|
978
1327
|
children: model.title
|
|
979
1328
|
}, undefined, false, undefined, this),
|
|
980
|
-
/* @__PURE__ */
|
|
1329
|
+
/* @__PURE__ */ jsxDEV4("strong", {
|
|
981
1330
|
className: "absolute-voice-provider-simulation__label",
|
|
982
1331
|
children: model.label
|
|
983
1332
|
}, undefined, false, undefined, this)
|
|
984
1333
|
]
|
|
985
1334
|
}, undefined, true, undefined, this),
|
|
986
|
-
/* @__PURE__ */
|
|
1335
|
+
/* @__PURE__ */ jsxDEV4("p", {
|
|
987
1336
|
className: "absolute-voice-provider-simulation__description",
|
|
988
1337
|
children: model.description
|
|
989
1338
|
}, undefined, false, undefined, this),
|
|
990
|
-
model.canSimulateFailure ? null : /* @__PURE__ */
|
|
1339
|
+
model.canSimulateFailure ? null : /* @__PURE__ */ jsxDEV4("p", {
|
|
991
1340
|
className: "absolute-voice-provider-simulation__empty",
|
|
992
1341
|
children: options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure."
|
|
993
1342
|
}, undefined, false, undefined, this),
|
|
994
|
-
/* @__PURE__ */
|
|
1343
|
+
/* @__PURE__ */ jsxDEV4("div", {
|
|
995
1344
|
className: "absolute-voice-provider-simulation__actions",
|
|
996
1345
|
children: [
|
|
997
|
-
model.failureProviders.map((provider) => /* @__PURE__ */
|
|
1346
|
+
model.failureProviders.map((provider) => /* @__PURE__ */ jsxDEV4("button", {
|
|
998
1347
|
disabled: !model.canSimulateFailure || snapshot.isRunning,
|
|
999
1348
|
onClick: () => run(provider.provider, "failure"),
|
|
1000
1349
|
type: "button",
|
|
@@ -1007,7 +1356,7 @@ var VoiceProviderSimulationControls = ({
|
|
|
1007
1356
|
"failure"
|
|
1008
1357
|
]
|
|
1009
1358
|
}, `fail-${provider.provider}`, true, undefined, this)),
|
|
1010
|
-
model.providers.map((provider) => /* @__PURE__ */
|
|
1359
|
+
model.providers.map((provider) => /* @__PURE__ */ jsxDEV4("button", {
|
|
1011
1360
|
disabled: snapshot.isRunning,
|
|
1012
1361
|
onClick: () => run(provider.provider, "recovery"),
|
|
1013
1362
|
type: "button",
|
|
@@ -1019,11 +1368,11 @@ var VoiceProviderSimulationControls = ({
|
|
|
1019
1368
|
}, `recover-${provider.provider}`, true, undefined, this))
|
|
1020
1369
|
]
|
|
1021
1370
|
}, undefined, true, undefined, this),
|
|
1022
|
-
snapshot.error ? /* @__PURE__ */
|
|
1371
|
+
snapshot.error ? /* @__PURE__ */ jsxDEV4("p", {
|
|
1023
1372
|
className: "absolute-voice-provider-simulation__error",
|
|
1024
1373
|
children: snapshot.error
|
|
1025
1374
|
}, undefined, false, undefined, this) : null,
|
|
1026
|
-
model.resultText ? /* @__PURE__ */
|
|
1375
|
+
model.resultText ? /* @__PURE__ */ jsxDEV4("pre", {
|
|
1027
1376
|
className: "absolute-voice-provider-simulation__result",
|
|
1028
1377
|
children: model.resultText
|
|
1029
1378
|
}, undefined, false, undefined, this) : null
|
|
@@ -1031,7 +1380,7 @@ var VoiceProviderSimulationControls = ({
|
|
|
1031
1380
|
}, undefined, true, undefined, this);
|
|
1032
1381
|
};
|
|
1033
1382
|
// src/react/useVoiceProviderCapabilities.tsx
|
|
1034
|
-
import { useEffect as
|
|
1383
|
+
import { useEffect as useEffect5, useRef as useRef5, useSyncExternalStore as useSyncExternalStore5 } from "react";
|
|
1035
1384
|
|
|
1036
1385
|
// src/client/providerCapabilities.ts
|
|
1037
1386
|
var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
|
|
@@ -1114,25 +1463,25 @@ var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities",
|
|
|
1114
1463
|
|
|
1115
1464
|
// src/react/useVoiceProviderCapabilities.tsx
|
|
1116
1465
|
var useVoiceProviderCapabilities = (path = "/api/provider-capabilities", options = {}) => {
|
|
1117
|
-
const storeRef =
|
|
1466
|
+
const storeRef = useRef5(null);
|
|
1118
1467
|
if (!storeRef.current) {
|
|
1119
1468
|
storeRef.current = createVoiceProviderCapabilitiesStore(path, options);
|
|
1120
1469
|
}
|
|
1121
1470
|
const store = storeRef.current;
|
|
1122
|
-
|
|
1471
|
+
useEffect5(() => {
|
|
1123
1472
|
store.refresh().catch(() => {});
|
|
1124
1473
|
return () => store.close();
|
|
1125
1474
|
}, [store]);
|
|
1126
1475
|
return {
|
|
1127
|
-
...
|
|
1476
|
+
...useSyncExternalStore5(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1128
1477
|
refresh: store.refresh
|
|
1129
1478
|
};
|
|
1130
1479
|
};
|
|
1131
1480
|
|
|
1132
1481
|
// src/client/providerCapabilitiesWidget.ts
|
|
1133
|
-
var
|
|
1134
|
-
var
|
|
1135
|
-
var
|
|
1482
|
+
var DEFAULT_TITLE4 = "Provider Capabilities";
|
|
1483
|
+
var DEFAULT_DESCRIPTION4 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
1484
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1136
1485
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1137
1486
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
1138
1487
|
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -1176,36 +1525,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
1176
1525
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
1177
1526
|
return {
|
|
1178
1527
|
capabilities,
|
|
1179
|
-
description: options.description ??
|
|
1528
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
1180
1529
|
error: snapshot.error,
|
|
1181
1530
|
isLoading: snapshot.isLoading,
|
|
1182
1531
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
1183
1532
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1184
|
-
title: options.title ??
|
|
1533
|
+
title: options.title ?? DEFAULT_TITLE4,
|
|
1185
1534
|
updatedAt: snapshot.updatedAt
|
|
1186
1535
|
};
|
|
1187
1536
|
};
|
|
1188
1537
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
1189
1538
|
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--${
|
|
1539
|
+
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
1540
|
<header>
|
|
1192
|
-
<strong>${
|
|
1193
|
-
<span>${
|
|
1541
|
+
<strong>${escapeHtml5(capability.label)}</strong>
|
|
1542
|
+
<span>${escapeHtml5(formatStatus(capability.status))}</span>
|
|
1194
1543
|
</header>
|
|
1195
|
-
<p>${
|
|
1544
|
+
<p>${escapeHtml5(capability.detail)}</p>
|
|
1196
1545
|
<dl>${capability.rows.map((row) => `<div>
|
|
1197
|
-
<dt>${
|
|
1198
|
-
<dd>${
|
|
1546
|
+
<dt>${escapeHtml5(row.label)}</dt>
|
|
1547
|
+
<dd>${escapeHtml5(row.value)}</dd>
|
|
1199
1548
|
</div>`).join("")}</dl>
|
|
1200
1549
|
</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--${
|
|
1550
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml5(model.status)}">
|
|
1202
1551
|
<header class="absolute-voice-provider-capabilities__header">
|
|
1203
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
1204
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
1552
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml5(model.title)}</span>
|
|
1553
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml5(model.label)}</strong>
|
|
1205
1554
|
</header>
|
|
1206
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
1555
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml5(model.description)}</p>
|
|
1207
1556
|
${capabilities}
|
|
1208
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
1557
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
1209
1558
|
</section>`;
|
|
1210
1559
|
};
|
|
1211
1560
|
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 +1596,7 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
1247
1596
|
};
|
|
1248
1597
|
|
|
1249
1598
|
// src/react/VoiceProviderCapabilities.tsx
|
|
1250
|
-
import { jsxDEV as
|
|
1599
|
+
import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
|
|
1251
1600
|
var VoiceProviderCapabilities = ({
|
|
1252
1601
|
className,
|
|
1253
1602
|
path = "/api/provider-capabilities",
|
|
@@ -1255,58 +1604,58 @@ var VoiceProviderCapabilities = ({
|
|
|
1255
1604
|
}) => {
|
|
1256
1605
|
const snapshot = useVoiceProviderCapabilities(path, options);
|
|
1257
1606
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
1258
|
-
return /* @__PURE__ */
|
|
1607
|
+
return /* @__PURE__ */ jsxDEV5("section", {
|
|
1259
1608
|
className: [
|
|
1260
1609
|
"absolute-voice-provider-capabilities",
|
|
1261
1610
|
`absolute-voice-provider-capabilities--${model.status}`,
|
|
1262
1611
|
className
|
|
1263
1612
|
].filter(Boolean).join(" "),
|
|
1264
1613
|
children: [
|
|
1265
|
-
/* @__PURE__ */
|
|
1614
|
+
/* @__PURE__ */ jsxDEV5("header", {
|
|
1266
1615
|
className: "absolute-voice-provider-capabilities__header",
|
|
1267
1616
|
children: [
|
|
1268
|
-
/* @__PURE__ */
|
|
1617
|
+
/* @__PURE__ */ jsxDEV5("span", {
|
|
1269
1618
|
className: "absolute-voice-provider-capabilities__eyebrow",
|
|
1270
1619
|
children: model.title
|
|
1271
1620
|
}, undefined, false, undefined, this),
|
|
1272
|
-
/* @__PURE__ */
|
|
1621
|
+
/* @__PURE__ */ jsxDEV5("strong", {
|
|
1273
1622
|
className: "absolute-voice-provider-capabilities__label",
|
|
1274
1623
|
children: model.label
|
|
1275
1624
|
}, undefined, false, undefined, this)
|
|
1276
1625
|
]
|
|
1277
1626
|
}, undefined, true, undefined, this),
|
|
1278
|
-
/* @__PURE__ */
|
|
1627
|
+
/* @__PURE__ */ jsxDEV5("p", {
|
|
1279
1628
|
className: "absolute-voice-provider-capabilities__description",
|
|
1280
1629
|
children: model.description
|
|
1281
1630
|
}, undefined, false, undefined, this),
|
|
1282
|
-
model.capabilities.length ? /* @__PURE__ */
|
|
1631
|
+
model.capabilities.length ? /* @__PURE__ */ jsxDEV5("div", {
|
|
1283
1632
|
className: "absolute-voice-provider-capabilities__providers",
|
|
1284
|
-
children: model.capabilities.map((capability) => /* @__PURE__ */
|
|
1633
|
+
children: model.capabilities.map((capability) => /* @__PURE__ */ jsxDEV5("article", {
|
|
1285
1634
|
className: [
|
|
1286
1635
|
"absolute-voice-provider-capabilities__provider",
|
|
1287
1636
|
`absolute-voice-provider-capabilities__provider--${capability.status}`
|
|
1288
1637
|
].join(" "),
|
|
1289
1638
|
children: [
|
|
1290
|
-
/* @__PURE__ */
|
|
1639
|
+
/* @__PURE__ */ jsxDEV5("header", {
|
|
1291
1640
|
children: [
|
|
1292
|
-
/* @__PURE__ */
|
|
1641
|
+
/* @__PURE__ */ jsxDEV5("strong", {
|
|
1293
1642
|
children: capability.label
|
|
1294
1643
|
}, undefined, false, undefined, this),
|
|
1295
|
-
/* @__PURE__ */
|
|
1644
|
+
/* @__PURE__ */ jsxDEV5("span", {
|
|
1296
1645
|
children: capability.status
|
|
1297
1646
|
}, undefined, false, undefined, this)
|
|
1298
1647
|
]
|
|
1299
1648
|
}, undefined, true, undefined, this),
|
|
1300
|
-
/* @__PURE__ */
|
|
1649
|
+
/* @__PURE__ */ jsxDEV5("p", {
|
|
1301
1650
|
children: capability.detail
|
|
1302
1651
|
}, undefined, false, undefined, this),
|
|
1303
|
-
/* @__PURE__ */
|
|
1304
|
-
children: capability.rows.map((row) => /* @__PURE__ */
|
|
1652
|
+
/* @__PURE__ */ jsxDEV5("dl", {
|
|
1653
|
+
children: capability.rows.map((row) => /* @__PURE__ */ jsxDEV5("div", {
|
|
1305
1654
|
children: [
|
|
1306
|
-
/* @__PURE__ */
|
|
1655
|
+
/* @__PURE__ */ jsxDEV5("dt", {
|
|
1307
1656
|
children: row.label
|
|
1308
1657
|
}, undefined, false, undefined, this),
|
|
1309
|
-
/* @__PURE__ */
|
|
1658
|
+
/* @__PURE__ */ jsxDEV5("dd", {
|
|
1310
1659
|
children: row.value
|
|
1311
1660
|
}, undefined, false, undefined, this)
|
|
1312
1661
|
]
|
|
@@ -1314,11 +1663,11 @@ var VoiceProviderCapabilities = ({
|
|
|
1314
1663
|
}, undefined, false, undefined, this)
|
|
1315
1664
|
]
|
|
1316
1665
|
}, `${capability.kind}:${capability.provider}`, true, undefined, this))
|
|
1317
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
1666
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV5("p", {
|
|
1318
1667
|
className: "absolute-voice-provider-capabilities__empty",
|
|
1319
1668
|
children: "Configure provider capabilities to see deployment coverage."
|
|
1320
1669
|
}, undefined, false, undefined, this),
|
|
1321
|
-
model.error ? /* @__PURE__ */
|
|
1670
|
+
model.error ? /* @__PURE__ */ jsxDEV5("p", {
|
|
1322
1671
|
className: "absolute-voice-provider-capabilities__error",
|
|
1323
1672
|
children: model.error
|
|
1324
1673
|
}, undefined, false, undefined, this) : null
|
|
@@ -1326,7 +1675,7 @@ var VoiceProviderCapabilities = ({
|
|
|
1326
1675
|
}, undefined, true, undefined, this);
|
|
1327
1676
|
};
|
|
1328
1677
|
// src/react/useVoiceProviderStatus.tsx
|
|
1329
|
-
import { useEffect as
|
|
1678
|
+
import { useEffect as useEffect6, useRef as useRef6, useSyncExternalStore as useSyncExternalStore6 } from "react";
|
|
1330
1679
|
|
|
1331
1680
|
// src/client/providerStatus.ts
|
|
1332
1681
|
var fetchVoiceProviderStatus = async (path = "/api/provider-status", options = {}) => {
|
|
@@ -1410,25 +1759,25 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
1410
1759
|
|
|
1411
1760
|
// src/react/useVoiceProviderStatus.tsx
|
|
1412
1761
|
var useVoiceProviderStatus = (path = "/api/provider-status", options = {}) => {
|
|
1413
|
-
const storeRef =
|
|
1762
|
+
const storeRef = useRef6(null);
|
|
1414
1763
|
if (!storeRef.current) {
|
|
1415
1764
|
storeRef.current = createVoiceProviderStatusStore(path, options);
|
|
1416
1765
|
}
|
|
1417
1766
|
const store = storeRef.current;
|
|
1418
|
-
|
|
1767
|
+
useEffect6(() => {
|
|
1419
1768
|
store.refresh().catch(() => {});
|
|
1420
1769
|
return () => store.close();
|
|
1421
1770
|
}, [store]);
|
|
1422
1771
|
return {
|
|
1423
|
-
...
|
|
1772
|
+
...useSyncExternalStore6(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1424
1773
|
refresh: store.refresh
|
|
1425
1774
|
};
|
|
1426
1775
|
};
|
|
1427
1776
|
|
|
1428
1777
|
// src/client/providerStatusWidget.ts
|
|
1429
|
-
var
|
|
1430
|
-
var
|
|
1431
|
-
var
|
|
1778
|
+
var DEFAULT_TITLE5 = "Voice Providers";
|
|
1779
|
+
var DEFAULT_DESCRIPTION5 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
1780
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1432
1781
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1433
1782
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
1434
1783
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -1472,37 +1821,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
1472
1821
|
const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
|
|
1473
1822
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
1474
1823
|
return {
|
|
1475
|
-
description: options.description ??
|
|
1824
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
1476
1825
|
error: snapshot.error,
|
|
1477
1826
|
isLoading: snapshot.isLoading,
|
|
1478
1827
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
1479
1828
|
providers,
|
|
1480
1829
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1481
|
-
title: options.title ??
|
|
1830
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
1482
1831
|
updatedAt: snapshot.updatedAt
|
|
1483
1832
|
};
|
|
1484
1833
|
};
|
|
1485
1834
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
1486
1835
|
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--${
|
|
1836
|
+
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
1837
|
<header>
|
|
1489
|
-
<strong>${
|
|
1490
|
-
<span>${
|
|
1838
|
+
<strong>${escapeHtml6(provider.label)}</strong>
|
|
1839
|
+
<span>${escapeHtml6(formatStatus2(provider.status))}</span>
|
|
1491
1840
|
</header>
|
|
1492
|
-
<p>${
|
|
1841
|
+
<p>${escapeHtml6(provider.detail)}</p>
|
|
1493
1842
|
<dl>${provider.rows.map((row) => `<div>
|
|
1494
|
-
<dt>${
|
|
1495
|
-
<dd>${
|
|
1843
|
+
<dt>${escapeHtml6(row.label)}</dt>
|
|
1844
|
+
<dd>${escapeHtml6(row.value)}</dd>
|
|
1496
1845
|
</div>`).join("")}</dl>
|
|
1497
1846
|
</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--${
|
|
1847
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml6(model.status)}">
|
|
1499
1848
|
<header class="absolute-voice-provider-status__header">
|
|
1500
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
1501
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
1849
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml6(model.title)}</span>
|
|
1850
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml6(model.label)}</strong>
|
|
1502
1851
|
</header>
|
|
1503
|
-
<p class="absolute-voice-provider-status__description">${
|
|
1852
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml6(model.description)}</p>
|
|
1504
1853
|
${providers}
|
|
1505
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
1854
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
1506
1855
|
</section>`;
|
|
1507
1856
|
};
|
|
1508
1857
|
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 +1893,7 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
1544
1893
|
};
|
|
1545
1894
|
|
|
1546
1895
|
// src/react/VoiceProviderStatus.tsx
|
|
1547
|
-
import { jsxDEV as
|
|
1896
|
+
import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
|
|
1548
1897
|
var VoiceProviderStatus = ({
|
|
1549
1898
|
className,
|
|
1550
1899
|
path = "/api/provider-status",
|
|
@@ -1552,58 +1901,58 @@ var VoiceProviderStatus = ({
|
|
|
1552
1901
|
}) => {
|
|
1553
1902
|
const snapshot = useVoiceProviderStatus(path, options);
|
|
1554
1903
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
1555
|
-
return /* @__PURE__ */
|
|
1904
|
+
return /* @__PURE__ */ jsxDEV6("section", {
|
|
1556
1905
|
className: [
|
|
1557
1906
|
"absolute-voice-provider-status",
|
|
1558
1907
|
`absolute-voice-provider-status--${model.status}`,
|
|
1559
1908
|
className
|
|
1560
1909
|
].filter(Boolean).join(" "),
|
|
1561
1910
|
children: [
|
|
1562
|
-
/* @__PURE__ */
|
|
1911
|
+
/* @__PURE__ */ jsxDEV6("header", {
|
|
1563
1912
|
className: "absolute-voice-provider-status__header",
|
|
1564
1913
|
children: [
|
|
1565
|
-
/* @__PURE__ */
|
|
1914
|
+
/* @__PURE__ */ jsxDEV6("span", {
|
|
1566
1915
|
className: "absolute-voice-provider-status__eyebrow",
|
|
1567
1916
|
children: model.title
|
|
1568
1917
|
}, undefined, false, undefined, this),
|
|
1569
|
-
/* @__PURE__ */
|
|
1918
|
+
/* @__PURE__ */ jsxDEV6("strong", {
|
|
1570
1919
|
className: "absolute-voice-provider-status__label",
|
|
1571
1920
|
children: model.label
|
|
1572
1921
|
}, undefined, false, undefined, this)
|
|
1573
1922
|
]
|
|
1574
1923
|
}, undefined, true, undefined, this),
|
|
1575
|
-
/* @__PURE__ */
|
|
1924
|
+
/* @__PURE__ */ jsxDEV6("p", {
|
|
1576
1925
|
className: "absolute-voice-provider-status__description",
|
|
1577
1926
|
children: model.description
|
|
1578
1927
|
}, undefined, false, undefined, this),
|
|
1579
|
-
model.providers.length ? /* @__PURE__ */
|
|
1928
|
+
model.providers.length ? /* @__PURE__ */ jsxDEV6("div", {
|
|
1580
1929
|
className: "absolute-voice-provider-status__providers",
|
|
1581
|
-
children: model.providers.map((provider) => /* @__PURE__ */
|
|
1930
|
+
children: model.providers.map((provider) => /* @__PURE__ */ jsxDEV6("article", {
|
|
1582
1931
|
className: [
|
|
1583
1932
|
"absolute-voice-provider-status__provider",
|
|
1584
1933
|
`absolute-voice-provider-status__provider--${provider.status}`
|
|
1585
1934
|
].join(" "),
|
|
1586
1935
|
children: [
|
|
1587
|
-
/* @__PURE__ */
|
|
1936
|
+
/* @__PURE__ */ jsxDEV6("header", {
|
|
1588
1937
|
children: [
|
|
1589
|
-
/* @__PURE__ */
|
|
1938
|
+
/* @__PURE__ */ jsxDEV6("strong", {
|
|
1590
1939
|
children: provider.label
|
|
1591
1940
|
}, undefined, false, undefined, this),
|
|
1592
|
-
/* @__PURE__ */
|
|
1941
|
+
/* @__PURE__ */ jsxDEV6("span", {
|
|
1593
1942
|
children: provider.status
|
|
1594
1943
|
}, undefined, false, undefined, this)
|
|
1595
1944
|
]
|
|
1596
1945
|
}, undefined, true, undefined, this),
|
|
1597
|
-
/* @__PURE__ */
|
|
1946
|
+
/* @__PURE__ */ jsxDEV6("p", {
|
|
1598
1947
|
children: provider.detail
|
|
1599
1948
|
}, undefined, false, undefined, this),
|
|
1600
|
-
/* @__PURE__ */
|
|
1601
|
-
children: provider.rows.map((row) => /* @__PURE__ */
|
|
1949
|
+
/* @__PURE__ */ jsxDEV6("dl", {
|
|
1950
|
+
children: provider.rows.map((row) => /* @__PURE__ */ jsxDEV6("div", {
|
|
1602
1951
|
children: [
|
|
1603
|
-
/* @__PURE__ */
|
|
1952
|
+
/* @__PURE__ */ jsxDEV6("dt", {
|
|
1604
1953
|
children: row.label
|
|
1605
1954
|
}, undefined, false, undefined, this),
|
|
1606
|
-
/* @__PURE__ */
|
|
1955
|
+
/* @__PURE__ */ jsxDEV6("dd", {
|
|
1607
1956
|
children: row.value
|
|
1608
1957
|
}, undefined, false, undefined, this)
|
|
1609
1958
|
]
|
|
@@ -1611,11 +1960,11 @@ var VoiceProviderStatus = ({
|
|
|
1611
1960
|
}, undefined, false, undefined, this)
|
|
1612
1961
|
]
|
|
1613
1962
|
}, provider.provider, true, undefined, this))
|
|
1614
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
1963
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV6("p", {
|
|
1615
1964
|
className: "absolute-voice-provider-status__empty",
|
|
1616
1965
|
children: "Run voice traffic to see provider health."
|
|
1617
1966
|
}, undefined, false, undefined, this),
|
|
1618
|
-
model.error ? /* @__PURE__ */
|
|
1967
|
+
model.error ? /* @__PURE__ */ jsxDEV6("p", {
|
|
1619
1968
|
className: "absolute-voice-provider-status__error",
|
|
1620
1969
|
children: model.error
|
|
1621
1970
|
}, undefined, false, undefined, this) : null
|
|
@@ -1623,7 +1972,7 @@ var VoiceProviderStatus = ({
|
|
|
1623
1972
|
}, undefined, true, undefined, this);
|
|
1624
1973
|
};
|
|
1625
1974
|
// src/react/useVoiceRoutingStatus.tsx
|
|
1626
|
-
import { useEffect as
|
|
1975
|
+
import { useEffect as useEffect7, useRef as useRef7, useSyncExternalStore as useSyncExternalStore7 } from "react";
|
|
1627
1976
|
|
|
1628
1977
|
// src/client/routingStatus.ts
|
|
1629
1978
|
var fetchVoiceRoutingStatus = async (path = "/api/routing/latest", options = {}) => {
|
|
@@ -1707,25 +2056,25 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
1707
2056
|
|
|
1708
2057
|
// src/react/useVoiceRoutingStatus.tsx
|
|
1709
2058
|
var useVoiceRoutingStatus = (path = "/api/routing/latest", options = {}) => {
|
|
1710
|
-
const storeRef =
|
|
2059
|
+
const storeRef = useRef7(null);
|
|
1711
2060
|
if (!storeRef.current) {
|
|
1712
2061
|
storeRef.current = createVoiceRoutingStatusStore(path, options);
|
|
1713
2062
|
}
|
|
1714
2063
|
const store = storeRef.current;
|
|
1715
|
-
|
|
2064
|
+
useEffect7(() => {
|
|
1716
2065
|
store.refresh().catch(() => {});
|
|
1717
2066
|
return () => store.close();
|
|
1718
2067
|
}, [store]);
|
|
1719
2068
|
return {
|
|
1720
|
-
...
|
|
2069
|
+
...useSyncExternalStore7(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
1721
2070
|
refresh: store.refresh
|
|
1722
2071
|
};
|
|
1723
2072
|
};
|
|
1724
2073
|
|
|
1725
2074
|
// src/client/routingStatusWidget.ts
|
|
1726
|
-
var
|
|
1727
|
-
var
|
|
1728
|
-
var
|
|
2075
|
+
var DEFAULT_TITLE6 = "Voice Routing";
|
|
2076
|
+
var DEFAULT_DESCRIPTION6 = "Latest provider routing decision from the self-hosted trace store.";
|
|
2077
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1729
2078
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
1730
2079
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
1731
2080
|
const decision = snapshot.decision;
|
|
@@ -1749,30 +2098,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
1749
2098
|
] : [];
|
|
1750
2099
|
return {
|
|
1751
2100
|
decision,
|
|
1752
|
-
description: options.description ??
|
|
2101
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
1753
2102
|
error: snapshot.error,
|
|
1754
2103
|
isLoading: snapshot.isLoading,
|
|
1755
2104
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
1756
2105
|
rows,
|
|
1757
2106
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1758
|
-
title: options.title ??
|
|
2107
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
1759
2108
|
updatedAt: snapshot.updatedAt
|
|
1760
2109
|
};
|
|
1761
2110
|
};
|
|
1762
2111
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
1763
2112
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
1764
2113
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
1765
|
-
<span>${
|
|
1766
|
-
<strong>${
|
|
2114
|
+
<span>${escapeHtml7(row.label)}</span>
|
|
2115
|
+
<strong>${escapeHtml7(row.value)}</strong>
|
|
1767
2116
|
</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--${
|
|
2117
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml7(model.status)}">
|
|
1769
2118
|
<header class="absolute-voice-routing-status__header">
|
|
1770
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
1771
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
2119
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml7(model.title)}</span>
|
|
2120
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml7(model.label)}</strong>
|
|
1772
2121
|
</header>
|
|
1773
|
-
<p class="absolute-voice-routing-status__description">${
|
|
2122
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml7(model.description)}</p>
|
|
1774
2123
|
${rows}
|
|
1775
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
2124
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
1776
2125
|
</section>`;
|
|
1777
2126
|
};
|
|
1778
2127
|
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 +2163,7 @@ var defineVoiceRoutingStatusElement = (tagName = "absolute-voice-routing-status"
|
|
|
1814
2163
|
};
|
|
1815
2164
|
|
|
1816
2165
|
// src/react/VoiceRoutingStatus.tsx
|
|
1817
|
-
import { jsxDEV as
|
|
2166
|
+
import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
|
|
1818
2167
|
var VoiceRoutingStatus = ({
|
|
1819
2168
|
className,
|
|
1820
2169
|
path = "/api/routing/latest",
|
|
@@ -1822,47 +2171,47 @@ var VoiceRoutingStatus = ({
|
|
|
1822
2171
|
}) => {
|
|
1823
2172
|
const snapshot = useVoiceRoutingStatus(path, options);
|
|
1824
2173
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
1825
|
-
return /* @__PURE__ */
|
|
2174
|
+
return /* @__PURE__ */ jsxDEV7("section", {
|
|
1826
2175
|
className: [
|
|
1827
2176
|
"absolute-voice-routing-status",
|
|
1828
2177
|
`absolute-voice-routing-status--${model.status}`,
|
|
1829
2178
|
className
|
|
1830
2179
|
].filter(Boolean).join(" "),
|
|
1831
2180
|
children: [
|
|
1832
|
-
/* @__PURE__ */
|
|
2181
|
+
/* @__PURE__ */ jsxDEV7("header", {
|
|
1833
2182
|
className: "absolute-voice-routing-status__header",
|
|
1834
2183
|
children: [
|
|
1835
|
-
/* @__PURE__ */
|
|
2184
|
+
/* @__PURE__ */ jsxDEV7("span", {
|
|
1836
2185
|
className: "absolute-voice-routing-status__eyebrow",
|
|
1837
2186
|
children: model.title
|
|
1838
2187
|
}, undefined, false, undefined, this),
|
|
1839
|
-
/* @__PURE__ */
|
|
2188
|
+
/* @__PURE__ */ jsxDEV7("strong", {
|
|
1840
2189
|
className: "absolute-voice-routing-status__label",
|
|
1841
2190
|
children: model.label
|
|
1842
2191
|
}, undefined, false, undefined, this)
|
|
1843
2192
|
]
|
|
1844
2193
|
}, undefined, true, undefined, this),
|
|
1845
|
-
/* @__PURE__ */
|
|
2194
|
+
/* @__PURE__ */ jsxDEV7("p", {
|
|
1846
2195
|
className: "absolute-voice-routing-status__description",
|
|
1847
2196
|
children: model.description
|
|
1848
2197
|
}, undefined, false, undefined, this),
|
|
1849
|
-
model.rows.length ? /* @__PURE__ */
|
|
2198
|
+
model.rows.length ? /* @__PURE__ */ jsxDEV7("div", {
|
|
1850
2199
|
className: "absolute-voice-routing-status__grid",
|
|
1851
|
-
children: model.rows.map((row) => /* @__PURE__ */
|
|
2200
|
+
children: model.rows.map((row) => /* @__PURE__ */ jsxDEV7("div", {
|
|
1852
2201
|
children: [
|
|
1853
|
-
/* @__PURE__ */
|
|
2202
|
+
/* @__PURE__ */ jsxDEV7("span", {
|
|
1854
2203
|
children: row.label
|
|
1855
2204
|
}, undefined, false, undefined, this),
|
|
1856
|
-
/* @__PURE__ */
|
|
2205
|
+
/* @__PURE__ */ jsxDEV7("strong", {
|
|
1857
2206
|
children: row.value
|
|
1858
2207
|
}, undefined, false, undefined, this)
|
|
1859
2208
|
]
|
|
1860
2209
|
}, row.label, true, undefined, this))
|
|
1861
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2210
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV7("p", {
|
|
1862
2211
|
className: "absolute-voice-routing-status__empty",
|
|
1863
2212
|
children: "Start a voice session to see the selected provider."
|
|
1864
2213
|
}, undefined, false, undefined, this),
|
|
1865
|
-
model.error ? /* @__PURE__ */
|
|
2214
|
+
model.error ? /* @__PURE__ */ jsxDEV7("p", {
|
|
1866
2215
|
className: "absolute-voice-routing-status__error",
|
|
1867
2216
|
children: model.error
|
|
1868
2217
|
}, undefined, false, undefined, this) : null
|
|
@@ -1950,9 +2299,9 @@ var createVoiceTraceTimelineStore = (path = "/api/voice-traces", options = {}) =
|
|
|
1950
2299
|
};
|
|
1951
2300
|
|
|
1952
2301
|
// src/client/traceTimelineWidget.ts
|
|
1953
|
-
var
|
|
1954
|
-
var
|
|
1955
|
-
var
|
|
2302
|
+
var DEFAULT_TITLE7 = "Voice Traces";
|
|
2303
|
+
var DEFAULT_DESCRIPTION7 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
2304
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1956
2305
|
var formatMs = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
1957
2306
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
1958
2307
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -1966,34 +2315,34 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
1966
2315
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
1967
2316
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
1968
2317
|
return {
|
|
1969
|
-
description: options.description ??
|
|
2318
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
1970
2319
|
error: snapshot.error,
|
|
1971
2320
|
isLoading: snapshot.isLoading,
|
|
1972
2321
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
1973
2322
|
sessions,
|
|
1974
2323
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1975
|
-
title: options.title ??
|
|
2324
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
1976
2325
|
updatedAt: snapshot.updatedAt
|
|
1977
2326
|
};
|
|
1978
2327
|
};
|
|
1979
2328
|
var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
1980
2329
|
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--${
|
|
2330
|
+
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
2331
|
<header>
|
|
1983
|
-
<strong>${
|
|
1984
|
-
<span>${
|
|
2332
|
+
<strong>${escapeHtml8(session.sessionId)}</strong>
|
|
2333
|
+
<span>${escapeHtml8(session.status)}</span>
|
|
1985
2334
|
</header>
|
|
1986
|
-
<p>${
|
|
1987
|
-
<a href="${
|
|
2335
|
+
<p>${escapeHtml8(session.label)} \xB7 ${escapeHtml8(session.durationLabel)} \xB7 ${escapeHtml8(session.providerLabel)}</p>
|
|
2336
|
+
<a href="${escapeHtml8(session.detailHref)}">Open timeline</a>
|
|
1988
2337
|
</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--${
|
|
2338
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml8(model.status)}">
|
|
1990
2339
|
<header class="absolute-voice-trace-timeline__header">
|
|
1991
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
1992
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
2340
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml8(model.title)}</span>
|
|
2341
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml8(model.label)}</strong>
|
|
1993
2342
|
</header>
|
|
1994
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
2343
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml8(model.description)}</p>
|
|
1995
2344
|
${sessions}
|
|
1996
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
2345
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
1997
2346
|
</section>`;
|
|
1998
2347
|
};
|
|
1999
2348
|
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 +2387,25 @@ var defineVoiceTraceTimelineElement = (tagName = "absolute-voice-trace-timeline"
|
|
|
2038
2387
|
};
|
|
2039
2388
|
|
|
2040
2389
|
// src/react/useVoiceTraceTimeline.tsx
|
|
2041
|
-
import { useEffect as
|
|
2390
|
+
import { useEffect as useEffect8, useRef as useRef8, useSyncExternalStore as useSyncExternalStore8 } from "react";
|
|
2042
2391
|
var useVoiceTraceTimeline = (path = "/api/voice-traces", options = {}) => {
|
|
2043
|
-
const storeRef =
|
|
2392
|
+
const storeRef = useRef8(null);
|
|
2044
2393
|
if (!storeRef.current) {
|
|
2045
2394
|
storeRef.current = createVoiceTraceTimelineStore(path, options);
|
|
2046
2395
|
}
|
|
2047
2396
|
const store = storeRef.current;
|
|
2048
|
-
|
|
2397
|
+
useEffect8(() => {
|
|
2049
2398
|
store.refresh().catch(() => {});
|
|
2050
2399
|
return () => store.close();
|
|
2051
2400
|
}, [store]);
|
|
2052
2401
|
return {
|
|
2053
|
-
...
|
|
2402
|
+
...useSyncExternalStore8(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2054
2403
|
refresh: store.refresh
|
|
2055
2404
|
};
|
|
2056
2405
|
};
|
|
2057
2406
|
|
|
2058
2407
|
// src/react/VoiceTraceTimeline.tsx
|
|
2059
|
-
import { jsxDEV as
|
|
2408
|
+
import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
|
|
2060
2409
|
var VoiceTraceTimeline = ({
|
|
2061
2410
|
className,
|
|
2062
2411
|
path = "/api/voice-traces",
|
|
@@ -2064,49 +2413,49 @@ var VoiceTraceTimeline = ({
|
|
|
2064
2413
|
}) => {
|
|
2065
2414
|
const snapshot = useVoiceTraceTimeline(path, options);
|
|
2066
2415
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
2067
|
-
return /* @__PURE__ */
|
|
2416
|
+
return /* @__PURE__ */ jsxDEV8("section", {
|
|
2068
2417
|
className: [
|
|
2069
2418
|
"absolute-voice-trace-timeline",
|
|
2070
2419
|
`absolute-voice-trace-timeline--${model.status}`,
|
|
2071
2420
|
className
|
|
2072
2421
|
].filter(Boolean).join(" "),
|
|
2073
2422
|
children: [
|
|
2074
|
-
/* @__PURE__ */
|
|
2423
|
+
/* @__PURE__ */ jsxDEV8("header", {
|
|
2075
2424
|
className: "absolute-voice-trace-timeline__header",
|
|
2076
2425
|
children: [
|
|
2077
|
-
/* @__PURE__ */
|
|
2426
|
+
/* @__PURE__ */ jsxDEV8("span", {
|
|
2078
2427
|
className: "absolute-voice-trace-timeline__eyebrow",
|
|
2079
2428
|
children: model.title
|
|
2080
2429
|
}, undefined, false, undefined, this),
|
|
2081
|
-
/* @__PURE__ */
|
|
2430
|
+
/* @__PURE__ */ jsxDEV8("strong", {
|
|
2082
2431
|
className: "absolute-voice-trace-timeline__label",
|
|
2083
2432
|
children: model.label
|
|
2084
2433
|
}, undefined, false, undefined, this)
|
|
2085
2434
|
]
|
|
2086
2435
|
}, undefined, true, undefined, this),
|
|
2087
|
-
/* @__PURE__ */
|
|
2436
|
+
/* @__PURE__ */ jsxDEV8("p", {
|
|
2088
2437
|
className: "absolute-voice-trace-timeline__description",
|
|
2089
2438
|
children: model.description
|
|
2090
2439
|
}, undefined, false, undefined, this),
|
|
2091
|
-
model.sessions.length ? /* @__PURE__ */
|
|
2440
|
+
model.sessions.length ? /* @__PURE__ */ jsxDEV8("div", {
|
|
2092
2441
|
className: "absolute-voice-trace-timeline__sessions",
|
|
2093
|
-
children: model.sessions.map((session) => /* @__PURE__ */
|
|
2442
|
+
children: model.sessions.map((session) => /* @__PURE__ */ jsxDEV8("article", {
|
|
2094
2443
|
className: [
|
|
2095
2444
|
"absolute-voice-trace-timeline__session",
|
|
2096
2445
|
`absolute-voice-trace-timeline__session--${session.status}`
|
|
2097
2446
|
].join(" "),
|
|
2098
2447
|
children: [
|
|
2099
|
-
/* @__PURE__ */
|
|
2448
|
+
/* @__PURE__ */ jsxDEV8("header", {
|
|
2100
2449
|
children: [
|
|
2101
|
-
/* @__PURE__ */
|
|
2450
|
+
/* @__PURE__ */ jsxDEV8("strong", {
|
|
2102
2451
|
children: session.sessionId
|
|
2103
2452
|
}, undefined, false, undefined, this),
|
|
2104
|
-
/* @__PURE__ */
|
|
2453
|
+
/* @__PURE__ */ jsxDEV8("span", {
|
|
2105
2454
|
children: session.status
|
|
2106
2455
|
}, undefined, false, undefined, this)
|
|
2107
2456
|
]
|
|
2108
2457
|
}, undefined, true, undefined, this),
|
|
2109
|
-
/* @__PURE__ */
|
|
2458
|
+
/* @__PURE__ */ jsxDEV8("p", {
|
|
2110
2459
|
children: [
|
|
2111
2460
|
session.label,
|
|
2112
2461
|
" \xB7 ",
|
|
@@ -2116,17 +2465,17 @@ var VoiceTraceTimeline = ({
|
|
|
2116
2465
|
session.providerLabel
|
|
2117
2466
|
]
|
|
2118
2467
|
}, undefined, true, undefined, this),
|
|
2119
|
-
/* @__PURE__ */
|
|
2468
|
+
/* @__PURE__ */ jsxDEV8("a", {
|
|
2120
2469
|
href: session.detailHref,
|
|
2121
2470
|
children: "Open timeline"
|
|
2122
2471
|
}, undefined, false, undefined, this)
|
|
2123
2472
|
]
|
|
2124
2473
|
}, session.sessionId, true, undefined, this))
|
|
2125
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2474
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV8("p", {
|
|
2126
2475
|
className: "absolute-voice-trace-timeline__empty",
|
|
2127
2476
|
children: "Run a voice session to see call timelines."
|
|
2128
2477
|
}, undefined, false, undefined, this),
|
|
2129
|
-
model.error ? /* @__PURE__ */
|
|
2478
|
+
model.error ? /* @__PURE__ */ jsxDEV8("p", {
|
|
2130
2479
|
className: "absolute-voice-trace-timeline__error",
|
|
2131
2480
|
children: model.error
|
|
2132
2481
|
}, undefined, false, undefined, this) : null
|
|
@@ -2134,7 +2483,7 @@ var VoiceTraceTimeline = ({
|
|
|
2134
2483
|
}, undefined, true, undefined, this);
|
|
2135
2484
|
};
|
|
2136
2485
|
// src/react/useVoiceTurnLatency.tsx
|
|
2137
|
-
import { useEffect as
|
|
2486
|
+
import { useEffect as useEffect9, useRef as useRef9, useSyncExternalStore as useSyncExternalStore9 } from "react";
|
|
2138
2487
|
|
|
2139
2488
|
// src/client/turnLatency.ts
|
|
2140
2489
|
var fetchVoiceTurnLatency = async (path = "/api/turn-latency", options = {}) => {
|
|
@@ -2241,27 +2590,27 @@ var createVoiceTurnLatencyStore = (path = "/api/turn-latency", options = {}) =>
|
|
|
2241
2590
|
|
|
2242
2591
|
// src/react/useVoiceTurnLatency.tsx
|
|
2243
2592
|
var useVoiceTurnLatency = (path = "/api/turn-latency", options = {}) => {
|
|
2244
|
-
const storeRef =
|
|
2593
|
+
const storeRef = useRef9(null);
|
|
2245
2594
|
if (!storeRef.current) {
|
|
2246
2595
|
storeRef.current = createVoiceTurnLatencyStore(path, options);
|
|
2247
2596
|
}
|
|
2248
2597
|
const store = storeRef.current;
|
|
2249
|
-
|
|
2598
|
+
useEffect9(() => {
|
|
2250
2599
|
store.refresh().catch(() => {});
|
|
2251
2600
|
return () => store.close();
|
|
2252
2601
|
}, [store]);
|
|
2253
2602
|
return {
|
|
2254
|
-
...
|
|
2603
|
+
...useSyncExternalStore9(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2255
2604
|
refresh: store.refresh,
|
|
2256
2605
|
runProof: store.runProof
|
|
2257
2606
|
};
|
|
2258
2607
|
};
|
|
2259
2608
|
|
|
2260
2609
|
// src/client/turnLatencyWidget.ts
|
|
2261
|
-
var
|
|
2262
|
-
var
|
|
2610
|
+
var DEFAULT_TITLE8 = "Turn Latency";
|
|
2611
|
+
var DEFAULT_DESCRIPTION8 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
2263
2612
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
2264
|
-
var
|
|
2613
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2265
2614
|
var formatMs2 = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
2266
2615
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
2267
2616
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -2275,39 +2624,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
2275
2624
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2276
2625
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2277
2626
|
return {
|
|
2278
|
-
description: options.description ??
|
|
2627
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
2279
2628
|
error: snapshot.error,
|
|
2280
2629
|
isLoading: snapshot.isLoading,
|
|
2281
2630
|
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
2631
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
2283
2632
|
showProofAction: Boolean(options.proofPath),
|
|
2284
2633
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2285
|
-
title: options.title ??
|
|
2634
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
2286
2635
|
turns,
|
|
2287
2636
|
updatedAt: snapshot.updatedAt
|
|
2288
2637
|
};
|
|
2289
2638
|
};
|
|
2290
2639
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
2291
2640
|
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--${
|
|
2641
|
+
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
2642
|
<header>
|
|
2294
|
-
<strong>${
|
|
2295
|
-
<span>${
|
|
2643
|
+
<strong>${escapeHtml9(turn.label)}</strong>
|
|
2644
|
+
<span>${escapeHtml9(turn.status)}</span>
|
|
2296
2645
|
</header>
|
|
2297
2646
|
<dl>${turn.rows.map((row) => `<div>
|
|
2298
|
-
<dt>${
|
|
2299
|
-
<dd>${
|
|
2647
|
+
<dt>${escapeHtml9(row.label)}</dt>
|
|
2648
|
+
<dd>${escapeHtml9(row.value)}</dd>
|
|
2300
2649
|
</div>`).join("")}</dl>
|
|
2301
2650
|
</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--${
|
|
2651
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml9(model.status)}">
|
|
2303
2652
|
<header class="absolute-voice-turn-latency__header">
|
|
2304
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
2305
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
2653
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml9(model.title)}</span>
|
|
2654
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml9(model.label)}</strong>
|
|
2306
2655
|
</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">${
|
|
2656
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml9(model.description)}</p>
|
|
2657
|
+
${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
2658
|
${turns}
|
|
2310
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
2659
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
2311
2660
|
</section>`;
|
|
2312
2661
|
};
|
|
2313
2662
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -2358,7 +2707,7 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
2358
2707
|
};
|
|
2359
2708
|
|
|
2360
2709
|
// src/react/VoiceTurnLatency.tsx
|
|
2361
|
-
import { jsxDEV as
|
|
2710
|
+
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
2362
2711
|
var VoiceTurnLatency = ({
|
|
2363
2712
|
className,
|
|
2364
2713
|
path = "/api/turn-latency",
|
|
@@ -2366,31 +2715,31 @@ var VoiceTurnLatency = ({
|
|
|
2366
2715
|
}) => {
|
|
2367
2716
|
const latency = useVoiceTurnLatency(path, options);
|
|
2368
2717
|
const model = createVoiceTurnLatencyViewModel(latency, options);
|
|
2369
|
-
return /* @__PURE__ */
|
|
2718
|
+
return /* @__PURE__ */ jsxDEV9("section", {
|
|
2370
2719
|
className: [
|
|
2371
2720
|
"absolute-voice-turn-latency",
|
|
2372
2721
|
`absolute-voice-turn-latency--${model.status}`,
|
|
2373
2722
|
className
|
|
2374
2723
|
].filter(Boolean).join(" "),
|
|
2375
2724
|
children: [
|
|
2376
|
-
/* @__PURE__ */
|
|
2725
|
+
/* @__PURE__ */ jsxDEV9("header", {
|
|
2377
2726
|
className: "absolute-voice-turn-latency__header",
|
|
2378
2727
|
children: [
|
|
2379
|
-
/* @__PURE__ */
|
|
2728
|
+
/* @__PURE__ */ jsxDEV9("span", {
|
|
2380
2729
|
className: "absolute-voice-turn-latency__eyebrow",
|
|
2381
2730
|
children: model.title
|
|
2382
2731
|
}, undefined, false, undefined, this),
|
|
2383
|
-
/* @__PURE__ */
|
|
2732
|
+
/* @__PURE__ */ jsxDEV9("strong", {
|
|
2384
2733
|
className: "absolute-voice-turn-latency__label",
|
|
2385
2734
|
children: model.label
|
|
2386
2735
|
}, undefined, false, undefined, this)
|
|
2387
2736
|
]
|
|
2388
2737
|
}, undefined, true, undefined, this),
|
|
2389
|
-
/* @__PURE__ */
|
|
2738
|
+
/* @__PURE__ */ jsxDEV9("p", {
|
|
2390
2739
|
className: "absolute-voice-turn-latency__description",
|
|
2391
2740
|
children: model.description
|
|
2392
2741
|
}, undefined, false, undefined, this),
|
|
2393
|
-
model.showProofAction ? /* @__PURE__ */
|
|
2742
|
+
model.showProofAction ? /* @__PURE__ */ jsxDEV9("button", {
|
|
2394
2743
|
className: "absolute-voice-turn-latency__proof",
|
|
2395
2744
|
onClick: () => {
|
|
2396
2745
|
latency.runProof().catch(() => {});
|
|
@@ -2398,31 +2747,31 @@ var VoiceTurnLatency = ({
|
|
|
2398
2747
|
type: "button",
|
|
2399
2748
|
children: model.proofLabel
|
|
2400
2749
|
}, undefined, false, undefined, this) : null,
|
|
2401
|
-
model.turns.length ? /* @__PURE__ */
|
|
2750
|
+
model.turns.length ? /* @__PURE__ */ jsxDEV9("div", {
|
|
2402
2751
|
className: "absolute-voice-turn-latency__turns",
|
|
2403
|
-
children: model.turns.map((turn) => /* @__PURE__ */
|
|
2752
|
+
children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV9("article", {
|
|
2404
2753
|
className: [
|
|
2405
2754
|
"absolute-voice-turn-latency__turn",
|
|
2406
2755
|
`absolute-voice-turn-latency__turn--${turn.status}`
|
|
2407
2756
|
].join(" "),
|
|
2408
2757
|
children: [
|
|
2409
|
-
/* @__PURE__ */
|
|
2758
|
+
/* @__PURE__ */ jsxDEV9("header", {
|
|
2410
2759
|
children: [
|
|
2411
|
-
/* @__PURE__ */
|
|
2760
|
+
/* @__PURE__ */ jsxDEV9("strong", {
|
|
2412
2761
|
children: turn.label
|
|
2413
2762
|
}, undefined, false, undefined, this),
|
|
2414
|
-
/* @__PURE__ */
|
|
2763
|
+
/* @__PURE__ */ jsxDEV9("span", {
|
|
2415
2764
|
children: turn.status
|
|
2416
2765
|
}, undefined, false, undefined, this)
|
|
2417
2766
|
]
|
|
2418
2767
|
}, undefined, true, undefined, this),
|
|
2419
|
-
/* @__PURE__ */
|
|
2420
|
-
children: turn.rows.map((row) => /* @__PURE__ */
|
|
2768
|
+
/* @__PURE__ */ jsxDEV9("dl", {
|
|
2769
|
+
children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV9("div", {
|
|
2421
2770
|
children: [
|
|
2422
|
-
/* @__PURE__ */
|
|
2771
|
+
/* @__PURE__ */ jsxDEV9("dt", {
|
|
2423
2772
|
children: row.label
|
|
2424
2773
|
}, undefined, false, undefined, this),
|
|
2425
|
-
/* @__PURE__ */
|
|
2774
|
+
/* @__PURE__ */ jsxDEV9("dd", {
|
|
2426
2775
|
children: row.value
|
|
2427
2776
|
}, undefined, false, undefined, this)
|
|
2428
2777
|
]
|
|
@@ -2430,11 +2779,11 @@ var VoiceTurnLatency = ({
|
|
|
2430
2779
|
}, undefined, false, undefined, this)
|
|
2431
2780
|
]
|
|
2432
2781
|
}, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
|
|
2433
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
2782
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV9("p", {
|
|
2434
2783
|
className: "absolute-voice-turn-latency__empty",
|
|
2435
2784
|
children: "Complete a voice turn to see latency diagnostics."
|
|
2436
2785
|
}, undefined, false, undefined, this),
|
|
2437
|
-
model.error ? /* @__PURE__ */
|
|
2786
|
+
model.error ? /* @__PURE__ */ jsxDEV9("p", {
|
|
2438
2787
|
className: "absolute-voice-turn-latency__error",
|
|
2439
2788
|
children: model.error
|
|
2440
2789
|
}, undefined, false, undefined, this) : null
|
|
@@ -2442,7 +2791,7 @@ var VoiceTurnLatency = ({
|
|
|
2442
2791
|
}, undefined, true, undefined, this);
|
|
2443
2792
|
};
|
|
2444
2793
|
// src/react/useVoiceTurnQuality.tsx
|
|
2445
|
-
import { useEffect as
|
|
2794
|
+
import { useEffect as useEffect10, useRef as useRef10, useSyncExternalStore as useSyncExternalStore10 } from "react";
|
|
2446
2795
|
|
|
2447
2796
|
// src/client/turnQuality.ts
|
|
2448
2797
|
var fetchVoiceTurnQuality = async (path = "/api/turn-quality", options = {}) => {
|
|
@@ -2525,25 +2874,25 @@ var createVoiceTurnQualityStore = (path = "/api/turn-quality", options = {}) =>
|
|
|
2525
2874
|
|
|
2526
2875
|
// src/react/useVoiceTurnQuality.tsx
|
|
2527
2876
|
var useVoiceTurnQuality = (path = "/api/turn-quality", options = {}) => {
|
|
2528
|
-
const storeRef =
|
|
2877
|
+
const storeRef = useRef10(null);
|
|
2529
2878
|
if (!storeRef.current) {
|
|
2530
2879
|
storeRef.current = createVoiceTurnQualityStore(path, options);
|
|
2531
2880
|
}
|
|
2532
2881
|
const store = storeRef.current;
|
|
2533
|
-
|
|
2882
|
+
useEffect10(() => {
|
|
2534
2883
|
store.refresh().catch(() => {});
|
|
2535
2884
|
return () => store.close();
|
|
2536
2885
|
}, [store]);
|
|
2537
2886
|
return {
|
|
2538
|
-
...
|
|
2887
|
+
...useSyncExternalStore10(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2539
2888
|
refresh: store.refresh
|
|
2540
2889
|
};
|
|
2541
2890
|
};
|
|
2542
2891
|
|
|
2543
2892
|
// src/client/turnQualityWidget.ts
|
|
2544
|
-
var
|
|
2545
|
-
var
|
|
2546
|
-
var
|
|
2893
|
+
var DEFAULT_TITLE9 = "Turn Quality";
|
|
2894
|
+
var DEFAULT_DESCRIPTION9 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
2895
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2547
2896
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
2548
2897
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
2549
2898
|
var getTurnDetail = (turn) => {
|
|
@@ -2581,37 +2930,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
2581
2930
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
2582
2931
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
2583
2932
|
return {
|
|
2584
|
-
description: options.description ??
|
|
2933
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
2585
2934
|
error: snapshot.error,
|
|
2586
2935
|
isLoading: snapshot.isLoading,
|
|
2587
2936
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
2588
2937
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2589
|
-
title: options.title ??
|
|
2938
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
2590
2939
|
turns,
|
|
2591
2940
|
updatedAt: snapshot.updatedAt
|
|
2592
2941
|
};
|
|
2593
2942
|
};
|
|
2594
2943
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
2595
2944
|
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--${
|
|
2945
|
+
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
2946
|
<header>
|
|
2598
|
-
<strong>${
|
|
2599
|
-
<span>${
|
|
2947
|
+
<strong>${escapeHtml10(turn.label)}</strong>
|
|
2948
|
+
<span>${escapeHtml10(turn.status)}</span>
|
|
2600
2949
|
</header>
|
|
2601
|
-
<p>${
|
|
2950
|
+
<p>${escapeHtml10(turn.detail)}</p>
|
|
2602
2951
|
<dl>${turn.rows.map((row) => `<div>
|
|
2603
|
-
<dt>${
|
|
2604
|
-
<dd>${
|
|
2952
|
+
<dt>${escapeHtml10(row.label)}</dt>
|
|
2953
|
+
<dd>${escapeHtml10(row.value)}</dd>
|
|
2605
2954
|
</div>`).join("")}</dl>
|
|
2606
2955
|
</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--${
|
|
2956
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml10(model.status)}">
|
|
2608
2957
|
<header class="absolute-voice-turn-quality__header">
|
|
2609
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
2610
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
2958
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml10(model.title)}</span>
|
|
2959
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml10(model.label)}</strong>
|
|
2611
2960
|
</header>
|
|
2612
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
2961
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml10(model.description)}</p>
|
|
2613
2962
|
${turns}
|
|
2614
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
2963
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
2615
2964
|
</section>`;
|
|
2616
2965
|
};
|
|
2617
2966
|
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 +3002,7 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
2653
3002
|
};
|
|
2654
3003
|
|
|
2655
3004
|
// src/react/VoiceTurnQuality.tsx
|
|
2656
|
-
import { jsxDEV as
|
|
3005
|
+
import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
|
|
2657
3006
|
var VoiceTurnQuality = ({
|
|
2658
3007
|
className,
|
|
2659
3008
|
path = "/api/turn-quality",
|
|
@@ -2661,58 +3010,58 @@ var VoiceTurnQuality = ({
|
|
|
2661
3010
|
}) => {
|
|
2662
3011
|
const snapshot = useVoiceTurnQuality(path, options);
|
|
2663
3012
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
2664
|
-
return /* @__PURE__ */
|
|
3013
|
+
return /* @__PURE__ */ jsxDEV10("section", {
|
|
2665
3014
|
className: [
|
|
2666
3015
|
"absolute-voice-turn-quality",
|
|
2667
3016
|
`absolute-voice-turn-quality--${model.status}`,
|
|
2668
3017
|
className
|
|
2669
3018
|
].filter(Boolean).join(" "),
|
|
2670
3019
|
children: [
|
|
2671
|
-
/* @__PURE__ */
|
|
3020
|
+
/* @__PURE__ */ jsxDEV10("header", {
|
|
2672
3021
|
className: "absolute-voice-turn-quality__header",
|
|
2673
3022
|
children: [
|
|
2674
|
-
/* @__PURE__ */
|
|
3023
|
+
/* @__PURE__ */ jsxDEV10("span", {
|
|
2675
3024
|
className: "absolute-voice-turn-quality__eyebrow",
|
|
2676
3025
|
children: model.title
|
|
2677
3026
|
}, undefined, false, undefined, this),
|
|
2678
|
-
/* @__PURE__ */
|
|
3027
|
+
/* @__PURE__ */ jsxDEV10("strong", {
|
|
2679
3028
|
className: "absolute-voice-turn-quality__label",
|
|
2680
3029
|
children: model.label
|
|
2681
3030
|
}, undefined, false, undefined, this)
|
|
2682
3031
|
]
|
|
2683
3032
|
}, undefined, true, undefined, this),
|
|
2684
|
-
/* @__PURE__ */
|
|
3033
|
+
/* @__PURE__ */ jsxDEV10("p", {
|
|
2685
3034
|
className: "absolute-voice-turn-quality__description",
|
|
2686
3035
|
children: model.description
|
|
2687
3036
|
}, undefined, false, undefined, this),
|
|
2688
|
-
model.turns.length ? /* @__PURE__ */
|
|
3037
|
+
model.turns.length ? /* @__PURE__ */ jsxDEV10("div", {
|
|
2689
3038
|
className: "absolute-voice-turn-quality__turns",
|
|
2690
|
-
children: model.turns.map((turn) => /* @__PURE__ */
|
|
3039
|
+
children: model.turns.map((turn) => /* @__PURE__ */ jsxDEV10("article", {
|
|
2691
3040
|
className: [
|
|
2692
3041
|
"absolute-voice-turn-quality__turn",
|
|
2693
3042
|
`absolute-voice-turn-quality__turn--${turn.status}`
|
|
2694
3043
|
].join(" "),
|
|
2695
3044
|
children: [
|
|
2696
|
-
/* @__PURE__ */
|
|
3045
|
+
/* @__PURE__ */ jsxDEV10("header", {
|
|
2697
3046
|
children: [
|
|
2698
|
-
/* @__PURE__ */
|
|
3047
|
+
/* @__PURE__ */ jsxDEV10("strong", {
|
|
2699
3048
|
children: turn.label
|
|
2700
3049
|
}, undefined, false, undefined, this),
|
|
2701
|
-
/* @__PURE__ */
|
|
3050
|
+
/* @__PURE__ */ jsxDEV10("span", {
|
|
2702
3051
|
children: turn.status
|
|
2703
3052
|
}, undefined, false, undefined, this)
|
|
2704
3053
|
]
|
|
2705
3054
|
}, undefined, true, undefined, this),
|
|
2706
|
-
/* @__PURE__ */
|
|
3055
|
+
/* @__PURE__ */ jsxDEV10("p", {
|
|
2707
3056
|
children: turn.detail
|
|
2708
3057
|
}, undefined, false, undefined, this),
|
|
2709
|
-
/* @__PURE__ */
|
|
2710
|
-
children: turn.rows.map((row) => /* @__PURE__ */
|
|
3058
|
+
/* @__PURE__ */ jsxDEV10("dl", {
|
|
3059
|
+
children: turn.rows.map((row) => /* @__PURE__ */ jsxDEV10("div", {
|
|
2711
3060
|
children: [
|
|
2712
|
-
/* @__PURE__ */
|
|
3061
|
+
/* @__PURE__ */ jsxDEV10("dt", {
|
|
2713
3062
|
children: row.label
|
|
2714
3063
|
}, undefined, false, undefined, this),
|
|
2715
|
-
/* @__PURE__ */
|
|
3064
|
+
/* @__PURE__ */ jsxDEV10("dd", {
|
|
2716
3065
|
children: row.value
|
|
2717
3066
|
}, undefined, false, undefined, this)
|
|
2718
3067
|
]
|
|
@@ -2720,11 +3069,11 @@ var VoiceTurnQuality = ({
|
|
|
2720
3069
|
}, undefined, false, undefined, this)
|
|
2721
3070
|
]
|
|
2722
3071
|
}, `${turn.sessionId}:${turn.turnId}`, true, undefined, this))
|
|
2723
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
3072
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV10("p", {
|
|
2724
3073
|
className: "absolute-voice-turn-quality__empty",
|
|
2725
3074
|
children: "Complete a voice turn to see STT quality diagnostics."
|
|
2726
3075
|
}, undefined, false, undefined, this),
|
|
2727
|
-
model.error ? /* @__PURE__ */
|
|
3076
|
+
model.error ? /* @__PURE__ */ jsxDEV10("p", {
|
|
2728
3077
|
className: "absolute-voice-turn-quality__error",
|
|
2729
3078
|
children: model.error
|
|
2730
3079
|
}, undefined, false, undefined, this) : null
|
|
@@ -2732,7 +3081,7 @@ var VoiceTurnQuality = ({
|
|
|
2732
3081
|
}, undefined, true, undefined, this);
|
|
2733
3082
|
};
|
|
2734
3083
|
// src/react/useVoiceCampaignDialerProof.tsx
|
|
2735
|
-
import { useEffect as
|
|
3084
|
+
import { useEffect as useEffect11, useRef as useRef11, useSyncExternalStore as useSyncExternalStore11 } from "react";
|
|
2736
3085
|
|
|
2737
3086
|
// src/client/campaignDialerProof.ts
|
|
2738
3087
|
var fetchVoiceCampaignDialerProofStatus = async (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
|
|
@@ -2854,23 +3203,23 @@ var createVoiceCampaignDialerProofStore = (path = "/api/voice/campaigns/dialer-p
|
|
|
2854
3203
|
|
|
2855
3204
|
// src/react/useVoiceCampaignDialerProof.tsx
|
|
2856
3205
|
var useVoiceCampaignDialerProof = (path = "/api/voice/campaigns/dialer-proof", options = {}) => {
|
|
2857
|
-
const storeRef =
|
|
3206
|
+
const storeRef = useRef11(null);
|
|
2858
3207
|
if (!storeRef.current) {
|
|
2859
3208
|
storeRef.current = createVoiceCampaignDialerProofStore(path, options);
|
|
2860
3209
|
}
|
|
2861
3210
|
const store = storeRef.current;
|
|
2862
|
-
|
|
3211
|
+
useEffect11(() => {
|
|
2863
3212
|
store.refresh().catch(() => {});
|
|
2864
3213
|
return () => store.close();
|
|
2865
3214
|
}, [store]);
|
|
2866
3215
|
return {
|
|
2867
|
-
...
|
|
3216
|
+
...useSyncExternalStore11(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
2868
3217
|
refresh: store.refresh,
|
|
2869
3218
|
runProof: store.runProof
|
|
2870
3219
|
};
|
|
2871
3220
|
};
|
|
2872
3221
|
// src/react/useVoiceStream.tsx
|
|
2873
|
-
import { useEffect as
|
|
3222
|
+
import { useEffect as useEffect12, useRef as useRef12, useSyncExternalStore as useSyncExternalStore12 } from "react";
|
|
2874
3223
|
|
|
2875
3224
|
// src/client/actions.ts
|
|
2876
3225
|
var normalizeErrorMessage = (value) => {
|
|
@@ -3530,13 +3879,13 @@ var EMPTY_SNAPSHOT = {
|
|
|
3530
3879
|
turns: []
|
|
3531
3880
|
};
|
|
3532
3881
|
var useVoiceStream = (path, options = {}) => {
|
|
3533
|
-
const streamRef =
|
|
3882
|
+
const streamRef = useRef12(null);
|
|
3534
3883
|
if (!streamRef.current) {
|
|
3535
3884
|
streamRef.current = createVoiceStream(path, options);
|
|
3536
3885
|
}
|
|
3537
3886
|
const stream = streamRef.current;
|
|
3538
|
-
|
|
3539
|
-
const snapshot =
|
|
3887
|
+
useEffect12(() => () => stream.close(), [stream]);
|
|
3888
|
+
const snapshot = useSyncExternalStore12(stream.subscribe, stream.getSnapshot, stream.getServerSnapshot) ?? EMPTY_SNAPSHOT;
|
|
3540
3889
|
return {
|
|
3541
3890
|
...snapshot,
|
|
3542
3891
|
callControl: (message) => stream.callControl(message),
|
|
@@ -3546,7 +3895,7 @@ var useVoiceStream = (path, options = {}) => {
|
|
|
3546
3895
|
};
|
|
3547
3896
|
};
|
|
3548
3897
|
// src/react/useVoiceController.tsx
|
|
3549
|
-
import { useEffect as
|
|
3898
|
+
import { useEffect as useEffect13, useRef as useRef13, useSyncExternalStore as useSyncExternalStore13 } from "react";
|
|
3550
3899
|
|
|
3551
3900
|
// src/client/htmx.ts
|
|
3552
3901
|
var DEFAULT_EVENT_NAME = "voice-refresh";
|
|
@@ -4209,13 +4558,13 @@ var EMPTY_SNAPSHOT2 = {
|
|
|
4209
4558
|
turns: []
|
|
4210
4559
|
};
|
|
4211
4560
|
var useVoiceController = (path, options = {}) => {
|
|
4212
|
-
const controllerRef =
|
|
4561
|
+
const controllerRef = useRef13(null);
|
|
4213
4562
|
if (!controllerRef.current) {
|
|
4214
4563
|
controllerRef.current = createVoiceController(path, options);
|
|
4215
4564
|
}
|
|
4216
4565
|
const controller = controllerRef.current;
|
|
4217
|
-
|
|
4218
|
-
const snapshot =
|
|
4566
|
+
useEffect13(() => () => controller.close(), [controller]);
|
|
4567
|
+
const snapshot = useSyncExternalStore13(controller.subscribe, controller.getSnapshot, controller.getServerSnapshot) ?? EMPTY_SNAPSHOT2;
|
|
4219
4568
|
return {
|
|
4220
4569
|
...snapshot,
|
|
4221
4570
|
bindHTMX: controller.bindHTMX,
|
|
@@ -4229,7 +4578,7 @@ var useVoiceController = (path, options = {}) => {
|
|
|
4229
4578
|
};
|
|
4230
4579
|
};
|
|
4231
4580
|
// src/react/useVoiceWorkflowStatus.tsx
|
|
4232
|
-
import { useEffect as
|
|
4581
|
+
import { useEffect as useEffect14, useRef as useRef14, useSyncExternalStore as useSyncExternalStore14 } from "react";
|
|
4233
4582
|
|
|
4234
4583
|
// src/client/workflowStatus.ts
|
|
4235
4584
|
var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
|
|
@@ -4312,17 +4661,17 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
|
|
|
4312
4661
|
|
|
4313
4662
|
// src/react/useVoiceWorkflowStatus.tsx
|
|
4314
4663
|
var useVoiceWorkflowStatus = (path = "/evals/scenarios/json", options = {}) => {
|
|
4315
|
-
const storeRef =
|
|
4664
|
+
const storeRef = useRef14(null);
|
|
4316
4665
|
if (!storeRef.current) {
|
|
4317
4666
|
storeRef.current = createVoiceWorkflowStatusStore(path, options);
|
|
4318
4667
|
}
|
|
4319
4668
|
const store = storeRef.current;
|
|
4320
|
-
|
|
4669
|
+
useEffect14(() => {
|
|
4321
4670
|
store.refresh().catch(() => {});
|
|
4322
4671
|
return () => store.close();
|
|
4323
4672
|
}, [store]);
|
|
4324
4673
|
return {
|
|
4325
|
-
...
|
|
4674
|
+
...useSyncExternalStore14(store.subscribe, store.getSnapshot, store.getServerSnapshot),
|
|
4326
4675
|
refresh: store.refresh
|
|
4327
4676
|
};
|
|
4328
4677
|
};
|
|
@@ -4337,6 +4686,7 @@ export {
|
|
|
4337
4686
|
useVoiceProviderSimulationControls,
|
|
4338
4687
|
useVoiceProviderCapabilities,
|
|
4339
4688
|
useVoiceOpsStatus,
|
|
4689
|
+
useVoiceOpsActionCenter,
|
|
4340
4690
|
useVoiceDeliveryRuntime,
|
|
4341
4691
|
useVoiceController,
|
|
4342
4692
|
useVoiceCampaignDialerProof,
|
|
@@ -4348,5 +4698,6 @@ export {
|
|
|
4348
4698
|
VoiceProviderSimulationControls,
|
|
4349
4699
|
VoiceProviderCapabilities,
|
|
4350
4700
|
VoiceOpsStatus,
|
|
4701
|
+
VoiceOpsActionCenter,
|
|
4351
4702
|
VoiceDeliveryRuntime
|
|
4352
4703
|
};
|