@absolutejs/voice 0.0.22-beta.59 → 0.0.22-beta.60
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/client/index.d.ts +2 -0
- package/dist/client/index.js +122 -0
- package/dist/client/providerStatusWidget.d.ts +32 -0
- package/dist/react/VoiceProviderStatus.d.ts +6 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.js +334 -135
- package/dist/svelte/createVoiceProviderStatus.d.ts +4 -2
- package/dist/svelte/index.js +138 -13
- package/dist/vue/VoiceProviderStatus.d.ts +51 -0
- package/dist/vue/index.d.ts +1 -0
- package/dist/vue/index.js +358 -166
- package/package.json +1 -1
package/dist/client/index.d.ts
CHANGED
|
@@ -10,10 +10,12 @@ export { createVoiceOpsStatusViewModel, defineVoiceOpsStatusElement, getVoiceOps
|
|
|
10
10
|
export { createVoiceRoutingStatusStore, fetchVoiceRoutingStatus } from './routingStatus';
|
|
11
11
|
export { createVoiceRoutingStatusViewModel, defineVoiceRoutingStatusElement, getVoiceRoutingStatusCSS, mountVoiceRoutingStatus, renderVoiceRoutingStatusHTML } from './routingStatusWidget';
|
|
12
12
|
export { createVoiceProviderStatusStore, fetchVoiceProviderStatus } from './providerStatus';
|
|
13
|
+
export { createVoiceProviderStatusViewModel, defineVoiceProviderStatusElement, getVoiceProviderStatusCSS, mountVoiceProviderStatus, renderVoiceProviderStatusHTML } from './providerStatusWidget';
|
|
13
14
|
export { createVoiceWorkflowStatusStore, fetchVoiceWorkflowStatus } from './workflowStatus';
|
|
14
15
|
export type { VoiceAppKitStatusClientOptions, VoiceAppKitStatusSnapshot } from './appKitStatus';
|
|
15
16
|
export type { VoiceOpsStatusSurfaceView, VoiceOpsStatusViewModel, VoiceOpsStatusWidgetOptions } from './opsStatusWidget';
|
|
16
17
|
export type { VoiceRoutingStatusClientOptions, VoiceRoutingStatusSnapshot } from './routingStatus';
|
|
17
18
|
export type { VoiceRoutingStatusViewModel, VoiceRoutingStatusWidgetOptions } from './routingStatusWidget';
|
|
18
19
|
export type { VoiceProviderStatusClientOptions, VoiceProviderStatusSnapshot } from './providerStatus';
|
|
20
|
+
export type { VoiceProviderStatusCardView, VoiceProviderStatusViewModel, VoiceProviderStatusWidgetOptions } from './providerStatusWidget';
|
|
19
21
|
export type { VoiceWorkflowStatusClientOptions, VoiceWorkflowStatusSnapshot } from './workflowStatus';
|
package/dist/client/index.js
CHANGED
|
@@ -2073,6 +2073,123 @@ var createVoiceProviderStatusStore = (path = "/api/provider-status", options = {
|
|
|
2073
2073
|
}
|
|
2074
2074
|
};
|
|
2075
2075
|
};
|
|
2076
|
+
// src/client/providerStatusWidget.ts
|
|
2077
|
+
var DEFAULT_TITLE3 = "Voice Providers";
|
|
2078
|
+
var DEFAULT_DESCRIPTION3 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
2079
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2080
|
+
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
2081
|
+
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
2082
|
+
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
2083
|
+
var formatSuppression = (value) => typeof value === "number" ? `${Math.ceil(value / 1000)}s` : "None";
|
|
2084
|
+
var getProviderDetail = (provider) => {
|
|
2085
|
+
if (provider.status === "suppressed") {
|
|
2086
|
+
return provider.lastError ? `Suppressed for ${formatSuppression(provider.suppressionRemainingMs)} after ${provider.lastError}.` : `Suppressed for ${formatSuppression(provider.suppressionRemainingMs)}.`;
|
|
2087
|
+
}
|
|
2088
|
+
if (provider.status === "recoverable") {
|
|
2089
|
+
return "Cooldown expired; ready for recovery traffic.";
|
|
2090
|
+
}
|
|
2091
|
+
if (provider.status === "rate-limited") {
|
|
2092
|
+
return "Rate limit detected; router should avoid this provider.";
|
|
2093
|
+
}
|
|
2094
|
+
if (provider.status === "degraded") {
|
|
2095
|
+
return provider.lastError ?? "Recent provider errors detected.";
|
|
2096
|
+
}
|
|
2097
|
+
if (provider.status === "healthy") {
|
|
2098
|
+
return provider.recommended ? "Healthy and currently recommended." : "Healthy and available for routing.";
|
|
2099
|
+
}
|
|
2100
|
+
return "No provider traffic observed yet.";
|
|
2101
|
+
};
|
|
2102
|
+
var isWarningStatus = (status) => status === "degraded" || status === "rate-limited" || status === "recoverable" || status === "suppressed";
|
|
2103
|
+
var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
2104
|
+
const providers = snapshot.providers.map((provider) => ({
|
|
2105
|
+
...provider,
|
|
2106
|
+
detail: getProviderDetail(provider),
|
|
2107
|
+
label: `${formatProvider(provider.provider)}${provider.recommended ? " recommended" : ""}`,
|
|
2108
|
+
rows: [
|
|
2109
|
+
{ label: "Runs", value: String(provider.runCount) },
|
|
2110
|
+
{ label: "Avg latency", value: formatLatency(provider.averageElapsedMs) },
|
|
2111
|
+
{ label: "Errors", value: String(provider.errorCount) },
|
|
2112
|
+
{ label: "Timeouts", value: String(provider.timeoutCount) },
|
|
2113
|
+
{ label: "Fallbacks", value: String(provider.fallbackCount) },
|
|
2114
|
+
{
|
|
2115
|
+
label: "Suppression",
|
|
2116
|
+
value: formatSuppression(provider.suppressionRemainingMs)
|
|
2117
|
+
}
|
|
2118
|
+
]
|
|
2119
|
+
}));
|
|
2120
|
+
const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
|
|
2121
|
+
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
2122
|
+
return {
|
|
2123
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
2124
|
+
error: snapshot.error,
|
|
2125
|
+
isLoading: snapshot.isLoading,
|
|
2126
|
+
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
2127
|
+
providers,
|
|
2128
|
+
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2129
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
2130
|
+
updatedAt: snapshot.updatedAt
|
|
2131
|
+
};
|
|
2132
|
+
};
|
|
2133
|
+
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
2134
|
+
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
2135
|
+
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--${escapeHtml3(provider.status)}">
|
|
2136
|
+
<header>
|
|
2137
|
+
<strong>${escapeHtml3(provider.label)}</strong>
|
|
2138
|
+
<span>${escapeHtml3(formatStatus(provider.status))}</span>
|
|
2139
|
+
</header>
|
|
2140
|
+
<p>${escapeHtml3(provider.detail)}</p>
|
|
2141
|
+
<dl>${provider.rows.map((row) => `<div>
|
|
2142
|
+
<dt>${escapeHtml3(row.label)}</dt>
|
|
2143
|
+
<dd>${escapeHtml3(row.value)}</dd>
|
|
2144
|
+
</div>`).join("")}</dl>
|
|
2145
|
+
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
2146
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml3(model.status)}">
|
|
2147
|
+
<header class="absolute-voice-provider-status__header">
|
|
2148
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml3(model.title)}</span>
|
|
2149
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml3(model.label)}</strong>
|
|
2150
|
+
</header>
|
|
2151
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml3(model.description)}</p>
|
|
2152
|
+
${providers}
|
|
2153
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml3(model.error)}</p>` : ""}
|
|
2154
|
+
</section>`;
|
|
2155
|
+
};
|
|
2156
|
+
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}`;
|
|
2157
|
+
var mountVoiceProviderStatus = (element, path = "/api/provider-status", options = {}) => {
|
|
2158
|
+
const store = createVoiceProviderStatusStore(path, options);
|
|
2159
|
+
const render = () => {
|
|
2160
|
+
element.innerHTML = renderVoiceProviderStatusHTML(store.getSnapshot(), options);
|
|
2161
|
+
};
|
|
2162
|
+
const unsubscribe = store.subscribe(render);
|
|
2163
|
+
render();
|
|
2164
|
+
store.refresh().catch(() => {});
|
|
2165
|
+
return {
|
|
2166
|
+
close: () => {
|
|
2167
|
+
unsubscribe();
|
|
2168
|
+
store.close();
|
|
2169
|
+
},
|
|
2170
|
+
refresh: store.refresh
|
|
2171
|
+
};
|
|
2172
|
+
};
|
|
2173
|
+
var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-status") => {
|
|
2174
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
2175
|
+
return;
|
|
2176
|
+
}
|
|
2177
|
+
customElements.define(tagName, class AbsoluteVoiceProviderStatusElement extends HTMLElement {
|
|
2178
|
+
mounted;
|
|
2179
|
+
connectedCallback() {
|
|
2180
|
+
const intervalMs = Number(this.getAttribute("interval-ms") ?? 5000);
|
|
2181
|
+
this.mounted = mountVoiceProviderStatus(this, this.getAttribute("path") ?? "/api/provider-status", {
|
|
2182
|
+
description: this.getAttribute("description") ?? undefined,
|
|
2183
|
+
intervalMs: Number.isFinite(intervalMs) ? intervalMs : 5000,
|
|
2184
|
+
title: this.getAttribute("title") ?? undefined
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
disconnectedCallback() {
|
|
2188
|
+
this.mounted?.close();
|
|
2189
|
+
this.mounted = undefined;
|
|
2190
|
+
}
|
|
2191
|
+
});
|
|
2192
|
+
};
|
|
2076
2193
|
// src/client/workflowStatus.ts
|
|
2077
2194
|
var fetchVoiceWorkflowStatus = async (path = "/evals/scenarios/json", options = {}) => {
|
|
2078
2195
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
@@ -2153,10 +2270,13 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
|
|
|
2153
2270
|
};
|
|
2154
2271
|
export {
|
|
2155
2272
|
renderVoiceRoutingStatusHTML,
|
|
2273
|
+
renderVoiceProviderStatusHTML,
|
|
2156
2274
|
renderVoiceOpsStatusHTML,
|
|
2157
2275
|
mountVoiceRoutingStatus,
|
|
2276
|
+
mountVoiceProviderStatus,
|
|
2158
2277
|
mountVoiceOpsStatus,
|
|
2159
2278
|
getVoiceRoutingStatusCSS,
|
|
2279
|
+
getVoiceProviderStatusCSS,
|
|
2160
2280
|
getVoiceOpsStatusLabel,
|
|
2161
2281
|
getVoiceOpsStatusCSS,
|
|
2162
2282
|
fetchVoiceWorkflowStatus,
|
|
@@ -2164,12 +2284,14 @@ export {
|
|
|
2164
2284
|
fetchVoiceProviderStatus,
|
|
2165
2285
|
fetchVoiceAppKitStatus,
|
|
2166
2286
|
defineVoiceRoutingStatusElement,
|
|
2287
|
+
defineVoiceProviderStatusElement,
|
|
2167
2288
|
defineVoiceOpsStatusElement,
|
|
2168
2289
|
decodeVoiceAudioChunk,
|
|
2169
2290
|
createVoiceWorkflowStatusStore,
|
|
2170
2291
|
createVoiceStream,
|
|
2171
2292
|
createVoiceRoutingStatusViewModel,
|
|
2172
2293
|
createVoiceRoutingStatusStore,
|
|
2294
|
+
createVoiceProviderStatusViewModel,
|
|
2173
2295
|
createVoiceProviderStatusStore,
|
|
2174
2296
|
createVoiceOpsStatusViewModel,
|
|
2175
2297
|
createVoiceDuplexController,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { VoiceProviderHealthSummary } from '../providerHealth';
|
|
2
|
+
import { type VoiceProviderStatusClientOptions, type VoiceProviderStatusSnapshot } from './providerStatus';
|
|
3
|
+
export type VoiceProviderStatusCardView<TProvider extends string = string> = VoiceProviderHealthSummary<TProvider> & {
|
|
4
|
+
detail: string;
|
|
5
|
+
label: string;
|
|
6
|
+
rows: Array<{
|
|
7
|
+
label: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}>;
|
|
10
|
+
};
|
|
11
|
+
export type VoiceProviderStatusViewModel<TProvider extends string = string> = {
|
|
12
|
+
description: string;
|
|
13
|
+
error: string | null;
|
|
14
|
+
isLoading: boolean;
|
|
15
|
+
label: string;
|
|
16
|
+
providers: VoiceProviderStatusCardView<TProvider>[];
|
|
17
|
+
status: 'empty' | 'error' | 'loading' | 'ready' | 'warning';
|
|
18
|
+
title: string;
|
|
19
|
+
updatedAt?: number;
|
|
20
|
+
};
|
|
21
|
+
export type VoiceProviderStatusWidgetOptions = VoiceProviderStatusClientOptions & {
|
|
22
|
+
description?: string;
|
|
23
|
+
title?: string;
|
|
24
|
+
};
|
|
25
|
+
export declare const createVoiceProviderStatusViewModel: <TProvider extends string = string>(snapshot: VoiceProviderStatusSnapshot<TProvider>, options?: VoiceProviderStatusWidgetOptions) => VoiceProviderStatusViewModel<TProvider>;
|
|
26
|
+
export declare const renderVoiceProviderStatusHTML: <TProvider extends string = string>(snapshot: VoiceProviderStatusSnapshot<TProvider>, options?: VoiceProviderStatusWidgetOptions) => string;
|
|
27
|
+
export declare const getVoiceProviderStatusCSS: () => string;
|
|
28
|
+
export declare const mountVoiceProviderStatus: <TProvider extends string = string>(element: Element, path?: string, options?: VoiceProviderStatusWidgetOptions) => {
|
|
29
|
+
close: () => void;
|
|
30
|
+
refresh: () => Promise<VoiceProviderHealthSummary<TProvider>[]>;
|
|
31
|
+
};
|
|
32
|
+
export declare const defineVoiceProviderStatusElement: (tagName?: string) => void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type VoiceProviderStatusWidgetOptions } from '../client/providerStatusWidget';
|
|
2
|
+
export type VoiceProviderStatusProps = VoiceProviderStatusWidgetOptions & {
|
|
3
|
+
className?: string;
|
|
4
|
+
path?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const VoiceProviderStatus: ({ className, path, ...options }: VoiceProviderStatusProps) => import("react/jsx-runtime").JSX.Element;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { VoiceOpsStatus } from './VoiceOpsStatus';
|
|
2
|
+
export { VoiceProviderStatus } from './VoiceProviderStatus';
|
|
2
3
|
export { VoiceRoutingStatus } from './VoiceRoutingStatus';
|
|
3
4
|
export { useVoiceAppKitStatus } from './useVoiceAppKitStatus';
|
|
4
5
|
export { useVoiceStream } from './useVoiceStream';
|