@absolutejs/voice 0.0.22-beta.152 → 0.0.22-beta.154
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/dist/angular/index.d.ts +1 -0
- package/dist/angular/index.js +471 -137
- package/dist/angular/voice-delivery-runtime.component.d.ts +3 -0
- package/dist/angular/voice-delivery-runtime.service.d.ts +4 -0
- package/dist/angular/voice-ops-action-center.service.d.ts +13 -0
- package/dist/client/deliveryRuntime.d.ts +15 -0
- package/dist/client/deliveryRuntimeWidget.d.ts +3 -0
- package/dist/client/index.d.ts +6 -2
- package/dist/client/index.js +454 -114
- package/dist/client/opsActionCenter.d.ts +50 -0
- package/dist/client/opsActionCenterWidget.d.ts +29 -0
- package/dist/deliveryRuntime.d.ts +13 -1
- package/dist/index.js +44 -1
- package/dist/react/VoiceDeliveryRuntime.d.ts +2 -1
- package/dist/react/VoiceOpsActionCenter.d.ts +5 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +720 -286
- package/dist/react/useVoiceDeliveryRuntime.d.ts +5 -0
- package/dist/react/useVoiceOpsActionCenter.d.ts +11 -0
- package/dist/svelte/createVoiceDeliveryRuntime.d.ts +2 -0
- package/dist/svelte/createVoiceOpsActionCenter.d.ts +10 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.js +464 -115
- package/dist/vue/VoiceDeliveryRuntime.d.ts +9 -0
- package/dist/vue/VoiceOpsActionCenter.d.ts +13 -0
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.js +748 -292
- package/dist/vue/useVoiceDeliveryRuntime.d.ts +4 -0
- package/dist/vue/useVoiceOpsActionCenter.d.ts +11 -0
- package/package.json +1 -1
package/dist/client/index.js
CHANGED
|
@@ -2062,7 +2062,174 @@ var createVoiceOpsStatusStore = (path = "/api/voice/ops-status", options = {}) =
|
|
|
2062
2062
|
}
|
|
2063
2063
|
};
|
|
2064
2064
|
};
|
|
2065
|
+
// src/client/opsActionCenter.ts
|
|
2066
|
+
var createVoiceOpsActionCenterActions = (options = {}) => {
|
|
2067
|
+
const deliveryRuntimePath = options.deliveryRuntimePath ?? "/api/voice-delivery-runtime";
|
|
2068
|
+
const actions = [];
|
|
2069
|
+
if (options.includeProductionReadiness !== false) {
|
|
2070
|
+
actions.push({
|
|
2071
|
+
description: "Refresh the production readiness report.",
|
|
2072
|
+
id: "production-readiness",
|
|
2073
|
+
label: "Refresh readiness",
|
|
2074
|
+
method: "GET",
|
|
2075
|
+
path: options.productionReadinessPath ?? "/api/production-readiness"
|
|
2076
|
+
});
|
|
2077
|
+
}
|
|
2078
|
+
if (options.includeDeliveryRuntime !== false) {
|
|
2079
|
+
actions.push({
|
|
2080
|
+
description: "Drain pending and failed audit/trace deliveries.",
|
|
2081
|
+
id: "delivery-runtime.tick",
|
|
2082
|
+
label: "Tick delivery workers",
|
|
2083
|
+
method: "POST",
|
|
2084
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/tick`
|
|
2085
|
+
}, {
|
|
2086
|
+
description: "Move reviewed dead letters back to live delivery queues.",
|
|
2087
|
+
id: "delivery-runtime.requeue-dead-letters",
|
|
2088
|
+
label: "Requeue dead letters",
|
|
2089
|
+
method: "POST",
|
|
2090
|
+
path: `${deliveryRuntimePath.replace(/\/$/, "")}/requeue-dead-letters`
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2093
|
+
if (options.includeTurnLatencyProof !== false) {
|
|
2094
|
+
actions.push({
|
|
2095
|
+
description: "Run the synthetic turn latency proof.",
|
|
2096
|
+
id: "turn-latency.proof",
|
|
2097
|
+
label: "Run latency proof",
|
|
2098
|
+
method: "POST",
|
|
2099
|
+
path: options.turnLatencyProofPath ?? "/api/turn-latency/proof"
|
|
2100
|
+
});
|
|
2101
|
+
}
|
|
2102
|
+
if (options.includeProviderSimulation !== false) {
|
|
2103
|
+
const pathPrefix = options.providerSimulationPathPrefix ?? "/api/stt-simulate";
|
|
2104
|
+
for (const provider of options.providers ?? []) {
|
|
2105
|
+
actions.push({
|
|
2106
|
+
description: `Simulate ${provider} provider failure.`,
|
|
2107
|
+
id: `provider.${provider}.failure`,
|
|
2108
|
+
label: `Simulate ${provider} failure`,
|
|
2109
|
+
method: "POST",
|
|
2110
|
+
path: `${pathPrefix}/failure?provider=${encodeURIComponent(provider)}`
|
|
2111
|
+
}, {
|
|
2112
|
+
description: `Mark ${provider} provider recovered.`,
|
|
2113
|
+
id: `provider.${provider}.recovery`,
|
|
2114
|
+
label: `Recover ${provider}`,
|
|
2115
|
+
method: "POST",
|
|
2116
|
+
path: `${pathPrefix}/recovery?provider=${encodeURIComponent(provider)}`
|
|
2117
|
+
});
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
return actions;
|
|
2121
|
+
};
|
|
2122
|
+
var runVoiceOpsAction = async (action, options = {}) => {
|
|
2123
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2124
|
+
const response = await fetchImpl(action.path, {
|
|
2125
|
+
method: action.method ?? "POST"
|
|
2126
|
+
});
|
|
2127
|
+
const body = await response.json().catch(() => null);
|
|
2128
|
+
if (!response.ok) {
|
|
2129
|
+
const message = body && typeof body === "object" && "error" in body ? String(body.error) : `Voice ops action "${action.id}" failed: HTTP ${response.status}`;
|
|
2130
|
+
throw new Error(message);
|
|
2131
|
+
}
|
|
2132
|
+
return {
|
|
2133
|
+
actionId: action.id,
|
|
2134
|
+
body,
|
|
2135
|
+
ok: response.ok,
|
|
2136
|
+
ranAt: Date.now(),
|
|
2137
|
+
status: response.status
|
|
2138
|
+
};
|
|
2139
|
+
};
|
|
2140
|
+
var createVoiceOpsActionCenterStore = (options = {}) => {
|
|
2141
|
+
const listeners = new Set;
|
|
2142
|
+
let closed = false;
|
|
2143
|
+
let timer;
|
|
2144
|
+
let snapshot = {
|
|
2145
|
+
actions: options.actions ?? createVoiceOpsActionCenterActions(),
|
|
2146
|
+
error: null,
|
|
2147
|
+
isRunning: false
|
|
2148
|
+
};
|
|
2149
|
+
const emit = () => {
|
|
2150
|
+
for (const listener of listeners) {
|
|
2151
|
+
listener();
|
|
2152
|
+
}
|
|
2153
|
+
};
|
|
2154
|
+
const setActions = (actions) => {
|
|
2155
|
+
snapshot = { ...snapshot, actions, updatedAt: Date.now() };
|
|
2156
|
+
emit();
|
|
2157
|
+
};
|
|
2158
|
+
const run = async (actionId) => {
|
|
2159
|
+
if (closed) {
|
|
2160
|
+
return snapshot.lastResult;
|
|
2161
|
+
}
|
|
2162
|
+
const action = snapshot.actions.find((item) => item.id === actionId);
|
|
2163
|
+
if (!action) {
|
|
2164
|
+
throw new Error(`Voice ops action "${actionId}" is not configured.`);
|
|
2165
|
+
}
|
|
2166
|
+
if (action.disabled) {
|
|
2167
|
+
throw new Error(`Voice ops action "${actionId}" is disabled.`);
|
|
2168
|
+
}
|
|
2169
|
+
snapshot = {
|
|
2170
|
+
...snapshot,
|
|
2171
|
+
error: null,
|
|
2172
|
+
isRunning: true,
|
|
2173
|
+
runningActionId: action.id
|
|
2174
|
+
};
|
|
2175
|
+
emit();
|
|
2176
|
+
try {
|
|
2177
|
+
const result = await runVoiceOpsAction(action, options);
|
|
2178
|
+
snapshot = {
|
|
2179
|
+
...snapshot,
|
|
2180
|
+
error: null,
|
|
2181
|
+
isRunning: false,
|
|
2182
|
+
lastResult: result,
|
|
2183
|
+
runningActionId: undefined,
|
|
2184
|
+
updatedAt: Date.now()
|
|
2185
|
+
};
|
|
2186
|
+
emit();
|
|
2187
|
+
return result;
|
|
2188
|
+
} catch (error) {
|
|
2189
|
+
snapshot = {
|
|
2190
|
+
...snapshot,
|
|
2191
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2192
|
+
isRunning: false,
|
|
2193
|
+
runningActionId: undefined
|
|
2194
|
+
};
|
|
2195
|
+
emit();
|
|
2196
|
+
throw error;
|
|
2197
|
+
}
|
|
2198
|
+
};
|
|
2199
|
+
const close = () => {
|
|
2200
|
+
closed = true;
|
|
2201
|
+
if (timer) {
|
|
2202
|
+
clearInterval(timer);
|
|
2203
|
+
timer = undefined;
|
|
2204
|
+
}
|
|
2205
|
+
listeners.clear();
|
|
2206
|
+
};
|
|
2207
|
+
if (options.intervalMs && options.intervalMs > 0) {
|
|
2208
|
+
timer = setInterval(() => {
|
|
2209
|
+
emit();
|
|
2210
|
+
}, options.intervalMs);
|
|
2211
|
+
}
|
|
2212
|
+
return {
|
|
2213
|
+
close,
|
|
2214
|
+
getServerSnapshot: () => snapshot,
|
|
2215
|
+
getSnapshot: () => snapshot,
|
|
2216
|
+
run,
|
|
2217
|
+
setActions,
|
|
2218
|
+
subscribe: (listener) => {
|
|
2219
|
+
listeners.add(listener);
|
|
2220
|
+
return () => {
|
|
2221
|
+
listeners.delete(listener);
|
|
2222
|
+
};
|
|
2223
|
+
}
|
|
2224
|
+
};
|
|
2225
|
+
};
|
|
2065
2226
|
// src/client/deliveryRuntime.ts
|
|
2227
|
+
var getDefaultActionPath = (path, action, options) => {
|
|
2228
|
+
if (action === "tick") {
|
|
2229
|
+
return options.tickPath ?? `${path.replace(/\/$/, "")}/tick`;
|
|
2230
|
+
}
|
|
2231
|
+
return options.requeueDeadLettersPath ?? `${path.replace(/\/$/, "")}/requeue-dead-letters`;
|
|
2232
|
+
};
|
|
2066
2233
|
var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
2067
2234
|
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2068
2235
|
const response = await fetchImpl(path);
|
|
@@ -2071,11 +2238,29 @@ var fetchVoiceDeliveryRuntime = async (path = "/api/voice-delivery-runtime", opt
|
|
|
2071
2238
|
}
|
|
2072
2239
|
return await response.json();
|
|
2073
2240
|
};
|
|
2241
|
+
var runVoiceDeliveryRuntimeAction = async (action, path = "/api/voice-delivery-runtime", options = {}) => {
|
|
2242
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
2243
|
+
const response = await fetchImpl(getDefaultActionPath(path, action, options), {
|
|
2244
|
+
method: "POST"
|
|
2245
|
+
});
|
|
2246
|
+
if (!response.ok) {
|
|
2247
|
+
throw new Error(`Voice delivery runtime ${action} failed: HTTP ${response.status}`);
|
|
2248
|
+
}
|
|
2249
|
+
const body = await response.json();
|
|
2250
|
+
return {
|
|
2251
|
+
action,
|
|
2252
|
+
result: body.result,
|
|
2253
|
+
summary: body.summary,
|
|
2254
|
+
updatedAt: Date.now()
|
|
2255
|
+
};
|
|
2256
|
+
};
|
|
2074
2257
|
var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", options = {}) => {
|
|
2075
2258
|
const listeners = new Set;
|
|
2076
2259
|
let closed = false;
|
|
2077
2260
|
let timer;
|
|
2078
2261
|
let snapshot = {
|
|
2262
|
+
actionError: null,
|
|
2263
|
+
actionStatus: "idle",
|
|
2079
2264
|
error: null,
|
|
2080
2265
|
isLoading: false
|
|
2081
2266
|
};
|
|
@@ -2097,6 +2282,7 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
|
|
|
2097
2282
|
try {
|
|
2098
2283
|
const report = await fetchVoiceDeliveryRuntime(path, options);
|
|
2099
2284
|
snapshot = {
|
|
2285
|
+
...snapshot,
|
|
2100
2286
|
error: null,
|
|
2101
2287
|
isLoading: false,
|
|
2102
2288
|
report,
|
|
@@ -2114,6 +2300,37 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
|
|
|
2114
2300
|
throw error;
|
|
2115
2301
|
}
|
|
2116
2302
|
};
|
|
2303
|
+
const runAction = async (action) => {
|
|
2304
|
+
if (closed) {
|
|
2305
|
+
return snapshot.lastAction;
|
|
2306
|
+
}
|
|
2307
|
+
snapshot = {
|
|
2308
|
+
...snapshot,
|
|
2309
|
+
actionError: null,
|
|
2310
|
+
actionStatus: "running"
|
|
2311
|
+
};
|
|
2312
|
+
emit();
|
|
2313
|
+
try {
|
|
2314
|
+
const result = await runVoiceDeliveryRuntimeAction(action, path, options);
|
|
2315
|
+
snapshot = {
|
|
2316
|
+
...snapshot,
|
|
2317
|
+
actionError: null,
|
|
2318
|
+
actionStatus: "completed",
|
|
2319
|
+
lastAction: result
|
|
2320
|
+
};
|
|
2321
|
+
emit();
|
|
2322
|
+
await refresh();
|
|
2323
|
+
return result;
|
|
2324
|
+
} catch (error) {
|
|
2325
|
+
snapshot = {
|
|
2326
|
+
...snapshot,
|
|
2327
|
+
actionError: error instanceof Error ? error.message : String(error),
|
|
2328
|
+
actionStatus: "failed"
|
|
2329
|
+
};
|
|
2330
|
+
emit();
|
|
2331
|
+
throw error;
|
|
2332
|
+
}
|
|
2333
|
+
};
|
|
2117
2334
|
const close = () => {
|
|
2118
2335
|
closed = true;
|
|
2119
2336
|
if (timer) {
|
|
@@ -2131,7 +2348,9 @@ var createVoiceDeliveryRuntimeStore = (path = "/api/voice-delivery-runtime", opt
|
|
|
2131
2348
|
close,
|
|
2132
2349
|
getServerSnapshot: () => snapshot,
|
|
2133
2350
|
getSnapshot: () => snapshot,
|
|
2351
|
+
requeueDeadLetters: () => runAction("requeue-dead-letters"),
|
|
2134
2352
|
refresh,
|
|
2353
|
+
tick: () => runAction("tick"),
|
|
2135
2354
|
subscribe: (listener) => {
|
|
2136
2355
|
listeners.add(listener);
|
|
2137
2356
|
return () => {
|
|
@@ -2264,10 +2483,97 @@ var defineVoiceOpsStatusElement = (tagName = "absolute-voice-ops-status") => {
|
|
|
2264
2483
|
}
|
|
2265
2484
|
});
|
|
2266
2485
|
};
|
|
2267
|
-
// src/client/
|
|
2268
|
-
var DEFAULT_TITLE2 = "Voice
|
|
2269
|
-
var DEFAULT_DESCRIPTION2 = "
|
|
2486
|
+
// src/client/opsActionCenterWidget.ts
|
|
2487
|
+
var DEFAULT_TITLE2 = "Voice Ops Action Center";
|
|
2488
|
+
var DEFAULT_DESCRIPTION2 = "Run production voice proofs and operator actions from one primitive panel.";
|
|
2270
2489
|
var escapeHtml2 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2490
|
+
var createVoiceOpsActionCenterViewModel = (snapshot, options = {}) => {
|
|
2491
|
+
const status = snapshot.error ? "error" : snapshot.isRunning ? "running" : snapshot.lastResult ? "completed" : "ready";
|
|
2492
|
+
return {
|
|
2493
|
+
actions: snapshot.actions.map((action) => ({
|
|
2494
|
+
description: action.description ?? "",
|
|
2495
|
+
disabled: Boolean(action.disabled || snapshot.isRunning),
|
|
2496
|
+
id: action.id,
|
|
2497
|
+
isRunning: snapshot.runningActionId === action.id,
|
|
2498
|
+
label: action.label
|
|
2499
|
+
})),
|
|
2500
|
+
description: options.description ?? DEFAULT_DESCRIPTION2,
|
|
2501
|
+
error: snapshot.error,
|
|
2502
|
+
isRunning: snapshot.isRunning,
|
|
2503
|
+
label: status === "error" ? "Needs attention" : status === "running" ? "Running" : status === "completed" ? "Action completed" : "Ready",
|
|
2504
|
+
lastResultLabel: snapshot.lastResult ? `${snapshot.lastResult.actionId} returned HTTP ${snapshot.lastResult.status}` : "No action has run yet.",
|
|
2505
|
+
status,
|
|
2506
|
+
title: options.title ?? DEFAULT_TITLE2
|
|
2507
|
+
};
|
|
2508
|
+
};
|
|
2509
|
+
var renderVoiceOpsActionCenterHTML = (snapshot, options = {}) => {
|
|
2510
|
+
const model = createVoiceOpsActionCenterViewModel(snapshot, options);
|
|
2511
|
+
const actions = model.actions.map((action) => `<button type="button" data-absolute-voice-ops-action="${escapeHtml2(action.id)}"${action.disabled ? " disabled" : ""}>
|
|
2512
|
+
${escapeHtml2(action.isRunning ? "Working..." : action.label)}
|
|
2513
|
+
</button>`).join("");
|
|
2514
|
+
return `<section class="absolute-voice-ops-action-center absolute-voice-ops-action-center--${escapeHtml2(model.status)}">
|
|
2515
|
+
<header class="absolute-voice-ops-action-center__header">
|
|
2516
|
+
<span class="absolute-voice-ops-action-center__eyebrow">${escapeHtml2(model.title)}</span>
|
|
2517
|
+
<strong class="absolute-voice-ops-action-center__label">${escapeHtml2(model.label)}</strong>
|
|
2518
|
+
</header>
|
|
2519
|
+
<p class="absolute-voice-ops-action-center__description">${escapeHtml2(model.description)}</p>
|
|
2520
|
+
<div class="absolute-voice-ops-action-center__actions">${actions}</div>
|
|
2521
|
+
<p class="absolute-voice-ops-action-center__result">${escapeHtml2(model.lastResultLabel)}</p>
|
|
2522
|
+
${model.error ? `<p class="absolute-voice-ops-action-center__error">${escapeHtml2(model.error)}</p>` : ""}
|
|
2523
|
+
</section>`;
|
|
2524
|
+
};
|
|
2525
|
+
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}`;
|
|
2526
|
+
var mountVoiceOpsActionCenter = (element, options = {}) => {
|
|
2527
|
+
const store = createVoiceOpsActionCenterStore(options);
|
|
2528
|
+
const render = () => {
|
|
2529
|
+
element.innerHTML = renderVoiceOpsActionCenterHTML(store.getSnapshot(), options);
|
|
2530
|
+
};
|
|
2531
|
+
const unsubscribe = store.subscribe(render);
|
|
2532
|
+
const handleClick = (event) => {
|
|
2533
|
+
const target = event.target;
|
|
2534
|
+
if (!(target instanceof Element)) {
|
|
2535
|
+
return;
|
|
2536
|
+
}
|
|
2537
|
+
const action = target.closest("[data-absolute-voice-ops-action]");
|
|
2538
|
+
const actionId = action?.getAttribute("data-absolute-voice-ops-action");
|
|
2539
|
+
if (actionId) {
|
|
2540
|
+
store.run(actionId).catch(() => {});
|
|
2541
|
+
}
|
|
2542
|
+
};
|
|
2543
|
+
element.addEventListener?.("click", handleClick);
|
|
2544
|
+
render();
|
|
2545
|
+
return {
|
|
2546
|
+
close: () => {
|
|
2547
|
+
element.removeEventListener?.("click", handleClick);
|
|
2548
|
+
unsubscribe();
|
|
2549
|
+
store.close();
|
|
2550
|
+
},
|
|
2551
|
+
run: store.run
|
|
2552
|
+
};
|
|
2553
|
+
};
|
|
2554
|
+
var defineVoiceOpsActionCenterElement = (tagName = "absolute-voice-ops-action-center", options = {}) => {
|
|
2555
|
+
if (typeof window === "undefined" || typeof customElements === "undefined" || customElements.get(tagName)) {
|
|
2556
|
+
return;
|
|
2557
|
+
}
|
|
2558
|
+
customElements.define(tagName, class AbsoluteVoiceOpsActionCenterElement extends HTMLElement {
|
|
2559
|
+
mounted;
|
|
2560
|
+
connectedCallback() {
|
|
2561
|
+
this.mounted = mountVoiceOpsActionCenter(this, {
|
|
2562
|
+
...options,
|
|
2563
|
+
description: this.getAttribute("description") ?? options.description,
|
|
2564
|
+
title: this.getAttribute("title") ?? options.title
|
|
2565
|
+
});
|
|
2566
|
+
}
|
|
2567
|
+
disconnectedCallback() {
|
|
2568
|
+
this.mounted?.close();
|
|
2569
|
+
this.mounted = undefined;
|
|
2570
|
+
}
|
|
2571
|
+
});
|
|
2572
|
+
};
|
|
2573
|
+
// src/client/deliveryRuntimeWidget.ts
|
|
2574
|
+
var DEFAULT_TITLE3 = "Voice Delivery Runtime";
|
|
2575
|
+
var DEFAULT_DESCRIPTION3 = "Audit and trace delivery worker health from your AbsoluteJS voice app.";
|
|
2576
|
+
var escapeHtml3 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2271
2577
|
var createSurface = (id, summary) => {
|
|
2272
2578
|
if (!summary) {
|
|
2273
2579
|
return {
|
|
@@ -2301,45 +2607,70 @@ var createVoiceDeliveryRuntimeViewModel = (snapshot, options = {}) => {
|
|
|
2301
2607
|
];
|
|
2302
2608
|
const hasWarnings = surfaces.some((surface) => surface.status === "warn");
|
|
2303
2609
|
return {
|
|
2304
|
-
description: options.description ??
|
|
2610
|
+
description: options.description ?? DEFAULT_DESCRIPTION3,
|
|
2305
2611
|
error: snapshot.error,
|
|
2612
|
+
actionError: snapshot.actionError,
|
|
2613
|
+
actionStatus: snapshot.actionStatus,
|
|
2306
2614
|
isLoading: snapshot.isLoading,
|
|
2307
2615
|
isRunning: Boolean(report?.isRunning),
|
|
2308
2616
|
label: snapshot.error ? "Unavailable" : report ? report.isRunning ? "Running" : "Stopped" : "Checking",
|
|
2309
2617
|
status: snapshot.error ? "error" : report ? hasWarnings ? "warn" : "pass" : "loading",
|
|
2310
2618
|
surfaces,
|
|
2311
|
-
title: options.title ??
|
|
2619
|
+
title: options.title ?? DEFAULT_TITLE3,
|
|
2312
2620
|
updatedAt: snapshot.updatedAt
|
|
2313
2621
|
};
|
|
2314
2622
|
};
|
|
2315
2623
|
var renderVoiceDeliveryRuntimeHTML = (snapshot, options = {}) => {
|
|
2316
2624
|
const model = createVoiceDeliveryRuntimeViewModel(snapshot, options);
|
|
2317
|
-
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${
|
|
2318
|
-
<span>${
|
|
2319
|
-
<strong>${
|
|
2625
|
+
const surfaces = model.surfaces.map((surface) => `<li class="absolute-voice-delivery-runtime__surface absolute-voice-delivery-runtime__surface--${escapeHtml3(surface.status)}">
|
|
2626
|
+
<span>${escapeHtml3(surface.label)}</span>
|
|
2627
|
+
<strong>${escapeHtml3(surface.detail)}</strong>
|
|
2320
2628
|
<small>${String(surface.failed)} failed · ${String(surface.deadLettered)} dead-lettered</small>
|
|
2321
2629
|
</li>`).join("");
|
|
2322
|
-
|
|
2630
|
+
const actions = options.includeActions === false ? "" : `<div class="absolute-voice-delivery-runtime__actions">
|
|
2631
|
+
<button type="button" data-absolute-voice-delivery-runtime-action="tick">${model.actionStatus === "running" ? "Working..." : "Tick workers"}</button>
|
|
2632
|
+
<button type="button" data-absolute-voice-delivery-runtime-action="requeue-dead-letters"${model.surfaces.some((surface) => surface.deadLettered > 0) ? "" : " disabled"}>Requeue dead letters</button>
|
|
2633
|
+
</div>`;
|
|
2634
|
+
const actionError = model.actionError ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.actionError)}</p>` : "";
|
|
2635
|
+
return `<section class="absolute-voice-delivery-runtime absolute-voice-delivery-runtime--${escapeHtml3(model.status)}">
|
|
2323
2636
|
<header class="absolute-voice-delivery-runtime__header">
|
|
2324
|
-
<span class="absolute-voice-delivery-runtime__eyebrow">${
|
|
2325
|
-
<strong class="absolute-voice-delivery-runtime__label">${
|
|
2637
|
+
<span class="absolute-voice-delivery-runtime__eyebrow">${escapeHtml3(model.title)}</span>
|
|
2638
|
+
<strong class="absolute-voice-delivery-runtime__label">${escapeHtml3(model.label)}</strong>
|
|
2326
2639
|
</header>
|
|
2327
|
-
<p class="absolute-voice-delivery-runtime__description">${
|
|
2640
|
+
<p class="absolute-voice-delivery-runtime__description">${escapeHtml3(model.description)}</p>
|
|
2328
2641
|
<ul class="absolute-voice-delivery-runtime__surfaces">${surfaces}</ul>
|
|
2329
|
-
${
|
|
2642
|
+
${actions}
|
|
2643
|
+
${actionError}
|
|
2644
|
+
${model.error ? `<p class="absolute-voice-delivery-runtime__error">${escapeHtml3(model.error)}</p>` : ""}
|
|
2330
2645
|
</section>`;
|
|
2331
2646
|
};
|
|
2332
|
-
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__error{color:#9f1239;font-weight:700}`;
|
|
2647
|
+
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}`;
|
|
2333
2648
|
var mountVoiceDeliveryRuntime = (element, path = "/api/voice-delivery-runtime", options = {}) => {
|
|
2334
2649
|
const store = createVoiceDeliveryRuntimeStore(path, options);
|
|
2335
2650
|
const render = () => {
|
|
2336
2651
|
element.innerHTML = renderVoiceDeliveryRuntimeHTML(store.getSnapshot(), options);
|
|
2337
2652
|
};
|
|
2338
2653
|
const unsubscribe = store.subscribe(render);
|
|
2654
|
+
const handleClick = (event) => {
|
|
2655
|
+
const target = event.target;
|
|
2656
|
+
if (!(target instanceof Element)) {
|
|
2657
|
+
return;
|
|
2658
|
+
}
|
|
2659
|
+
const action = target.closest("[data-absolute-voice-delivery-runtime-action]");
|
|
2660
|
+
const actionName = action?.getAttribute("data-absolute-voice-delivery-runtime-action");
|
|
2661
|
+
if (actionName === "tick") {
|
|
2662
|
+
store.tick().catch(() => {});
|
|
2663
|
+
}
|
|
2664
|
+
if (actionName === "requeue-dead-letters") {
|
|
2665
|
+
store.requeueDeadLetters().catch(() => {});
|
|
2666
|
+
}
|
|
2667
|
+
};
|
|
2668
|
+
element.addEventListener?.("click", handleClick);
|
|
2339
2669
|
render();
|
|
2340
2670
|
store.refresh().catch(() => {});
|
|
2341
2671
|
return {
|
|
2342
2672
|
close: () => {
|
|
2673
|
+
element.removeEventListener?.("click", handleClick);
|
|
2343
2674
|
unsubscribe();
|
|
2344
2675
|
store.close();
|
|
2345
2676
|
},
|
|
@@ -2446,9 +2777,9 @@ var createVoiceRoutingStatusStore = (path = "/api/routing/latest", options = {})
|
|
|
2446
2777
|
};
|
|
2447
2778
|
};
|
|
2448
2779
|
// src/client/routingStatusWidget.ts
|
|
2449
|
-
var
|
|
2450
|
-
var
|
|
2451
|
-
var
|
|
2780
|
+
var DEFAULT_TITLE4 = "Voice Routing";
|
|
2781
|
+
var DEFAULT_DESCRIPTION4 = "Latest provider routing decision from the self-hosted trace store.";
|
|
2782
|
+
var escapeHtml4 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
2452
2783
|
var formatValue = (value, fallback = "None") => typeof value === "string" && value.trim() ? value : typeof value === "number" && Number.isFinite(value) ? String(value) : fallback;
|
|
2453
2784
|
var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
2454
2785
|
const decision = snapshot.decision;
|
|
@@ -2472,30 +2803,30 @@ var createVoiceRoutingStatusViewModel = (snapshot, options = {}) => {
|
|
|
2472
2803
|
] : [];
|
|
2473
2804
|
return {
|
|
2474
2805
|
decision,
|
|
2475
|
-
description: options.description ??
|
|
2806
|
+
description: options.description ?? DEFAULT_DESCRIPTION4,
|
|
2476
2807
|
error: snapshot.error,
|
|
2477
2808
|
isLoading: snapshot.isLoading,
|
|
2478
2809
|
label: snapshot.error ? "Unavailable" : decision ? `${formatValue(decision.kind).toUpperCase()} ${formatValue(decision.status, "unknown")}` : snapshot.isLoading ? "Checking" : "No routing yet",
|
|
2479
2810
|
rows,
|
|
2480
2811
|
status: snapshot.error ? "error" : decision ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
2481
|
-
title: options.title ??
|
|
2812
|
+
title: options.title ?? DEFAULT_TITLE4,
|
|
2482
2813
|
updatedAt: snapshot.updatedAt
|
|
2483
2814
|
};
|
|
2484
2815
|
};
|
|
2485
2816
|
var renderVoiceRoutingStatusHTML = (snapshot, options = {}) => {
|
|
2486
2817
|
const model = createVoiceRoutingStatusViewModel(snapshot, options);
|
|
2487
2818
|
const rows = model.rows.length ? `<div class="absolute-voice-routing-status__grid">${model.rows.map((row) => `<div>
|
|
2488
|
-
<span>${
|
|
2489
|
-
<strong>${
|
|
2819
|
+
<span>${escapeHtml4(row.label)}</span>
|
|
2820
|
+
<strong>${escapeHtml4(row.value)}</strong>
|
|
2490
2821
|
</div>`).join("")}</div>` : '<p class="absolute-voice-routing-status__empty">Start a voice session to see the selected provider.</p>';
|
|
2491
|
-
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${
|
|
2822
|
+
return `<section class="absolute-voice-routing-status absolute-voice-routing-status--${escapeHtml4(model.status)}">
|
|
2492
2823
|
<header class="absolute-voice-routing-status__header">
|
|
2493
|
-
<span class="absolute-voice-routing-status__eyebrow">${
|
|
2494
|
-
<strong class="absolute-voice-routing-status__label">${
|
|
2824
|
+
<span class="absolute-voice-routing-status__eyebrow">${escapeHtml4(model.title)}</span>
|
|
2825
|
+
<strong class="absolute-voice-routing-status__label">${escapeHtml4(model.label)}</strong>
|
|
2495
2826
|
</header>
|
|
2496
|
-
<p class="absolute-voice-routing-status__description">${
|
|
2827
|
+
<p class="absolute-voice-routing-status__description">${escapeHtml4(model.description)}</p>
|
|
2497
2828
|
${rows}
|
|
2498
|
-
${model.error ? `<p class="absolute-voice-routing-status__error">${
|
|
2829
|
+
${model.error ? `<p class="absolute-voice-routing-status__error">${escapeHtml4(model.error)}</p>` : ""}
|
|
2499
2830
|
</section>`;
|
|
2500
2831
|
};
|
|
2501
2832
|
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}`;
|
|
@@ -3147,7 +3478,7 @@ var createVoiceProviderSimulationControlsStore = (options) => {
|
|
|
3147
3478
|
};
|
|
3148
3479
|
};
|
|
3149
3480
|
// src/client/providerSimulationControlsWidget.ts
|
|
3150
|
-
var
|
|
3481
|
+
var escapeHtml5 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3151
3482
|
var formatKind = (kind) => (kind ?? "stt").toUpperCase();
|
|
3152
3483
|
var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
3153
3484
|
const configuredProviders = options.providers.filter((provider) => provider.configured !== false);
|
|
@@ -3167,18 +3498,18 @@ var createVoiceProviderSimulationControlsViewModel = (snapshot, options) => {
|
|
|
3167
3498
|
};
|
|
3168
3499
|
var renderVoiceProviderSimulationControlsHTML = (snapshot, options) => {
|
|
3169
3500
|
const model = createVoiceProviderSimulationControlsViewModel(snapshot, options);
|
|
3170
|
-
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${
|
|
3171
|
-
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${
|
|
3501
|
+
const failureButtons = model.failureProviders.map((provider) => `<button type="button" data-voice-provider-fail="${escapeHtml5(provider.provider)}"${!model.canSimulateFailure || snapshot.isRunning ? " disabled" : ""}>Simulate ${escapeHtml5(provider.provider)} ${escapeHtml5(formatKind(options.kind))} failure</button>`).join("");
|
|
3502
|
+
const recoveryButtons = model.providers.map((provider) => `<button type="button" data-voice-provider-recover="${escapeHtml5(provider.provider)}"${snapshot.isRunning ? " disabled" : ""}>Mark ${escapeHtml5(provider.provider)} recovered</button>`).join("");
|
|
3172
3503
|
return `<section class="absolute-voice-provider-simulation absolute-voice-provider-simulation--${snapshot.error ? "error" : snapshot.isRunning ? "running" : "ready"}">
|
|
3173
3504
|
<header class="absolute-voice-provider-simulation__header">
|
|
3174
|
-
<span class="absolute-voice-provider-simulation__eyebrow">${
|
|
3175
|
-
<strong class="absolute-voice-provider-simulation__label">${
|
|
3505
|
+
<span class="absolute-voice-provider-simulation__eyebrow">${escapeHtml5(model.title)}</span>
|
|
3506
|
+
<strong class="absolute-voice-provider-simulation__label">${escapeHtml5(model.label)}</strong>
|
|
3176
3507
|
</header>
|
|
3177
|
-
<p class="absolute-voice-provider-simulation__description">${
|
|
3178
|
-
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${
|
|
3508
|
+
<p class="absolute-voice-provider-simulation__description">${escapeHtml5(model.description)}</p>
|
|
3509
|
+
${model.canSimulateFailure ? "" : `<p class="absolute-voice-provider-simulation__empty">${escapeHtml5(options.fallbackRequiredMessage ?? "Configure fallback providers before simulating failure.")}</p>`}
|
|
3179
3510
|
<div class="absolute-voice-provider-simulation__actions">${failureButtons}${recoveryButtons}</div>
|
|
3180
|
-
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${
|
|
3181
|
-
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${
|
|
3511
|
+
${snapshot.error ? `<p class="absolute-voice-provider-simulation__error">${escapeHtml5(snapshot.error)}</p>` : ""}
|
|
3512
|
+
${model.resultText ? `<pre class="absolute-voice-provider-simulation__result">${escapeHtml5(model.resultText)}</pre>` : ""}
|
|
3182
3513
|
</section>`;
|
|
3183
3514
|
};
|
|
3184
3515
|
var bindVoiceProviderSimulationControls = (element, store) => {
|
|
@@ -3243,9 +3574,9 @@ var defineVoiceProviderSimulationControlsElement = (tagName = "absolute-voice-pr
|
|
|
3243
3574
|
});
|
|
3244
3575
|
};
|
|
3245
3576
|
// src/client/providerStatusWidget.ts
|
|
3246
|
-
var
|
|
3247
|
-
var
|
|
3248
|
-
var
|
|
3577
|
+
var DEFAULT_TITLE5 = "Voice Providers";
|
|
3578
|
+
var DEFAULT_DESCRIPTION5 = "Live provider health, fallback counts, latency, and suppression state from your self-hosted trace store.";
|
|
3579
|
+
var escapeHtml6 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3249
3580
|
var formatProvider = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3250
3581
|
var formatStatus = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
3251
3582
|
var formatLatency = (value) => typeof value === "number" ? `${value}ms` : "No samples";
|
|
@@ -3289,37 +3620,37 @@ var createVoiceProviderStatusViewModel = (snapshot, options = {}) => {
|
|
|
3289
3620
|
const warningCount = providers.filter((provider) => isWarningStatus(provider.status)).length;
|
|
3290
3621
|
const healthyCount = providers.filter((provider) => provider.status === "healthy").length;
|
|
3291
3622
|
return {
|
|
3292
|
-
description: options.description ??
|
|
3623
|
+
description: options.description ?? DEFAULT_DESCRIPTION5,
|
|
3293
3624
|
error: snapshot.error,
|
|
3294
3625
|
isLoading: snapshot.isLoading,
|
|
3295
3626
|
label: snapshot.error ? "Unavailable" : providers.length ? warningCount > 0 ? `${warningCount} needs attention` : `${healthyCount} healthy` : snapshot.isLoading ? "Checking" : "No provider traffic",
|
|
3296
3627
|
providers,
|
|
3297
3628
|
status: snapshot.error ? "error" : providers.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3298
|
-
title: options.title ??
|
|
3629
|
+
title: options.title ?? DEFAULT_TITLE5,
|
|
3299
3630
|
updatedAt: snapshot.updatedAt
|
|
3300
3631
|
};
|
|
3301
3632
|
};
|
|
3302
3633
|
var renderVoiceProviderStatusHTML = (snapshot, options = {}) => {
|
|
3303
3634
|
const model = createVoiceProviderStatusViewModel(snapshot, options);
|
|
3304
|
-
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--${
|
|
3635
|
+
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)}">
|
|
3305
3636
|
<header>
|
|
3306
|
-
<strong>${
|
|
3307
|
-
<span>${
|
|
3637
|
+
<strong>${escapeHtml6(provider.label)}</strong>
|
|
3638
|
+
<span>${escapeHtml6(formatStatus(provider.status))}</span>
|
|
3308
3639
|
</header>
|
|
3309
|
-
<p>${
|
|
3640
|
+
<p>${escapeHtml6(provider.detail)}</p>
|
|
3310
3641
|
<dl>${provider.rows.map((row) => `<div>
|
|
3311
|
-
<dt>${
|
|
3312
|
-
<dd>${
|
|
3642
|
+
<dt>${escapeHtml6(row.label)}</dt>
|
|
3643
|
+
<dd>${escapeHtml6(row.value)}</dd>
|
|
3313
3644
|
</div>`).join("")}</dl>
|
|
3314
3645
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-status__empty">Run voice traffic to see provider health.</p>';
|
|
3315
|
-
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${
|
|
3646
|
+
return `<section class="absolute-voice-provider-status absolute-voice-provider-status--${escapeHtml6(model.status)}">
|
|
3316
3647
|
<header class="absolute-voice-provider-status__header">
|
|
3317
|
-
<span class="absolute-voice-provider-status__eyebrow">${
|
|
3318
|
-
<strong class="absolute-voice-provider-status__label">${
|
|
3648
|
+
<span class="absolute-voice-provider-status__eyebrow">${escapeHtml6(model.title)}</span>
|
|
3649
|
+
<strong class="absolute-voice-provider-status__label">${escapeHtml6(model.label)}</strong>
|
|
3319
3650
|
</header>
|
|
3320
|
-
<p class="absolute-voice-provider-status__description">${
|
|
3651
|
+
<p class="absolute-voice-provider-status__description">${escapeHtml6(model.description)}</p>
|
|
3321
3652
|
${providers}
|
|
3322
|
-
${model.error ? `<p class="absolute-voice-provider-status__error">${
|
|
3653
|
+
${model.error ? `<p class="absolute-voice-provider-status__error">${escapeHtml6(model.error)}</p>` : ""}
|
|
3323
3654
|
</section>`;
|
|
3324
3655
|
};
|
|
3325
3656
|
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}`;
|
|
@@ -3360,9 +3691,9 @@ var defineVoiceProviderStatusElement = (tagName = "absolute-voice-provider-statu
|
|
|
3360
3691
|
});
|
|
3361
3692
|
};
|
|
3362
3693
|
// src/client/providerCapabilitiesWidget.ts
|
|
3363
|
-
var
|
|
3364
|
-
var
|
|
3365
|
-
var
|
|
3694
|
+
var DEFAULT_TITLE6 = "Provider Capabilities";
|
|
3695
|
+
var DEFAULT_DESCRIPTION6 = "Configured, selected, and healthy voice providers for this deployment.";
|
|
3696
|
+
var escapeHtml7 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3366
3697
|
var formatProvider2 = (provider) => provider.split(/[-_\s]+/).filter(Boolean).map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ") || provider;
|
|
3367
3698
|
var formatKind2 = (kind) => kind.toUpperCase();
|
|
3368
3699
|
var formatStatus2 = (status) => status.split("-").map((part) => `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
|
|
@@ -3406,36 +3737,36 @@ var createVoiceProviderCapabilitiesViewModel = (snapshot, options = {}) => {
|
|
|
3406
3737
|
const selectedCount = snapshot.report?.selected ?? capabilities.filter((capability) => capability.selected).length;
|
|
3407
3738
|
return {
|
|
3408
3739
|
capabilities,
|
|
3409
|
-
description: options.description ??
|
|
3740
|
+
description: options.description ?? DEFAULT_DESCRIPTION6,
|
|
3410
3741
|
error: snapshot.error,
|
|
3411
3742
|
isLoading: snapshot.isLoading,
|
|
3412
3743
|
label: snapshot.error ? "Unavailable" : capabilities.length ? warningCount > 0 ? `${warningCount} needs attention` : `${selectedCount} selected` : snapshot.isLoading ? "Checking" : "No capabilities",
|
|
3413
3744
|
status: snapshot.error ? "error" : capabilities.length ? warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3414
|
-
title: options.title ??
|
|
3745
|
+
title: options.title ?? DEFAULT_TITLE6,
|
|
3415
3746
|
updatedAt: snapshot.updatedAt
|
|
3416
3747
|
};
|
|
3417
3748
|
};
|
|
3418
3749
|
var renderVoiceProviderCapabilitiesHTML = (snapshot, options = {}) => {
|
|
3419
3750
|
const model = createVoiceProviderCapabilitiesViewModel(snapshot, options);
|
|
3420
|
-
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--${
|
|
3751
|
+
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--${escapeHtml7(capability.status)}">
|
|
3421
3752
|
<header>
|
|
3422
|
-
<strong>${
|
|
3423
|
-
<span>${
|
|
3753
|
+
<strong>${escapeHtml7(capability.label)}</strong>
|
|
3754
|
+
<span>${escapeHtml7(formatStatus2(capability.status))}</span>
|
|
3424
3755
|
</header>
|
|
3425
|
-
<p>${
|
|
3756
|
+
<p>${escapeHtml7(capability.detail)}</p>
|
|
3426
3757
|
<dl>${capability.rows.map((row) => `<div>
|
|
3427
|
-
<dt>${
|
|
3428
|
-
<dd>${
|
|
3758
|
+
<dt>${escapeHtml7(row.label)}</dt>
|
|
3759
|
+
<dd>${escapeHtml7(row.value)}</dd>
|
|
3429
3760
|
</div>`).join("")}</dl>
|
|
3430
3761
|
</article>`).join("")}</div>` : '<p class="absolute-voice-provider-capabilities__empty">Configure provider capabilities to see deployment coverage.</p>';
|
|
3431
|
-
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${
|
|
3762
|
+
return `<section class="absolute-voice-provider-capabilities absolute-voice-provider-capabilities--${escapeHtml7(model.status)}">
|
|
3432
3763
|
<header class="absolute-voice-provider-capabilities__header">
|
|
3433
|
-
<span class="absolute-voice-provider-capabilities__eyebrow">${
|
|
3434
|
-
<strong class="absolute-voice-provider-capabilities__label">${
|
|
3764
|
+
<span class="absolute-voice-provider-capabilities__eyebrow">${escapeHtml7(model.title)}</span>
|
|
3765
|
+
<strong class="absolute-voice-provider-capabilities__label">${escapeHtml7(model.label)}</strong>
|
|
3435
3766
|
</header>
|
|
3436
|
-
<p class="absolute-voice-provider-capabilities__description">${
|
|
3767
|
+
<p class="absolute-voice-provider-capabilities__description">${escapeHtml7(model.description)}</p>
|
|
3437
3768
|
${capabilities}
|
|
3438
|
-
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${
|
|
3769
|
+
${model.error ? `<p class="absolute-voice-provider-capabilities__error">${escapeHtml7(model.error)}</p>` : ""}
|
|
3439
3770
|
</section>`;
|
|
3440
3771
|
};
|
|
3441
3772
|
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}`;
|
|
@@ -3476,9 +3807,9 @@ var defineVoiceProviderCapabilitiesElement = (tagName = "absolute-voice-provider
|
|
|
3476
3807
|
});
|
|
3477
3808
|
};
|
|
3478
3809
|
// src/client/turnQualityWidget.ts
|
|
3479
|
-
var
|
|
3480
|
-
var
|
|
3481
|
-
var
|
|
3810
|
+
var DEFAULT_TITLE7 = "Turn Quality";
|
|
3811
|
+
var DEFAULT_DESCRIPTION7 = "Per-turn STT confidence, fallback selection, corrections, and transcript coverage.";
|
|
3812
|
+
var escapeHtml8 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3482
3813
|
var formatConfidence = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : "n/a";
|
|
3483
3814
|
var formatMaybe = (value) => value === undefined || value === "" ? "n/a" : String(value);
|
|
3484
3815
|
var getTurnDetail = (turn) => {
|
|
@@ -3516,37 +3847,37 @@ var createVoiceTurnQualityViewModel = (snapshot, options = {}) => {
|
|
|
3516
3847
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
3517
3848
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
3518
3849
|
return {
|
|
3519
|
-
description: options.description ??
|
|
3850
|
+
description: options.description ?? DEFAULT_DESCRIPTION7,
|
|
3520
3851
|
error: snapshot.error,
|
|
3521
3852
|
isLoading: snapshot.isLoading,
|
|
3522
3853
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} failed` : warningCount > 0 ? `${warningCount} warnings` : `${turns.length} healthy` : snapshot.isLoading ? "Checking" : "No turns",
|
|
3523
3854
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3524
|
-
title: options.title ??
|
|
3855
|
+
title: options.title ?? DEFAULT_TITLE7,
|
|
3525
3856
|
turns,
|
|
3526
3857
|
updatedAt: snapshot.updatedAt
|
|
3527
3858
|
};
|
|
3528
3859
|
};
|
|
3529
3860
|
var renderVoiceTurnQualityHTML = (snapshot, options = {}) => {
|
|
3530
3861
|
const model = createVoiceTurnQualityViewModel(snapshot, options);
|
|
3531
|
-
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--${
|
|
3862
|
+
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--${escapeHtml8(turn.status)}">
|
|
3532
3863
|
<header>
|
|
3533
|
-
<strong>${
|
|
3534
|
-
<span>${
|
|
3864
|
+
<strong>${escapeHtml8(turn.label)}</strong>
|
|
3865
|
+
<span>${escapeHtml8(turn.status)}</span>
|
|
3535
3866
|
</header>
|
|
3536
|
-
<p>${
|
|
3867
|
+
<p>${escapeHtml8(turn.detail)}</p>
|
|
3537
3868
|
<dl>${turn.rows.map((row) => `<div>
|
|
3538
|
-
<dt>${
|
|
3539
|
-
<dd>${
|
|
3869
|
+
<dt>${escapeHtml8(row.label)}</dt>
|
|
3870
|
+
<dd>${escapeHtml8(row.value)}</dd>
|
|
3540
3871
|
</div>`).join("")}</dl>
|
|
3541
3872
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-quality__empty">Complete a voice turn to see STT quality diagnostics.</p>';
|
|
3542
|
-
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${
|
|
3873
|
+
return `<section class="absolute-voice-turn-quality absolute-voice-turn-quality--${escapeHtml8(model.status)}">
|
|
3543
3874
|
<header class="absolute-voice-turn-quality__header">
|
|
3544
|
-
<span class="absolute-voice-turn-quality__eyebrow">${
|
|
3545
|
-
<strong class="absolute-voice-turn-quality__label">${
|
|
3875
|
+
<span class="absolute-voice-turn-quality__eyebrow">${escapeHtml8(model.title)}</span>
|
|
3876
|
+
<strong class="absolute-voice-turn-quality__label">${escapeHtml8(model.label)}</strong>
|
|
3546
3877
|
</header>
|
|
3547
|
-
<p class="absolute-voice-turn-quality__description">${
|
|
3878
|
+
<p class="absolute-voice-turn-quality__description">${escapeHtml8(model.description)}</p>
|
|
3548
3879
|
${turns}
|
|
3549
|
-
${model.error ? `<p class="absolute-voice-turn-quality__error">${
|
|
3880
|
+
${model.error ? `<p class="absolute-voice-turn-quality__error">${escapeHtml8(model.error)}</p>` : ""}
|
|
3550
3881
|
</section>`;
|
|
3551
3882
|
};
|
|
3552
3883
|
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}`;
|
|
@@ -3587,10 +3918,10 @@ var defineVoiceTurnQualityElement = (tagName = "absolute-voice-turn-quality") =>
|
|
|
3587
3918
|
});
|
|
3588
3919
|
};
|
|
3589
3920
|
// src/client/turnLatencyWidget.ts
|
|
3590
|
-
var
|
|
3591
|
-
var
|
|
3921
|
+
var DEFAULT_TITLE8 = "Turn Latency";
|
|
3922
|
+
var DEFAULT_DESCRIPTION8 = "Per-turn timing from first transcript to commit and assistant response start.";
|
|
3592
3923
|
var DEFAULT_PROOF_LABEL = "Run latency proof";
|
|
3593
|
-
var
|
|
3924
|
+
var escapeHtml9 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3594
3925
|
var formatMs = (value) => typeof value === "number" ? `${Math.round(value)}ms` : "n/a";
|
|
3595
3926
|
var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
3596
3927
|
const turns = (snapshot.report?.turns ?? []).map((turn) => ({
|
|
@@ -3604,39 +3935,39 @@ var createVoiceTurnLatencyViewModel = (snapshot, options = {}) => {
|
|
|
3604
3935
|
const warningCount = snapshot.report?.warnings ?? turns.filter((turn) => turn.status === "warn").length;
|
|
3605
3936
|
const failedCount = snapshot.report?.failed ?? turns.filter((turn) => turn.status === "fail").length;
|
|
3606
3937
|
return {
|
|
3607
|
-
description: options.description ??
|
|
3938
|
+
description: options.description ?? DEFAULT_DESCRIPTION8,
|
|
3608
3939
|
error: snapshot.error,
|
|
3609
3940
|
isLoading: snapshot.isLoading,
|
|
3610
3941
|
label: snapshot.error ? "Unavailable" : turns.length ? failedCount > 0 ? `${failedCount} slow` : warningCount > 0 ? `${warningCount} warnings` : `avg ${formatMs(snapshot.report?.averageTotalMs)}` : snapshot.isLoading ? "Checking" : "No turns",
|
|
3611
3942
|
proofLabel: options.proofPath ? options.proofLabel ?? DEFAULT_PROOF_LABEL : undefined,
|
|
3612
3943
|
showProofAction: Boolean(options.proofPath),
|
|
3613
3944
|
status: snapshot.error ? "error" : turns.length ? failedCount > 0 || warningCount > 0 ? "warning" : "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3614
|
-
title: options.title ??
|
|
3945
|
+
title: options.title ?? DEFAULT_TITLE8,
|
|
3615
3946
|
turns,
|
|
3616
3947
|
updatedAt: snapshot.updatedAt
|
|
3617
3948
|
};
|
|
3618
3949
|
};
|
|
3619
3950
|
var renderVoiceTurnLatencyHTML = (snapshot, options = {}) => {
|
|
3620
3951
|
const model = createVoiceTurnLatencyViewModel(snapshot, options);
|
|
3621
|
-
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--${
|
|
3952
|
+
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)}">
|
|
3622
3953
|
<header>
|
|
3623
|
-
<strong>${
|
|
3624
|
-
<span>${
|
|
3954
|
+
<strong>${escapeHtml9(turn.label)}</strong>
|
|
3955
|
+
<span>${escapeHtml9(turn.status)}</span>
|
|
3625
3956
|
</header>
|
|
3626
3957
|
<dl>${turn.rows.map((row) => `<div>
|
|
3627
|
-
<dt>${
|
|
3628
|
-
<dd>${
|
|
3958
|
+
<dt>${escapeHtml9(row.label)}</dt>
|
|
3959
|
+
<dd>${escapeHtml9(row.value)}</dd>
|
|
3629
3960
|
</div>`).join("")}</dl>
|
|
3630
3961
|
</article>`).join("")}</div>` : '<p class="absolute-voice-turn-latency__empty">Complete a voice turn to see latency diagnostics.</p>';
|
|
3631
|
-
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${
|
|
3962
|
+
return `<section class="absolute-voice-turn-latency absolute-voice-turn-latency--${escapeHtml9(model.status)}">
|
|
3632
3963
|
<header class="absolute-voice-turn-latency__header">
|
|
3633
|
-
<span class="absolute-voice-turn-latency__eyebrow">${
|
|
3634
|
-
<strong class="absolute-voice-turn-latency__label">${
|
|
3964
|
+
<span class="absolute-voice-turn-latency__eyebrow">${escapeHtml9(model.title)}</span>
|
|
3965
|
+
<strong class="absolute-voice-turn-latency__label">${escapeHtml9(model.label)}</strong>
|
|
3635
3966
|
</header>
|
|
3636
|
-
<p class="absolute-voice-turn-latency__description">${
|
|
3637
|
-
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${
|
|
3967
|
+
<p class="absolute-voice-turn-latency__description">${escapeHtml9(model.description)}</p>
|
|
3968
|
+
${model.showProofAction ? `<button class="absolute-voice-turn-latency__proof" data-absolute-voice-turn-latency-proof type="button">${escapeHtml9(model.proofLabel ?? DEFAULT_PROOF_LABEL)}</button>` : ""}
|
|
3638
3969
|
${turns}
|
|
3639
|
-
${model.error ? `<p class="absolute-voice-turn-latency__error">${
|
|
3970
|
+
${model.error ? `<p class="absolute-voice-turn-latency__error">${escapeHtml9(model.error)}</p>` : ""}
|
|
3640
3971
|
</section>`;
|
|
3641
3972
|
};
|
|
3642
3973
|
var mountVoiceTurnLatency = (element, path = "/api/turn-latency", options = {}) => {
|
|
@@ -3686,9 +4017,9 @@ var defineVoiceTurnLatencyElement = (tagName = "absolute-voice-turn-latency") =>
|
|
|
3686
4017
|
});
|
|
3687
4018
|
};
|
|
3688
4019
|
// src/client/traceTimelineWidget.ts
|
|
3689
|
-
var
|
|
3690
|
-
var
|
|
3691
|
-
var
|
|
4020
|
+
var DEFAULT_TITLE9 = "Voice Traces";
|
|
4021
|
+
var DEFAULT_DESCRIPTION9 = "Latest call timelines with provider latency, fallbacks, handoffs, and errors from your self-hosted trace store.";
|
|
4022
|
+
var escapeHtml10 = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
3692
4023
|
var formatMs2 = (value) => typeof value === "number" ? `${value}ms` : "n/a";
|
|
3693
4024
|
var formatProviders = (session) => session.providers.length ? session.providers.map((provider) => provider.provider).join(", ") : "No providers";
|
|
3694
4025
|
var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
@@ -3702,34 +4033,34 @@ var createVoiceTraceTimelineViewModel = (snapshot, options = {}) => {
|
|
|
3702
4033
|
const failed = sessions.filter((session) => session.status === "failed").length;
|
|
3703
4034
|
const warnings = sessions.filter((session) => session.status === "warning").length;
|
|
3704
4035
|
return {
|
|
3705
|
-
description: options.description ??
|
|
4036
|
+
description: options.description ?? DEFAULT_DESCRIPTION9,
|
|
3706
4037
|
error: snapshot.error,
|
|
3707
4038
|
isLoading: snapshot.isLoading,
|
|
3708
4039
|
label: snapshot.error ? "Unavailable" : failed > 0 ? `${failed} failed` : warnings > 0 ? `${warnings} warning` : sessions.length ? `${sessions.length} recent` : snapshot.isLoading ? "Checking" : "No traces yet",
|
|
3709
4040
|
sessions,
|
|
3710
4041
|
status: snapshot.error ? "error" : failed > 0 ? "failed" : warnings > 0 ? "warning" : sessions.length ? "ready" : snapshot.isLoading ? "loading" : "empty",
|
|
3711
|
-
title: options.title ??
|
|
4042
|
+
title: options.title ?? DEFAULT_TITLE9,
|
|
3712
4043
|
updatedAt: snapshot.updatedAt
|
|
3713
4044
|
};
|
|
3714
4045
|
};
|
|
3715
4046
|
var renderVoiceTraceTimelineWidgetHTML = (snapshot, options = {}) => {
|
|
3716
4047
|
const model = createVoiceTraceTimelineViewModel(snapshot, options);
|
|
3717
|
-
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--${
|
|
4048
|
+
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--${escapeHtml10(session.status)}">
|
|
3718
4049
|
<header>
|
|
3719
|
-
<strong>${
|
|
3720
|
-
<span>${
|
|
4050
|
+
<strong>${escapeHtml10(session.sessionId)}</strong>
|
|
4051
|
+
<span>${escapeHtml10(session.status)}</span>
|
|
3721
4052
|
</header>
|
|
3722
|
-
<p>${
|
|
3723
|
-
<a href="${
|
|
4053
|
+
<p>${escapeHtml10(session.label)} \xB7 ${escapeHtml10(session.durationLabel)} \xB7 ${escapeHtml10(session.providerLabel)}</p>
|
|
4054
|
+
<a href="${escapeHtml10(session.detailHref)}">Open timeline</a>
|
|
3724
4055
|
</article>`).join("")}</div>` : '<p class="absolute-voice-trace-timeline__empty">Run a voice session to see call timelines.</p>';
|
|
3725
|
-
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${
|
|
4056
|
+
return `<section class="absolute-voice-trace-timeline absolute-voice-trace-timeline--${escapeHtml10(model.status)}">
|
|
3726
4057
|
<header class="absolute-voice-trace-timeline__header">
|
|
3727
|
-
<span class="absolute-voice-trace-timeline__eyebrow">${
|
|
3728
|
-
<strong class="absolute-voice-trace-timeline__label">${
|
|
4058
|
+
<span class="absolute-voice-trace-timeline__eyebrow">${escapeHtml10(model.title)}</span>
|
|
4059
|
+
<strong class="absolute-voice-trace-timeline__label">${escapeHtml10(model.label)}</strong>
|
|
3729
4060
|
</header>
|
|
3730
|
-
<p class="absolute-voice-trace-timeline__description">${
|
|
4061
|
+
<p class="absolute-voice-trace-timeline__description">${escapeHtml10(model.description)}</p>
|
|
3731
4062
|
${sessions}
|
|
3732
|
-
${model.error ? `<p class="absolute-voice-trace-timeline__error">${
|
|
4063
|
+
${model.error ? `<p class="absolute-voice-trace-timeline__error">${escapeHtml10(model.error)}</p>` : ""}
|
|
3733
4064
|
</section>`;
|
|
3734
4065
|
};
|
|
3735
4066
|
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}`;
|
|
@@ -3852,6 +4183,8 @@ var createVoiceWorkflowStatusStore = (path = "/evals/scenarios/json", options =
|
|
|
3852
4183
|
};
|
|
3853
4184
|
export {
|
|
3854
4185
|
runVoiceTurnLatencyProof,
|
|
4186
|
+
runVoiceOpsAction,
|
|
4187
|
+
runVoiceDeliveryRuntimeAction,
|
|
3855
4188
|
runVoiceCampaignDialerProofAction,
|
|
3856
4189
|
renderVoiceTurnQualityHTML,
|
|
3857
4190
|
renderVoiceTurnLatencyHTML,
|
|
@@ -3861,6 +4194,7 @@ export {
|
|
|
3861
4194
|
renderVoiceProviderSimulationControlsHTML,
|
|
3862
4195
|
renderVoiceProviderCapabilitiesHTML,
|
|
3863
4196
|
renderVoiceOpsStatusHTML,
|
|
4197
|
+
renderVoiceOpsActionCenterHTML,
|
|
3864
4198
|
renderVoiceDeliveryRuntimeHTML,
|
|
3865
4199
|
mountVoiceTurnQuality,
|
|
3866
4200
|
mountVoiceTurnLatency,
|
|
@@ -3870,6 +4204,7 @@ export {
|
|
|
3870
4204
|
mountVoiceProviderSimulationControls,
|
|
3871
4205
|
mountVoiceProviderCapabilities,
|
|
3872
4206
|
mountVoiceOpsStatus,
|
|
4207
|
+
mountVoiceOpsActionCenter,
|
|
3873
4208
|
mountVoiceDeliveryRuntime,
|
|
3874
4209
|
getVoiceTurnQualityCSS,
|
|
3875
4210
|
getVoiceTraceTimelineCSS,
|
|
@@ -3878,6 +4213,7 @@ export {
|
|
|
3878
4213
|
getVoiceProviderCapabilitiesCSS,
|
|
3879
4214
|
getVoiceOpsStatusLabel,
|
|
3880
4215
|
getVoiceOpsStatusCSS,
|
|
4216
|
+
getVoiceOpsActionCenterCSS,
|
|
3881
4217
|
getVoiceDeliveryRuntimeCSS,
|
|
3882
4218
|
fetchVoiceWorkflowStatus,
|
|
3883
4219
|
fetchVoiceTurnQuality,
|
|
@@ -3897,6 +4233,7 @@ export {
|
|
|
3897
4233
|
defineVoiceProviderSimulationControlsElement,
|
|
3898
4234
|
defineVoiceProviderCapabilitiesElement,
|
|
3899
4235
|
defineVoiceOpsStatusElement,
|
|
4236
|
+
defineVoiceOpsActionCenterElement,
|
|
3900
4237
|
defineVoiceDeliveryRuntimeElement,
|
|
3901
4238
|
decodeVoiceAudioChunk,
|
|
3902
4239
|
createVoiceWorkflowStatusStore,
|
|
@@ -3917,6 +4254,9 @@ export {
|
|
|
3917
4254
|
createVoiceProviderCapabilitiesStore,
|
|
3918
4255
|
createVoiceOpsStatusViewModel,
|
|
3919
4256
|
createVoiceOpsStatusStore,
|
|
4257
|
+
createVoiceOpsActionCenterViewModel,
|
|
4258
|
+
createVoiceOpsActionCenterStore,
|
|
4259
|
+
createVoiceOpsActionCenterActions,
|
|
3920
4260
|
createVoiceLiveTurnLatencyMonitor,
|
|
3921
4261
|
createVoiceDuplexController,
|
|
3922
4262
|
createVoiceDeliveryRuntimeViewModel,
|