@absolutejs/voice 0.0.22-beta.64 → 0.0.22-beta.66
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/dist/angular/index.d.ts +1 -0
- package/dist/angular/index.js +149 -26
- package/dist/angular/voice-provider-capabilities.service.d.ts +12 -0
- package/dist/appKit.d.ts +3 -1
- package/dist/client/index.d.ts +4 -0
- package/dist/client/index.js +201 -0
- package/dist/client/providerCapabilities.d.ts +19 -0
- package/dist/client/providerCapabilitiesWidget.d.ts +32 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +142 -13
- package/dist/providerCapabilities.d.ts +92 -0
- package/dist/react/VoiceProviderCapabilities.d.ts +6 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +380 -83
- package/dist/react/useVoiceProviderCapabilities.d.ts +8 -0
- package/dist/svelte/createVoiceProviderCapabilities.d.ts +10 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +239 -33
- package/dist/vue/VoiceProviderCapabilities.d.ts +51 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +387 -84
- package/dist/vue/useVoiceProviderCapabilities.d.ts +9 -0
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type VoiceProviderCapabilitiesClientOptions } from '../client/providerCapabilities';
|
|
2
|
+
export declare const useVoiceProviderCapabilities: <TProvider extends string = string>(path?: string, options?: VoiceProviderCapabilitiesClientOptions) => {
|
|
3
|
+
refresh: () => Promise<import("..").VoiceProviderCapabilityReport<TProvider> | undefined>;
|
|
4
|
+
error: string | null;
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
report?: import("..").VoiceProviderCapabilityReport<TProvider> | undefined;
|
|
7
|
+
updatedAt?: number;
|
|
8
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type VoiceProviderCapabilitiesWidgetOptions } from '../client/providerCapabilitiesWidget';
|
|
2
|
+
export declare const createVoiceProviderCapabilities: <TProvider extends string = string>(path?: string, options?: VoiceProviderCapabilitiesWidgetOptions) => {
|
|
3
|
+
getHTML: () => string;
|
|
4
|
+
getViewModel: () => import("../client").VoiceProviderCapabilitiesViewModel<TProvider>;
|
|
5
|
+
close: () => void;
|
|
6
|
+
getServerSnapshot: () => import("../client").VoiceProviderCapabilitiesSnapshot<TProvider>;
|
|
7
|
+
getSnapshot: () => import("../client").VoiceProviderCapabilitiesSnapshot<TProvider>;
|
|
8
|
+
refresh: () => Promise<import("..").VoiceProviderCapabilityReport<TProvider> | undefined>;
|
|
9
|
+
subscribe: (listener: () => void) => () => void;
|
|
10
|
+
};
|
package/dist/svelte/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { createVoiceAppKitStatus } from './createVoiceAppKitStatus';
|
|
2
2
|
export { createVoiceOpsStatus } from './createVoiceOpsStatus';
|
|
3
3
|
export { createVoiceProviderSimulationControls } from './createVoiceProviderSimulationControls';
|
|
4
|
+
export { createVoiceProviderCapabilities } from './createVoiceProviderCapabilities';
|
|
4
5
|
export { createVoiceStream } from './createVoiceStream';
|
|
5
6
|
export { createVoiceProviderStatus } from './createVoiceProviderStatus';
|
|
6
7
|
export { createVoiceRoutingStatus } from './createVoiceRoutingStatus';
|
package/dist/svelte/index.js
CHANGED
|
@@ -473,6 +473,211 @@ var createVoiceProviderSimulationControls = (options) => {
|
|
|
473
473
|
getViewModel: () => createVoiceProviderSimulationControlsViewModel(store.getSnapshot(), options)
|
|
474
474
|
};
|
|
475
475
|
};
|
|
476
|
+
// src/client/providerCapabilities.ts
|
|
477
|
+
var fetchVoiceProviderCapabilities = async (path = "/api/provider-capabilities", options = {}) => {
|
|
478
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
479
|
+
const response = await fetchImpl(path);
|
|
480
|
+
if (!response.ok) {
|
|
481
|
+
throw new Error(`Voice provider capabilities failed: HTTP ${response.status}`);
|
|
482
|
+
}
|
|
483
|
+
return await response.json();
|
|
484
|
+
};
|
|
485
|
+
var createVoiceProviderCapabilitiesStore = (path = "/api/provider-capabilities", options = {}) => {
|
|
486
|
+
const listeners = new Set;
|
|
487
|
+
let closed = false;
|
|
488
|
+
let timer;
|
|
489
|
+
let snapshot = {
|
|
490
|
+
error: null,
|
|
491
|
+
isLoading: false
|
|
492
|
+
};
|
|
493
|
+
const emit = () => {
|
|
494
|
+
for (const listener of listeners) {
|
|
495
|
+
listener();
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
const refresh = async () => {
|
|
499
|
+
if (closed) {
|
|
500
|
+
return snapshot.report;
|
|
501
|
+
}
|
|
502
|
+
snapshot = {
|
|
503
|
+
...snapshot,
|
|
504
|
+
error: null,
|
|
505
|
+
isLoading: true
|
|
506
|
+
};
|
|
507
|
+
emit();
|
|
508
|
+
try {
|
|
509
|
+
const report = await fetchVoiceProviderCapabilities(path, options);
|
|
510
|
+
snapshot = {
|
|
511
|
+
error: null,
|
|
512
|
+
isLoading: false,
|
|
513
|
+
report,
|
|
514
|
+
updatedAt: Date.now()
|
|
515
|
+
};
|
|
516
|
+
emit();
|
|
517
|
+
return report;
|
|
518
|
+
} catch (error) {
|
|
519
|
+
snapshot = {
|
|
520
|
+
...snapshot,
|
|
521
|
+
error: error instanceof Error ? error.message : String(error),
|
|
522
|
+
isLoading: false
|
|
523
|
+
};
|
|
524
|
+
emit();
|
|
525
|
+
throw error;
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
const close = () => {
|
|
529
|
+
closed = true;
|
|
530
|
+
if (timer) {
|
|
531
|
+
clearInterval(timer);
|
|
532
|
+
timer = undefined;
|
|
533
|
+
}
|
|
534
|
+
listeners.clear();
|
|
535
|
+
};
|
|
536
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
537
|
+
timer = setInterval(() => {
|
|
538
|
+
refresh().catch(() => {});
|
|
539
|
+
}, options.intervalMs);
|
|
540
|
+
}
|
|
541
|
+
return {
|
|
542
|
+
close,
|
|
543
|
+
getServerSnapshot: () => snapshot,
|
|
544
|
+
getSnapshot: () => snapshot,
|
|
545
|
+
refresh,
|
|
546
|
+
subscribe: (listener) => {
|
|
547
|
+
listeners.add(listener);
|
|
548
|
+
return () => {
|
|
549
|
+
listeners.delete(listener);
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
// src/client/providerCapabilitiesWidget.ts
|
|
556
|
+
var DEFAULT_TITLE2 = "Provider Capabilities";
|
|
557
|
+
var DEFAULT_DESCRIPTION2 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
558
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
559
|
+
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
560
|
+
var formatKind2 = (kind) => kind.toUpperCase();
|
|
561
|
+
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
562
|
+
var getCapabilityDetail = (capability) => {
|
|
563
|
+
if (!capability.configured) {
|
|
564
|
+
return "Not configured in this deployment.";
|
|
565
|
+
}
|
|
566
|
+
if (capability.selected) {
|
|
567
|
+
return `Selected ${capability.kind.toUpperCase()} provider for new sessions.`;
|
|
568
|
+
}
|
|
569
|
+
if (capability.health?.status === "healthy") {
|
|
570
|
+
return "Configured and healthy fallback candidate.";
|
|
571
|
+
}
|
|
572
|
+
if (capability.health?.status === "idle") {
|
|
573
|
+
return "Configured; no traffic observed yet.";
|
|
574
|
+
}
|
|
575
|
+
if (capability.health?.lastError) {
|
|
576
|
+
return capability.health.lastError;
|
|
577
|
+
}
|
|
578
|
+
return "Configured and available.";
|
|
579
|
+
};
|
|
580
|
+
var isWarningStatus = (status) => status === "degraded" || status === "rate-limited" || status === "suppressed" || status === "unconfigured";
|
|
581
|
+
var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
582
|
+
const capabilities = (snapshot.report?.capabilities ?? []).map((capability) => ({
|
|
583
|
+
...capability,
|
|
584
|
+
detail: getCapabilityDetail(capability),
|
|
585
|
+
label: `${formatProvider(capability.provider)} ${formatKind2(capability.kind)}`,
|
|
586
|
+
rows: [
|
|
587
|
+
{ label: "Status", value: formatStatus(capability.status) },
|
|
588
|
+
{ label: "Selected", value: capability.selected ? "Yes" : "No" },
|
|
589
|
+
{ label: "Model", value: capability.model ?? "Default" },
|
|
590
|
+
{
|
|
591
|
+
label: "Features",
|
|
592
|
+
value: capability.features?.join(", ") || "Not specified"
|
|
593
|
+
},
|
|
594
|
+
{ label: "Runs", value: String(capability.health?.runCount ?? 0) },
|
|
595
|
+
{ label: "Errors", value: String(capability.health?.errorCount ?? 0) }
|
|
596
|
+
]
|
|
597
|
+
}));
|
|
598
|
+
const warningCount = capabilities.filter((capability) => isWarningStatus(capability.status)).length;
|
|
599
|
+
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
600
|
+
return {
|
|
601
|
+
capabilities,
|
|
602
|
+
description: options.description ?? DEFAULT_DESCRIPTION2,
|
|
603
|
+
error: snapshot.error,
|
|
604
|
+
isLoading: snapshot.isLoading,
|
|
605
|
+
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
606
|
+
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
607
|
+
title: options.title ?? DEFAULT_TITLE2,
|
|
608
|
+
updatedAt: snapshot.updatedAt
|
|
609
|
+
};
|
|
610
|
+
};
|
|
611
|
+
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
612
|
+
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
613
|
+
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--${escapeHtml3(capability.status)}">
|
|
614
|
+
<header>
|
|
615
|
+
<strong>${escapeHtml3(capability.label)}</strong>
|
|
616
|
+
<span>${escapeHtml3(formatStatus(capability.status))}</span>
|
|
617
|
+
</header>
|
|
618
|
+
<p>${escapeHtml3(capability.detail)}</p>
|
|
619
|
+
<dl>${capability.rows.map((row) => `<div>
|
|
620
|
+
<dt>${escapeHtml3(row.label)}</dt>
|
|
621
|
+
<dd>${escapeHtml3(row.value)}</dd>
|
|
622
|
+
</div>`).join("")}</dl>
|
|
623
|
+
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
624
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml3(model.status)}">
|
|
625
|
+
<header class="absolute-voice-provider-capabilities__header">
|
|
626
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml3(model.title)}</span>
|
|
627
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml3(model.label)}</strong>
|
|
628
|
+
</header>
|
|
629
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml3(model.description)}</p>
|
|
630
|
+
${capabilities}
|
|
631
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml3(model.error)}</p>` : ""}
|
|
632
|
+
</section>`;
|
|
633
|
+
};
|
|
634
|
+
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}`;
|
|
635
|
+
var mountVoiceProviderCapabilities = (element, path = "/api/provider-capabilities", options = {}) => {
|
|
636
|
+
const store = createVoiceProviderCapabilitiesStore(path, options);
|
|
637
|
+
const render = () => {
|
|
638
|
+
element.innerHTML = renderVoiceProviderCapabilitiesHTML(store.getSnapshot(), options);
|
|
639
|
+
};
|
|
640
|
+
const unsubscribe = store.subscribe(render);
|
|
641
|
+
render();
|
|
642
|
+
store.refresh().catch(() => {});
|
|
643
|
+
return {
|
|
644
|
+
close: () => {
|
|
645
|
+
unsubscribe();
|
|
646
|
+
store.close();
|
|
647
|
+
},
|
|
648
|
+
refresh: store.refresh
|
|
649
|
+
};
|
|
650
|
+
};
|
|
651
|
+
var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider-capabilities") => {
|
|
652
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
customElements.define(tagName, class AbsoluteVoiceProviderCapabilitiesElement extends HTMLElement {
|
|
656
|
+
mounted;
|
|
657
|
+
connectedCallback() {
|
|
658
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
659
|
+
this.mounted = mountVoiceProviderCapabilities(this, this.getAttribute("path") ?? "/api/provider-capabilities", {
|
|
660
|
+
description: this.getAttribute("description") ?? undefined,
|
|
661
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
662
|
+
title: this.getAttribute("title") ?? undefined
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
disconnectedCallback() {
|
|
666
|
+
this.mounted?.close();
|
|
667
|
+
this.mounted = undefined;
|
|
668
|
+
}
|
|
669
|
+
});
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
// src/svelte/createVoiceProviderCapabilities.ts
|
|
673
|
+
var createVoiceProviderCapabilities = (path = "/api/provider-capabilities", options = {}) => {
|
|
674
|
+
const store = createVoiceProviderCapabilitiesStore(path, options);
|
|
675
|
+
return {
|
|
676
|
+
...store,
|
|
677
|
+
getHTML: () => renderVoiceProviderCapabilitiesHTML(store.getSnapshot(), options),
|
|
678
|
+
getViewModel: () => createVoiceProviderCapabilitiesViewModel(store.getSnapshot(), options)
|
|
679
|
+
};
|
|
680
|
+
};
|
|
476
681
|
// src/client/actions.ts
|
|
477
682
|
var normalizeErrorMessage = (value) => {
|
|
478
683
|
if (typeof value === "string" && value.trim()) {
|
|
@@ -1069,11 +1274,11 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
1069
1274
|
};
|
|
1070
1275
|
|
|
1071
1276
|
// src/client/providerStatusWidget.ts
|
|
1072
|
-
var
|
|
1073
|
-
var
|
|
1074
|
-
var
|
|
1075
|
-
var
|
|
1076
|
-
var
|
|
1277
|
+
var DEFAULT_TITLE3 = "Voice Providers";
|
|
1278
|
+
var DEFAULT_DESCRIPTION3 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
1279
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1280
|
+
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
1281
|
+
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
1077
1282
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
1078
1283
|
var formatSuppression = (value) => typeof value === "number" ? `${Math.ceil(value / 1000)}s` : "None";
|
|
1079
1284
|
var getProviderDetail = (provider) => {
|
|
@@ -1094,12 +1299,12 @@ var getProviderDetail = (provider) => {
|
|
|
1094
1299
|
}
|
|
1095
1300
|
return "No provider traffic observed yet.";
|
|
1096
1301
|
};
|
|
1097
|
-
var
|
|
1302
|
+
var isWarningStatus2 = (status) => status === "degraded" || status === "rate-limited" || status === "recoverable" || status === "suppressed";
|
|
1098
1303
|
var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
1099
1304
|
const providers = snapshot.providers.map((provider) => ({
|
|
1100
1305
|
...provider,
|
|
1101
1306
|
detail: getProviderDetail(provider),
|
|
1102
|
-
label: `${
|
|
1307
|
+
label: `${formatProvider2(provider.provider)}${provider.recommended ? " recommended" : ""}`,
|
|
1103
1308
|
rows: [
|
|
1104
1309
|
{ label: "Runs", value: String(provider.runCount) },
|
|
1105
1310
|
{ label: "Avg latency", value: formatLatency(provider.averageElapsedMs) },
|
|
@@ -1112,40 +1317,40 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
1112
1317
|
}
|
|
1113
1318
|
]
|
|
1114
1319
|
}));
|
|
1115
|
-
const warningCount = providers.filter((provider) =>
|
|
1320
|
+
const warningCount = providers.filter((provider) => isWarningStatus2(provider.status)).length;
|
|
1116
1321
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
1117
1322
|
return {
|
|
1118
|
-
description: options.description ??
|
|
1323
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
1119
1324
|
error: snapshot.error,
|
|
1120
1325
|
isLoading: snapshot.isLoading,
|
|
1121
1326
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
1122
1327
|
providers,
|
|
1123
1328
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1124
|
-
title: options.title ??
|
|
1329
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
1125
1330
|
updatedAt: snapshot.updatedAt
|
|
1126
1331
|
};
|
|
1127
1332
|
};
|
|
1128
1333
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
1129
1334
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
1130
|
-
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--${
|
|
1335
|
+
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--${escapeHtml4(provider.status)}">
|
|
1131
1336
|
<header>
|
|
1132
|
-
<strong>${
|
|
1133
|
-
<span>${
|
|
1337
|
+
<strong>${escapeHtml4(provider.label)}</strong>
|
|
1338
|
+
<span>${escapeHtml4(formatStatus2(provider.status))}</span>
|
|
1134
1339
|
</header>
|
|
1135
|
-
<p>${
|
|
1340
|
+
<p>${escapeHtml4(provider.detail)}</p>
|
|
1136
1341
|
<dl>${provider.rows.map((row) => `<div>
|
|
1137
|
-
<dt>${
|
|
1138
|
-
<dd>${
|
|
1342
|
+
<dt>${escapeHtml4(row.label)}</dt>
|
|
1343
|
+
<dd>${escapeHtml4(row.value)}</dd>
|
|
1139
1344
|
</div>`).join("")}</dl>
|
|
1140
1345
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
1141
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
1346
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml4(model.status)}">
|
|
1142
1347
|
<header class="absolute-voice-provider-status__header">
|
|
1143
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
1144
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
1348
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml4(model.title)}</span>
|
|
1349
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml4(model.label)}</strong>
|
|
1145
1350
|
</header>
|
|
1146
|
-
<p class="absolute-voice-provider-status__description">${
|
|
1351
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml4(model.description)}</p>
|
|
1147
1352
|
${providers}
|
|
1148
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
1353
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml4(model.error)}</p>` : ""}
|
|
1149
1354
|
</section>`;
|
|
1150
1355
|
};
|
|
1151
1356
|
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}`;
|
|
@@ -1276,9 +1481,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
1276
1481
|
};
|
|
1277
1482
|
|
|
1278
1483
|
// src/client/routingStatusWidget.ts
|
|
1279
|
-
var
|
|
1280
|
-
var
|
|
1281
|
-
var
|
|
1484
|
+
var DEFAULT_TITLE4 = "Voice Routing";
|
|
1485
|
+
var DEFAULT_DESCRIPTION4 = "Latest provider routing decision from the self-hosted trace store.";
|
|
1486
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
1282
1487
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
1283
1488
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
1284
1489
|
const decision = snapshot.decision;
|
|
@@ -1302,30 +1507,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
1302
1507
|
] : [];
|
|
1303
1508
|
return {
|
|
1304
1509
|
decision,
|
|
1305
|
-
description: options.description ??
|
|
1510
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
1306
1511
|
error: snapshot.error,
|
|
1307
1512
|
isLoading: snapshot.isLoading,
|
|
1308
1513
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
1309
1514
|
rows,
|
|
1310
1515
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
1311
|
-
title: options.title ??
|
|
1516
|
+
title: options.title ?? DEFAULT_TITLE4,
|
|
1312
1517
|
updatedAt: snapshot.updatedAt
|
|
1313
1518
|
};
|
|
1314
1519
|
};
|
|
1315
1520
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
1316
1521
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
1317
1522
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
1318
|
-
<span>${
|
|
1319
|
-
<strong>${
|
|
1523
|
+
<span>${escapeHtml5(row.label)}</span>
|
|
1524
|
+
<strong>${escapeHtml5(row.value)}</strong>
|
|
1320
1525
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
1321
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
1526
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml5(model.status)}">
|
|
1322
1527
|
<header class="absolute-voice-routing-status__header">
|
|
1323
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
1324
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
1528
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml5(model.title)}</span>
|
|
1529
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml5(model.label)}</strong>
|
|
1325
1530
|
</header>
|
|
1326
|
-
<p class="absolute-voice-routing-status__description">${
|
|
1531
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml5(model.description)}</p>
|
|
1327
1532
|
${rows}
|
|
1328
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
1533
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml5(model.error)}</p>` : ""}
|
|
1329
1534
|
</section>`;
|
|
1330
1535
|
};
|
|
1331
1536
|
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}`;
|
|
@@ -2091,6 +2296,7 @@ export {
|
|
|
2091
2296
|
createVoiceRoutingStatus,
|
|
2092
2297
|
createVoiceProviderStatus,
|
|
2093
2298
|
createVoiceProviderSimulationControls,
|
|
2299
|
+
createVoiceProviderCapabilities,
|
|
2094
2300
|
createVoiceOpsStatus,
|
|
2095
2301
|
createVoiceController,
|
|
2096
2302
|
createVoiceAppKitStatus
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export declare const VoiceProviderCapabilities: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
2
|
+
class: {
|
|
3
|
+
default: string;
|
|
4
|
+
type: StringConstructor;
|
|
5
|
+
};
|
|
6
|
+
description: {
|
|
7
|
+
default: undefined;
|
|
8
|
+
type: StringConstructor;
|
|
9
|
+
};
|
|
10
|
+
intervalMs: {
|
|
11
|
+
default: number;
|
|
12
|
+
type: NumberConstructor;
|
|
13
|
+
};
|
|
14
|
+
path: {
|
|
15
|
+
default: string;
|
|
16
|
+
type: StringConstructor;
|
|
17
|
+
};
|
|
18
|
+
title: {
|
|
19
|
+
default: undefined;
|
|
20
|
+
type: StringConstructor;
|
|
21
|
+
};
|
|
22
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
25
|
+
class: {
|
|
26
|
+
default: string;
|
|
27
|
+
type: StringConstructor;
|
|
28
|
+
};
|
|
29
|
+
description: {
|
|
30
|
+
default: undefined;
|
|
31
|
+
type: StringConstructor;
|
|
32
|
+
};
|
|
33
|
+
intervalMs: {
|
|
34
|
+
default: number;
|
|
35
|
+
type: NumberConstructor;
|
|
36
|
+
};
|
|
37
|
+
path: {
|
|
38
|
+
default: string;
|
|
39
|
+
type: StringConstructor;
|
|
40
|
+
};
|
|
41
|
+
title: {
|
|
42
|
+
default: undefined;
|
|
43
|
+
type: StringConstructor;
|
|
44
|
+
};
|
|
45
|
+
}>> & Readonly<{}>, {
|
|
46
|
+
description: string;
|
|
47
|
+
title: string;
|
|
48
|
+
path: string;
|
|
49
|
+
intervalMs: number;
|
|
50
|
+
class: string;
|
|
51
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
package/dist/vue/index.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export { VoiceOpsStatus } from './VoiceOpsStatus';
|
|
2
2
|
export { VoiceProviderSimulationControls } from './VoiceProviderSimulationControls';
|
|
3
|
+
export { VoiceProviderCapabilities } from './VoiceProviderCapabilities';
|
|
3
4
|
export { VoiceProviderStatus } from './VoiceProviderStatus';
|
|
4
5
|
export { VoiceRoutingStatus } from './VoiceRoutingStatus';
|
|
5
6
|
export { useVoiceAppKitStatus } from './useVoiceAppKitStatus';
|
|
6
7
|
export { useVoiceStream } from './useVoiceStream';
|
|
7
8
|
export { useVoiceController } from './useVoiceController';
|
|
8
9
|
export { useVoiceProviderStatus } from './useVoiceProviderStatus';
|
|
10
|
+
export { useVoiceProviderCapabilities } from './useVoiceProviderCapabilities';
|
|
9
11
|
export { useVoiceProviderSimulationControls } from './useVoiceProviderSimulationControls';
|
|
10
12
|
export { useVoiceRoutingStatus } from './useVoiceRoutingStatus';
|
|
11
13
|
export { useVoiceWorkflowStatus } from './useVoiceWorkflowStatus';
|